"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get Comments () {
        return Comments;
    },
    get META_COMMENT () {
        return META_COMMENT;
    },
    get META_COMMENT_VALUE () {
        return META_COMMENT_VALUE;
    },
    get META_READONLY () {
        return META_READONLY;
    },
    get META_STYLE () {
        return META_STYLE;
    },
    get PLUGIN_KEY () {
        return PLUGIN_KEY;
    },
    get PLUGIN_PRIORITY () {
        return PLUGIN_PRIORITY;
    }
});
const _element = require("../../helpers/dom/element");
const _event = require("../../helpers/dom/event");
const _object = require("../../helpers/object");
const _src = require("../../3rdparty/walkontable/src");
const _base = require("../base");
const _errors = require("../../helpers/errors");
const _commentEditor = /*#__PURE__*/ _interop_require_default(require("./commentEditor"));
const _displaySwitch = /*#__PURE__*/ _interop_require_default(require("./displaySwitch"));
const _utils = require("./utils");
const _predefinedItems = require("../contextMenu/predefinedItems");
const _addEditComment = /*#__PURE__*/ _interop_require_default(require("./contextMenuItem/addEditComment"));
const _removeComment = /*#__PURE__*/ _interop_require_default(require("./contextMenuItem/removeComment"));
const _readOnlyComment = /*#__PURE__*/ _interop_require_default(require("./contextMenuItem/readOnlyComment"));
function _check_private_redeclaration(obj, privateCollection) {
    if (privateCollection.has(obj)) {
        throw new TypeError("Cannot initialize the same private elements twice on an object");
    }
}
function _class_apply_descriptor_get(receiver, descriptor) {
    if (descriptor.get) {
        return descriptor.get.call(receiver);
    }
    return descriptor.value;
}
function _class_apply_descriptor_set(receiver, descriptor, value) {
    if (descriptor.set) {
        descriptor.set.call(receiver, value);
    } else {
        if (!descriptor.writable) {
            throw new TypeError("attempted to set read only private field");
        }
        descriptor.value = value;
    }
}
function _class_extract_field_descriptor(receiver, privateMap, action) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to " + action + " private field on non-instance");
    }
    return privateMap.get(receiver);
}
function _class_private_field_get(receiver, privateMap) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
    return _class_apply_descriptor_get(receiver, descriptor);
}
function _class_private_field_init(obj, privateMap, value) {
    _check_private_redeclaration(obj, privateMap);
    privateMap.set(obj, value);
}
function _class_private_field_set(receiver, privateMap, value) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
    _class_apply_descriptor_set(receiver, descriptor, value);
    return value;
}
function _class_private_method_get(receiver, privateSet, fn) {
    if (!privateSet.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return fn;
}
function _class_private_method_init(obj, privateSet) {
    _check_private_redeclaration(obj, privateSet);
    privateSet.add(obj);
}
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
const PLUGIN_KEY = 'comments';
const PLUGIN_PRIORITY = 60;
const META_COMMENT = 'comment';
const META_COMMENT_VALUE = 'value';
const META_STYLE = 'style';
const META_READONLY = 'readOnly';
const SHORTCUTS_GROUP = PLUGIN_KEY;
const SHORTCUTS_CONTEXT_NAME = `plugin:${PLUGIN_KEY}`;
var /**
   * Instance of {@link CommentEditor}.
   *
   * @type {CommentEditor}
   */ _editor = /*#__PURE__*/ new WeakMap(), /**
   * Instance of {@link DisplaySwitch}.
   *
   * @type {DisplaySwitch}
   */ _displaySwitch1 = /*#__PURE__*/ new WeakMap(), /**
   * Prevents showing/hiding editor that reacts on the logic triggered by the "mouseover" events.
   *
   * @type {boolean}
   */ _preventEditorAutoSwitch = /*#__PURE__*/ new WeakMap(), /**
   * Prevents hiding editor when the table viewport is scrolled and that scroll is triggered by the
   * keyboard shortcut that insert or edits the comment.
   *
   * @type {boolean}
   */ _preventEditorHiding = /*#__PURE__*/ new WeakMap(), /**
   * Prevents saving the comment value when the editor is blurred.
   *
   * @type {boolean}
   */ _preventEditorSaveOnBlur = /*#__PURE__*/ new WeakMap(), /**
   * The flag that allows processing mousedown event correctly when comments editor is triggered.
   *
   * @type {boolean}
   */ _cellBelowCursor = /*#__PURE__*/ new WeakMap(), /**
   * Holds the comment value before it's actually saved to the cell meta.
   *
   * @type {string}
   */ _commentValueBeforeSave = /*#__PURE__*/ new WeakMap(), /**
   * `mousedown` event callback.
   *
   * @param {MouseEvent} event The `mousedown` event.
   */ _onMouseDown = /*#__PURE__*/ new WeakSet(), /**
   * Prevent recognizing clicking on the comment editor as clicking outside of table.
   *
   * @param {MouseEvent} event The `mousedown` event.
   */ _onInputElementMouseDown = /*#__PURE__*/ new WeakSet(), /**
   * `mouseover` event callback.
   *
   * @param {MouseEvent} event The `mouseover` event.
   */ _onMouseOver = /*#__PURE__*/ new WeakSet(), /**
   * `mouseup` event callback.
   */ _onMouseUp = /*#__PURE__*/ new WeakSet(), /**
   * The `afterRenderer` hook callback.
   *
   * @param {HTMLTableCellElement} TD The rendered `TD` element.
   * @param {object} cellProperties The rendered cell's property object.
   */ _onAfterRenderer = /*#__PURE__*/ new WeakSet(), /**
   * Hook observer the "blur" event from the comments editor element. The hook clears the
   * editor content and gives back the keyboard shortcuts control by switching to the "grid" context.
   */ _onEditorBlur = /*#__PURE__*/ new WeakSet(), /**
   * Hook observer the "focus" event from the comments editor element. The hook takes the control of
   * the keyboard shortcuts by switching the context to plugins one.
   */ _onEditorFocus = /*#__PURE__*/ new WeakSet(), /**
   * Stops keyboard events from propagating to the grid's shortcut system while the comment
   * textarea is visible. Without this, keys like Ctrl+A trigger grid-level actions (e.g.
   * "select all cells") instead of native textarea behavior. Events matching shortcuts
   * registered in the `plugin:comments` context are allowed through.
   *
   * @param {KeyboardEvent} event The keydown event from the comment textarea.
   */ _onEditorKeyDown = /*#__PURE__*/ new WeakSet(), /**
   * Saves the comments editor size to the cell meta.
   *
   * @param {number} width The new width of the editor.
   * @param {number} height The new height of the editor.
   */ _onEditorResize = /*#__PURE__*/ new WeakSet(), /**
   * Observes the pressed keys and if there is already opened the comment editor prevents open
   * the table editor into the fast edit mode.
   *
   * @param {Event} event The keydown event.
   */ _onAfterDocumentKeyDown = /*#__PURE__*/ new WeakSet(), /**
   * Observes the changes in the scroll position if triggered it hides the comment editor.
   */ _onAfterScroll = /*#__PURE__*/ new WeakSet(), /**
   * Gets the coords object from the range object.
   *
   * @returns {CellCoords} The coords object.
   */ _getRangeCoords = /*#__PURE__*/ new WeakSet();
class Comments extends _base.BasePlugin {
    static get PLUGIN_KEY() {
        return PLUGIN_KEY;
    }
    static get PLUGIN_PRIORITY() {
        return PLUGIN_PRIORITY;
    }
    static get DEFAULT_SETTINGS() {
        return {
            displayDelay: 250
        };
    }
    /**
   * Checks if the plugin is enabled in the handsontable settings. This method is executed in {@link Hooks#beforeInit}
   * hook and if it returns `true` then the {@link Comments#enablePlugin} method is called.
   *
   * @returns {boolean}
   */ isEnabled() {
        return !!this.hot.getSettings()[PLUGIN_KEY];
    }
    /**
   * Enables the plugin functionality for this Handsontable instance.
   */ enablePlugin() {
        if (this.enabled) {
            return;
        }
        if (!_class_private_field_get(this, _editor)) {
            _class_private_field_set(this, _editor, new _commentEditor.default(this.hot.rootDocument, this.hot.isRtl(), this.hot.rootPortalElement));
            _class_private_field_get(this, _editor).addLocalHook('resize', (...args)=>_class_private_method_get(this, _onEditorResize, onEditorResize).call(this, ...args));
            this.hot.addHook('afterSetTheme', (themeName, firstRun)=>{
                if (!firstRun) {
                    this.hide();
                }
            });
        }
        if (!_class_private_field_get(this, _displaySwitch1)) {
            _class_private_field_set(this, _displaySwitch1, new _displaySwitch.default(this.getSetting('displayDelay')));
        }
        this.addHook('afterContextMenuDefaultOptions', (options)=>this.addToContextMenu(options));
        this.addHook('afterRenderer', (TD, row, col, prop, value, cellProperties)=>_class_private_method_get(this, _onAfterRenderer, onAfterRenderer).call(this, TD, cellProperties));
        this.addHook('afterScroll', ()=>_class_private_method_get(this, _onAfterScroll, onAfterScroll).call(this));
        this.addHook('afterBeginEditing', ()=>this.hide());
        this.addHook('afterDocumentKeyDown', (event)=>_class_private_method_get(this, _onAfterDocumentKeyDown, onAfterDocumentKeyDown).call(this, event));
        this.addHook('beforeCompositionStart', (event)=>_class_private_method_get(this, _onAfterDocumentKeyDown, onAfterDocumentKeyDown).call(this, event));
        _class_private_field_get(this, _displaySwitch1).addLocalHook('hide', ()=>this.hide());
        _class_private_field_get(this, _displaySwitch1).addLocalHook('show', (row, col)=>this.showAtCell(row, col));
        this.registerShortcuts();
        this.registerListeners();
        super.enablePlugin();
    }
    /**
   * Updates the plugin's state.
   *
   * This method is executed when [`updateSettings()`](@/api/core.md#updatesettings) is invoked with any of the following configuration options:
   *   - [`comments`](@/api/options.md#comments)
   */ updatePlugin() {
        _class_private_field_get(this, _displaySwitch1).updateDelay(this.getSetting('displayDelay'));
        super.updatePlugin();
    }
    /**
   * Disables the plugin functionality for this Handsontable instance.
   */ disablePlugin() {
        this.unregisterShortcuts();
        super.disablePlugin();
    }
    /**
   * Register shortcuts responsible for toggling context menu.
   *
   * @private
   */ registerShortcuts() {
        const manager = this.hot.getShortcutManager();
        const gridContext = manager.getContext('grid');
        const pluginContext = manager.addContext(SHORTCUTS_CONTEXT_NAME);
        gridContext.addShortcut({
            keys: [
                [
                    'Control',
                    'Alt',
                    'M'
                ]
            ],
            callback: ()=>{
                const range = this.hot.getSelectedRangeActive();
                _class_private_field_set(this, _preventEditorHiding, true);
                this.hot.scrollToFocusedCell(()=>{
                    this.setRange(range);
                    this.show();
                    this.focusEditor();
                    manager.setActiveContextName(SHORTCUTS_CONTEXT_NAME);
                    this.hot._registerTimeout(()=>{
                        _class_private_field_set(this, _preventEditorHiding, false);
                    });
                });
            },
            stopPropagation: true,
            runOnlyIf: ()=>this.hot.getSelectedRangeActive()?.highlight.isCell(),
            group: SHORTCUTS_GROUP
        });
        pluginContext.addShortcut({
            keys: [
                [
                    'Escape'
                ]
            ],
            callback: ()=>{
                _class_private_field_get(this, _editor).setValue(_class_private_field_get(this, _commentValueBeforeSave));
                this.hide();
                manager.setActiveContextName('grid');
            },
            runOnlyIf: ()=>_class_private_field_get(this, _editor).isVisible() && _class_private_field_get(this, _editor).isFocused(),
            group: SHORTCUTS_GROUP
        });
        pluginContext.addShortcut({
            keys: [
                [
                    'Control/Meta',
                    'Enter'
                ]
            ],
            callback: ()=>{
                this.hide();
                manager.setActiveContextName('grid');
            },
            runOnlyIf: ()=>_class_private_field_get(this, _editor).isVisible() && _class_private_field_get(this, _editor).isFocused(),
            group: SHORTCUTS_GROUP
        });
        pluginContext.addShortcut({
            keys: [
                [
                    'Shift',
                    'Tab'
                ],
                [
                    'Tab'
                ]
            ],
            forwardToContext: manager.getContext('grid'),
            callback: ()=>{
                _class_private_field_set(this, _preventEditorSaveOnBlur, true);
                _class_private_field_get(this, _editor).setValue(_class_private_field_get(this, _editor).getValue());
                this.setComment();
                this.hide();
                manager.setActiveContextName('grid');
            },
            group: SHORTCUTS_GROUP
        });
    }
    /**
   * Unregister shortcuts responsible for toggling context menu.
   *
   * @private
   */ unregisterShortcuts() {
        this.hot.getShortcutManager().getContext('grid').removeShortcutsByGroup(SHORTCUTS_GROUP);
    }
    /**
   * Registers all necessary DOM listeners.
   *
   * @private
   */ registerListeners() {
        const { rootDocument } = this.hot;
        const editorElement = this.getEditorInputElement();
        this.eventManager.addEventListener(rootDocument, 'mouseover', (event)=>_class_private_method_get(this, _onMouseOver, onMouseOver).call(this, event));
        this.eventManager.addEventListener(rootDocument, 'mousedown', (event)=>_class_private_method_get(this, _onMouseDown, onMouseDown).call(this, event));
        this.eventManager.addEventListener(rootDocument, 'mouseup', ()=>_class_private_method_get(this, _onMouseUp, onMouseUp).call(this));
        this.eventManager.addEventListener(editorElement, 'focus', ()=>_class_private_method_get(this, _onEditorFocus, onEditorFocus).call(this));
        this.eventManager.addEventListener(editorElement, 'blur', ()=>_class_private_method_get(this, _onEditorBlur, onEditorBlur).call(this));
        this.eventManager.addEventListener(editorElement, 'keydown', (event)=>_class_private_method_get(this, _onEditorKeyDown, onEditorKeyDown).call(this, event));
        this.eventManager.addEventListener(this.getEditorInputElement(), 'mousedown', (event)=>_class_private_method_get(this, _onInputElementMouseDown, onInputElementMouseDown).call(this, event));
    }
    /**
   * Sets the current cell range to be able to use general methods like {@link Comments#setComment}, {@link Comments#removeComment}, {@link Comments#show}.
   *
   * @param {object} range Object with `from` property, each with `row` and `col` properties.
   */ setRange(range) {
        this.range = range;
    }
    /**
   * Clears the currently selected cell.
   */ clearRange() {
        this.range = {};
    }
    /**
   * Checks if the event target is a cell containing a comment.
   *
   * @private
   * @param {Event} event DOM event.
   * @returns {boolean}
   */ targetIsCellWithComment(event) {
        const closestCell = (0, _element.closest)(event.target, 'TD', 'TBODY');
        return !!(closestCell && (0, _element.hasClass)(closestCell, 'htCommentCell') && (0, _element.closest)(closestCell, [
            this.hot.rootElement
        ]));
    }
    /**
   * Checks if the event target is a comment textarea.
   *
   * @private
   * @param {Event} event DOM event.
   * @returns {boolean}
   */ targetIsCommentTextArea(event) {
        return this.getEditorInputElement() === event.target;
    }
    /**
   * Sets a comment for a cell according to the previously set range (see {@link Comments#setRange}).
   *
   * @param {string} value Comment contents.
   */ setComment(value) {
        if (!this.range.from) {
            (0, _errors.throwWithCause)('Before using this method, first set cell range (hot.getPlugin("comment").setRange())');
        }
        const editorValue = _class_private_field_get(this, _editor).getValue();
        let comment = '';
        if (value !== null && value !== undefined) {
            comment = value;
        } else if (editorValue !== null && editorValue !== undefined) {
            comment = editorValue;
        }
        const { row, col } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
        this.updateCommentMeta(row, col, {
            [META_COMMENT_VALUE]: comment
        });
        this.hot.render();
    }
    /**
   * Sets a comment for a specified cell.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {string} value Comment contents.
   */ setCommentAtCell(row, column, value) {
        this.setRange({
            from: this.hot._createCellCoords(row, column)
        });
        this.setComment(value);
    }
    /**
   * Removes a comment from a cell according to previously set range (see {@link Comments#setRange}).
   *
   * @param {boolean} [forceRender=true] If set to `true`, the table will be re-rendered at the end of the operation.
   */ removeComment(forceRender = true) {
        if (!this.range.from) {
            (0, _errors.throwWithCause)('Before using this method, first set cell range (hot.getPlugin("comment").setRange())');
        }
        const { row, col } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
        this.hot.setCellMeta(row, col, META_COMMENT);
        if (forceRender) {
            this.hot.render();
        }
        this.hide();
    }
    /**
   * Removes a comment from a specified cell.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {boolean} [forceRender=true] If `true`, the table will be re-rendered at the end of the operation.
   */ removeCommentAtCell(row, column, forceRender = true) {
        this.setRange({
            from: this.hot._createCellCoords(row, column)
        });
        this.removeComment(forceRender);
    }
    /**
   * Gets comment from a cell according to previously set range (see {@link Comments#setRange}).
   *
   * @returns {string|undefined} Returns a content of the comment.
   */ getComment() {
        const { row, col } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
        return this.getCommentMeta(row, col, META_COMMENT_VALUE);
    }
    /**
   * Gets comment from a cell at the provided coordinates.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @returns {string|undefined} Returns a content of the comment.
   */ getCommentAtCell(row, column) {
        return this.getCommentMeta(row, column, META_COMMENT_VALUE);
    }
    /**
   * Shows the comment editor accordingly to the previously set range (see {@link Comments#setRange}).
   *
   * @returns {boolean} Returns `true` if comment editor was shown.
   */ show() {
        if (!this.range.from) {
            (0, _errors.throwWithCause)('Before using this method, first set cell range (hot.getPlugin("comment").setRange())');
        }
        const { row, col } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
        if (row < 0 || row > this.hot.countSourceRows() - 1 || col < 0 || col > this.hot.countSourceCols() - 1) {
            return false;
        }
        const meta = this.hot.getCellMeta(row, col);
        _class_private_field_get(this, _displaySwitch1).cancelHiding();
        _class_private_field_get(this, _editor).setValue((meta[META_COMMENT] ? meta[META_COMMENT][META_COMMENT_VALUE] : null) ?? '');
        _class_private_field_get(this, _editor).show();
        this.refreshEditor(true);
        return true;
    }
    /**
   * Shows comment editor according to cell coordinates.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @returns {boolean} Returns `true` if comment editor was shown.
   */ showAtCell(row, column) {
        this.setRange({
            from: this.hot._createCellCoords(row, column)
        });
        return this.show();
    }
    /**
   * Hides the comment editor.
   */ hide() {
        _class_private_field_get(this, _editor).hide();
    }
    /**
   * Refreshes comment editor position and styling.
   *
   * @param {boolean} [force=false] If `true` then recalculation will be forced.
   */ refreshEditor(force = false) {
        if (!force && (!this.range.from || !_class_private_field_get(this, _editor).isVisible())) {
            return;
        }
        const { rowIndexMapper, columnIndexMapper } = this.hot;
        const { row: visualRow, col: visualColumn } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
        let renderableRow = rowIndexMapper.getRenderableFromVisualIndex(visualRow);
        let renderableColumn = columnIndexMapper.getRenderableFromVisualIndex(visualColumn);
        // Used when the requested row is hidden, and the editor needs to be positioned on the previous row's coords.
        const targetingPreviousRow = renderableRow === null;
        // Reset the editor position to (0, 0) so the opening direction calculation wouldn't be influenced by its
        // previous position
        _class_private_field_get(this, _editor).setPosition(0, 0);
        if (renderableRow === null) {
            renderableRow = rowIndexMapper.getRenderableFromVisualIndex(rowIndexMapper.getNearestNotHiddenIndex(visualRow, -1));
        }
        if (renderableColumn === null) {
            renderableColumn = columnIndexMapper.getRenderableFromVisualIndex(columnIndexMapper.getNearestNotHiddenIndex(visualColumn, -1));
        }
        const isBeforeRenderedRows = renderableRow === null;
        const isBeforeRenderedColumns = renderableColumn === null;
        renderableRow = renderableRow ?? 0;
        renderableColumn = renderableColumn ?? 0;
        const { rootWindow, view: { _wt: wt } } = this.hot;
        const { wtTable } = wt;
        // TODO: Probably using `hot.getCell` would be the best. However, case for showing comment editor for hidden cell
        // potentially should be removed with that change (currently a test for it is passing).
        const TD = wt.getCell({
            row: renderableRow,
            col: renderableColumn
        }, true);
        const cellMeta = this.hot.getCellMeta(visualRow, visualColumn);
        const metaColspan = cellMeta.colspan ?? 1;
        const commentStyle = this.getCommentMeta(visualRow, visualColumn, META_STYLE);
        if (commentStyle) {
            _class_private_field_get(this, _editor).setSize(commentStyle.width, commentStyle.height);
        } else {
            _class_private_field_get(this, _editor).resetSize();
        }
        const lastColWidth = isBeforeRenderedColumns ? 0 : (0, _utils.getEditorAnchorWidth)(metaColspan, TD, wtTable.getColumnWidth(renderableColumn));
        const lastRowHeight = targetingPreviousRow && !isBeforeRenderedRows ? (0, _element.outerHeight)(TD) : 0;
        const { left, top, width: cellWidth, height: cellHeight } = TD.getBoundingClientRect();
        const { width: editorWidth, height: editorHeight } = _class_private_field_get(this, _editor).getSize();
        const { innerWidth, innerHeight } = this.hot.rootWindow;
        const documentElement = this.hot.rootDocument.documentElement;
        const scrollbarWidth = (0, _element.getScrollbarWidth)(this.hot.rootDocument);
        const verticalScrollbarWidth = (0, _element.hasVerticalScrollbar)(this.hot.rootWindow) ? scrollbarWidth : 0;
        const horizontalScrollbarWidth = (0, _element.hasHorizontalScrollbar)(this.hot.rootWindow) ? scrollbarWidth : 0;
        const mergedBorderCompensation = metaColspan > 1 ? 1 : 0;
        let x = left + rootWindow.scrollX + lastColWidth - mergedBorderCompensation;
        let y = top + rootWindow.scrollY + lastRowHeight;
        if (this.hot.isRtl()) {
            x -= editorWidth + lastColWidth;
        }
        // flip to the right or left the comments editor position when it goes out of browser viewport
        if (this.hot.isLtr() && left + cellWidth + editorWidth > innerWidth - verticalScrollbarWidth) {
            x = left + rootWindow.scrollX - editorWidth - 1;
        } else if (this.hot.isRtl() && x < -(documentElement.scrollWidth - documentElement.clientWidth)) {
            x = left + rootWindow.scrollX + lastColWidth + 1;
        }
        if (top + editorHeight > innerHeight - horizontalScrollbarWidth) {
            y -= editorHeight - cellHeight + 1;
        }
        _class_private_field_get(this, _editor).setPosition(x, y);
        _class_private_field_get(this, _editor).setReadOnlyState(this.getCommentMeta(visualRow, visualColumn, META_READONLY));
        _class_private_field_get(this, _editor).observeSize();
    }
    /**
   * Focuses the comments editor element.
   */ focusEditor() {
        _class_private_field_get(this, _editor).focus();
    }
    /**
   * Sets or update the comment-related cell meta.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {object} metaObject Object defining all the comment-related meta information.
   */ updateCommentMeta(row, column, metaObject) {
        const oldComment = this.hot.getCellMeta(row, column)[META_COMMENT];
        let newComment;
        if (oldComment) {
            newComment = (0, _object.deepClone)(oldComment);
            (0, _object.deepExtend)(newComment, metaObject);
        } else {
            newComment = metaObject;
        }
        this.hot.setCellMeta(row, column, META_COMMENT, newComment);
    }
    /**
   * Gets the comment related meta information.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {string} property Cell meta property.
   * @returns {Mixed}
   */ getCommentMeta(row, column, property) {
        const cellMeta = this.hot.getCellMeta(row, column);
        if (!cellMeta[META_COMMENT]) {
            return undefined;
        }
        return cellMeta[META_COMMENT][property];
    }
    /**
   * Add Comments plugin options to the Context Menu.
   *
   * @private
   * @param {object} options The menu options.
   */ addToContextMenu(options) {
        options.items.push({
            name: _predefinedItems.SEPARATOR
        }, (0, _addEditComment.default)(this), (0, _removeComment.default)(this), (0, _readOnlyComment.default)(this));
    }
    /**
   * Gets the editors input element.
   *
   * @private
   * @returns {HTMLTextAreaElement}
   */ getEditorInputElement() {
        return _class_private_field_get(this, _editor).getInputElement();
    }
    /**
   * Destroys the plugin instance.
   */ destroy() {
        _class_private_field_get(this, _editor)?.destroy();
        _class_private_field_get(this, _displaySwitch1)?.destroy();
        super.destroy();
    }
    constructor(...args){
        super(...args), _class_private_method_init(this, _onMouseDown), _class_private_method_init(this, _onInputElementMouseDown), _class_private_method_init(this, _onMouseOver), _class_private_method_init(this, _onMouseUp), _class_private_method_init(this, _onAfterRenderer), _class_private_method_init(this, _onEditorBlur), _class_private_method_init(this, _onEditorFocus), _class_private_method_init(this, _onEditorKeyDown), _class_private_method_init(this, _onEditorResize), _class_private_method_init(this, _onAfterDocumentKeyDown), _class_private_method_init(this, _onAfterScroll), _class_private_method_init(this, _getRangeCoords), _class_private_field_init(this, _editor, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _displaySwitch1, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _preventEditorAutoSwitch, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _preventEditorHiding, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _preventEditorSaveOnBlur, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _cellBelowCursor, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _commentValueBeforeSave, {
            writable: true,
            value: void 0
        }), /**
   * Current cell range, an object with `from` property, with `row` and `col` properties (e.q. `{from: {row: 1, col: 6}}`).
   *
   * @type {object}
   */ this.range = {}, _class_private_field_set(this, _editor, null), _class_private_field_set(this, _displaySwitch1, null), _class_private_field_set(this, _preventEditorAutoSwitch, false), _class_private_field_set(this, _preventEditorHiding, false), _class_private_field_set(this, _preventEditorSaveOnBlur, false), _class_private_field_set(this, _cellBelowCursor, null), _class_private_field_set(this, _commentValueBeforeSave, '');
    }
}
function onMouseDown(event) {
    if (!this.hot.view || !this.hot.view._wt) {
        return;
    }
    if (!_class_private_field_get(this, _preventEditorAutoSwitch) && !this.targetIsCommentTextArea(event)) {
        const eventCell = (0, _element.closest)(event.target, 'TD', 'TBODY');
        let coordinates = null;
        if (eventCell) {
            coordinates = this.hot.getCoords(eventCell);
        }
        if (!eventCell || this.range.from && coordinates && (this.range.from.row !== coordinates.row || this.range.from.col !== coordinates.col)) {
            this.hide();
        }
    }
}
function onInputElementMouseDown(event) {
    event.stopPropagation();
}
function onMouseOver(event) {
    const { rootDocument } = this.hot;
    if (_class_private_field_get(this, _preventEditorAutoSwitch) || _class_private_field_get(this, _editor).isFocused() || (0, _element.hasClass)(event.target, 'wtBorder') || _class_private_field_get(this, _cellBelowCursor) === event.target || !_class_private_field_get(this, _editor)) {
        return;
    }
    _class_private_field_set(this, _cellBelowCursor, rootDocument.elementFromPoint(event.clientX, event.clientY));
    if (this.targetIsCellWithComment(event)) {
        const range = this.hot._createCellRange(this.hot.getCoords(event.target));
        _class_private_field_get(this, _displaySwitch1).show(range);
    } else if ((0, _element.isChildOf)(event.target, rootDocument) && !this.targetIsCommentTextArea(event)) {
        _class_private_field_get(this, _displaySwitch1).hide();
    }
}
function onMouseUp() {
    _class_private_field_set(this, _preventEditorAutoSwitch, false);
}
function onAfterRenderer(TD, cellProperties) {
    if (cellProperties[META_COMMENT] && cellProperties[META_COMMENT][META_COMMENT_VALUE]) {
        (0, _element.addClass)(TD, cellProperties.commentedCellClassName);
    }
}
function onEditorBlur() {
    if (_class_private_field_get(this, _preventEditorSaveOnBlur)) {
        _class_private_field_set(this, _preventEditorSaveOnBlur, false);
        return;
    }
    _class_private_field_set(this, _commentValueBeforeSave, '');
    this.hot.getShortcutManager().setActiveContextName('grid');
    this.setComment();
}
function onEditorFocus() {
    _class_private_field_set(this, _commentValueBeforeSave, this.getComment());
    this.hot.listen();
    this.hot.getShortcutManager().setActiveContextName(SHORTCUTS_CONTEXT_NAME);
}
function onEditorKeyDown(event) {
    if (!_class_private_field_get(this, _editor).isVisible()) {
        return;
    }
    if (!this.hot.getShortcutManager().hasEventShortcut(SHORTCUTS_CONTEXT_NAME, event)) {
        event.stopPropagation();
    }
}
function onEditorResize(width, height) {
    const { row, col } = _class_private_method_get(this, _getRangeCoords, getRangeCoords).call(this);
    this.updateCommentMeta(row, col, {
        [META_STYLE]: {
            width,
            height
        }
    });
}
function onAfterDocumentKeyDown(event) {
    if (_class_private_field_get(this, _editor).isFocused()) {
        (0, _event.stopImmediatePropagation)(event);
    }
}
function onAfterScroll() {
    if (!_class_private_field_get(this, _preventEditorHiding)) {
        this.hide();
    }
}
function getRangeCoords() {
    if (this.range instanceof _src.CellRange) {
        return this.range.highlight;
    }
    return this.hot._createCellCoords(this.range.from.row, this.range.from.col);
}
