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);
}
import { html } from '../../helpers/templateLiteralTag.mjs';
import { mixin } from '../../helpers/object.mjs';
import localHooks from '../../mixins/localHooks.mjs';
import * as C from '../../i18n/constants.mjs';
import { addClass, removeClass, setAttribute } from '../../helpers/dom/element.mjs';
import { A11Y_DISABLED, A11Y_LABEL } from '../../helpers/a11y.mjs';
const TEMPLATE = `
<div data-ref="container" class="ht-pagination handsontable">
  <div class="ht-pagination__inner">
    <div data-ref="pageSizeSection" class="ht-page-size-section">
      <span data-ref="pageSizeLabel" class="ht-page-size-section__label"></span>
      <div class="ht-page-size-section__select-wrapper">
        <select data-ref="pageSizeSelect" name="pageSize" data-hot-input></select>
      </div>
    </div>
    <div data-ref="pageCounterSection" class="ht-page-counter-section"></div>
    <nav data-ref="pageNavSection" class="ht-page-navigation-section">
      <button data-ref="first" class="ht-page-navigation-section__button ht-page-first"></button>
      <button data-ref="prev" class="ht-page-navigation-section__button ht-page-prev"></button>
      <span data-ref="pageNavLabel" class="ht-page-navigation-section__label"></span>
      <button data-ref="next" class="ht-page-navigation-section__button ht-page-next"></button>
      <button data-ref="last" class="ht-page-navigation-section__button ht-page-last"></button>
    </nav>
  </div>
</div>
`;
var /**
   * The root element where the pagination UI will be installed.
   *
   * @type {HTMLElement}
   */ _rootElement = /*#__PURE__*/ new WeakMap(), /**
   * The container element where the pagination UI will be installed.
   * If not provided, the pagination container will be injected after the root element.
   *
   * @type {HTMLElement}
   */ _uiContainer = /*#__PURE__*/ new WeakMap(), /**
   * Indicates if the UI is in RTL mode.
   *
   * @type {boolean}
   */ _isRtl = /*#__PURE__*/ new WeakMap(), /**
   * The references to the UI elements.
   *
   * @type {object}
   */ _refs = /*#__PURE__*/ new WeakMap(), /**
   * The name of the current theme.
   *
   * @type {string | undefined}
   */ _themeName = /*#__PURE__*/ new WeakMap(), /**
   * A function to translate phrases used in the UI.
   *
   * @type {function(string): string}
   */ _phraseTranslator = /*#__PURE__*/ new WeakMap(), /**
   * A function that determines whether the pagination should have a border.
   *
   * @type {function(): void}
   */ _shouldHaveBorder = /*#__PURE__*/ new WeakMap(), /**
   * A function allowing to announce accessibility messages.
   *
   * @type {function(string): void}
   */ _a11yAnnouncer = /*#__PURE__*/ new WeakMap(), /**
   * Updates the visibility of the pagination container based on the visibility of its sections.
   */ _updateContainerVisibility = /*#__PURE__*/ new WeakSet();
