"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 NestedHeaders () {
        return NestedHeaders;
    },
    get PLUGIN_KEY () {
        return PLUGIN_KEY;
    },
    get PLUGIN_PRIORITY () {
        return PLUGIN_PRIORITY;
    }
});
const _element = require("../../helpers/dom/element");
const _number = require("../../helpers/number");
const _templateLiteralTag = require("../../helpers/templateLiteralTag");
const _event = require("../../helpers/dom/event");
const _console = require("../../helpers/console");
const _selection = require("../../selection");
const _base = require("../base");
const _stateManager = /*#__PURE__*/ _interop_require_default(require("./stateManager"));
const _ghostTable = /*#__PURE__*/ _interop_require_default(require("./utils/ghostTable"));
const _navigation = require("./utils/navigation");
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 = 'nestedHeaders';
const PLUGIN_PRIORITY = 280;
var /**
   * The state manager for the nested headers.
   *
   * @type {StateManager}
   */ _stateManager1 = /*#__PURE__*/ new WeakMap(), /**
   * The instance of the ChangesObservable class that allows track the changes that happens in the
   * column indexes.
   *
   * @type {ChangesObservable}
   */ _hidingIndexMapObserver = /*#__PURE__*/ new WeakMap(), /**
   * Holds the coords that points to the place where the column selection starts.
   *
   * @type {number|null}
   */ _focusInitialCoords = /*#__PURE__*/ new WeakMap(), /**
   * Determines if there is performed the column selection.
   *
   * @type {boolean}
   */ _isColumnsSelectionInProgress = /*#__PURE__*/ new WeakMap(), /**
   * Keeps the last highlight position made by column selection. The coords are necessary to scroll
   * the viewport to the correct position when the nested header is clicked when the `navigableHeaders`
   * option is disabled.
   *
   * @type {CellCoords | null}
   */ _recentlyHighlightCoords = /*#__PURE__*/ new WeakMap(), /**
   * Stores the header row level used as context for horizontal navigation when entering
   * and leaving rowspanned headers.
   *
   * @type {number|null}
   */ _rowspanHeaderNavigationContextRow = /*#__PURE__*/ new WeakMap(), /**
   * Stores the expected next highlight coordinates after keyboard navigation. If the next
   * keyboard move starts from different coordinates, the horizontal navigation context
   * is considered stale and should be reset.
   *
   * @type {{row: number, col: number}|null}
   */ _expectedNextKeyboardHighlightCoords = /*#__PURE__*/ new WeakMap(), /**
   * Determines if the widths map should be updated.
   *
   * @type {boolean}
   */ _updateWidthsMap = /*#__PURE__*/ new WeakMap(), /**
   * Determines if the current nested headers state contains headers with `rowspan`.
   *
   * @type {boolean}
   */ _hasRowspanHeaders = /*#__PURE__*/ new WeakMap(), /**
   * Updates the selection focus highlight position to point to the nested header root element (TH)
   * even when the logical coordinates point in-between the header.
   *
   * The method uses arrow function to keep the reference to the class method. Necessary for
   * the `removeLocalHook` method of the row and column index mapper.
   */ _updateFocusHighlightPosition = /*#__PURE__*/ new WeakMap(), /**
   * Finds the first visible header row for the passed coordinates. If the passed coordinates point
   * to a rowspan placeholder, the method traverses up through header levels to find the header cell
   * that visually represents that placeholder.
   *
   * @param {number} headerRow A negative row index that points to a column header level.
   * @param {number} visualColumnIndex A visual column index.
   * @returns {number}
   */ _findRenderableHeaderRow = /*#__PURE__*/ new WeakSet(), /**
   * Returns the rowspan of the root header node for the passed coordinates.
   *
   * @param {number} headerRow A negative row index that points to a column header level.
   * @param {number} visualColumnIndex A visual column index.
   * @returns {number}
   */ _getRootHeaderRowspan = /*#__PURE__*/ new WeakSet(), /**
   * Checks whether the passed header coordinates point to a visible and navigable header cell.
   *
   * @param {number} headerRow A negative row index that points to a column header level.
   * @param {number} visualColumnIndex A visual column index.
   * @returns {boolean}
   */ _isNavigableHeaderCell = /*#__PURE__*/ new WeakSet(), /**
   * Finds the nearest visual column index in the given direction that can be navigated to
   * in the provided header row.
   *
   * @param {number} headerRow A negative row index that points to a column header level.
   * @param {number} visualColumnIndex A visual column index to start searching from.
   * @param {number} direction A direction of the search (`-1` for left, `1` for right).
   * @returns {number|null}
   */ _findNearestNavigableHeaderColumn = /*#__PURE__*/ new WeakSet(), /**
   * Allows to control to which column index the viewport will be scrolled. To ensure that the viewport
   * is scrolled to the correct column for the nested header the most left and the most right visual column
   * indexes are used.
   *
   * @param {number} visualColumn A visual column index to which the viewport will be scrolled.
   * @param {{ value: 'auto' | 'start' | 'end' }} snapping If `'start'`, viewport is scrolled to show
   * the cell on the left of the table. If `'end'`, viewport is scrolled to show the cell on the right of
   * the table. When `'auto'`, the viewport is scrolled only when the column is outside of the viewport.
   * @returns {number}
   */ _onBeforeViewportScrollHorizontally = /*#__PURE__*/ new WeakSet(), /**
   * Allows to control which header DOM element will be used to highlight.
   *
   * @param {number} visualColumn A visual column index of the highlighted row header.
   * @param {number} headerLevel A row header level that is currently highlighted.
   * @param {object} highlightMeta An object with meta data that describes the highlight state.
   * @returns {number}
   */ _onBeforeHighlightingColumnHeader = /*#__PURE__*/ new WeakSet(), /**
   * Listens the `beforeCopy` hook that allows processing the copied column headers so that the
   * merged column headers do not propagate the value for each column but only once at the beginning
   * of the column.
   *
   * @private
   * @param {Array[]} data An array of arrays which contains data to copied.
   * @param {object[]} copyableRanges An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)
   *                                  which will copied.
   * @param {{ columnHeadersCount: number }} copiedHeadersCount An object with keys that holds information with
   *                                                            the number of copied headers.
   */ _onBeforeCopy = /*#__PURE__*/ new WeakSet(), /**
   * Allows blocking the column selection that is controlled by the core Selection module.
   *
   * @param {MouseEvent} event Mouse event.
   * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
   * @param {CellCoords} TD The table cell or header element.
   * @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains
   *                            a boolean value that allows or disallows changing the selection for that particular area.
   */ _onBeforeOnCellMouseDown = /*#__PURE__*/ new WeakSet(), /**
   * Allows to control how the column selection based on the coordinates and the nested headers is made.
   *
   * @param {MouseEvent} event Mouse event.
   * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
   */ _onAfterOnCellMouseDown = /*#__PURE__*/ new WeakSet(), /**
   * Makes the header-selection properly select the nested headers.
   *
   * @param {MouseEvent} event Mouse event.
   * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.
   * @param {HTMLElement} TD The cell element.
   * @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains
   *                            a boolean value that allows or disallows changing the selection for that particular area.
   */ _onBeforeOnCellMouseOver = /*#__PURE__*/ new WeakSet(), /**
   * Switches internal flag about selection progress to `false`.
   */ _onBeforeOnCellMouseUp = /*#__PURE__*/ new WeakSet(), /**
   * The hook checks and ensures that the focus position that depends on the selected columns
   * range is always positioned within the range.
   */ _onBeforeSelectionHighlightSet = /*#__PURE__*/ new WeakSet(), /**
   * `modifyTransformStart` hook is called every time the keyboard navigation is used.
   *
   * @param {object} delta The transformation delta.
   */ _onModifyTransformStart = /*#__PURE__*/ new WeakSet(), /**
   * The hook observes the column selection from the Selection API and modifies the column range to
   * ensure that the whole nested column will be covered.
   *
   * @param {CellCoords} from The coords object where the selection starts.
   * @param {CellCoords} to The coords object where the selection ends.
   * @param {CellCoords} highlight The coords object where the focus is.
   */ _onBeforeSelectColumns = /*#__PURE__*/ new WeakSet(), /**
   * `afterGetColumnHeader` hook callback - prepares the header structure.
   *
   * @param {Array} renderersArray Array of renderers.
   */ _onAfterGetColumnHeaderRenderers = /*#__PURE__*/ new WeakSet(), /**
   * Make the renderer render the first nested column in its entirety.
   *
   * @param {object} calc Viewport column calculator.
   */ _onAfterViewportColumnCalculatorOverride = /*#__PURE__*/ new WeakSet(), /**
   * `modifyColWidth` hook callback - returns width from cache, when is greater than incoming from hook.
   *
   * @param {number} width Width from hook.
   * @param {number} column Visual index of an column.
   * @returns {number}
   */ _onModifyColWidth = /*#__PURE__*/ new WeakSet(), /**
   * Equalizes all nested column header layers' heights when rowspans are used.
   *
   * @returns {number[]|undefined}
   */ _onModifyColumnHeaderHeight = /*#__PURE__*/ new WeakSet(), /**
   * Listens the `modifyColumnHeaderValue` hook that overwrites the column headers values based on
   * the internal state and settings of the plugin.
   *
   * @param {string} value The column header value.
   * @param {number} visualColumnIndex The visual column index.
   * @param {number} headerLevel The index of header level. The header level accepts positive (0 to N)
   *                             and negative (-1 to -N) values. For positive values, 0 points to the
   *                             top most header, and for negative direction, -1 points to the most bottom
   *                             header (the header closest to the cells).
   * @returns {string} Returns the column header value to update.
   */ _onModifyColumnHeaderValue = /*#__PURE__*/ new WeakSet(), /**
   * `modifyFocusedElement` hook callback.
   *
   * @param {number} row Row index.
   * @param {number} column Column index.
   * @returns {HTMLTableCellElement} The `TH` element to be focused.
   */ _onModifyFocusedElement = /*#__PURE__*/ new WeakSet(), /**
   * Updates the plugin state after HoT initialization.
   */ _onInit = /*#__PURE__*/ new WeakSet(), /**
   * Updates the plugin state after new dataset load.
   *
   * @param {Array[]} sourceData Array of arrays or array of objects containing data.
   * @param {boolean} initialLoad Flag that determines whether the data has been loaded
   *                              during the initialization.
   */ _onAfterLoadData = /*#__PURE__*/ new WeakSet(), /**
   * Builds the widths map before the view is rendered.
   */ _onBeforeViewRender = /*#__PURE__*/ new WeakSet();
