/**
 * DevExtreme (cjs/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.virtualScrollingModule = exports.rowsView = exports.resizing = exports.dataSourceAdapterExtender = exports.data = void 0;
var _renderer = _interopRequireDefault(require("../../../../core/renderer"));
var _browser = _interopRequireDefault(require("../../../../core/utils/browser"));
var _deferred = require("../../../../core/utils/deferred");
var _dom = require("../../../../core/utils/dom");
var _iterator = require("../../../../core/utils/iterator");
var _position = require("../../../../core/utils/position");
var _size = require("../../../../core/utils/size");
var _type = require("../../../../core/utils/type");
var _window = require("../../../../core/utils/window");
var _load_indicator = _interopRequireDefault(require("../../../../ui/load_indicator"));
var _ui = _interopRequireDefault(require("../../../../ui/widget/ui.errors"));
var _m_utils = _interopRequireDefault(require("../m_utils"));
var _m_virtual_scrolling_core = require("./m_virtual_scrolling_core");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}

function _inheritsLoose(subClass, superClass) {
    subClass.prototype = Object.create(superClass.prototype);
    subClass.prototype.constructor = subClass;
    _setPrototypeOf(subClass, superClass)
}

function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(o, p) {
        o.__proto__ = p;
        return o
    };
    return _setPrototypeOf(o, p)
}
const BOTTOM_LOAD_PANEL_CLASS = "bottom-load-panel";
const GROUP_SPACE_CLASS = "group-space";
const FREESPACE_CLASS = "dx-freespace-row";
const COLUMN_LINES_CLASS = "dx-column-lines";
const VIRTUAL_ROW_CLASS = "dx-virtual-row";
const ROW_INSERTED = "dx-row-inserted";
const SCROLLING_MODE_INFINITE = "infinite";
const SCROLLING_MODE_VIRTUAL = "virtual";
const LOAD_TIMEOUT = 300;
const LEGACY_SCROLLING_MODE = "scrolling.legacyMode";
const VISIBLE_PAGE_INDEX = "paging.pageIndex";
const PAGING_METHOD_NAMES = ["beginPageIndex", "endPageIndex", "pageIndex"];
const isVirtualMode = function(that) {
    return "virtual" === that.option("scrolling.mode")
};
const isAppendMode = function(that) {
    return "infinite" === that.option("scrolling.mode")
};
const isVirtualPaging = function(that) {
    return isVirtualMode(that) || isAppendMode(that)
};
const correctCount = function(items, count, fromEnd, isItemCountableFunc) {
    for (let i = 0; i < count + 1; i++) {
        const item = items[fromEnd ? items.length - 1 - i : i];
        if (item && !isItemCountableFunc(item, i === count, fromEnd)) {
            count++
        }
    }
    return count
};
const isItemCountableByDataSource = function(item, dataSource) {
    return "data" === item.rowType && !item.isNewRow || "group" === item.rowType && dataSource.isGroupItemCountable(item.data)
};
const updateItemIndices = function(items) {
    items.forEach((item, index) => {
        item.rowIndex = index
    });
    return items
};
const updateLoading = function(that) {
    const beginPageIndex = that._virtualScrollController.beginPageIndex(-1);
    if (isVirtualMode(that)) {
        if (beginPageIndex < 0 || that.viewportSize() >= 0 && that.getViewportItemIndex() >= 0 && (beginPageIndex * that.pageSize() > that.getViewportItemIndex() || beginPageIndex * that.pageSize() + that.itemsCount() < that.getViewportItemIndex() + that.viewportSize()) && that._dataSource.isLoading()) {
            if (!that._isLoading) {
                that._isLoading = true;
                that.loadingChanged.fire(true)
            }
        } else if (that._isLoading) {
            that._isLoading = false;
            that.loadingChanged.fire(false)
        }
    }
};
const proxyDataSourceAdapterMethod = function(that, methodName, args) {
    if (false === that.option(LEGACY_SCROLLING_MODE) && PAGING_METHOD_NAMES.includes(methodName)) {
        const dataSource = that._dataSource;
        return dataSource.pageIndex.apply(dataSource, args)
    }
    const virtualScrollController = that._virtualScrollController;
    return virtualScrollController[methodName].apply(virtualScrollController, args)
};
const removeEmptyRows = function($emptyRows, className) {
    const tBodies = $emptyRows.toArray().map(row => (0, _renderer.default)(row).parent(".".concat(className)).get(0)).filter(row => row);
    if (tBodies.length) {
        $emptyRows = (0, _renderer.default)(tBodies)
    }
    const rowCount = className === FREESPACE_CLASS ? $emptyRows.length - 1 : $emptyRows.length;
    for (let i = 0; i < rowCount; i++) {
        $emptyRows.eq(i).remove()
    }
};
const dataSourceAdapterExtender = Base => function(_Base) {
    _inheritsLoose(VirtualScrollingCoreDataSourceAdapterExtender, _Base);

    function VirtualScrollingCoreDataSourceAdapterExtender() {
        return _Base.apply(this, arguments) || this
    }
    var _proto = VirtualScrollingCoreDataSourceAdapterExtender.prototype;
    _proto.init = function() {
        _Base.prototype.init.apply(this, arguments);
        this._items = [];
        this._totalCount = -1;
        this._isLoaded = true;
        this._loadPageCount = 1;
        this._virtualScrollController = new _m_virtual_scrolling_core.VirtualScrollController(this.component, this._getVirtualScrollDataOptions())
    };
    _proto.dispose = function() {
        this._virtualScrollController.dispose();
        _Base.prototype.dispose.apply(this, arguments)
    };
    _proto._getVirtualScrollDataOptions = function() {
        const that = this;
        return {
            pageSize: () => that.pageSize(),
            totalItemsCount: () => that.totalItemsCount(),
            hasKnownLastPage: () => that.hasKnownLastPage(),
            pageIndex: index => that._dataSource.pageIndex(index),
            isLoading: () => that._dataSource.isLoading() && !that.isCustomLoading(),
            pageCount: () => that.pageCount(),
            load: () => that._dataSource.load(),
            updateLoading() {
                updateLoading(that)
            },
            itemsCount: () => that.itemsCount(true),
            items: () => that._dataSource.items(),
            viewportItems(items) {
                if (items) {
                    that._items = items
                }
                return that._items
            },
            onChanged(e) {
                that.changed.fire(e)
            },
            changingDuration() {
                if (that.isLoading()) {
                    return 300
                }
                return that._renderTime || 0
            }
        }
    };
    _proto._handleLoadingChanged = function(isLoading) {
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            _Base.prototype._handleLoadingChanged.apply(this, arguments);
            return
        }
        if (!isVirtualMode(this) || this._isLoadingAll) {
            this._isLoading = isLoading;
            _Base.prototype._handleLoadingChanged.apply(this, arguments)
        }
        if (isLoading) {
            this._startLoadTime = new Date
        } else {
            this._startLoadTime = void 0
        }
    };
    _proto._handleLoadError = function() {
        if (false !== this.option(LEGACY_SCROLLING_MODE)) {
            this._isLoading = false;
            this.loadingChanged.fire(false)
        }
        _Base.prototype._handleLoadError.apply(this, arguments)
    };
    _proto._handleDataChanged = function(e) {
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            this._items = this._dataSource.items().slice();
            this._totalCount = this._dataSourceTotalCount(true);
            _Base.prototype._handleDataChanged.apply(this, arguments);
            return
        }
        const callBase = _Base.prototype._handleDataChanged.bind(this);
        this._virtualScrollController.handleDataChanged(callBase, e)
    };
    _proto._customizeRemoteOperations = function(options, operationTypes) {
        const newMode = false === this.option(LEGACY_SCROLLING_MODE);
        let renderAsync = this.option("scrolling.renderAsync");
        if (!(0, _type.isDefined)(renderAsync)) {
            renderAsync = this._renderTime >= this.option("scrolling.renderingThreshold")
        }
        if ((isVirtualMode(this) || isAppendMode(this) && newMode) && !operationTypes.reload && (operationTypes.skip || newMode) && !renderAsync) {
            options.delay = void 0
        }
        _Base.prototype._customizeRemoteOperations.apply(this, arguments)
    };
    _proto.items = function() {
        return this._items
    };
    _proto._dataSourceTotalCount = function(isBase) {
        return false === this.option(LEGACY_SCROLLING_MODE) && isVirtualMode(this) && !isBase ? this._totalCount : _Base.prototype._dataSourceTotalCount.call(this)
    };
    _proto.itemsCount = function(isBase) {
        if (isBase || false === this.option(LEGACY_SCROLLING_MODE)) {
            return _Base.prototype.itemsCount.call(this)
        }
        return this._virtualScrollController.itemsCount()
    };
    _proto.load = function(loadOptions) {
        if (false === this.option(LEGACY_SCROLLING_MODE) || loadOptions) {
            return _Base.prototype.load.call(this, loadOptions)
        }
        return this._virtualScrollController.load()
    };
    _proto.isLoading = function() {
        return false === this.option(LEGACY_SCROLLING_MODE) ? this._dataSource.isLoading() : this._isLoading
    };
    _proto.isLoaded = function() {
        return this._dataSource.isLoaded() && this._isLoaded
    };
    _proto.resetPagesCache = function(isLiveUpdate) {
        if (!isLiveUpdate) {
            this._virtualScrollController.reset(true)
        }
        _Base.prototype.resetPagesCache.apply(this, arguments)
    };
    _proto._changeRowExpandCore = function() {
        const result = _Base.prototype._changeRowExpandCore.apply(this, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return result
        }
        this.resetPagesCache();
        updateLoading(this);
        return result
    };
    _proto.reload = function() {
        this._dataSource.pageIndex(this.pageIndex());
        const virtualScrollController = this._virtualScrollController;
        if (false !== this.option(LEGACY_SCROLLING_MODE) && virtualScrollController) {
            const d = new _deferred.Deferred;
            _Base.prototype.reload.apply(this, arguments).done(r => {
                const delayDeferred = virtualScrollController.getDelayDeferred();
                if (delayDeferred) {
                    delayDeferred.done(d.resolve).fail(d.reject)
                } else {
                    d.resolve(r)
                }
            }).fail(d.reject);
            return d
        }
        return _Base.prototype.reload.apply(this, arguments)
    };
    _proto.refresh = function(options, operationTypes) {
        if (false !== this.option(LEGACY_SCROLLING_MODE)) {
            const {
                storeLoadOptions: storeLoadOptions
            } = options;
            const dataSource = this._dataSource;
            if (operationTypes.reload) {
                this._virtualScrollController.reset();
                dataSource.items().length = 0;
                this._isLoaded = false;
                updateLoading(this);
                this._isLoaded = true;
                if (isAppendMode(this)) {
                    this.pageIndex(0);
                    dataSource.pageIndex(0);
                    storeLoadOptions.pageIndex = 0;
                    options.pageIndex = 0;
                    storeLoadOptions.skip = 0
                } else {
                    dataSource.pageIndex(this.pageIndex());
                    if (dataSource.paginate()) {
                        options.pageIndex = this.pageIndex();
                        storeLoadOptions.skip = this.pageIndex() * this.pageSize()
                    }
                }
            } else if (isAppendMode(this) && storeLoadOptions.skip && this._totalCountCorrection < 0) {
                storeLoadOptions.skip += this._totalCountCorrection
            }
        }
        return _Base.prototype.refresh.apply(this, arguments)
    };
    _proto.loadPageCount = function(count) {
        if (!(0, _type.isDefined)(count)) {
            return this._loadPageCount
        }
        this._loadPageCount = count
    };
    _proto._handleDataLoading = function(options) {
        const loadPageCount = this.loadPageCount();
        const pageSize = this.pageSize();
        const newMode = false === this.option(LEGACY_SCROLLING_MODE);
        const {
            storeLoadOptions: storeLoadOptions
        } = options;
        const takeIsDefined = (0, _type.isDefined)(storeLoadOptions.take);
        options.loadPageCount = loadPageCount;
        if (!options.isCustomLoading && newMode && takeIsDefined && loadPageCount > 1 && pageSize > 0) {
            storeLoadOptions.take = loadPageCount * pageSize
        }
        _Base.prototype._handleDataLoading.apply(this, arguments)
    };
    _proto._loadPageSize = function() {
        return _Base.prototype._loadPageSize.apply(this, arguments) * this.loadPageCount()
    };
    _proto.beginPageIndex = function() {
        return proxyDataSourceAdapterMethod(this, "beginPageIndex", [...arguments])
    };
    _proto.endPageIndex = function() {
        return proxyDataSourceAdapterMethod(this, "endPageIndex", [...arguments])
    };
    _proto.pageIndex = function(_pageIndex) {
        return proxyDataSourceAdapterMethod(this, "pageIndex", [...arguments])
    };
    _proto.virtualItemsCount = function() {
        return proxyDataSourceAdapterMethod(this, "virtualItemsCount", [...arguments])
    };
    _proto.getContentOffset = function() {
        return proxyDataSourceAdapterMethod(this, "getContentOffset", [...arguments])
    };
    _proto.getVirtualContentSize = function() {
        return proxyDataSourceAdapterMethod(this, "getVirtualContentSize", [...arguments])
    };
    _proto.setContentItemSizes = function() {
        return proxyDataSourceAdapterMethod(this, "setContentItemSizes", [...arguments])
    };
    _proto.setViewportPosition = function() {
        return proxyDataSourceAdapterMethod(this, "setViewportPosition", [...arguments])
    };
    _proto.getViewportItemIndex = function() {
        return proxyDataSourceAdapterMethod(this, "getViewportItemIndex", [...arguments])
    };
    _proto.setViewportItemIndex = function(viewportItemIndex) {
        return proxyDataSourceAdapterMethod(this, "setViewportItemIndex", [...arguments])
    };
    _proto.getItemIndexByPosition = function() {
        return proxyDataSourceAdapterMethod(this, "getItemIndexByPosition", [...arguments])
    };
    _proto.viewportSize = function() {
        return proxyDataSourceAdapterMethod(this, "viewportSize", [...arguments])
    };
    _proto.viewportItemSize = function() {
        return proxyDataSourceAdapterMethod(this, "viewportItemSize", [...arguments])
    };
    _proto.getItemSize = function() {
        return proxyDataSourceAdapterMethod(this, "getItemSize", [...arguments])
    };
    _proto.getItemSizes = function() {
        return proxyDataSourceAdapterMethod(this, "getItemSizes", [...arguments])
    };
    _proto.loadIfNeed = function() {
        return proxyDataSourceAdapterMethod(this, "loadIfNeed", [...arguments])
    };
    return VirtualScrollingCoreDataSourceAdapterExtender
}(Base);
exports.dataSourceAdapterExtender = dataSourceAdapterExtender;
const data = Base => function(_Base2) {
    _inheritsLoose(VirtualScrollingDataControllerExtender, _Base2);

    function VirtualScrollingDataControllerExtender() {
        return _Base2.apply(this, arguments) || this
    }
    var _proto2 = VirtualScrollingDataControllerExtender.prototype;
    _proto2.dispose = function() {
        const rowsScrollController = this._rowsScrollController;
        rowsScrollController && rowsScrollController.dispose();
        _Base2.prototype.dispose.apply(this, arguments)
    };
    _proto2._refreshDataSource = function() {
        const baseResult = _Base2.prototype._refreshDataSource.apply(this, arguments) || (new _deferred.Deferred).resolve().promise();
        baseResult.done(this.initVirtualRows.bind(this));
        return baseResult
    };
    _proto2._loadDataSource = function() {
        var _a;
        if (this._rowsScrollController && isVirtualPaging(this)) {
            const {
                loadPageCount: loadPageCount
            } = (0, _type.isDefined)(this._loadViewportParams) ? this.getLoadPageParams(): {
                loadPageCount: 0
            };
            loadPageCount >= 1 && (null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.loadPageCount(loadPageCount))
        }
        return _Base2.prototype._loadDataSource.apply(this, arguments)
    };
    _proto2.getRowPageSize = function() {
        const rowPageSize = this.option("scrolling.rowPageSize");
        const pageSize = this.pageSize();
        return pageSize && pageSize < rowPageSize ? pageSize : rowPageSize
    };
    _proto2.reload = function() {
        const rowsScrollController = this._rowsScrollController || this._dataSource;
        const itemIndex = rowsScrollController && rowsScrollController.getItemIndexByPosition();
        const result = _Base2.prototype.reload.apply(this, arguments);
        return result && result.done(() => {
            var _a, _b;
            if (isVirtualMode(this) || _m_utils.default.isVirtualRowRendering(this)) {
                const rowIndexOffset = this.getRowIndexOffset();
                const rowIndex = Math.floor(itemIndex) - rowIndexOffset;
                const {
                    component: component
                } = this;
                const scrollable = component.getScrollable && component.getScrollable();
                const isSortingOperation = this.dataSource().operationTypes().sorting;
                if (scrollable && !isSortingOperation && rowIndex >= 0) {
                    const rowElement = component.getRowElement(rowIndex);
                    const $rowElement = rowElement && rowElement[0] && (0, _renderer.default)(rowElement[0]);
                    let top = $rowElement && (null === (_a = $rowElement.position()) || void 0 === _a ? void 0 : _a.top);
                    const isChromeLatest = _browser.default.chrome && Number(null !== (_b = _browser.default.version) && void 0 !== _b ? _b : 0) >= 91;
                    const allowedTopOffset = _browser.default.mozilla || isChromeLatest ? 1 : 0;
                    if (top && top > allowedTopOffset) {
                        top = Math.round(top + (0, _size.getOuterHeight)($rowElement) * (itemIndex % 1));
                        scrollable.scrollTo({
                            y: top
                        })
                    }
                }
            }
        })
    };
    _proto2.initVirtualRows = function() {
        const virtualRowsRendering = _m_utils.default.isVirtualRowRendering(this);
        this._allItems = null;
        this._loadViewportParams = null;
        if ("virtual" !== this.option("scrolling.mode") && !virtualRowsRendering || !virtualRowsRendering || false !== this.option(LEGACY_SCROLLING_MODE) && !this.option("scrolling.rowPageSize")) {
            this._visibleItems = null;
            this._rowsScrollController = null;
            return
        }
        const pageIndex = !isVirtualMode(this) && this.pageIndex() >= this.pageCount() ? this.pageCount() - 1 : this.pageIndex();
        this._rowPageIndex = Math.ceil(pageIndex * this.pageSize() / this.getRowPageSize());
        this._visibleItems = false === this.option(LEGACY_SCROLLING_MODE) ? null : [];
        this._viewportChanging = false;
        this._needUpdateViewportAfterLoading = false;
        if (!this._rowsScrollController) {
            this._rowsScrollController = new _m_virtual_scrolling_core.VirtualScrollController(this.component, this._getRowsScrollDataOptions(), true);
            this._rowsScrollController.positionChanged.add(() => {
                var _a;
                if (false === this.option(LEGACY_SCROLLING_MODE)) {
                    this._viewportChanging = true;
                    this.loadViewport();
                    this._viewportChanging = false;
                    return
                }
                null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.setViewportItemIndex(this._rowsScrollController.getViewportItemIndex())
            })
        }
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            this._updateLoadViewportParams()
        }
        if (this.isLoaded() && false !== this.option(LEGACY_SCROLLING_MODE)) {
            this._rowsScrollController.load()
        }
    };
    _proto2.isViewportChanging = function() {
        return this._viewportChanging
    };
    _proto2._getRowsScrollDataOptions = function() {
        const that = this;
        const isItemCountable = function(item) {
            return isItemCountableByDataSource(item, that._dataSource)
        };
        return {
            pageSize: () => that.getRowPageSize(),
            loadedOffset() {
                var _a;
                return isVirtualMode(that) && (null === (_a = that._dataSource) || void 0 === _a ? void 0 : _a.lastLoadOptions().skip) || 0
            },
            loadedItemCount: () => that._itemCount,
            totalItemsCount() {
                if (isVirtualPaging(that)) {
                    return that.totalItemsCount()
                }
                return false === that.option(LEGACY_SCROLLING_MODE) ? that._itemCount : that._items.filter(isItemCountable).length
            },
            hasKnownLastPage: () => false === that.option(LEGACY_SCROLLING_MODE) ? that.hasKnownLastPage() : true,
            pageIndex(index) {
                if (void 0 !== index) {
                    that._rowPageIndex = index
                }
                return that._rowPageIndex
            },
            isLoading: () => that.isLoading(),
            pageCount() {
                const pageCount = Math.ceil(this.totalItemsCount() / this.pageSize());
                return pageCount || 1
            },
            load() {
                if (that._rowsScrollController.pageIndex() >= this.pageCount()) {
                    that._rowPageIndex = this.pageCount() - 1;
                    that._rowsScrollController.pageIndex(that._rowPageIndex)
                }
                if (!this.items().length && this.totalItemsCount()) {
                    return
                }
                that._rowsScrollController.handleDataChanged(change => {
                    change = change || {};
                    change.changeType = change.changeType || "refresh";
                    change.items = change.items || that._visibleItems;
                    that._visibleItems.forEach((item, index) => {
                        item.rowIndex = index
                    });
                    that._fireChanged(change)
                })
            },
            updateLoading() {},
            itemsCount() {
                return this.items(true).length
            },
            correctCount: (items, count, fromEnd) => correctCount(items, count, fromEnd, (item, isNextAfterLast, fromEnd) => {
                if (item.isNewRow) {
                    return isNextAfterLast && !fromEnd
                }
                if (isNextAfterLast && fromEnd) {
                    return !item.isNewRow
                }
                return isItemCountable(item)
            }),
            items(countableOnly) {
                let result = that._items;
                if (that.option(LEGACY_SCROLLING_MODE)) {
                    const dataSource = that.dataSource();
                    const virtualItemsCount = null === dataSource || void 0 === dataSource ? void 0 : dataSource.virtualItemsCount();
                    const begin = virtualItemsCount ? virtualItemsCount.begin : 0;
                    const rowPageSize = that.getRowPageSize();
                    let skip = that._rowPageIndex * rowPageSize - begin;
                    let take = rowPageSize;
                    if (skip < 0) {
                        return []
                    }
                    if (skip) {
                        skip = this.correctCount(result, skip);
                        result = result.slice(skip)
                    }
                    if (take) {
                        take = this.correctCount(result, take);
                        result = result.slice(0, take)
                    }
                }
                return countableOnly ? result.filter(isItemCountable) : result
            },
            viewportItems(items) {
                if (items && false !== that.option(LEGACY_SCROLLING_MODE)) {
                    that._visibleItems = items
                }
                return that._visibleItems
            },
            onChanged() {},
            changingDuration() {
                const dataSource = that.dataSource();
                if ((null === dataSource || void 0 === dataSource ? void 0 : dataSource.isLoading()) && false !== that.option(LEGACY_SCROLLING_MODE)) {
                    return 300
                }
                return (null === dataSource || void 0 === dataSource ? void 0 : dataSource._renderTime) || 0
            }
        }
    };
    _proto2._updateItemsCore = function(change) {
        const delta = this.getRowIndexDelta();
        _Base2.prototype._updateItemsCore.apply(this, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE) && _m_utils.default.isVirtualRowRendering(this)) {
            if ("update" === change.changeType && 0 === change.rowIndices.length && change.cancelEmptyChanges) {
                change.cancel = true
            }
            return
        }
        const rowsScrollController = this._rowsScrollController;
        if (rowsScrollController) {
            const visibleItems = this._visibleItems;
            const isRefresh = "refresh" === change.changeType || change.isLiveUpdate;
            if ("append" === change.changeType && change.items && !change.items.length) {
                return
            }
            if (isRefresh || "append" === change.changeType || "prepend" === change.changeType) {
                change.cancel = true;
                isRefresh && rowsScrollController.reset(true);
                rowsScrollController.load()
            } else {
                if ("update" === change.changeType) {
                    change.rowIndices.forEach((rowIndex, index) => {
                        const changeType = change.changeTypes[index];
                        const newItem = change.items[index];
                        if ("update" === changeType) {
                            visibleItems[rowIndex] = newItem
                        } else if ("insert" === changeType) {
                            visibleItems.splice(rowIndex, 0, newItem)
                        } else if ("remove" === changeType) {
                            visibleItems.splice(rowIndex, 1)
                        }
                    })
                } else {
                    visibleItems.forEach((item, index) => {
                        visibleItems[index] = this._items[index + delta] || visibleItems[index]
                    });
                    change.items = visibleItems
                }
                updateItemIndices(visibleItems)
            }
        }
    };
    _proto2._updateLoadViewportParams = function() {
        const viewportParams = this._rowsScrollController.getViewportParams();
        const pageSize = this.pageSize();
        if (viewportParams && !isVirtualPaging(this) && pageSize > 0) {
            const pageOffset = this.pageIndex() * pageSize;
            viewportParams.skip += pageOffset
        }
        this._loadViewportParams = viewportParams
    };
    _proto2._processItems = function() {
        var _a;
        const resultItems = _Base2.prototype._processItems.apply(this, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            const dataSource = this._dataSource;
            let currentIndex = null !== (_a = null === dataSource || void 0 === dataSource ? void 0 : dataSource.lastLoadOptions().skip) && void 0 !== _a ? _a : 0;
            let prevCountable;
            let prevRowType;
            let isPrevRowNew;
            let wasCountableItem = false;
            let newRows = [];
            resultItems.forEach(item => {
                const {
                    rowType: rowType
                } = item;
                const itemCountable = isItemCountableByDataSource(item, dataSource);
                const isNextGroupItem = "group" === rowType && (prevCountable || itemCountable || "group" !== prevRowType && currentIndex > 0);
                const isNextDataItem = "data" === rowType && itemCountable && (prevCountable || "group" !== prevRowType);
                if (!item.isNewRow && (0, _type.isDefined)(prevCountable)) {
                    const isPrevNewRowFirst = isPrevRowNew && !wasCountableItem;
                    if ((isNextGroupItem || isNextDataItem) && !isPrevNewRowFirst) {
                        currentIndex++
                    }
                }
                if (isNextGroupItem || isNextDataItem) {
                    wasCountableItem = true
                }
                if (item.isNewRow) {
                    newRows.push(item)
                } else {
                    newRows.forEach(it => {
                        it.loadIndex = currentIndex
                    });
                    newRows = []
                }
                item.loadIndex = currentIndex;
                prevCountable = itemCountable;
                prevRowType = rowType;
                isPrevRowNew = item.isNewRow
            });
            newRows.forEach(it => {
                it.loadIndex = currentIndex
            })
        }
        return resultItems
    };
    _proto2._afterProcessItems = function(items) {
        this._itemCount = items.filter(item => isItemCountableByDataSource(item, this._dataSource)).length;
        if ((0, _type.isDefined)(this._loadViewportParams)) {
            this._updateLoadViewportParams();
            let result = items;
            this._allItems = items;
            if (items.length) {
                const {
                    skipForCurrentPage: skipForCurrentPage
                } = this.getLoadPageParams(true);
                const skip = items[0].loadIndex + skipForCurrentPage;
                const {
                    take: take
                } = this._loadViewportParams;
                result = items.filter(it => {
                    const isNewRowInEmptyData = it.isNewRow && it.loadIndex === skip && 0 === take;
                    const isLoadIndexGreaterStart = it.loadIndex >= skip;
                    const isLoadIndexLessEnd = it.loadIndex < skip + take || isNewRowInEmptyData;
                    return isLoadIndexGreaterStart && isLoadIndexLessEnd
                })
            }
            return result
        }
        return _Base2.prototype._afterProcessItems.apply(this, arguments)
    };
    _proto2._applyChange = function(change) {
        const that = this;
        const {
            items: items
        } = change;
        const {
            changeType: changeType
        } = change;
        let {
            removeCount: removeCount
        } = change;
        if (removeCount) {
            const fromEnd = "prepend" === changeType;
            removeCount = correctCount(that._items, removeCount, fromEnd, (item, isNextAfterLast) => "data" === item.rowType && !item.isNewRow || "group" === item.rowType && (that._dataSource.isGroupItemCountable(item.data) || isNextAfterLast));
            change.removeCount = removeCount
        }
        switch (changeType) {
            case "prepend":
                that._items.unshift.apply(that._items, items);
                if (removeCount) {
                    that._items.splice(-removeCount)
                }
                break;
            case "append":
                that._items.push.apply(that._items, items);
                if (removeCount) {
                    that._items.splice(0, removeCount)
                }
                break;
            default:
                _Base2.prototype._applyChange.call(this, change)
        }
    };
    _proto2.items = function(allItems) {
        return allItems ? this._allItems || this._items : this._visibleItems || this._items
    };
    _proto2.getRowIndexDelta = function() {
        let delta = 0;
        if (this.option(LEGACY_SCROLLING_MODE)) {
            const visibleItems = this._visibleItems;
            if (visibleItems && visibleItems[0]) {
                delta = this._items.indexOf(visibleItems[0])
            }
        }
        return delta < 0 ? 0 : delta
    };
    _proto2.getRowIndexOffset = function(byLoadedRows, needGroupOffset) {
        var _a, _b;
        let offset = 0;
        const dataSource = this.dataSource();
        const rowsScrollController = this._rowsScrollController;
        const newMode = false === this.option(LEGACY_SCROLLING_MODE);
        const virtualPaging = isVirtualPaging(this);
        if (rowsScrollController && !byLoadedRows) {
            if (newMode && (0, _type.isDefined)(this._loadViewportParams)) {
                const {
                    skipForCurrentPage: skipForCurrentPage,
                    pageIndex: pageIndex
                } = this.getLoadPageParams(true);
                const items = this.items(true);
                offset = virtualPaging ? pageIndex * this.pageSize() : 0;
                if (items.length) {
                    const firstLoadIndex = items[0].loadIndex;
                    offset += items.filter(item => item.loadIndex < firstLoadIndex + skipForCurrentPage).length
                }
            } else {
                offset = rowsScrollController.beginPageIndex() * rowsScrollController.pageSize()
            }
        } else if (virtualPaging && newMode && dataSource) {
            const lastLoadOptions = dataSource.lastLoadOptions();
            if (needGroupOffset && (null === (_a = lastLoadOptions.skips) || void 0 === _a ? void 0 : _a.length)) {
                offset = lastLoadOptions.skips.reduce((res, skip) => res + skip, 0)
            } else {
                offset = null !== (_b = lastLoadOptions.skip) && void 0 !== _b ? _b : 0
            }
        } else if (isVirtualMode(this) && dataSource) {
            offset = dataSource.beginPageIndex() * dataSource.pageSize()
        }
        return offset
    };
    _proto2.getDataIndex = function() {
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return this.getRowIndexOffset(true, true)
        }
        return _Base2.prototype.getDataIndex.apply(this, arguments)
    };
    _proto2.viewportSize = function() {
        const rowsScrollController = this._rowsScrollController;
        const dataSource = this._dataSource;
        const result = null === rowsScrollController || void 0 === rowsScrollController ? void 0 : rowsScrollController.viewportSize.apply(rowsScrollController, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return result
        }
        return null === dataSource || void 0 === dataSource ? void 0 : dataSource.viewportSize.apply(dataSource, arguments)
    };
    _proto2.viewportHeight = function(height, scrollTop) {
        var _a;
        null === (_a = this._rowsScrollController) || void 0 === _a ? void 0 : _a.viewportHeight(height, scrollTop)
    };
    _proto2.viewportItemSize = function() {
        const rowsScrollController = this._rowsScrollController;
        const dataSource = this._dataSource;
        const result = null === rowsScrollController || void 0 === rowsScrollController ? void 0 : rowsScrollController.viewportItemSize.apply(rowsScrollController, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return result
        }
        return null === dataSource || void 0 === dataSource ? void 0 : dataSource.viewportItemSize.apply(dataSource, arguments)
    };
    _proto2.setViewportPosition = function() {
        const rowsScrollController = this._rowsScrollController;
        const dataSource = this._dataSource;
        this._isPaging = false;
        if (rowsScrollController) {
            rowsScrollController.setViewportPosition.apply(rowsScrollController, arguments)
        } else {
            null === dataSource || void 0 === dataSource ? void 0 : dataSource.setViewportPosition.apply(dataSource, arguments)
        }
    };
    _proto2.setContentItemSizes = function(sizes) {
        const rowsScrollController = this._rowsScrollController;
        const dataSource = this._dataSource;
        const result = null === rowsScrollController || void 0 === rowsScrollController ? void 0 : rowsScrollController.setContentItemSizes(sizes);
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return result
        }
        return null === dataSource || void 0 === dataSource ? void 0 : dataSource.setContentItemSizes(sizes)
    };
    _proto2.getPreloadedRowCount = function() {
        const preloadCount = this.option("scrolling.preloadedRowCount");
        const preloadEnabled = this.option("scrolling.preloadEnabled");
        if ((0, _type.isDefined)(preloadCount)) {
            return preloadCount
        }
        const viewportSize = this.viewportSize();
        return preloadEnabled ? 2 * viewportSize : viewportSize
    };
    _proto2.getLoadPageParams = function(byLoadedPage) {
        var _a, _b;
        const pageSize = this.pageSize();
        const viewportParams = this._loadViewportParams;
        const lastLoadOptions = null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.lastLoadOptions();
        const loadedPageIndex = (null === lastLoadOptions || void 0 === lastLoadOptions ? void 0 : lastLoadOptions.pageIndex) || 0;
        const loadedTake = (null === lastLoadOptions || void 0 === lastLoadOptions ? void 0 : lastLoadOptions.take) || 0;
        const isScrollingBack = this._rowsScrollController.isScrollingBack();
        const topPreloadCount = isScrollingBack ? this.getPreloadedRowCount() : 0;
        const bottomPreloadCount = isScrollingBack ? 0 : this.getPreloadedRowCount();
        const totalCountCorrection = (null === (_b = this._dataSource) || void 0 === _b ? void 0 : _b.totalCountCorrection()) || 0;
        const skipWithPreload = Math.max(0, viewportParams.skip - topPreloadCount);
        const pageIndex = byLoadedPage ? loadedPageIndex : Math.floor(pageSize ? skipWithPreload / pageSize : 0);
        const pageOffset = pageIndex * pageSize;
        const skipForCurrentPage = viewportParams.skip - pageOffset;
        const loadingTake = viewportParams.take + skipForCurrentPage + bottomPreloadCount - totalCountCorrection;
        const take = byLoadedPage ? loadedTake : loadingTake;
        const loadPageCount = Math.ceil(pageSize ? take / pageSize : 0);
        return {
            pageIndex: pageIndex,
            loadPageCount: Math.max(1, loadPageCount),
            skipForCurrentPage: Math.max(0, skipForCurrentPage)
        }
    };
    _proto2._updateVisiblePageIndex = function(currentPageIndex) {
        if (!this._rowsScrollController) {
            return
        }
        if ((0, _type.isDefined)(currentPageIndex)) {
            this._silentOption("paging.pageIndex", currentPageIndex);
            this.pageChanged.fire();
            return
        }
        const viewPortItemIndex = this._rowsScrollController.getViewportItemIndex();
        const newPageIndex = Math.floor(viewPortItemIndex / this.pageSize());
        if (this.pageIndex() !== newPageIndex) {
            this._silentOption("paging.pageIndex", newPageIndex);
            this.updateItems({
                changeType: "pageIndex"
            })
        }
    };
    _proto2._getChangedLoadParams = function() {
        const loadedPageParams = this.getLoadPageParams(true);
        const {
            pageIndex: pageIndex,
            loadPageCount: loadPageCount
        } = this.getLoadPageParams();
        const pageIndexIsValid = this._pageIndexIsValid(pageIndex);
        let result = null;
        if (!this._isLoading && pageIndexIsValid && (pageIndex !== loadedPageParams.pageIndex || loadPageCount !== loadedPageParams.loadPageCount)) {
            result = {
                pageIndex: pageIndex,
                loadPageCount: loadPageCount
            }
        }
        return result
    };
    _proto2._pageIndexIsValid = function(pageIndex) {
        let result = true;
        if (isAppendMode(this) && this.hasKnownLastPage() || isVirtualMode(this)) {
            result = pageIndex * this.pageSize() < this.totalItemsCount()
        }
        return result
    };
    _proto2._loadItems = function(checkLoading, viewportIsFilled) {
        var _a, _b;
        const virtualPaging = isVirtualPaging(this);
        const dataSourceAdapter = this._dataSource;
        const changedParams = this._getChangedLoadParams();
        const currentLoadPageCount = null !== (_a = null === dataSourceAdapter || void 0 === dataSourceAdapter ? void 0 : dataSourceAdapter.loadPageCount()) && void 0 !== _a ? _a : 0;
        const lastRequiredItemCount = this.pageSize() * currentLoadPageCount;
        const currentPageIndex = null !== (_b = null === dataSourceAdapter || void 0 === dataSourceAdapter ? void 0 : dataSourceAdapter.pageIndex()) && void 0 !== _b ? _b : 0;
        const pageIndexNotChanged = (null === changedParams || void 0 === changedParams ? void 0 : changedParams.pageIndex) === currentPageIndex;
        const allLoadedInAppendMode = isAppendMode(this) && this.totalItemsCount() < lastRequiredItemCount;
        const isRepaintMode = "repaint" === this.option("editing.refreshMode");
        const pageIndexIncreased = (null === changedParams || void 0 === changedParams ? void 0 : changedParams.pageIndex) > currentPageIndex;
        let result = false;
        if (!dataSourceAdapter || virtualPaging && checkLoading && (isRepaintMode && viewportIsFilled || pageIndexIncreased || pageIndexNotChanged && allLoadedInAppendMode)) {
            return result
        }
        if (virtualPaging && this._isLoading) {
            this._needUpdateViewportAfterLoading = true
        }
        if (virtualPaging && changedParams) {
            result = true;
            dataSourceAdapter.pageIndex(changedParams.pageIndex);
            dataSourceAdapter.loadPageCount(changedParams.loadPageCount);
            this._repaintChangesOnly = true;
            this._needUpdateDimensions = true;
            const viewportChanging = this._viewportChanging;
            this.load().always(() => {
                this._repaintChangesOnly = void 0;
                this._needUpdateDimensions = void 0
            }).done(() => {
                const isLastPage = this.pageCount() > 0 && this.pageIndex() === this.pageCount() - 1;
                (viewportChanging || isLastPage) && this._updateVisiblePageIndex();
                if (this._needUpdateViewportAfterLoading) {
                    this._needUpdateViewportAfterLoading = false;
                    this.loadViewport({
                        checkLoadedParamsOnly: true
                    })
                }
            })
        }
        return result
    };
    _proto2.loadViewport = function(params) {
        var _a, _b, _c;
        const {
            checkLoadedParamsOnly: checkLoadedParamsOnly,
            checkLoading: checkLoading,
            viewportIsNotFilled: viewportIsNotFilled
        } = null !== params && void 0 !== params ? params : {};
        const virtualPaging = isVirtualPaging(this);
        if (virtualPaging || _m_utils.default.isVirtualRowRendering(this)) {
            this._updateLoadViewportParams();
            const loadingItemsStarted = this._loadItems(checkLoading, !viewportIsNotFilled);
            const isCustomLoading = null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.isCustomLoading();
            const isLoading = checkLoading && !isCustomLoading && this._isLoading;
            const needToUpdateItems = !(loadingItemsStarted || isLoading || checkLoadedParamsOnly);
            if (needToUpdateItems) {
                const noPendingChangesInEditing = !(null === (_c = null === (_b = this._editingController) || void 0 === _b ? void 0 : _b.getChanges()) || void 0 === _c ? void 0 : _c.length);
                this.updateItems({
                    repaintChangesOnly: true,
                    needUpdateDimensions: true,
                    useProcessedItemsCache: noPendingChangesInEditing,
                    cancelEmptyChanges: true
                })
            }
        }
    };
    _proto2.updateViewport = function() {
        var _a, _b;
        const viewportSize = this.viewportSize();
        const itemCount = this.items().length;
        const viewportIsNotFilled = viewportSize > itemCount;
        const currentTake = null !== (_b = null === (_a = this._loadViewportParams) || void 0 === _a ? void 0 : _a.take) && void 0 !== _b ? _b : 0;
        const rowsScrollController = this._rowsScrollController;
        const newTake = null === rowsScrollController || void 0 === rowsScrollController ? void 0 : rowsScrollController.getViewportParams().take;
        (viewportIsNotFilled || currentTake < newTake) && !this._isPaging && itemCount && this.loadViewport({
            checkLoading: true,
            viewportIsNotFilled: viewportIsNotFilled
        })
    };
    _proto2.loadIfNeed = function() {
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            return
        }
        const rowsScrollController = this._rowsScrollController;
        rowsScrollController && rowsScrollController.loadIfNeed();
        const dataSource = this._dataSource;
        return dataSource && dataSource.loadIfNeed()
    };
    _proto2.getItemSize = function() {
        const rowsScrollController = this._rowsScrollController;
        if (rowsScrollController) {
            return rowsScrollController.getItemSize.apply(rowsScrollController, arguments)
        }
        const dataSource = this._dataSource;
        return dataSource && dataSource.getItemSize.apply(dataSource, arguments)
    };
    _proto2.getItemSizes = function() {
        const rowsScrollController = this._rowsScrollController;
        if (rowsScrollController) {
            return rowsScrollController.getItemSizes.apply(rowsScrollController, arguments)
        }
        const dataSource = this._dataSource;
        return dataSource && dataSource.getItemSizes.apply(dataSource, arguments)
    };
    _proto2.getContentOffset = function() {
        const rowsScrollController = this._rowsScrollController;
        if (rowsScrollController) {
            return rowsScrollController.getContentOffset.apply(rowsScrollController, arguments)
        }
        const dataSource = this._dataSource;
        return dataSource && dataSource.getContentOffset.apply(dataSource, arguments)
    };
    _proto2.refresh = function(options) {
        const dataSource = this._dataSource;
        if (dataSource && options && options.load && isAppendMode(this)) {
            dataSource.resetCurrentTotalCount()
        }
        return _Base2.prototype.refresh.apply(this, arguments)
    };
    _proto2.topItemIndex = function() {
        var _a;
        return null === (_a = this._loadViewportParams) || void 0 === _a ? void 0 : _a.skip
    };
    _proto2.bottomItemIndex = function() {
        const viewportParams = this._loadViewportParams;
        return viewportParams && viewportParams.skip + viewportParams.take
    };
    _proto2.virtualItemsCount = function() {
        const rowsScrollController = this._rowsScrollController;
        if (rowsScrollController) {
            return rowsScrollController.virtualItemsCount.apply(rowsScrollController, arguments)
        }
        const dataSource = this._dataSource;
        return null === dataSource || void 0 === dataSource ? void 0 : dataSource.virtualItemsCount.apply(dataSource, arguments)
    };
    _proto2.pageIndex = function(_pageIndex2) {
        var _a;
        const virtualPaging = isVirtualPaging(this);
        const rowsScrollController = this._rowsScrollController;
        if (false === this.option(LEGACY_SCROLLING_MODE) && virtualPaging && rowsScrollController) {
            if (void 0 === _pageIndex2) {
                return null !== (_a = this.option("paging.pageIndex")) && void 0 !== _a ? _a : 0
            }
        }
        return _Base2.prototype.pageIndex.apply(this, arguments)
    };
    _proto2._fireChanged = function(e) {
        _Base2.prototype._fireChanged.apply(this, arguments);
        const {
            operationTypes: operationTypes
        } = e;
        if (false === this.option(LEGACY_SCROLLING_MODE) && isVirtualPaging(this) && operationTypes) {
            const {
                fullReload: fullReload,
                pageIndex: pageIndex
            } = operationTypes;
            if (e.isDataChanged && !fullReload && pageIndex) {
                this._updateVisiblePageIndex(this._dataSource.pageIndex())
            }
        }
    };
    _proto2._getPagingOptionValue = function(optionName) {
        let result = _Base2.prototype._getPagingOptionValue.apply(this, arguments);
        if (false === this.option(LEGACY_SCROLLING_MODE) && isVirtualPaging(this)) {
            result = this[optionName]()
        }
        return result
    };
    _proto2.isEmpty = function() {
        return false === this.option(LEGACY_SCROLLING_MODE) ? !this.items(true).length : _Base2.prototype.isEmpty.apply(this, arguments)
    };
    _proto2.isLastPageLoaded = function() {
        let result = false;
        if (false === this.option(LEGACY_SCROLLING_MODE) && isVirtualPaging(this)) {
            const {
                pageIndex: pageIndex,
                loadPageCount: loadPageCount
            } = this.getLoadPageParams(true);
            const pageCount = this.pageCount();
            result = pageIndex + loadPageCount >= pageCount
        } else {
            result = _Base2.prototype.isLastPageLoaded.apply(this, arguments)
        }
        return result
    };
    _proto2.reset = function() {
        this._itemCount = 0;
        this._allItems = null;
        _Base2.prototype.reset.apply(this, arguments)
    };
    _proto2._applyFilter = function() {
        var _a;
        null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.loadPageCount(1);
        return _Base2.prototype._applyFilter.apply(this, arguments)
    };
    _proto2.getVirtualContentSize = function() {
        var _a;
        return null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.getVirtualContentSize.apply(this._dataSource, arguments)
    };
    _proto2.setViewportItemIndex = function() {
        var _a;
        return null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.setViewportItemIndex.apply(this._dataSource, arguments)
    };
    return VirtualScrollingDataControllerExtender
}(Base);
exports.data = data;
const resizing = Base => function(_Base3) {
    _inheritsLoose(VirtualScrollingResizingControllerExtender, _Base3);

    function VirtualScrollingResizingControllerExtender() {
        return _Base3.apply(this, arguments) || this
    }
    var _proto3 = VirtualScrollingResizingControllerExtender.prototype;
    _proto3.dispose = function() {
        _Base3.prototype.dispose.apply(this, arguments);
        clearTimeout(this._resizeTimeout)
    };
    _proto3._updateMasterDataGridCore = function(masterDataGrid) {
        return (0, _deferred.when)(_Base3.prototype._updateMasterDataGridCore.apply(this, arguments)).done(masterDataGridUpdated => {
            const isNewVirtualMode = isVirtualMode(masterDataGrid) && false === masterDataGrid.option(LEGACY_SCROLLING_MODE);
            if (!masterDataGridUpdated && isNewVirtualMode) {
                const scrollable = masterDataGrid.getScrollable();
                if (scrollable) {
                    masterDataGrid.updateDimensions()
                }
            }
        })
    };
    _proto3.hasResizeTimeout = function() {
        return !!this._resizeTimeout
    };
    _proto3.resize = function() {
        let result;
        if (isVirtualMode(this) || _m_utils.default.isVirtualRowRendering(this)) {
            clearTimeout(this._resizeTimeout);
            this._resizeTimeout = null;
            const diff = new Date - this._lastTime;
            const updateTimeout = this.option("scrolling.updateTimeout");
            if (this._lastTime && diff < updateTimeout) {
                result = new _deferred.Deferred;
                this._resizeTimeout = setTimeout(() => {
                    this._resizeTimeout = null;
                    _Base3.prototype.resize.apply(this).done(result.resolve).fail(result.reject);
                    this._lastTime = new Date
                }, updateTimeout);
                this._lastTime = new Date
            } else {
                result = _Base3.prototype.resize.apply(this);
                if (this._dataController.isLoaded()) {
                    this._lastTime = new Date
                }
            }
        } else {
            result = _Base3.prototype.resize.apply(this)
        }
        return result
    };
    return VirtualScrollingResizingControllerExtender
}(Base);
exports.resizing = resizing;
const rowsView = Base => function(_Base4) {
    _inheritsLoose(VirtualScrollingRowsViewExtender, _Base4);

    function VirtualScrollingRowsViewExtender() {
        return _Base4.apply(this, arguments) || this
    }
    var _proto4 = VirtualScrollingRowsViewExtender.prototype;
    _proto4.init = function() {
        var _a;
        _Base4.prototype.init.call(this);
        this._dataController.pageChanged.add(pageIndex => {
            const scrollTop = this._scrollTop;
            this.scrollToPage(null !== pageIndex && void 0 !== pageIndex ? pageIndex : this._dataController.pageIndex());
            if (false === this.option(LEGACY_SCROLLING_MODE) && this._scrollTop === scrollTop) {
                this._dataController.updateViewport()
            }
        });
        this._dataController.dataSourceChanged.add(() => {
            !this._scrollTop && this._scrollToCurrentPageOnResize()
        });
        null === (_a = this._dataController.stateLoaded) || void 0 === _a ? void 0 : _a.add(() => {
            this._scrollToCurrentPageOnResize()
        });
        this._scrollToCurrentPageOnResize()
    };
    _proto4.dispose = function() {
        clearTimeout(this._scrollTimeoutID);
        _Base4.prototype.dispose.call(this)
    };
    _proto4._scrollToCurrentPageOnResize = function() {
        if (this._dataController.pageIndex() > 0) {
            const resizeHandler = () => {
                this.resizeCompleted.remove(resizeHandler);
                this.scrollToPage(this._dataController.pageIndex())
            };
            this.resizeCompleted.add(resizeHandler)
        }
    };
    _proto4.scrollToPage = function(pageIndex) {
        const pageSize = this._dataController ? this._dataController.pageSize() : 0;
        let scrollPosition;
        if (isVirtualMode(this) || isAppendMode(this)) {
            const itemSize = this._dataController.getItemSize();
            const itemSizes = this._dataController.getItemSizes();
            const itemIndex = pageIndex * pageSize;
            scrollPosition = itemIndex * itemSize;
            for (const index in itemSizes) {
                if (parseInt(index) < itemIndex) {
                    scrollPosition += itemSizes[index] - itemSize
                }
            }
        } else {
            scrollPosition = 0
        }
        this.scrollTo({
            y: scrollPosition,
            x: this._scrollLeft
        })
    };
    _proto4.renderDelayedTemplates = function() {
        this.waitAsyncTemplates().done(() => {
            this._updateContentPosition(true)
        });
        _Base4.prototype.renderDelayedTemplates.apply(this, arguments)
    };
    _proto4._renderCore = function(e) {
        const startRenderTime = new Date;
        const deferred = _Base4.prototype._renderCore.apply(this, arguments);
        const dataSource = this._dataController._dataSource;
        if (dataSource && e) {
            const itemCount = e.items ? e.items.length : 20;
            const viewportSize = this._dataController.viewportSize() || 20;
            if (_m_utils.default.isVirtualRowRendering(this) && itemCount > 0 && false !== this.option(LEGACY_SCROLLING_MODE)) {
                dataSource._renderTime = (new Date - startRenderTime) * viewportSize / itemCount
            } else {
                dataSource._renderTime = new Date - startRenderTime
            }
        }
        return deferred
    };
    _proto4._getRowElements = function(tableElement) {
        const $rows = _Base4.prototype._getRowElements.call(this, tableElement);
        return $rows && $rows.not(".".concat("dx-virtual-row"))
    };
    _proto4._removeRowsElements = function(contentTable, removeCount, changeType) {
        let rowElements = this._getRowElements(contentTable).toArray();
        if ("append" === changeType) {
            rowElements = rowElements.slice(0, removeCount)
        } else {
            rowElements = rowElements.slice(-removeCount)
        }
        rowElements.map(rowElement => {
            const $rowElement = (0, _renderer.default)(rowElement);
            this._errorHandlingController && this._errorHandlingController.removeErrorRow($rowElement.next());
            $rowElement.remove()
        })
    };
    _proto4._updateContent = function(tableElement, change) {
        let $freeSpaceRowElements;
        const contentElement = this._findContentElement();
        const changeType = change && change.changeType;
        const d = (0, _deferred.Deferred)();
        const contentTable = contentElement.children().first();
        if ("append" === changeType || "prepend" === changeType) {
            this.waitAsyncTemplates().done(() => {
                const $tBodies = this._getBodies(tableElement);
                if (1 === $tBodies.length) {
                    this._getBodies(contentTable)["append" === changeType ? "append" : "prepend"]($tBodies.children())
                } else {
                    $tBodies["append" === changeType ? "appendTo" : "prependTo"](contentTable)
                }
                tableElement.remove();
                $freeSpaceRowElements = this._getFreeSpaceRowElements(contentTable);
                removeEmptyRows($freeSpaceRowElements, FREESPACE_CLASS);
                if (change.removeCount) {
                    this._removeRowsElements(contentTable, change.removeCount, changeType)
                }
                this._restoreErrorRow(contentTable);
                d.resolve()
            }).fail(d.reject)
        } else {
            _Base4.prototype._updateContent.apply(this, arguments).done(() => {
                if ("update" === changeType) {
                    this._restoreErrorRow(contentTable)
                }
                d.resolve()
            }).fail(d.reject)
        }
        return d.promise().done(() => {
            this._updateBottomLoading()
        })
    };
    _proto4._addVirtualRow = function($table, isFixed, location, position) {
        if (!position) {
            return
        }
        let $virtualRow = this._createEmptyRow("dx-virtual-row", isFixed, position);
        $virtualRow = this._wrapRowIfNeed($table, $virtualRow);
        this._appendEmptyRow($table, $virtualRow, location)
    };
    _proto4._updateContentItemSizes = function() {
        const rowHeights = this._getRowHeights();
        const correctedRowHeights = this._correctRowHeights(rowHeights);
        this._dataController.setContentItemSizes(correctedRowHeights)
    };
    _proto4._updateViewportSize = function(viewportHeight, scrollTop) {
        if (!(0, _type.isDefined)(viewportHeight)) {
            viewportHeight = this._hasHeight ? (0, _size.getOuterHeight)(this.element()) : (0, _size.getOuterHeight)((0, _window.getWindow)())
        }
        this._dataController.viewportHeight(viewportHeight, scrollTop)
    };
    _proto4._getRowHeights = function() {
        var _a, _b;
        const isPopupEditMode = null === (_b = null === (_a = this._editingController) || void 0 === _a ? void 0 : _a.isPopupEditMode) || void 0 === _b ? void 0 : _b.call(_a);
        let rowElements = this._getRowElements(this._tableElement).toArray();
        if (isPopupEditMode) {
            rowElements = rowElements.filter(row => !(0, _renderer.default)(row).hasClass(ROW_INSERTED))
        }
        return rowElements.map(row => (0, _position.getBoundingRect)(row).height)
    };
    _proto4._correctRowHeights = function(rowHeights) {
        const dataController = this._dataController;
        const dataSource = dataController._dataSource;
        const correctedRowHeights = [];
        const visibleRows = dataController.getVisibleRows();
        let itemSize = 0;
        let firstCountableItem = true;
        let lastLoadIndex = -1;
        for (let i = 0; i < rowHeights.length; i++) {
            const currentItem = visibleRows[i];
            if (!(0, _type.isDefined)(currentItem)) {
                continue
            }
            if (false === this.option(LEGACY_SCROLLING_MODE)) {
                if (lastLoadIndex >= 0 && lastLoadIndex !== currentItem.loadIndex) {
                    correctedRowHeights.push(itemSize);
                    itemSize = 0
                }
                lastLoadIndex = currentItem.loadIndex
            } else if (isItemCountableByDataSource(currentItem, dataSource)) {
                if (firstCountableItem) {
                    firstCountableItem = false
                } else {
                    correctedRowHeights.push(itemSize);
                    itemSize = 0
                }
            }
            itemSize += rowHeights[i]
        }
        itemSize > 0 && correctedRowHeights.push(itemSize);
        return correctedRowHeights
    };
    _proto4._updateContentPosition = function(isRender) {
        const rowHeight = this._rowHeight || 20;
        this._dataController.viewportItemSize(rowHeight);
        if (isVirtualMode(this) || _m_utils.default.isVirtualRowRendering(this)) {
            if (!isRender) {
                this._updateContentItemSizes()
            }
            const top = this._dataController.getContentOffset("begin");
            const bottom = this._dataController.getContentOffset("end");
            const $tables = this.getTableElements();
            const $virtualRows = $tables.children("tbody").children(".".concat("dx-virtual-row"));
            removeEmptyRows($virtualRows, "dx-virtual-row");
            $tables.each((index, element) => {
                const isFixed = index > 0;
                const prevFixed = this._isFixedTableRendering;
                this._isFixedTableRendering = isFixed;
                this._addVirtualRow((0, _renderer.default)(element), isFixed, "top", top);
                this._addVirtualRow((0, _renderer.default)(element), isFixed, "bottom", bottom);
                this._isFixedTableRendering = prevFixed
            })
        }
    };
    _proto4._isTableLinesDisplaysCorrect = function(table) {
        const hasColumnLines = table.find(".".concat("dx-column-lines")).length > 0;
        return hasColumnLines === this.option("showColumnLines")
    };
    _proto4._isColumnElementsEqual = function($columns, $virtualColumns) {
        let result = $columns.length === $virtualColumns.length;
        if (result) {
            (0, _iterator.each)($columns, (index, element) => {
                if (element.style.width !== $virtualColumns[index].style.width) {
                    result = false;
                    return result
                }
                return
            })
        }
        return result
    };
    _proto4._getCellClasses = function(column) {
        const classes = [];
        const {
            cssClass: cssClass
        } = column;
        const isExpandColumn = "expand" === column.command;
        cssClass && classes.push(cssClass);
        isExpandColumn && classes.push(this.addWidgetPrefix("group-space"));
        return classes
    };
    _proto4._findBottomLoadPanel = function($contentElement) {
        const $element = $contentElement || this.element();
        const $bottomLoadPanel = $element && $element.find(".".concat(this.addWidgetPrefix("bottom-load-panel")));
        if ($bottomLoadPanel && $bottomLoadPanel.length) {
            return $bottomLoadPanel
        }
    };
    _proto4._updateBottomLoading = function() {
        const that = this;
        const virtualMode = isVirtualMode(this);
        const appendMode = isAppendMode(this);
        const showBottomLoading = !that._dataController.hasKnownLastPage() && that._dataController.isLoaded() && (virtualMode || appendMode);
        const $contentElement = that._findContentElement();
        const bottomLoadPanelElement = that._findBottomLoadPanel($contentElement);
        if (showBottomLoading) {
            if (!bottomLoadPanelElement) {
                (0, _renderer.default)("<div>").addClass(that.addWidgetPrefix("bottom-load-panel")).append(that._createComponent((0, _renderer.default)("<div>"), _load_indicator.default).$element()).appendTo($contentElement)
            }
        } else if (bottomLoadPanelElement) {
            bottomLoadPanelElement.remove()
        }
    };
    _proto4._handleScroll = function(e) {
        const legacyScrollingMode = true === this.option(LEGACY_SCROLLING_MODE);
        const zeroTopPosition = 0 === e.scrollOffset.top;
        const isScrollTopChanged = this._scrollTop !== e.scrollOffset.top;
        const hasScrolled = isScrollTopChanged || e.forceUpdateScrollPosition;
        const isValidScrollTarget = this._hasHeight || !legacyScrollingMode && zeroTopPosition;
        if (hasScrolled && isValidScrollTarget && this._rowHeight) {
            this._scrollTop = e.scrollOffset.top;
            const isVirtualRowRendering = isVirtualMode(this) || "standard" !== this.option("scrolling.rowRenderingMode");
            if (isVirtualRowRendering && false === this.option(LEGACY_SCROLLING_MODE)) {
                this._updateContentItemSizes();
                this._updateViewportSize(null, this._scrollTop)
            }
            this._dataController.setViewportPosition(e.scrollOffset.top)
        }
        _Base4.prototype._handleScroll.apply(this, arguments)
    };
    _proto4._needUpdateRowHeight = function(itemsCount) {
        return _Base4.prototype._needUpdateRowHeight.apply(this, arguments) || itemsCount > 0 && isAppendMode(this) && !_m_utils.default.isVirtualRowRendering(this)
    };
    _proto4._updateRowHeight = function() {
        _Base4.prototype._updateRowHeight.apply(this, arguments);
        if (this._rowHeight) {
            this._updateContentPosition();
            const viewportHeight = this._hasHeight ? (0, _size.getOuterHeight)(this.element()) : (0, _size.getOuterHeight)((0, _window.getWindow)());
            if (false === this.option(LEGACY_SCROLLING_MODE)) {
                this._updateViewportSize(viewportHeight);
                this._dataController.updateViewport()
            } else {
                this._dataController.viewportSize(Math.ceil(viewportHeight / this._rowHeight))
            }
        }
    };
    _proto4.updateFreeSpaceRowHeight = function() {
        const result = _Base4.prototype.updateFreeSpaceRowHeight.apply(this, arguments);
        if (result) {
            this._updateContentPosition()
        }
        return result
    };
    _proto4.setLoading = function(isLoading, messageText) {
        const dataController = this._dataController;
        const hasBottomLoadPanel = dataController.pageIndex() > 0 && dataController.isLoaded() && !!this._findBottomLoadPanel();
        if (false === this.option(LEGACY_SCROLLING_MODE) && isLoading && dataController.isViewportChanging()) {
            return
        }
        if (hasBottomLoadPanel) {
            isLoading = false
        }
        _Base4.prototype.setLoading.call(this, isLoading, messageText)
    };
    _proto4.throwHeightWarningIfNeed = function() {
        if (void 0 === this._hasHeight) {
            return
        }
        const needToThrow = !this._hasHeight && isVirtualPaging(this);
        if (needToThrow && !this._heightWarningIsThrown) {
            this._heightWarningIsThrown = true;
            _ui.default.log("W1025")
        }
    };
    _proto4._resizeCore = function() {
        const that = this;
        const $element = that.element();
        _Base4.prototype._resizeCore.call(this);
        this.throwHeightWarningIfNeed();
        if (that.component.$element() && !that._windowScroll && (0, _dom.isElementInDom)($element)) {
            that._windowScroll = (0, _m_virtual_scrolling_core.subscribeToExternalScrollers)($element, scrollPos => {
                if (!that._hasHeight && that._rowHeight) {
                    that._dataController.setViewportPosition(scrollPos)
                }
            }, that.component.$element());
            that.on("disposing", () => {
                that._windowScroll.dispose()
            })
        }
        if (false !== this.option(LEGACY_SCROLLING_MODE)) {
            that.loadIfNeed()
        }
    };
    _proto4.loadIfNeed = function() {
        var _a, _b;
        null === (_b = null === (_a = this._dataController) || void 0 === _a ? void 0 : _a.loadIfNeed) || void 0 === _b ? void 0 : _b.call(_a)
    };
    _proto4._restoreErrorRow = function(contentTable) {
        var _a;
        if (false === this.option(LEGACY_SCROLLING_MODE)) {
            null === (_a = this._errorHandlingController) || void 0 === _a ? void 0 : _a.removeErrorRow()
        }
        _Base4.prototype._restoreErrorRow.apply(this, arguments)
    };
    return VirtualScrollingRowsViewExtender
}(Base);
exports.rowsView = rowsView;
const virtualScrollingModule = {
    defaultOptions: () => ({
        scrolling: {
            timeout: 300,
            updateTimeout: 300,
            minTimeout: 0,
            renderingThreshold: 100,
            removeInvisiblePages: true,
            rowPageSize: 5,
            prerenderedRowChunkSize: 1,
            mode: "standard",
            preloadEnabled: false,
            rowRenderingMode: "standard",
            loadTwoPagesOnStart: false,
            legacyMode: false,
            prerenderedRowCount: 1
        }
    }),
    extenders: {
        controllers: {
            data: data,
            resizing: resizing
        },
        views: {
            rowsView: rowsView
        }
    }
};
exports.virtualScrollingModule = virtualScrollingModule;