/**
 * PaginationUI is a UI component that renders and manages pagination controls.
 * It handles user interactions (navigation and page size changes), and exposes methods to
 * toggle visibility of pagination sections and update the state of the pagination controls.
 *
 * @private
 * @class PaginationUI
 */ export class PaginationUI {
    /**
   * Creates the pagination UI elements and sets up event listeners.
   */ install() {
        if (_class_private_field_get(this, _refs)?.container) {
            return;
        }
        const elements = html`${TEMPLATE}`;
        const { container, first, prev, next, last, pageSizeSelect } = elements.refs;
        _class_private_field_set(this, _refs, elements.refs);
        container.setAttribute('dir', _class_private_field_get(this, _isRtl) ? 'rtl' : 'ltr');
        container.tabIndex = -1;
        const isDisabled = (event)=>event.currentTarget.disabled;
        const addClickListener = (eventName, element, callback)=>{
            element.addEventListener(eventName, (event)=>{
                if (!isDisabled(event)) {
                    callback();
                }
            });
        };
        addClickListener('click', first, ()=>this.runLocalHooks('firstPageClick'));
        addClickListener('click', prev, ()=>this.runLocalHooks('prevPageClick'));
        addClickListener('click', next, ()=>this.runLocalHooks('nextPageClick'));
        addClickListener('click', last, ()=>this.runLocalHooks('lastPageClick'));
        pageSizeSelect.addEventListener('change', ()=>{
            const value = pageSizeSelect.value === 'auto' ? 'auto' : Number.parseInt(pageSizeSelect.value, 10);
            this.runLocalHooks('pageSizeChange', value);
        });
        this.setCounterSectionVisibility(false);
        this.setNavigationSectionVisibility(false);
        this.setPageSizeSectionVisibility(false);
        if (_class_private_field_get(this, _uiContainer)) {
            _class_private_field_get(this, _uiContainer).appendChild(elements.fragment);
            addClass(container, [
                _class_private_field_get(this, _themeName),
                'handsontable'
            ]);
        } else {
            _class_private_field_get(this, _rootElement).after(elements.fragment);
        }
    }
    /**
   * Gets the pagination element.
   *
   * @returns {HTMLElement} The pagination element.
   */ getContainer() {
        return _class_private_field_get(this, _refs).container;
    }
    /**
   * Gets the focusable elements.
   *
   * @returns {HTMLElement[]} The focusable elements.
   */ getFocusableElements() {
        const { first, prev, next, last, pageSizeSelect } = _class_private_field_get(this, _refs);
        return [
            pageSizeSelect,
            first,
            prev,
            next,
            last
        ].filter((element)=>!element.disabled);
    }
    /**
   * Updates the width of the pagination container.
   *
   * @param {number} width The new width of the pagination container.
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ updateWidth(width) {
        _class_private_field_get(this, _refs).container.style.width = `${width}px`;
        return this;
    }
    /**
   * Updates the theme of the pagination container.
   *
   * @param {string | false | undefined} themeName The name of the theme to use.
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ updateTheme(themeName) {
        _class_private_field_set(this, _themeName, themeName);
        if (_class_private_field_get(this, _uiContainer)) {
            const { container } = _class_private_field_get(this, _refs);
            removeClass(container, /ht-theme-.*/g);
            if (_class_private_field_get(this, _themeName)) {
                addClass(container, _class_private_field_get(this, _themeName));
            }
        }
        return this;
    }
    /**
   * Gets the height of the pagination container element.
   *
   * @returns {number}
   */ getHeight() {
        return _class_private_field_get(this, _refs).container.offsetHeight;
    }
    /**
   * Refreshes the border state of the pagination container based on the external condition.
   *
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ refreshBorderState() {
        const { container } = _class_private_field_get(this, _refs);
        if (_class_private_field_get(this, _uiContainer) || _class_private_field_get(this, _shouldHaveBorder).call(this)) {
            addClass(container, 'ht-pagination--bordered');
        } else {
            removeClass(container, 'ht-pagination--bordered');
        }
        return this;
    }
    /**
   * Updates the state of the pagination UI.
   *
   * @param {object} state The pagination state.
   * @param {number} state.currentPage The current page number.
   * @param {number} state.totalPages The total number of pages.
   * @param {number} state.firstVisibleRowIndex The index of the first visible row on the current page.
   * @param {number} state.lastVisibleRowIndex The index of the last visible row on the current page.
   * @param {number} state.totalRenderedRows The total number of renderable rows.
   * @param {Array<number | 'auto'>} state.pageSizeList The list of available page sizes.
   * @param {number} state.pageSize The current page size.
   * @param {boolean} state.autoPageSize Indicates if the page size is set to 'auto'.
   * @param {number} [state.counterStartRow] Optional 1-based start row for the counter (e.g. dataProvider mode).
   * @param {number} [state.counterEndRow] Optional 1-based end row for the counter (e.g. dataProvider mode).
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ updateState({ currentPage, totalPages, firstVisibleRowIndex, lastVisibleRowIndex, totalRenderedRows, pageSizeList, pageSize, autoPageSize, counterStartRow, counterEndRow }) {
        const { first, prev, next, last, pageCounterSection, pageNavSection, pageNavLabel, pageSizeSelect, pageSizeLabel } = _class_private_field_get(this, _refs);
        const counterStart = counterStartRow ?? firstVisibleRowIndex + 1;
        const counterEnd = counterEndRow ?? lastVisibleRowIndex + 1;
        const counterSectionText = _class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_COUNTER_SECTION, {
            start: counterStart,
            end: counterEnd,
            total: totalRenderedRows
        });
        const navLabelText = _class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_NAV_SECTION, {
            currentPage,
            totalPages
        });
        const pageSizeLabelText = _class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_PAGE_SIZE_SECTION);
        pageCounterSection.textContent = counterSectionText;
        pageNavLabel.textContent = navLabelText;
        pageSizeSelect.textContent = '';
        pageSizeLabel.textContent = `${pageSizeLabelText}:`;
        setAttribute(pageNavSection, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_SECTION))
            ]
        ]);
        setAttribute(pageSizeSelect, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_PAGE_SIZE_SECTION))
            ]
        ]);
        _class_private_field_get(this, _a11yAnnouncer).call(this, navLabelText);
        this.refreshBorderState();
        pageSizeList.forEach((pageSizeItem)=>{
            const label = pageSizeItem === 'auto' ? _class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_PAGE_SIZE_AUTO) : pageSizeItem;
            const option = new Option(label, pageSizeItem);
            if (autoPageSize && pageSizeItem === 'auto' || !autoPageSize && pageSizeItem === pageSize) {
                option.selected = true;
            }
            pageSizeSelect.add(option);
        });
        const isFirstPage = currentPage === 1;
        const isLastPage = currentPage === totalPages;
        if (pageNavSection.style.display !== 'none') {
            const activeElement = _class_private_field_get(this, _rootElement).ownerDocument.activeElement;
            if (isFirstPage) {
                addClass(first, 'ht-page-navigation-section__button--disabled');
                addClass(prev, 'ht-page-navigation-section__button--disabled');
                first.disabled = true;
                prev.disabled = true;
            } else {
                removeClass(first, 'ht-page-navigation-section__button--disabled');
                removeClass(prev, 'ht-page-navigation-section__button--disabled');
                first.disabled = false;
                prev.disabled = false;
            }
            if (isLastPage) {
                addClass(next, 'ht-page-navigation-section__button--disabled');
                addClass(last, 'ht-page-navigation-section__button--disabled');
                next.disabled = true;
                last.disabled = true;
            } else {
                removeClass(next, 'ht-page-navigation-section__button--disabled');
                removeClass(last, 'ht-page-navigation-section__button--disabled');
                next.disabled = false;
                last.disabled = false;
            }
            if ([
                first,
                prev,
                next,
                last
            ].includes(activeElement)) {
                if (prev.disabled) {
                    next.focus();
                } else if (next.disabled) {
                    prev.focus();
                }
            }
        }
        setAttribute(first, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_FIRST_PAGE))
            ],
            ...[
                A11Y_DISABLED(isFirstPage)
            ]
        ]);
        setAttribute(prev, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_PREV_PAGE))
            ],
            ...[
                A11Y_DISABLED(isFirstPage)
            ]
        ]);
        setAttribute(next, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_NEXT_PAGE))
            ],
            ...[
                A11Y_DISABLED(isLastPage)
            ]
        ]);
        setAttribute(last, [
            ...[
                A11Y_LABEL(_class_private_field_get(this, _phraseTranslator).call(this, C.PAGINATION_LAST_PAGE))
            ],
            ...[
                A11Y_DISABLED(isLastPage)
            ]
        ]);
        return this;
    }
    /**
   * Sets the visibility of the page size section.
   *
   * @param {boolean} isVisible True to show the page size section, false to hide it.
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ setPageSizeSectionVisibility(isVisible) {
        const { pageSizeSection, pageSizeSelect } = _class_private_field_get(this, _refs);
        pageSizeSection.style.display = isVisible ? '' : 'none';
        pageSizeSelect.disabled = !isVisible;
        _class_private_method_get(this, _updateContainerVisibility, updateContainerVisibility).call(this);
        return this;
    }
    /**
   * Sets the visibility of the page counter section.
   *
   * @param {boolean} isVisible True to show the page size section, false to hide it.
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ setCounterSectionVisibility(isVisible) {
        _class_private_field_get(this, _refs).pageCounterSection.style.display = isVisible ? '' : 'none';
        _class_private_method_get(this, _updateContainerVisibility, updateContainerVisibility).call(this);
        return this;
    }
    /**
   * Sets the visibility of the page navigation section.
   *
   * @param {boolean} isVisible True to show the page size section, false to hide it.
   * @returns {PaginationUI} The instance of the PaginationUI for method chaining.
   */ setNavigationSectionVisibility(isVisible) {
        const { pageNavSection, first, prev, next, last } = _class_private_field_get(this, _refs);
        pageNavSection.style.display = isVisible ? '' : 'none';
        first.disabled = !isVisible;
        prev.disabled = !isVisible;
        next.disabled = !isVisible;
        last.disabled = !isVisible;
        _class_private_method_get(this, _updateContainerVisibility, updateContainerVisibility).call(this);
        return this;
    }
    /**
   * Removes the pagination UI elements from the DOM and clears the refs.
   */ destroy() {
        _class_private_field_get(this, _refs)?.container.remove();
        _class_private_field_set(this, _refs, null);
    }
    constructor({ rootElement, uiContainer, isRtl, themeName, phraseTranslator, shouldHaveBorder, a11yAnnouncer }){
        _class_private_method_init(this, _updateContainerVisibility);
        _class_private_field_init(this, _rootElement, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _uiContainer, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _isRtl, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _refs, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _themeName, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _phraseTranslator, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _shouldHaveBorder, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _a11yAnnouncer, {
            writable: true,
            value: void 0
        });
        _class_private_field_set(this, _isRtl, false);
        _class_private_field_set(this, _rootElement, rootElement);
        _class_private_field_set(this, _uiContainer, uiContainer);
        _class_private_field_set(this, _isRtl, isRtl);
        _class_private_field_set(this, _themeName, themeName);
        _class_private_field_set(this, _phraseTranslator, phraseTranslator);
        _class_private_field_set(this, _shouldHaveBorder, shouldHaveBorder);
        _class_private_field_set(this, _a11yAnnouncer, a11yAnnouncer);
        this.install();
    }
}
function updateContainerVisibility() {
    const { container, pageSizeSection, pageCounterSection, pageNavSection } = _class_private_field_get(this, _refs);
    const isSectionVisible = pageSizeSection.style.display !== 'none' || pageCounterSection.style.display !== 'none' || pageNavSection.style.display !== 'none';
    // adds or removes the corner around the Handsontable root element
    if (!_class_private_field_get(this, _uiContainer)) {
        if (isSectionVisible) {
            addClass(_class_private_field_get(this, _rootElement).querySelector('.ht-wrapper'), 'htPagination');
        } else {
            removeClass(_class_private_field_get(this, _rootElement).querySelector('.ht-wrapper'), 'htPagination');
        }
    }
    container.style.display = isSectionVisible ? '' : 'none';
}
mixin(PaginationUI, localHooks);