class NestedHeaders extends _base.BasePlugin {
    static get PLUGIN_KEY() {
        return PLUGIN_KEY;
    }
    static get PLUGIN_PRIORITY() {
        return PLUGIN_PRIORITY;
    }
    /**
   * Check if plugin is enabled.
   *
   * @returns {boolean}
   */ isEnabled() {
        return !!this.hot.getSettings()[PLUGIN_KEY];
    }
    /**
   * Enables the plugin functionality for this Handsontable instance.
   */ enablePlugin() {
        if (this.enabled) {
            return;
        }
        const { nestedHeaders } = this.hot.getSettings();
        if (!Array.isArray(nestedHeaders) || !Array.isArray(nestedHeaders[0])) {
            (0, _console.warn)((0, _templateLiteralTag.toSingleLine)`Your Nested Headers plugin configuration is invalid. The settings has to be\x20
                        passed as an array of arrays e.q. [['A1', { label: 'A2', colspan: 2 }]]`);
        }
        this.addHook('init', ()=>_class_private_method_get(this, _onInit, onInit).call(this));
        this.addHook('afterLoadData', (...args)=>_class_private_method_get(this, _onAfterLoadData, onAfterLoadData).call(this, ...args));
        this.addHook('beforeOnCellMouseDown', (...args)=>_class_private_method_get(this, _onBeforeOnCellMouseDown, onBeforeOnCellMouseDown).call(this, ...args));
        this.addHook('afterOnCellMouseDown', (...args)=>_class_private_method_get(this, _onAfterOnCellMouseDown, onAfterOnCellMouseDown).call(this, ...args));
        this.addHook('beforeOnCellMouseOver', (...args)=>_class_private_method_get(this, _onBeforeOnCellMouseOver, onBeforeOnCellMouseOver).call(this, ...args));
        this.addHook('beforeOnCellMouseUp', (...args)=>_class_private_method_get(this, _onBeforeOnCellMouseUp, onBeforeOnCellMouseUp).call(this, ...args));
        this.addHook('beforeSelectionHighlightSet', (...args)=>_class_private_method_get(this, _onBeforeSelectionHighlightSet, onBeforeSelectionHighlightSet).call(this, ...args));
        this.addHook('modifyTransformStart', (...args)=>_class_private_method_get(this, _onModifyTransformStart, onModifyTransformStart).call(this, ...args));
        this.addHook('afterSelection', ()=>_class_private_field_get(this, _updateFocusHighlightPosition).call(this));
        this.addHook('afterSelectionFocusSet', ()=>_class_private_field_get(this, _updateFocusHighlightPosition).call(this));
        this.addHook('beforeViewportScrollHorizontally', (...args)=>_class_private_method_get(this, _onBeforeViewportScrollHorizontally, onBeforeViewportScrollHorizontally).call(this, ...args));
        this.addHook('afterGetColumnHeaderRenderers', (array)=>_class_private_method_get(this, _onAfterGetColumnHeaderRenderers, onAfterGetColumnHeaderRenderers).call(this, array));
        this.addHook('modifyColWidth', (...args)=>_class_private_method_get(this, _onModifyColWidth, onModifyColWidth).call(this, ...args));
        this.addHook('modifyColumnHeaderHeight', (...args)=>_class_private_method_get(this, _onModifyColumnHeaderHeight, onModifyColumnHeaderHeight).call(this, ...args));
        this.addHook('modifyColumnHeaderValue', (...args)=>_class_private_method_get(this, _onModifyColumnHeaderValue, onModifyColumnHeaderValue).call(this, ...args));
        this.addHook('beforeHighlightingColumnHeader', (...args)=>_class_private_method_get(this, _onBeforeHighlightingColumnHeader, onBeforeHighlightingColumnHeader).call(this, ...args));
        this.addHook('beforeCopy', (...args)=>_class_private_method_get(this, _onBeforeCopy, onBeforeCopy).call(this, ...args));
        this.addHook('beforeSelectColumns', (...args)=>_class_private_method_get(this, _onBeforeSelectColumns, onBeforeSelectColumns).call(this, ...args));
        this.addHook('beforeViewRender', ()=>_class_private_method_get(this, _onBeforeViewRender, onBeforeViewRender).call(this));
        this.addHook('afterViewportColumnCalculatorOverride', (...args)=>_class_private_method_get(this, _onAfterViewportColumnCalculatorOverride, onAfterViewportColumnCalculatorOverride).call(this, ...args));
        this.addHook('modifyFocusedElement', (...args)=>_class_private_method_get(this, _onModifyFocusedElement, onModifyFocusedElement).call(this, ...args));
        this.hot.columnIndexMapper.addLocalHook('cacheUpdated', _class_private_field_get(this, _updateFocusHighlightPosition));
        this.hot.rowIndexMapper.addLocalHook('cacheUpdated', _class_private_field_get(this, _updateFocusHighlightPosition));
        super.enablePlugin();
        this.updatePlugin(); // @TODO: Workaround for broken plugin initialization abstraction.
    }
    /**
   * Updates the plugin's state.
   *
   * This method is executed when [`updateSettings()`](@/api/core.md#updatesettings) is invoked with any of the following configuration options:
   *  - [`nestedHeaders`](@/api/options.md#nestedheaders)
   */ updatePlugin() {
        if (!this.hot.view) {
            return;
        }
        const { nestedHeaders } = this.hot.getSettings();
        _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null);
        _class_private_field_set(this, _expectedNextKeyboardHighlightCoords, null);
        _class_private_field_get(this, _stateManager1).setColumnsLimit(this.hot.countCols());
        if (Array.isArray(nestedHeaders)) {
            this.detectedOverlappedHeaders = _class_private_field_get(this, _stateManager1).setState(nestedHeaders);
        }
        _class_private_field_set(this, _hasRowspanHeaders, _class_private_field_get(this, _stateManager1).mapNodes(({ origRowspan })=>origRowspan > 1 ? true : undefined).length > 0);
        if (_class_private_field_get(this, _hasRowspanHeaders)) {
            (0, _element.addClass)(this.hot.rootElement, 'htHasRowspanHeaders');
        } else {
            (0, _element.removeClass)(this.hot.rootElement, 'htHasRowspanHeaders');
        }
        if (this.detectedOverlappedHeaders) {
            (0, _console.warn)((0, _templateLiteralTag.toSingleLine)`Your Nested Headers plugin setup contains overlapping headers. This kind of configuration\x20
                        is currently not supported.`);
        }
        if (this.enabled) {
            // This line covers the case when a developer uses the external hiding maps to manipulate
            // the columns' visibility. The tree state built from the settings - which is always built
            // as if all the columns are visible, needs to be modified to be in sync with a dataset.
            this.hot.columnIndexMapper.hidingMapsCollection.getMergedValues().forEach((isColumnHidden, physicalColumnIndex)=>{
                const actionName = isColumnHidden === true ? 'hide-column' : 'show-column';
                _class_private_field_get(this, _stateManager1).triggerColumnModification(actionName, physicalColumnIndex);
            });
        }
        if (!_class_private_field_get(this, _hidingIndexMapObserver) && this.enabled) {
            _class_private_field_set(this, _hidingIndexMapObserver, this.hot.columnIndexMapper.createChangesObserver('hiding').subscribe((changes)=>{
                changes.forEach(({ op, index: columnIndex, newValue })=>{
                    if (op === 'replace') {
                        const actionName = newValue === true ? 'hide-column' : 'show-column';
                        _class_private_field_get(this, _stateManager1).triggerColumnModification(actionName, columnIndex);
                    }
                });
                this.ghostTable.buildWidthsMap();
            }));
        }
        _class_private_field_set(this, _updateWidthsMap, true);
        super.updatePlugin();
    }
    /**
   * Disables the plugin functionality for this Handsontable instance.
   */ disablePlugin() {
        this.hot.rowIndexMapper.removeLocalHook('cacheUpdated', _class_private_field_get(this, _updateFocusHighlightPosition));
        this.hot.columnIndexMapper.removeLocalHook('cacheUpdated', _class_private_field_get(this, _updateFocusHighlightPosition));
        this.clearColspans();
        _class_private_field_get(this, _stateManager1).clear();
        _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null);
        _class_private_field_set(this, _expectedNextKeyboardHighlightCoords, null);
        (0, _element.removeClass)(this.hot.rootElement, 'htHasRowspanHeaders');
        _class_private_field_get(this, _hidingIndexMapObserver).unsubscribe();
        _class_private_field_set(this, _hidingIndexMapObserver, null);
        this.ghostTable.clear();
        super.disablePlugin();
    }
    /**
   * Returns an instance of the internal state manager of the plugin.
   *
   * @private
   * @returns {StateManager}
   */ getStateManager() {
        return _class_private_field_get(this, _stateManager1);
    }
    /**
   * Gets a total number of headers levels.
   *
   * @private
   * @returns {number}
   */ getLayersCount() {
        return _class_private_field_get(this, _stateManager1).getLayersCount();
    }
    /**
   * Gets column settings for a specified header. The returned object contains
   * information about the header label, its colspan length, or if it is hidden
   * in the header renderers.
   *
   * @private
   * @param {number} headerLevel Header level (0 = most distant to the table).
   * @param {number} columnIndex A visual column index.
   * @returns {object}
   */ getHeaderSettings(headerLevel, columnIndex) {
        return _class_private_field_get(this, _stateManager1).getHeaderSettings(headerLevel, columnIndex);
    }
    /**
   * Clear the colspans remaining after plugin usage.
   *
   * @private
   */ clearColspans() {
        if (!this.hot.view) {
            return;
        }
        const { _wt: wt } = this.hot.view;
        const headerLevels = wt.getSetting('columnHeaders').length;
        const mainHeaders = wt.wtTable.THEAD;
        const topHeaders = wt.wtOverlays.topOverlay.clone.wtTable.THEAD;
        const topLeftCornerHeaders = wt.wtOverlays.topInlineStartCornerOverlay ? wt.wtOverlays.topInlineStartCornerOverlay.clone.wtTable.THEAD : null;
        for(let i = 0; i < headerLevels; i++){
            const masterLevel = mainHeaders.childNodes[i];
            if (!masterLevel) {
                break;
            }
            const topLevel = topHeaders.childNodes[i];
            const topLeftCornerLevel = topLeftCornerHeaders ? topLeftCornerHeaders.childNodes[i] : null;
            for(let j = 0, masterNodes = masterLevel.childNodes.length; j < masterNodes; j++){
                masterLevel.childNodes[j].removeAttribute('colspan');
                masterLevel.childNodes[j].removeAttribute('rowspan');
                masterLevel.childNodes[j].style.display = '';
                (0, _element.removeClass)(masterLevel.childNodes[j], 'hiddenHeader');
                if (topLevel && topLevel.childNodes[j]) {
                    topLevel.childNodes[j].removeAttribute('colspan');
                    topLevel.childNodes[j].removeAttribute('rowspan');
                    topLevel.childNodes[j].style.display = '';
                    (0, _element.removeClass)(topLevel.childNodes[j], 'hiddenHeader');
                }
                if (topLeftCornerHeaders && topLeftCornerLevel && topLeftCornerLevel.childNodes[j]) {
                    topLeftCornerLevel.childNodes[j].removeAttribute('colspan');
                    topLeftCornerLevel.childNodes[j].removeAttribute('rowspan');
                    topLeftCornerLevel.childNodes[j].style.display = '';
                    (0, _element.removeClass)(topLeftCornerLevel.childNodes[j], 'hiddenHeader');
                }
            }
        }
    }
    /**
   * Generates the appropriate header renderer for a header row.
   *
   * @private
   * @param {number} headerLevel The index of header level counting from the top (positive
   *                             values counting from 0 to N).
   * @returns {Function}
   * @fires Hooks#afterGetColHeader
   */ headerRendererFactory(headerLevel) {
        const fixedColumnsStart = this.hot.view._wt.getSetting('fixedColumnsStart');
        return (renderedColumnIndex, TH)=>{
            const { columnIndexMapper, view } = this.hot;
            let visualColumnIndex = columnIndexMapper.getVisualFromRenderableIndex(renderedColumnIndex);
            if (visualColumnIndex === null) {
                visualColumnIndex = renderedColumnIndex;
            }
            TH.removeAttribute('colspan');
            TH.removeAttribute('rowspan');
            TH.style.display = '';
            (0, _element.removeClass)(TH, 'hiddenHeader');
            (0, _element.removeClass)(TH, 'hiddenHeaderText');
            (0, _element.removeClass)(TH, 'htRowspanHeader');
            (0, _element.removeClass)(TH, 'htRowspanBottomLevel');
            const { colspan, rowspan, isHidden, isPlaceholder, isRowspanPlaceholder, headerClassNames } = _class_private_field_get(this, _stateManager1).getHeaderSettings(headerLevel, visualColumnIndex) ?? {
                label: ''
            };
            if (isRowspanPlaceholder) {
                (0, _element.addClass)(TH, 'hiddenHeader');
                TH.style.display = 'none';
            } else if (isPlaceholder || isHidden) {
                (0, _element.addClass)(TH, 'hiddenHeader');
            } else {
                if (colspan > 1) {
                    const { wtOverlays } = view._wt;
                    const isTopInlineStartOverlay = wtOverlays.topInlineStartCornerOverlay?.clone.wtTable.THEAD.contains(TH);
                    const isInlineStartOverlay = wtOverlays.inlineStartOverlay?.clone.wtTable.THEAD.contains(TH);
                    const isTopOverlay = wtOverlays.topOverlay?.clone.wtTable.THEAD.contains(TH);
                    if (isTopOverlay && visualColumnIndex < fixedColumnsStart) {
                        (0, _element.addClass)(TH, 'hiddenHeaderText');
                    }
                    const correctedColspan = isTopInlineStartOverlay || isInlineStartOverlay ? Math.min(colspan, fixedColumnsStart - renderedColumnIndex) : colspan;
                    if (correctedColspan > 1) {
                        TH.setAttribute('colspan', correctedColspan);
                    }
                }
                if (rowspan > 1) {
                    const isBottomMostRowspanHeader = headerLevel + rowspan === this.getLayersCount();
                    (0, _element.addClass)(TH, 'htRowspanHeader');
                    if (isBottomMostRowspanHeader) {
                        (0, _element.addClass)(TH, 'htRowspanBottomLevel');
                    }
                    TH.setAttribute('rowspan', rowspan);
                }
            }
            this.hot.view.appendColHeader(visualColumnIndex, TH, (...args)=>this.getColumnHeaderValue(...args), headerLevel);
            if (!isPlaceholder && !isHidden && !isRowspanPlaceholder) {
                const innerHeaderDiv = TH.querySelector('div.relative');
                if (innerHeaderDiv && headerClassNames && headerClassNames.length > 0) {
                    (0, _element.removeClass)(innerHeaderDiv, this.hot.getColumnMeta(visualColumnIndex).headerClassName);
                    (0, _element.addClass)(innerHeaderDiv, headerClassNames);
                }
            }
        };
    }
    /**
   * Returns the column header value for specified column and header level index.
   *
   * @private
   * @param {number} visualColumnIndex Visual column index.
   * @param {number} headerLevel The index of header level. The header level accepts positive (0 to N)
   *                             and negative (-1 to -N) values. For positive values, 0 points to the
   *                             top most header, and for negative direction, -1 points to the most bottom
   *                             header (the header closest to the cells).
   * @returns {string} Returns the column header value to update.
   */ getColumnHeaderValue(visualColumnIndex, headerLevel) {
        const { isHidden, isPlaceholder, isRowspanPlaceholder } = _class_private_field_get(this, _stateManager1).getHeaderSettings(headerLevel, visualColumnIndex) ?? {};
        if (isPlaceholder || isHidden || isRowspanPlaceholder) {
            return '';
        }
        return this.hot.getColHeader(visualColumnIndex, headerLevel);
    }
    /**
   * Destroys the plugin instance.
   */ destroy() {
        _class_private_field_set(this, _stateManager1, null);
        (0, _element.removeClass)(this.hot.rootElement, 'htHasRowspanHeaders');
        if (_class_private_field_get(this, _hidingIndexMapObserver) !== null) {
            _class_private_field_get(this, _hidingIndexMapObserver).unsubscribe();
            _class_private_field_set(this, _hidingIndexMapObserver, null);
        }
        super.destroy();
    }
    /**
   * Gets the tree data that belongs to the column headers pointed by the passed coordinates.
   *
   * @private
   * @param {CellCoords} coords The CellCoords instance.
   * @returns {object|undefined}
   */ _getHeaderTreeNodeDataByCoords(coords) {
        if (coords.row >= 0 || coords.col < 0) {
            return;
        }
        return _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(coords.row, coords.col);
    }
    constructor(...args){
        super(...args), _class_private_method_init(this, _findRenderableHeaderRow), _class_private_method_init(this, _getRootHeaderRowspan), _class_private_method_init(this, _isNavigableHeaderCell), _class_private_method_init(this, _findNearestNavigableHeaderColumn), _class_private_method_init(this, _onBeforeViewportScrollHorizontally), _class_private_method_init(this, _onBeforeHighlightingColumnHeader), _class_private_method_init(this, _onBeforeCopy), _class_private_method_init(this, _onBeforeOnCellMouseDown), _class_private_method_init(this, _onAfterOnCellMouseDown), _class_private_method_init(this, _onBeforeOnCellMouseOver), _class_private_method_init(this, _onBeforeOnCellMouseUp), _class_private_method_init(this, _onBeforeSelectionHighlightSet), _class_private_method_init(this, _onModifyTransformStart), _class_private_method_init(this, _onBeforeSelectColumns), _class_private_method_init(this, _onAfterGetColumnHeaderRenderers), _class_private_method_init(this, _onAfterViewportColumnCalculatorOverride), _class_private_method_init(this, _onModifyColWidth), _class_private_method_init(this, _onModifyColumnHeaderHeight), _class_private_method_init(this, _onModifyColumnHeaderValue), _class_private_method_init(this, _onModifyFocusedElement), _class_private_method_init(this, _onInit), _class_private_method_init(this, _onAfterLoadData), _class_private_method_init(this, _onBeforeViewRender), _class_private_field_init(this, _stateManager1, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _hidingIndexMapObserver, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _focusInitialCoords, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _isColumnsSelectionInProgress, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _recentlyHighlightCoords, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _rowspanHeaderNavigationContextRow, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _expectedNextKeyboardHighlightCoords, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _updateWidthsMap, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _hasRowspanHeaders, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _updateFocusHighlightPosition, {
            writable: true,
            value: void 0
        }), _class_private_field_set(this, _stateManager1, new _stateManager.default()), _class_private_field_set(this, _hidingIndexMapObserver, null), _class_private_field_set(this, _focusInitialCoords, null), _class_private_field_set(this, _isColumnsSelectionInProgress, false), _class_private_field_set(this, _recentlyHighlightCoords, null), _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null), _class_private_field_set(this, _expectedNextKeyboardHighlightCoords, null), _class_private_field_set(this, _updateWidthsMap, false), /**
   * Custom helper for getting widths of the nested headers.
   *
   * @private
   * @type {GhostTable}
   */ // @TODO This should be changed after refactor handsontable/utils/ghostTable.
        this.ghostTable = new _ghostTable.default({
            hot: this.hot,
            headersStateManager: _class_private_field_get(this, _stateManager1)
        }), /**
   * The flag which determines that the nested header settings contains overlapping headers
   * configuration.
   *
   * @type {boolean}
   */ this.detectedOverlappedHeaders = false, _class_private_field_set(this, _hasRowspanHeaders, false), _class_private_field_set(this, _updateFocusHighlightPosition, ()=>{
            const selection = this.hot?.getSelectedRangeActive();
            if (!selection) {
                return;
            }
            const { highlight } = selection;
            const isNestedHeadersRange = highlight.isHeader() && highlight.col >= 0;
            if (isNestedHeadersRange) {
                const { isRowspanPlaceholder } = _class_private_field_get(this, _stateManager1).getHeaderSettings(highlight.row, highlight.col) ?? {};
                const normalizedHighlightRow = isRowspanPlaceholder ? _class_private_method_get(this, _findRenderableHeaderRow, findRenderableHeaderRow).call(this, highlight.row, highlight.col) : highlight.row;
                const columnIndex = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(normalizedHighlightRow, highlight.col);
                const focusHighlight = this.hot.selection.highlight.getFocus();
                const focusVisualCellRange = focusHighlight.visualCellRange;
                if (focusVisualCellRange === null) {
                    return;
                }
                // Correct the highlight/focus selection to highlight the correct TH element
                focusVisualCellRange.highlight.row = normalizedHighlightRow;
                focusVisualCellRange.highlight.col = columnIndex;
                focusVisualCellRange.from.row = normalizedHighlightRow;
                focusVisualCellRange.from.col = columnIndex;
                focusVisualCellRange.to.row = normalizedHighlightRow;
                focusVisualCellRange.to.col = columnIndex;
                focusHighlight.commit();
            }
        });
    }
}
function findRenderableHeaderRow(headerRow, visualColumnIndex) {
    const highestHeaderRow = -this.getLayersCount();
    for(let row = headerRow; row >= highestHeaderRow; row--){
        const { isRowspanPlaceholder } = _class_private_field_get(this, _stateManager1).getHeaderSettings(row, visualColumnIndex) ?? {};
        if (!isRowspanPlaceholder) {
            return row;
        }
    }
    return headerRow;
}
function getRootHeaderRowspan(headerRow, visualColumnIndex) {
    const rootColumnIndex = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(headerRow, visualColumnIndex);
    const { rowspan = 1 } = _class_private_field_get(this, _stateManager1).getHeaderSettings(headerRow, rootColumnIndex) ?? {};
    return rowspan;
}
function isNavigableHeaderCell(headerRow, visualColumnIndex) {
    const headerSettings = _class_private_field_get(this, _stateManager1).getHeaderSettings(headerRow, visualColumnIndex);
    if (!headerSettings) {
        return false;
    }
    const { isPlaceholder, isRowspanPlaceholder, isHidden } = headerSettings;
    if (isRowspanPlaceholder) {
        return headerRow < -1;
    }
    return !isPlaceholder && !isRowspanPlaceholder && !isHidden;
}
function findNearestNavigableHeaderColumn(headerRow, visualColumnIndex, direction) {
    if (![
        -1,
        1
    ].includes(direction)) {
        return null;
    }
    for(let column = visualColumnIndex; column >= 0 && column < this.hot.countCols(); column += direction){
        if (_class_private_method_get(this, _isNavigableHeaderCell, isNavigableHeaderCell).call(this, headerRow, column)) {
            return column;
        }
    }
    return null;
}
function onBeforeViewportScrollHorizontally(visualColumn, snapping) {
    const selection = this.hot.getSelectedRangeActive();
    if (!selection) {
        return visualColumn;
    }
    const { highlight } = selection;
    const { navigableHeaders } = this.hot.getSettings();
    const isSelectedByColumnHeader = this.hot.selection.isSelectedByColumnHeader();
    const highlightRow = navigableHeaders ? highlight.row : _class_private_field_get(this, _recentlyHighlightCoords)?.row;
    const highlightColumn = isSelectedByColumnHeader ? visualColumn : highlight.col;
    const isNestedHeadersRange = highlightRow < 0 && highlightColumn >= 0;
    _class_private_field_set(this, _recentlyHighlightCoords, null);
    if (!isNestedHeadersRange) {
        return visualColumn;
    }
    const firstVisibleColumn = this.hot.getFirstFullyVisibleColumn();
    const lastVisibleColumn = this.hot.getLastFullyVisibleColumn();
    const viewportWidth = lastVisibleColumn - firstVisibleColumn + 1;
    const mostLeftColumnIndex = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(highlightRow, highlightColumn);
    const mostRightColumnIndex = _class_private_field_get(this, _stateManager1).findRightMostColumnIndex(highlightRow, highlightColumn);
    const headerWidth = mostRightColumnIndex - mostLeftColumnIndex + 1;
    // scroll the viewport always to the left when the header is wider than the viewport
    if (mostLeftColumnIndex < firstVisibleColumn && mostRightColumnIndex > lastVisibleColumn) {
        return mostLeftColumnIndex;
    }
    if (isSelectedByColumnHeader) {
        let scrollColumnIndex = null;
        if (mostLeftColumnIndex >= firstVisibleColumn && mostRightColumnIndex > lastVisibleColumn) {
            if (headerWidth > viewportWidth) {
                snapping.value = 'start';
                scrollColumnIndex = mostLeftColumnIndex;
            } else {
                snapping.value = 'end';
                scrollColumnIndex = mostRightColumnIndex;
            }
        } else if (mostLeftColumnIndex < firstVisibleColumn && mostRightColumnIndex <= lastVisibleColumn) {
            if (headerWidth > viewportWidth) {
                snapping.value = 'end';
                scrollColumnIndex = mostRightColumnIndex;
            } else {
                snapping.value = 'start';
                scrollColumnIndex = mostLeftColumnIndex;
            }
        }
        return scrollColumnIndex;
    }
    return mostLeftColumnIndex <= firstVisibleColumn ? mostLeftColumnIndex : mostRightColumnIndex;
}
function onBeforeHighlightingColumnHeader(visualColumn, headerLevel, highlightMeta) {
    const headerNodeData = _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(headerLevel, visualColumn);
    if (!headerNodeData) {
        return visualColumn;
    }
    const { columnCursor, selectionType, selectionWidth } = highlightMeta;
    const { isRoot, colspan } = _class_private_field_get(this, _stateManager1).getHeaderSettings(headerLevel, visualColumn);
    if (selectionType === _selection.HEADER_TYPE) {
        if (!isRoot) {
            return headerNodeData.columnIndex;
        }
    } else if (selectionType === _selection.ACTIVE_HEADER_TYPE) {
        if (colspan > selectionWidth - columnCursor || !isRoot) {
            // Prevents adding any CSS class names to the TH element
            return null;
        }
    }
    return visualColumn;
}
function onBeforeCopy(data, copyableRanges, { columnHeadersCount }) {
    if (columnHeadersCount === 0) {
        return;
    }
    for(let rangeIndex = 0; rangeIndex < copyableRanges.length; rangeIndex++){
        const { startRow, startCol, endRow, endCol } = copyableRanges[rangeIndex];
        const rowsCount = endRow - startRow + 1;
        const columnsCount = startCol - endCol + 1;
        // do not process dataset ranges and column headers where only one column is copied
        if (startRow >= 0 || columnsCount === 1) {
            break;
        }
        for(let column = startCol; column <= endCol; column++){
            for(let row = startRow; row <= endRow; row++){
                const zeroBasedColumnHeaderLevel = rowsCount + row;
                const zeroBasedColumnIndex = column - startCol;
                if (zeroBasedColumnIndex === 0) {
                    continue; // eslint-disable-line no-continue
                }
                const isRoot = _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(row, column)?.isRoot;
                if (isRoot === false) {
                    data[zeroBasedColumnHeaderLevel][zeroBasedColumnIndex] = '';
                }
            }
        }
    }
}
function onBeforeOnCellMouseDown(event, coords, TD, controller) {
    _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null);
    _class_private_field_set(this, _expectedNextKeyboardHighlightCoords, null);
    const headerNodeData = this._getHeaderTreeNodeDataByCoords(coords);
    if (headerNodeData) {
        // Block the Selection module in controlling how the columns are selected. Pass the
        // responsibility of the column selection to this plugin (see "onAfterOnCellMouseDown" hook).
        controller.column = true;
    }
}
function onAfterOnCellMouseDown(event, coords) {
    const headerNodeData = this._getHeaderTreeNodeDataByCoords(coords);
    if (!headerNodeData) {
        return;
    }
    _class_private_field_set(this, _focusInitialCoords, coords.clone());
    _class_private_field_set(this, _isColumnsSelectionInProgress, true);
    const { selection } = this.hot;
    const currentSelection = selection.isSelected() ? selection.getSelectedRange().current() : null;
    const columnsToSelect = [];
    const { columnIndex, origColspan } = headerNodeData;
    // The Selection module doesn't allow it to extend its behavior easily. That's why here we need
    // to re-implement the "click" and "shift" behavior. As a workaround, the logic for the nested
    // headers must implement a similar logic as in the original Selection handler
    // (see src/selection/mouseEventHandler.js).
    const allowRightClickSelection = !selection.inInSelection(coords);
    if (event.shiftKey && currentSelection) {
        if (coords.col < currentSelection.from.col) {
            columnsToSelect.push(currentSelection.getTopEndCorner().col, columnIndex, coords.row);
        } else if (coords.col > currentSelection.from.col) {
            columnsToSelect.push(currentSelection.getTopStartCorner().col, columnIndex + origColspan - 1, coords.row);
        } else {
            columnsToSelect.push(columnIndex, columnIndex + origColspan - 1, coords.row);
        }
    } else if ((0, _event.isLeftClick)(event) || (0, _event.isRightClick)(event) && allowRightClickSelection || (0, _event.isTouchEvent)(event)) {
        columnsToSelect.push(columnIndex, columnIndex + origColspan - 1, coords.row);
    }
    // The plugin takes control of how the columns are selected.
    selection.selectColumns(...columnsToSelect);
}
function onBeforeOnCellMouseOver(event, coords, TD, controller) {
    if (!this.hot.view.isMouseDown() || controller.column) {
        return;
    }
    const headerNodeData = this._getHeaderTreeNodeDataByCoords(coords);
    if (!headerNodeData) {
        return;
    }
    const { columnIndex, origColspan } = headerNodeData;
    const selectedRange = this.hot.getSelectedRangeActive();
    const topStartCoords = selectedRange.getTopStartCorner();
    const bottomEndCoords = selectedRange.getBottomEndCorner();
    const { from } = selectedRange;
    // Block the Selection module in controlling how the columns and cells are selected.
    // From now on, the plugin is responsible for the selection.
    controller.column = true;
    controller.cell = true;
    const columnsToSelect = [];
    const headerLevel = (0, _number.clamp)(coords.row, -Infinity, -1);
    if (coords.col < from.col) {
        columnsToSelect.push(bottomEndCoords.col, columnIndex, headerLevel);
    } else if (coords.col > from.col) {
        columnsToSelect.push(topStartCoords.col, columnIndex + origColspan - 1, headerLevel);
    } else {
        columnsToSelect.push(columnIndex, columnIndex + origColspan - 1, headerLevel);
    }
    this.hot.selection.selectColumns(...columnsToSelect);
}
function onBeforeOnCellMouseUp() {
    _class_private_field_set(this, _isColumnsSelectionInProgress, false);
}
function onBeforeSelectionHighlightSet() {
    const { navigableHeaders } = this.hot.getSettings();
    if (!this.hot.view.isMouseDown() || !_class_private_field_get(this, _isColumnsSelectionInProgress) || !navigableHeaders) {
        return;
    }
    const selectedRange = this.hot.getSelectedRangeLast();
    const columnStart = selectedRange.getTopStartCorner().col;
    const columnEnd = selectedRange.getBottomEndCorner().col;
    const { columnIndex, origColspan } = _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(_class_private_field_get(this, _focusInitialCoords).row, _class_private_field_get(this, _focusInitialCoords).col);
    selectedRange.setHighlight(_class_private_field_get(this, _focusInitialCoords));
    if (origColspan > selectedRange.getWidth() || columnIndex < columnStart || columnIndex + origColspan - 1 > columnEnd) {
        const headerLevel = _class_private_field_get(this, _stateManager1).findTopMostEntireHeaderLevel((0, _number.clamp)(columnStart, columnIndex, columnIndex + origColspan - 1), (0, _number.clamp)(columnEnd, columnIndex, columnIndex + origColspan - 1));
        selectedRange.highlight.row = headerLevel;
        selectedRange.highlight.col = selectedRange.from.col;
    }
}
function onModifyTransformStart(delta) {
    const { highlight } = this.hot.getSelectedRangeActive();
    const { row: expectedRow, col: expectedColumn } = _class_private_field_get(this, _expectedNextKeyboardHighlightCoords) ?? {};
    if (Number.isInteger(expectedRow) && Number.isInteger(expectedColumn)) {
        if (highlight.row !== expectedRow || highlight.col !== expectedColumn) {
            _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null);
        }
    }
    const initialDeltaRow = delta.row;
    const initialDeltaColumn = delta.col;
    let targetColumn = highlight.col + delta.col;
    let targetRow = highlight.row + delta.row;
    if (delta.row !== 0 && targetColumn >= 0) {
        const rowDirection = Math.sign(delta.row);
        const lowestHeaderRow = -1;
        const highestHeaderRow = -this.getLayersCount();
        let adjustedNextRow = targetRow;
        while(adjustedNextRow <= lowestHeaderRow && adjustedNextRow >= highestHeaderRow){
            const { isRowspanPlaceholder } = _class_private_field_get(this, _stateManager1).getHeaderSettings(adjustedNextRow, targetColumn) ?? {};
            if (!isRowspanPlaceholder) {
                break;
            }
            adjustedNextRow += rowDirection;
        }
        delta.row = adjustedNextRow - highlight.row;
        targetRow = adjustedNextRow;
    }
    if (initialDeltaRow === 0 && initialDeltaColumn !== 0 && highlight.row < 0) {
        if (Number.isInteger(_class_private_field_get(this, _rowspanHeaderNavigationContextRow))) {
            const contextTargetColumn = _class_private_method_get(this, _findNearestNavigableHeaderColumn, findNearestNavigableHeaderColumn).call(this, _class_private_field_get(this, _rowspanHeaderNavigationContextRow), targetColumn, Math.sign(initialDeltaColumn));
            if (contextTargetColumn !== null) {
                targetColumn = contextTargetColumn;
                targetRow = _class_private_field_get(this, _rowspanHeaderNavigationContextRow);
            }
        }
        if (targetColumn < 0 && initialDeltaColumn < 0 && Number.isInteger(_class_private_field_get(this, _rowspanHeaderNavigationContextRow))) {
            targetRow = _class_private_field_get(this, _rowspanHeaderNavigationContextRow);
        }
        const currentHeaderStartColumn = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(highlight.row, highlight.col);
        const currentHeaderEndColumn = _class_private_field_get(this, _stateManager1).findRightMostColumnIndex(highlight.row, highlight.col);
        const { isRowspanPlaceholder: isTargetRowspanPlaceholder } = _class_private_field_get(this, _stateManager1).getHeaderSettings(targetRow, targetColumn) ?? {};
        const isTargetInsideCurrentHeader = targetRow === highlight.row && targetColumn >= currentHeaderStartColumn && targetColumn <= currentHeaderEndColumn;
        const shouldKeepLogicalRowForRowspan = targetRow === highlight.row && isTargetRowspanPlaceholder && initialDeltaColumn > 0 && highlight.row < -1;
        if (!isTargetInsideCurrentHeader && !shouldKeepLogicalRowForRowspan) {
            targetRow = _class_private_method_get(this, _findRenderableHeaderRow, findRenderableHeaderRow).call(this, targetRow, targetColumn);
        }
        delta.row = targetRow - highlight.row;
        const targetHeaderRowspan = _class_private_method_get(this, _getRootHeaderRowspan, getRootHeaderRowspan).call(this, targetRow, targetColumn);
        if (targetHeaderRowspan > 1 && !Number.isInteger(_class_private_field_get(this, _rowspanHeaderNavigationContextRow))) {
            _class_private_field_set(this, _rowspanHeaderNavigationContextRow, (0, _navigation.resolveRowspanNavigationContextRow)(highlight.row, targetColumn, -this.getLayersCount(), (headerRow, visualColumn)=>_class_private_field_get(this, _stateManager1).getHeaderSettings(headerRow, visualColumn)));
        }
    }
    const nextCoords = this.hot._createCellCoords(targetRow, targetColumn);
    const isNestedHeadersRange = nextCoords.isHeader() && nextCoords.col >= 0;
    if (!isNestedHeadersRange || initialDeltaRow !== 0) {
        _class_private_field_set(this, _rowspanHeaderNavigationContextRow, null);
    }
    if (isNestedHeadersRange) {
        const { isRowspanPlaceholder: isCurrentHeaderRowspanPlaceholderForBounds } = _class_private_field_get(this, _stateManager1).getHeaderSettings(highlight.row, highlight.col) ?? {};
        const { isRowspanPlaceholder: isNextHeaderRowspanPlaceholderForBounds } = _class_private_field_get(this, _stateManager1).getHeaderSettings(nextCoords.row, nextCoords.col) ?? {};
        let visualColumnIndexStart = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(nextCoords.row, nextCoords.col);
        let visualColumnIndexEnd = _class_private_field_get(this, _stateManager1).findRightMostColumnIndex(nextCoords.row, nextCoords.col);
        if (isNextHeaderRowspanPlaceholderForBounds) {
            const renderableNextHeaderRow = _class_private_method_get(this, _findRenderableHeaderRow, findRenderableHeaderRow).call(this, nextCoords.row, nextCoords.col);
            visualColumnIndexStart = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(renderableNextHeaderRow, nextCoords.col);
            visualColumnIndexEnd = _class_private_field_get(this, _stateManager1).findRightMostColumnIndex(renderableNextHeaderRow, nextCoords.col);
        }
        if (isCurrentHeaderRowspanPlaceholderForBounds) {
            const renderableCurrentHeaderRow = _class_private_method_get(this, _findRenderableHeaderRow, findRenderableHeaderRow).call(this, highlight.row, highlight.col);
            visualColumnIndexStart = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(renderableCurrentHeaderRow, highlight.col);
            visualColumnIndexEnd = _class_private_field_get(this, _stateManager1).findRightMostColumnIndex(renderableCurrentHeaderRow, highlight.col);
            if (initialDeltaColumn < 0) {
                visualColumnIndexStart = Math.max(visualColumnIndexStart, Math.min(highlight.col, nextCoords.col));
            } else if (initialDeltaColumn > 0) {
                visualColumnIndexEnd = Math.min(visualColumnIndexEnd, Math.max(highlight.col, nextCoords.col));
            }
        }
        if (delta.col < 0) {
            const nextColumn = highlight.col >= visualColumnIndexStart && highlight.col <= visualColumnIndexEnd ? visualColumnIndexStart - 1 : visualColumnIndexEnd;
            const notHiddenColumnIndex = this.hot.columnIndexMapper.getNearestNotHiddenIndex(nextColumn, -1);
            if (notHiddenColumnIndex === null) {
                // There are no visible columns anymore, so move the selection out of the table edge. This will
                // be processed by the selection Transformer class as a move selection to the previous row (if autoWrapRow is enabled).
                delta.col = -this.hot.view.countRenderableColumnsInRange(0, highlight.col);
            } else {
                delta.col = -Math.max(this.hot.view.countRenderableColumnsInRange(notHiddenColumnIndex, highlight.col) - 1, 1);
            }
        } else if (delta.col > 0) {
            const nextColumn = highlight.col >= visualColumnIndexStart && highlight.col <= visualColumnIndexEnd ? visualColumnIndexEnd + 1 : visualColumnIndexStart;
            const notHiddenColumnIndex = this.hot.columnIndexMapper.getNearestNotHiddenIndex(nextColumn, 1);
            if (notHiddenColumnIndex === null) {
                // There are no visible columns anymore, so move the selection out of the table edge. This will
                // be processed by the selection Transformer class as a move selection to the next row (if autoWrapRow is enabled).
                delta.col = this.hot.view.countRenderableColumnsInRange(highlight.col, this.hot.countCols());
                if (isCurrentHeaderRowspanPlaceholderForBounds) {
                    delta.col += 1;
                    if (highlight.row < -1) {
                        delta.row = 1;
                        delta.col = -(highlight.col + 1);
                    }
                }
            } else {
                delta.col = Math.max(this.hot.view.countRenderableColumnsInRange(highlight.col, notHiddenColumnIndex) - 1, 1);
            }
        }
    }
    _class_private_field_set(this, _expectedNextKeyboardHighlightCoords, {
        row: highlight.row + delta.row,
        col: highlight.col + delta.col
    });
}
function onBeforeSelectColumns(from, to, highlight) {
    const headerLevel = from.row;
    const startNodeData = this._getHeaderTreeNodeDataByCoords({
        row: headerLevel,
        col: from.col
    });
    const endNodeData = this._getHeaderTreeNodeDataByCoords({
        row: headerLevel,
        col: to.col
    });
    _class_private_field_set(this, _recentlyHighlightCoords, highlight.clone());
    if (to.col < from.col) {
        if (startNodeData) {
            from.col = startNodeData.columnIndex + startNodeData.origColspan - 1;
        }
        if (endNodeData) {
            to.col = endNodeData.columnIndex;
        }
    } else if (to.col >= from.col) {
        if (startNodeData) {
            from.col = startNodeData.columnIndex;
        }
        if (endNodeData) {
            to.col = endNodeData.columnIndex + endNodeData.origColspan - 1;
        }
    }
}
function onAfterGetColumnHeaderRenderers(renderersArray) {
    if (_class_private_field_get(this, _stateManager1).getLayersCount() > 0) {
        renderersArray.length = 0;
        for(let headerLayer = 0; headerLayer < _class_private_field_get(this, _stateManager1).getLayersCount(); headerLayer++){
            renderersArray.push(this.headerRendererFactory(headerLayer));
        }
    }
}
function onAfterViewportColumnCalculatorOverride(calc) {
    const headerLayersCount = _class_private_field_get(this, _stateManager1).getLayersCount();
    let newStartColumn = calc.startColumn;
    let nonRenderable = !!headerLayersCount;
    for(let headerLayer = 0; headerLayer < headerLayersCount; headerLayer++){
        const startColumn = _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(headerLayer, calc.startColumn);
        const renderedStartColumn = this.hot.columnIndexMapper.getRenderableFromVisualIndex(startColumn);
        // If any of the headers for that column index is rendered, all of them should be rendered properly, see
        // comment below.
        if (startColumn >= 0) {
            nonRenderable = false;
        }
        // `renderedStartColumn` can be `null` if the leftmost columns are hidden. In that case -> ignore that header
        // level, as it should be handled by the "parent" header
        if ((0, _number.isNumeric)(renderedStartColumn) && renderedStartColumn < calc.startColumn) {
            newStartColumn = renderedStartColumn;
            break;
        }
    }
    // If no headers for the provided column index are renderable, start rendering from the beginning of the upmost
    // header for that position.
    calc.startColumn = nonRenderable ? _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(0, newStartColumn).columnIndex : newStartColumn;
}
function onModifyColWidth(width, column) {
    const cachedWidth = this.ghostTable.getWidth(column);
    return width > cachedWidth ? width : cachedWidth;
}
function onModifyColumnHeaderHeight() {
    if (!_class_private_field_get(this, _hasRowspanHeaders)) {
        return;
    }
    const computedStyle = this.hot.rootWindow.getComputedStyle(this.hot.rootElement);
    const cellVerticalPadding = Number.parseFloat(computedStyle.getPropertyValue('--ht-cell-vertical-padding'));
    const lineHeight = Number.parseFloat(computedStyle.getPropertyValue('--ht-line-height'));
    const baseHeaderHeight = Math.round(cellVerticalPadding * 2 + lineHeight + 1);
    if (!Number.isFinite(baseHeaderHeight)) {
        return;
    }
    return new Array(this.getLayersCount()).fill(baseHeaderHeight);
}
function onModifyColumnHeaderValue(value, visualColumnIndex, headerLevel) {
    const { label } = _class_private_field_get(this, _stateManager1).getHeaderTreeNodeData(headerLevel, visualColumnIndex) ?? {
        label: ''
    };
    return label;
}
function onModifyFocusedElement(row, column) {
    if (row < 0) {
        return this.hot.getCell(row, _class_private_field_get(this, _stateManager1).findLeftMostColumnIndex(row, column), true);
    }
}
function onInit() {
    // @TODO: Workaround for broken plugin initialization abstraction.
    this.updatePlugin();
}
function onAfterLoadData(sourceData, initialLoad) {
    if (!initialLoad) {
        this.updatePlugin();
    }
}
function onBeforeViewRender() {
    if (_class_private_field_get(this, _updateWidthsMap)) {
        this.ghostTable.setLayersCount(this.getLayersCount()).buildWidthsMap();
        _class_private_field_set(this, _updateWidthsMap, false);
    }
}
