{"version":3,"sources":["node_modules/core-js/internals/proxy-accessor.js","node_modules/core-js/internals/inherit-if-required.js","node_modules/core-js/internals/normalize-string-argument.js","node_modules/core-js/internals/install-error-cause.js","node_modules/core-js/internals/error-stack-clear.js","node_modules/core-js/internals/error-stack-installable.js","node_modules/core-js/internals/error-stack-install.js","node_modules/core-js/internals/wrap-error-constructor-with-cause.js","node_modules/core-js/modules/es.error.cause.js","node_modules/core-js/internals/array-set-length.js","node_modules/core-js/internals/does-not-exceed-safe-integer.js","node_modules/core-js/modules/es.array.push.js","node_modules/core-js/internals/set-helpers.js","node_modules/core-js/internals/a-set.js","node_modules/core-js/internals/iterate-simple.js","node_modules/core-js/internals/set-iterate.js","node_modules/core-js/internals/set-clone.js","node_modules/core-js/internals/set-size.js","node_modules/core-js/internals/get-iterator-direct.js","node_modules/core-js/internals/get-set-record.js","node_modules/core-js/internals/set-difference.js","node_modules/core-js/internals/set-method-accept-set-like.js","node_modules/core-js/modules/es.set.difference.v2.js","node_modules/core-js/modules/esnext.set.difference.v2.js","node_modules/core-js/internals/set-intersection.js","node_modules/core-js/modules/es.set.intersection.v2.js","node_modules/core-js/modules/esnext.set.intersection.v2.js","node_modules/core-js/internals/set-is-disjoint-from.js","node_modules/core-js/modules/es.set.is-disjoint-from.v2.js","node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js","node_modules/core-js/internals/set-is-subset-of.js","node_modules/core-js/modules/es.set.is-subset-of.v2.js","node_modules/core-js/modules/esnext.set.is-subset-of.v2.js","node_modules/core-js/internals/set-is-superset-of.js","node_modules/core-js/modules/es.set.is-superset-of.v2.js","node_modules/core-js/modules/esnext.set.is-superset-of.v2.js","node_modules/core-js/internals/set-symmetric-difference.js","node_modules/core-js/modules/es.set.symmetric-difference.v2.js","node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js","node_modules/core-js/internals/set-union.js","node_modules/core-js/modules/es.set.union.v2.js","node_modules/core-js/modules/esnext.set.union.v2.js","node_modules/core-js/modules/web.clear-immediate.js","node_modules/core-js/internals/schedulers-fix.js","node_modules/core-js/modules/web.set-immediate.js","node_modules/core-js/modules/web.immediate.js","node_modules/moment/moment.js","node_modules/core-js/internals/get-json-replacer-function.js","node_modules/core-js/modules/es.json.stringify.js","node_modules/core-js/modules/es.array.unscopables.flat-map.js","node_modules/core-js/modules/es.string.replace-all.js","node_modules/core-js/modules/es.array.at.js","node_modules/core-js/modules/es.string.at-alternative.js","node_modules/core-js/modules/es.array.unscopables.flat.js","node_modules/handsontable/core.mjs","node_modules/handsontable/helpers/dom/element.mjs","node_modules/handsontable/helpers/string.mjs","node_modules/handsontable/helpers/mixed.mjs","node_modules/handsontable/helpers/array.mjs","node_modules/handsontable/helpers/templateLiteralTag.mjs","node_modules/handsontable/helpers/a11y.mjs","node_modules/handsontable/helpers/function.mjs","node_modules/handsontable/helpers/object.mjs","node_modules/handsontable/helpers/feature.mjs","node_modules/handsontable/helpers/browser.mjs","node_modules/handsontable/editorManager.mjs","node_modules/handsontable/helpers/unicode.mjs","node_modules/handsontable/helpers/dom/event.mjs","node_modules/handsontable/editors/registry.mjs","node_modules/handsontable/pluginHooks.mjs","node_modules/handsontable/helpers/console.mjs","node_modules/handsontable/utils/staticRegister.mjs","node_modules/handsontable/eventManager.mjs","node_modules/handsontable/focusManager.mjs","node_modules/handsontable/utils/parseTable.mjs","node_modules/handsontable/plugins/registry.mjs","node_modules/handsontable/utils/dataStructures/priorityMap.mjs","node_modules/handsontable/helpers/number.mjs","node_modules/handsontable/utils/dataStructures/uniqueMap.mjs","node_modules/handsontable/utils/dataStructures/uniqueSet.mjs","node_modules/handsontable/renderers/registry.mjs","node_modules/handsontable/validators/registry.mjs","node_modules/handsontable/tableView.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/fullyVisibleRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/partiallyVisibleRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/renderedAllColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/renderedAllRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/renderedColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/calculationType/renderedRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/viewportColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/viewportBase.mjs","node_modules/handsontable/3rdparty/walkontable/src/calculator/viewportRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/cell/coords.mjs","node_modules/handsontable/3rdparty/walkontable/src/cell/range.mjs","node_modules/handsontable/3rdparty/walkontable/src/core/core.mjs","node_modules/handsontable/3rdparty/walkontable/src/event.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlays.mjs","node_modules/handsontable/3rdparty/walkontable/src/table.mjs","node_modules/handsontable/3rdparty/walkontable/src/filter/column.mjs","node_modules/handsontable/3rdparty/walkontable/src/filter/row.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/rowHeaders.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/orderView/view.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/orderView/constants.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/orderView/viewSizeSet.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/orderView/viewSize.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/orderView/sharedView.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/_base.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/nodesPool.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/columnHeaders.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/colGroup.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/rows.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/cells.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/table.mjs","node_modules/handsontable/3rdparty/walkontable/src/renderer/index.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/column.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/columnStretching.mjs","node_modules/handsontable/3rdparty/walkontable/src/utils/row.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/mixin/stickyRowsBottom.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/mixin/stickyColumnsStart.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/bottomInlineStartCorner.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/_base.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/constants.mjs","node_modules/handsontable/3rdparty/walkontable/src/core/clone.mjs","node_modules/handsontable/3rdparty/walkontable/src/core/_base.mjs","node_modules/handsontable/3rdparty/walkontable/src/scroll.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/bottomInlineStartCorner.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/bottom.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/mixin/calculatedColumns.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/bottom.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/inlineStart.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/mixin/calculatedRows.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/inlineStart.mjs","node_modules/handsontable/mixins/localHooks.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/selection.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/constants.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/border/constants.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/manager.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/scanner.mjs","node_modules/handsontable/3rdparty/walkontable/src/selection/border/border.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/topInlineStartCorner.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/mixin/stickyRowsTop.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/topInlineStartCorner.mjs","node_modules/handsontable/3rdparty/walkontable/src/overlay/top.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/top.mjs","node_modules/handsontable/3rdparty/walkontable/src/settings.mjs","node_modules/handsontable/3rdparty/walkontable/src/table/master.mjs","node_modules/handsontable/3rdparty/walkontable/src/viewport.mjs","node_modules/handsontable/3rdparty/walkontable/src/facade/core.mjs","node_modules/handsontable/selection/mouseEventHandler.mjs","node_modules/handsontable/utils/rootInstance.mjs","node_modules/handsontable/dataMap/dataSource.mjs","node_modules/handsontable/helpers/data.mjs","node_modules/handsontable/translations/indexMapper.mjs","node_modules/handsontable/translations/maps/index.mjs","node_modules/handsontable/translations/maps/hidingMap.mjs","node_modules/handsontable/translations/maps/indexMap.mjs","node_modules/handsontable/translations/maps/utils/physicallyIndexed.mjs","node_modules/handsontable/translations/maps/physicalIndexToValueMap.mjs","node_modules/handsontable/translations/maps/linkedPhysicalIndexToValueMap.mjs","node_modules/handsontable/translations/maps/utils/indexesSequence.mjs","node_modules/handsontable/translations/maps/utils/actionsOnIndexes.mjs","node_modules/handsontable/translations/maps/trimmingMap.mjs","node_modules/handsontable/translations/maps/utils/index.mjs","node_modules/handsontable/translations/maps/indexesSequence.mjs","node_modules/handsontable/translations/mapCollections/aggregatedCollection.mjs","node_modules/handsontable/translations/mapCollections/mapCollection.mjs","node_modules/handsontable/translations/changesObservable/observable.mjs","node_modules/handsontable/translations/changesObservable/observer.mjs","node_modules/handsontable/translations/changesObservable/utils.mjs","node_modules/handsontable/i18n/utils.mjs","node_modules/handsontable/i18n/phraseFormatters/pluralize.mjs","node_modules/handsontable/i18n/phraseFormatters/index.mjs","node_modules/handsontable/i18n/constants.mjs","node_modules/handsontable/i18n/languages/en-US.mjs","node_modules/handsontable/i18n/registry.mjs","node_modules/handsontable/selection/selection.mjs","node_modules/handsontable/selection/highlight/highlight.mjs","node_modules/handsontable/selection/highlight/visualSelection.mjs","node_modules/handsontable/selection/highlight/types/activeHeader.mjs","node_modules/handsontable/selection/highlight/types/areaLayered.mjs","node_modules/handsontable/selection/highlight/types/area.mjs","node_modules/handsontable/selection/highlight/types/column.mjs","node_modules/handsontable/selection/highlight/types/focus.mjs","node_modules/handsontable/selection/highlight/types/customSelection.mjs","node_modules/handsontable/selection/highlight/types/fill.mjs","node_modules/handsontable/selection/highlight/types/header.mjs","node_modules/handsontable/selection/highlight/types/row.mjs","node_modules/handsontable/selection/range.mjs","node_modules/handsontable/selection/transformation.mjs","node_modules/handsontable/selection/utils.mjs","node_modules/handsontable/dataMap/dataMap.mjs","node_modules/handsontable/3rdparty/SheetClip/SheetClip.mjs","node_modules/handsontable/dataMap/metaManager/index.mjs","node_modules/handsontable/dataMap/metaManager/metaLayers/globalMeta.mjs","node_modules/handsontable/dataMap/metaManager/utils.mjs","node_modules/handsontable/cellTypes/registry.mjs","node_modules/handsontable/dataMap/metaManager/metaSchema.mjs","node_modules/handsontable/dataMap/metaManager/metaLayers/tableMeta.mjs","node_modules/handsontable/dataMap/metaManager/metaLayers/columnMeta.mjs","node_modules/handsontable/dataMap/metaManager/lazyFactoryMap.mjs","node_modules/handsontable/dataMap/metaManager/metaLayers/cellMeta.mjs","node_modules/handsontable/dataMap/replaceData.mjs","node_modules/handsontable/dataMap/metaManager/mods/dynamicCellMeta.mjs","node_modules/handsontable/dataMap/metaManager/mods/extendMetaProperties.mjs","node_modules/handsontable/shortcutContexts/constants.mjs","node_modules/handsontable/shortcutContexts/commands/editor/closeAndSave.mjs","node_modules/handsontable/editors/baseEditor/baseEditor.mjs","node_modules/handsontable/mixins/hooksRefRegisterer.mjs","node_modules/handsontable/shortcutContexts/commands/editor/closeAndSaveByArrowKeys.mjs","node_modules/handsontable/shortcutContexts/commands/editor/closeAndSaveByEnter.mjs","node_modules/handsontable/shortcutContexts/commands/editor/closeWithoutSaving.mjs","node_modules/handsontable/shortcutContexts/commands/editor/fastOpen.mjs","node_modules/handsontable/shortcutContexts/commands/editor/open.mjs","node_modules/handsontable/shortcutContexts/commands/editor/index.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/down.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/downByViewportHeight.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/left.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/right.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toColumns.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostBottom.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostInlineEnd.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostInlineStart.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostLeft.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostRight.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toMostTop.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/toRows.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/up.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/upByViewportHeight.mjs","node_modules/handsontable/shortcutContexts/commands/extendCellsSelection/index.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/down.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/downByViewportHeight.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/inlineEnd.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/inlineStart.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/left.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/right.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostBottom.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostBottomInlineEnd.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostInlineEnd.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostInlineStart.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostLeft.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostRight.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostTop.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/toMostTopInlineStart.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/up.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/upByViewportHeight.mjs","node_modules/handsontable/shortcutContexts/commands/moveCellSelection/index.mjs","node_modules/handsontable/shortcutContexts/commands/emptySelectedCells.mjs","node_modules/handsontable/shortcutContexts/commands/scrollToFocusedCell.mjs","node_modules/handsontable/shortcutContexts/commands/selectAllCells.mjs","node_modules/handsontable/shortcutContexts/commands/selectAllCellsAndHeaders.mjs","node_modules/handsontable/shortcutContexts/commands/populateSelectedCellsData.mjs","node_modules/handsontable/shortcutContexts/commands/index.mjs","node_modules/handsontable/shortcutContexts/editor.mjs","node_modules/handsontable/shortcutContexts/grid.mjs","node_modules/handsontable/shortcutContexts/index.mjs","node_modules/handsontable/core/focusCatcher/focusDetector.mjs","node_modules/handsontable/core/focusCatcher/index.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/columnHeaderScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/cornerHeaderScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/focusScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/multipleScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/noncontiguousScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/rowHeaderScroll.mjs","node_modules/handsontable/core/viewportScroll/scrollStrategies/singleScroll.mjs","node_modules/handsontable/core/viewportScroll/index.mjs","node_modules/handsontable/shortcuts/manager.mjs","node_modules/handsontable/shortcuts/context.mjs","node_modules/handsontable/shortcuts/utils.mjs","node_modules/handsontable/shortcuts/recorder.mjs","node_modules/handsontable/shortcuts/keyObserver.mjs","node_modules/handsontable/editors/textEditor/textEditor.mjs","node_modules/handsontable/utils/autoResize.mjs","node_modules/handsontable/editors/textEditor/caretPositioner.mjs","node_modules/handsontable/renderers/baseRenderer/baseRenderer.mjs","node_modules/handsontable/renderers/textRenderer/textRenderer.mjs","node_modules/handsontable/cellTypes/textType/textType.mjs","node_modules/handsontable/base.mjs","node_modules/@handsontable/angular/fesm2022/handsontable-angular.mjs"],"sourcesContent":["'use strict';\nvar defineProperty = require('../internals/object-define-property').f;\n\nmodule.exports = function (Target, Source, key) {\n key in Target || defineProperty(Target, key, {\n configurable: true,\n get: function () { return Source[key]; },\n set: function (it) { Source[key] = it; }\n });\n};\n","'use strict';\nvar isCallable = require('../internals/is-callable');\nvar isObject = require('../internals/is-object');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\n\n// makes subclassing work correct for wrapped built-ins\nmodule.exports = function ($this, dummy, Wrapper) {\n var NewTarget, NewTargetPrototype;\n if (\n // it can work only with native `setPrototypeOf`\n setPrototypeOf &&\n // we haven't completely correct pre-ES6 way for getting `new.target`, so use this\n isCallable(NewTarget = dummy.constructor) &&\n NewTarget !== Wrapper &&\n isObject(NewTargetPrototype = NewTarget.prototype) &&\n NewTargetPrototype !== Wrapper.prototype\n ) setPrototypeOf($this, NewTargetPrototype);\n return $this;\n};\n","'use strict';\nvar toString = require('../internals/to-string');\n\nmodule.exports = function (argument, $default) {\n return argument === undefined ? arguments.length < 2 ? '' : $default : toString(argument);\n};\n","'use strict';\nvar isObject = require('../internals/is-object');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\n\n// `InstallErrorCause` abstract operation\n// https://tc39.es/proposal-error-cause/#sec-errorobjects-install-error-cause\nmodule.exports = function (O, options) {\n if (isObject(options) && 'cause' in options) {\n createNonEnumerableProperty(O, 'cause', options.cause);\n }\n};\n","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\n\nvar $Error = Error;\nvar replace = uncurryThis(''.replace);\n\nvar TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');\n// eslint-disable-next-line redos/no-vulnerable -- safe\nvar V8_OR_CHAKRA_STACK_ENTRY = /\\n\\s*at [^:]*:[^\\n]*/;\nvar IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);\n\nmodule.exports = function (stack, dropEntries) {\n if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {\n while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');\n } return stack;\n};\n","'use strict';\nvar fails = require('../internals/fails');\nvar createPropertyDescriptor = require('../internals/create-property-descriptor');\n\nmodule.exports = !fails(function () {\n var error = new Error('a');\n if (!('stack' in error)) return true;\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty(error, 'stack', createPropertyDescriptor(1, 7));\n return error.stack !== 7;\n});\n","'use strict';\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar clearErrorStack = require('../internals/error-stack-clear');\nvar ERROR_STACK_INSTALLABLE = require('../internals/error-stack-installable');\n\n// non-standard V8\nvar captureStackTrace = Error.captureStackTrace;\n\nmodule.exports = function (error, C, stack, dropEntries) {\n if (ERROR_STACK_INSTALLABLE) {\n if (captureStackTrace) captureStackTrace(error, C);\n else createNonEnumerableProperty(error, 'stack', clearErrorStack(stack, dropEntries));\n }\n};\n","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\nvar hasOwn = require('../internals/has-own-property');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar isPrototypeOf = require('../internals/object-is-prototype-of');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\nvar copyConstructorProperties = require('../internals/copy-constructor-properties');\nvar proxyAccessor = require('../internals/proxy-accessor');\nvar inheritIfRequired = require('../internals/inherit-if-required');\nvar normalizeStringArgument = require('../internals/normalize-string-argument');\nvar installErrorCause = require('../internals/install-error-cause');\nvar installErrorStack = require('../internals/error-stack-install');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar IS_PURE = require('../internals/is-pure');\n\nmodule.exports = function (FULL_NAME, wrapper, FORCED, IS_AGGREGATE_ERROR) {\n var STACK_TRACE_LIMIT = 'stackTraceLimit';\n var OPTIONS_POSITION = IS_AGGREGATE_ERROR ? 2 : 1;\n var path = FULL_NAME.split('.');\n var ERROR_NAME = path[path.length - 1];\n var OriginalError = getBuiltIn.apply(null, path);\n\n if (!OriginalError) return;\n\n var OriginalErrorPrototype = OriginalError.prototype;\n\n // V8 9.3- bug https://bugs.chromium.org/p/v8/issues/detail?id=12006\n if (!IS_PURE && hasOwn(OriginalErrorPrototype, 'cause')) delete OriginalErrorPrototype.cause;\n\n if (!FORCED) return OriginalError;\n\n var BaseError = getBuiltIn('Error');\n\n var WrappedError = wrapper(function (a, b) {\n var message = normalizeStringArgument(IS_AGGREGATE_ERROR ? b : a, undefined);\n var result = IS_AGGREGATE_ERROR ? new OriginalError(a) : new OriginalError();\n if (message !== undefined) createNonEnumerableProperty(result, 'message', message);\n installErrorStack(result, WrappedError, result.stack, 2);\n if (this && isPrototypeOf(OriginalErrorPrototype, this)) inheritIfRequired(result, this, WrappedError);\n if (arguments.length > OPTIONS_POSITION) installErrorCause(result, arguments[OPTIONS_POSITION]);\n return result;\n });\n\n WrappedError.prototype = OriginalErrorPrototype;\n\n if (ERROR_NAME !== 'Error') {\n if (setPrototypeOf) setPrototypeOf(WrappedError, BaseError);\n else copyConstructorProperties(WrappedError, BaseError, { name: true });\n } else if (DESCRIPTORS && STACK_TRACE_LIMIT in OriginalError) {\n proxyAccessor(WrappedError, OriginalError, STACK_TRACE_LIMIT);\n proxyAccessor(WrappedError, OriginalError, 'prepareStackTrace');\n }\n\n copyConstructorProperties(WrappedError, OriginalError);\n\n if (!IS_PURE) try {\n // Safari 13- bug: WebAssembly errors does not have a proper `.name`\n if (OriginalErrorPrototype.name !== ERROR_NAME) {\n createNonEnumerableProperty(OriginalErrorPrototype, 'name', ERROR_NAME);\n }\n OriginalErrorPrototype.constructor = WrappedError;\n } catch (error) { /* empty */ }\n\n return WrappedError;\n};\n","'use strict';\n/* eslint-disable no-unused-vars -- required for functions `.length` */\nvar $ = require('../internals/export');\nvar globalThis = require('../internals/global-this');\nvar apply = require('../internals/function-apply');\nvar wrapErrorConstructorWithCause = require('../internals/wrap-error-constructor-with-cause');\n\nvar WEB_ASSEMBLY = 'WebAssembly';\nvar WebAssembly = globalThis[WEB_ASSEMBLY];\n\n// eslint-disable-next-line es/no-error-cause -- feature detection\nvar FORCED = new Error('e', { cause: 7 }).cause !== 7;\n\nvar exportGlobalErrorCauseWrapper = function (ERROR_NAME, wrapper) {\n var O = {};\n O[ERROR_NAME] = wrapErrorConstructorWithCause(ERROR_NAME, wrapper, FORCED);\n $({ global: true, constructor: true, arity: 1, forced: FORCED }, O);\n};\n\nvar exportWebAssemblyErrorCauseWrapper = function (ERROR_NAME, wrapper) {\n if (WebAssembly && WebAssembly[ERROR_NAME]) {\n var O = {};\n O[ERROR_NAME] = wrapErrorConstructorWithCause(WEB_ASSEMBLY + '.' + ERROR_NAME, wrapper, FORCED);\n $({ target: WEB_ASSEMBLY, stat: true, constructor: true, arity: 1, forced: FORCED }, O);\n }\n};\n\n// https://tc39.es/ecma262/#sec-nativeerror\nexportGlobalErrorCauseWrapper('Error', function (init) {\n return function Error(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('EvalError', function (init) {\n return function EvalError(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('RangeError', function (init) {\n return function RangeError(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('ReferenceError', function (init) {\n return function ReferenceError(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('SyntaxError', function (init) {\n return function SyntaxError(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('TypeError', function (init) {\n return function TypeError(message) { return apply(init, this, arguments); };\n});\nexportGlobalErrorCauseWrapper('URIError', function (init) {\n return function URIError(message) { return apply(init, this, arguments); };\n});\nexportWebAssemblyErrorCauseWrapper('CompileError', function (init) {\n return function CompileError(message) { return apply(init, this, arguments); };\n});\nexportWebAssemblyErrorCauseWrapper('LinkError', function (init) {\n return function LinkError(message) { return apply(init, this, arguments); };\n});\nexportWebAssemblyErrorCauseWrapper('RuntimeError', function (init) {\n return function RuntimeError(message) { return apply(init, this, arguments); };\n});\n","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar isArray = require('../internals/is-array');\n\nvar $TypeError = TypeError;\n// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n// Safari < 13 does not throw an error in this case\nvar SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {\n // makes no sense without proper strict mode support\n if (this !== undefined) return true;\n try {\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty([], 'length', { writable: false }).length = 1;\n } catch (error) {\n return error instanceof TypeError;\n }\n}();\n\nmodule.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {\n if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {\n throw new $TypeError('Cannot set read only .length');\n } return O.length = length;\n} : function (O, length) {\n return O.length = length;\n};\n","'use strict';\nvar $TypeError = TypeError;\nvar MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991\n\nmodule.exports = function (it) {\n if (it > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed index exceeded');\n return it;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar toObject = require('../internals/to-object');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar setArrayLength = require('../internals/array-set-length');\nvar doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer');\nvar fails = require('../internals/fails');\n\nvar INCORRECT_TO_LENGTH = fails(function () {\n return [].push.call({ length: 0x100000000 }, 1) !== 4294967297;\n});\n\n// V8 <= 121 and Safari <= 15.4; FF < 23 throws InternalError\n// https://bugs.chromium.org/p/v8/issues/detail?id=12681\nvar properErrorOnNonWritableLength = function () {\n try {\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty([], 'length', { writable: false }).push();\n } catch (error) {\n return error instanceof TypeError;\n }\n};\n\nvar FORCED = INCORRECT_TO_LENGTH || !properErrorOnNonWritableLength();\n\n// `Array.prototype.push` method\n// https://tc39.es/ecma262/#sec-array.prototype.push\n$({ target: 'Array', proto: true, arity: 1, forced: FORCED }, {\n // eslint-disable-next-line no-unused-vars -- required for `.length`\n push: function push(item) {\n var O = toObject(this);\n var len = lengthOfArrayLike(O);\n var argCount = arguments.length;\n doesNotExceedSafeInteger(len + argCount);\n for (var i = 0; i < argCount; i++) {\n O[len] = arguments[i];\n len++;\n }\n setArrayLength(O, len);\n return len;\n }\n});\n","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\n\n// eslint-disable-next-line es/no-set -- safe\nvar SetPrototype = Set.prototype;\n\nmodule.exports = {\n // eslint-disable-next-line es/no-set -- safe\n Set: Set,\n add: uncurryThis(SetPrototype.add),\n has: uncurryThis(SetPrototype.has),\n remove: uncurryThis(SetPrototype['delete']),\n proto: SetPrototype\n};\n","'use strict';\nvar has = require('../internals/set-helpers').has;\n\n// Perform ? RequireInternalSlot(M, [[SetData]])\nmodule.exports = function (it) {\n has(it);\n return it;\n};\n","'use strict';\nvar call = require('../internals/function-call');\n\nmodule.exports = function (record, fn, ITERATOR_INSTEAD_OF_RECORD) {\n var iterator = ITERATOR_INSTEAD_OF_RECORD ? record : record.iterator;\n var next = record.next;\n var step, result;\n while (!(step = call(next, iterator)).done) {\n result = fn(step.value);\n if (result !== undefined) return result;\n }\n};\n","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar iterateSimple = require('../internals/iterate-simple');\nvar SetHelpers = require('../internals/set-helpers');\n\nvar Set = SetHelpers.Set;\nvar SetPrototype = SetHelpers.proto;\nvar forEach = uncurryThis(SetPrototype.forEach);\nvar keys = uncurryThis(SetPrototype.keys);\nvar next = keys(new Set()).next;\n\nmodule.exports = function (set, fn, interruptible) {\n return interruptible ? iterateSimple({ iterator: keys(set), next: next }, fn) : forEach(set, fn);\n};\n","'use strict';\nvar SetHelpers = require('../internals/set-helpers');\nvar iterate = require('../internals/set-iterate');\n\nvar Set = SetHelpers.Set;\nvar add = SetHelpers.add;\n\nmodule.exports = function (set) {\n var result = new Set();\n iterate(set, function (it) {\n add(result, it);\n });\n return result;\n};\n","'use strict';\nvar uncurryThisAccessor = require('../internals/function-uncurry-this-accessor');\nvar SetHelpers = require('../internals/set-helpers');\n\nmodule.exports = uncurryThisAccessor(SetHelpers.proto, 'size', 'get') || function (set) {\n return set.size;\n};\n","'use strict';\n// `GetIteratorDirect(obj)` abstract operation\n// https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect\nmodule.exports = function (obj) {\n return {\n iterator: obj,\n next: obj.next,\n done: false\n };\n};\n","'use strict';\nvar aCallable = require('../internals/a-callable');\nvar anObject = require('../internals/an-object');\nvar call = require('../internals/function-call');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar getIteratorDirect = require('../internals/get-iterator-direct');\n\nvar INVALID_SIZE = 'Invalid size';\nvar $RangeError = RangeError;\nvar $TypeError = TypeError;\nvar max = Math.max;\n\nvar SetRecord = function (set, intSize) {\n this.set = set;\n this.size = max(intSize, 0);\n this.has = aCallable(set.has);\n this.keys = aCallable(set.keys);\n};\n\nSetRecord.prototype = {\n getIterator: function () {\n return getIteratorDirect(anObject(call(this.keys, this.set)));\n },\n includes: function (it) {\n return call(this.has, this.set, it);\n }\n};\n\n// `GetSetRecord` abstract operation\n// https://tc39.es/proposal-set-methods/#sec-getsetrecord\nmodule.exports = function (obj) {\n anObject(obj);\n var numSize = +obj.size;\n // NOTE: If size is undefined, then numSize will be NaN\n // eslint-disable-next-line no-self-compare -- NaN check\n if (numSize !== numSize) throw new $TypeError(INVALID_SIZE);\n var intSize = toIntegerOrInfinity(numSize);\n if (intSize < 0) throw new $RangeError(INVALID_SIZE);\n return new SetRecord(obj, intSize);\n};\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar SetHelpers = require('../internals/set-helpers');\nvar clone = require('../internals/set-clone');\nvar size = require('../internals/set-size');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSet = require('../internals/set-iterate');\nvar iterateSimple = require('../internals/iterate-simple');\n\nvar has = SetHelpers.has;\nvar remove = SetHelpers.remove;\n\n// `Set.prototype.difference` method\n// https://github.com/tc39/proposal-set-methods\nmodule.exports = function difference(other) {\n var O = aSet(this);\n var otherRec = getSetRecord(other);\n var result = clone(O);\n if (size(O) <= otherRec.size) iterateSet(O, function (e) {\n if (otherRec.includes(e)) remove(result, e);\n });\n else iterateSimple(otherRec.getIterator(), function (e) {\n if (has(O, e)) remove(result, e);\n });\n return result;\n};\n","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\n\nvar createSetLike = function (size) {\n return {\n size: size,\n has: function () {\n return false;\n },\n keys: function () {\n return {\n next: function () {\n return { done: true };\n }\n };\n }\n };\n};\n\nmodule.exports = function (name) {\n var Set = getBuiltIn('Set');\n try {\n new Set()[name](createSetLike(0));\n try {\n // late spec change, early WebKit ~ Safari 17.0 beta implementation does not pass it\n // https://github.com/tc39/proposal-set-methods/pull/88\n new Set()[name](createSetLike(-1));\n return false;\n } catch (error2) {\n return true;\n }\n } catch (error) {\n return false;\n }\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar difference = require('../internals/set-difference');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.difference` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('difference') }, {\n difference: difference\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.difference.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar SetHelpers = require('../internals/set-helpers');\nvar size = require('../internals/set-size');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSet = require('../internals/set-iterate');\nvar iterateSimple = require('../internals/iterate-simple');\n\nvar Set = SetHelpers.Set;\nvar add = SetHelpers.add;\nvar has = SetHelpers.has;\n\n// `Set.prototype.intersection` method\n// https://github.com/tc39/proposal-set-methods\nmodule.exports = function intersection(other) {\n var O = aSet(this);\n var otherRec = getSetRecord(other);\n var result = new Set();\n\n if (size(O) > otherRec.size) {\n iterateSimple(otherRec.getIterator(), function (e) {\n if (has(O, e)) add(result, e);\n });\n } else {\n iterateSet(O, function (e) {\n if (otherRec.includes(e)) add(result, e);\n });\n }\n\n return result;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar fails = require('../internals/fails');\nvar intersection = require('../internals/set-intersection');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\nvar INCORRECT = !setMethodAcceptSetLike('intersection') || fails(function () {\n // eslint-disable-next-line es/no-array-from, es/no-set -- testing\n return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) !== '3,2';\n});\n\n// `Set.prototype.intersection` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {\n intersection: intersection\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.intersection.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar has = require('../internals/set-helpers').has;\nvar size = require('../internals/set-size');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSet = require('../internals/set-iterate');\nvar iterateSimple = require('../internals/iterate-simple');\nvar iteratorClose = require('../internals/iterator-close');\n\n// `Set.prototype.isDisjointFrom` method\n// https://tc39.github.io/proposal-set-methods/#Set.prototype.isDisjointFrom\nmodule.exports = function isDisjointFrom(other) {\n var O = aSet(this);\n var otherRec = getSetRecord(other);\n if (size(O) <= otherRec.size) return iterateSet(O, function (e) {\n if (otherRec.includes(e)) return false;\n }, true) !== false;\n var iterator = otherRec.getIterator();\n return iterateSimple(iterator, function (e) {\n if (has(O, e)) return iteratorClose(iterator, 'normal', false);\n }) !== false;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar isDisjointFrom = require('../internals/set-is-disjoint-from');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.isDisjointFrom` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isDisjointFrom') }, {\n isDisjointFrom: isDisjointFrom\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.is-disjoint-from.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar size = require('../internals/set-size');\nvar iterate = require('../internals/set-iterate');\nvar getSetRecord = require('../internals/get-set-record');\n\n// `Set.prototype.isSubsetOf` method\n// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSubsetOf\nmodule.exports = function isSubsetOf(other) {\n var O = aSet(this);\n var otherRec = getSetRecord(other);\n if (size(O) > otherRec.size) return false;\n return iterate(O, function (e) {\n if (!otherRec.includes(e)) return false;\n }, true) !== false;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar isSubsetOf = require('../internals/set-is-subset-of');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.isSubsetOf` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSubsetOf') }, {\n isSubsetOf: isSubsetOf\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.is-subset-of.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar has = require('../internals/set-helpers').has;\nvar size = require('../internals/set-size');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSimple = require('../internals/iterate-simple');\nvar iteratorClose = require('../internals/iterator-close');\n\n// `Set.prototype.isSupersetOf` method\n// https://tc39.github.io/proposal-set-methods/#Set.prototype.isSupersetOf\nmodule.exports = function isSupersetOf(other) {\n var O = aSet(this);\n var otherRec = getSetRecord(other);\n if (size(O) < otherRec.size) return false;\n var iterator = otherRec.getIterator();\n return iterateSimple(iterator, function (e) {\n if (!has(O, e)) return iteratorClose(iterator, 'normal', false);\n }) !== false;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar isSupersetOf = require('../internals/set-is-superset-of');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.isSupersetOf` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSupersetOf') }, {\n isSupersetOf: isSupersetOf\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.is-superset-of.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar SetHelpers = require('../internals/set-helpers');\nvar clone = require('../internals/set-clone');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSimple = require('../internals/iterate-simple');\n\nvar add = SetHelpers.add;\nvar has = SetHelpers.has;\nvar remove = SetHelpers.remove;\n\n// `Set.prototype.symmetricDifference` method\n// https://github.com/tc39/proposal-set-methods\nmodule.exports = function symmetricDifference(other) {\n var O = aSet(this);\n var keysIter = getSetRecord(other).getIterator();\n var result = clone(O);\n iterateSimple(keysIter, function (e) {\n if (has(O, e)) remove(result, e);\n else add(result, e);\n });\n return result;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar symmetricDifference = require('../internals/set-symmetric-difference');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.symmetricDifference` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('symmetricDifference') }, {\n symmetricDifference: symmetricDifference\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.symmetric-difference.v2');\n","'use strict';\nvar aSet = require('../internals/a-set');\nvar add = require('../internals/set-helpers').add;\nvar clone = require('../internals/set-clone');\nvar getSetRecord = require('../internals/get-set-record');\nvar iterateSimple = require('../internals/iterate-simple');\n\n// `Set.prototype.union` method\n// https://github.com/tc39/proposal-set-methods\nmodule.exports = function union(other) {\n var O = aSet(this);\n var keysIter = getSetRecord(other).getIterator();\n var result = clone(O);\n iterateSimple(keysIter, function (it) {\n add(result, it);\n });\n return result;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar union = require('../internals/set-union');\nvar setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');\n\n// `Set.prototype.union` method\n// https://github.com/tc39/proposal-set-methods\n$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('union') }, {\n union: union\n});\n","'use strict';\n// TODO: Remove from `core-js@4`\nrequire('../modules/es.set.union.v2');\n","'use strict';\nvar $ = require('../internals/export');\nvar globalThis = require('../internals/global-this');\nvar clearImmediate = require('../internals/task').clear;\n\n// `clearImmediate` method\n// http://w3c.github.io/setImmediate/#si-clearImmediate\n$({ global: true, bind: true, enumerable: true, forced: globalThis.clearImmediate !== clearImmediate }, {\n clearImmediate: clearImmediate\n});\n","'use strict';\nvar globalThis = require('../internals/global-this');\nvar apply = require('../internals/function-apply');\nvar isCallable = require('../internals/is-callable');\nvar ENVIRONMENT = require('../internals/environment');\nvar USER_AGENT = require('../internals/environment-user-agent');\nvar arraySlice = require('../internals/array-slice');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\n\nvar Function = globalThis.Function;\n// dirty IE9- and Bun 0.3.0- checks\nvar WRAP = /MSIE .\\./.test(USER_AGENT) || ENVIRONMENT === 'BUN' && (function () {\n var version = globalThis.Bun.version.split('.');\n return version.length < 3 || version[0] === '0' && (version[1] < 3 || version[1] === '3' && version[2] === '0');\n})();\n\n// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix\n// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers\n// https://github.com/oven-sh/bun/issues/1633\nmodule.exports = function (scheduler, hasTimeArg) {\n var firstParamIndex = hasTimeArg ? 2 : 1;\n return WRAP ? function (handler, timeout /* , ...arguments */) {\n var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;\n var fn = isCallable(handler) ? handler : Function(handler);\n var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];\n var callback = boundArgs ? function () {\n apply(fn, this, params);\n } : fn;\n return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);\n } : scheduler;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar globalThis = require('../internals/global-this');\nvar setTask = require('../internals/task').set;\nvar schedulersFix = require('../internals/schedulers-fix');\n\n// https://github.com/oven-sh/bun/issues/1633\nvar setImmediate = globalThis.setImmediate ? schedulersFix(setTask, false) : setTask;\n\n// `setImmediate` method\n// http://w3c.github.io/setImmediate/#si-setImmediate\n$({ global: true, bind: true, enumerable: true, forced: globalThis.setImmediate !== setImmediate }, {\n setImmediate: setImmediate\n});\n","'use strict';\n// TODO: Remove this module from `core-js@4` since it's split to modules listed below\nrequire('../modules/web.clear-immediate');\nrequire('../modules/web.set-immediate');\n","//! moment.js\n//! version : 2.30.1\n//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n//! license : MIT\n//! momentjs.com\n\n;(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n global.moment = factory()\n}(this, (function () { 'use strict';\n\n var hookCallback;\n\n function hooks() {\n return hookCallback.apply(null, arguments);\n }\n\n // This is done to register the method called with moment()\n // without creating circular dependencies.\n function setHookCallback(callback) {\n hookCallback = callback;\n }\n\n function isArray(input) {\n return (\n input instanceof Array ||\n Object.prototype.toString.call(input) === '[object Array]'\n );\n }\n\n function isObject(input) {\n // IE8 will treat undefined and null as object if it wasn't for\n // input != null\n return (\n input != null &&\n Object.prototype.toString.call(input) === '[object Object]'\n );\n }\n\n function hasOwnProp(a, b) {\n return Object.prototype.hasOwnProperty.call(a, b);\n }\n\n function isObjectEmpty(obj) {\n if (Object.getOwnPropertyNames) {\n return Object.getOwnPropertyNames(obj).length === 0;\n } else {\n var k;\n for (k in obj) {\n if (hasOwnProp(obj, k)) {\n return false;\n }\n }\n return true;\n }\n }\n\n function isUndefined(input) {\n return input === void 0;\n }\n\n function isNumber(input) {\n return (\n typeof input === 'number' ||\n Object.prototype.toString.call(input) === '[object Number]'\n );\n }\n\n function isDate(input) {\n return (\n input instanceof Date ||\n Object.prototype.toString.call(input) === '[object Date]'\n );\n }\n\n function map(arr, fn) {\n var res = [],\n i,\n arrLen = arr.length;\n for (i = 0; i < arrLen; ++i) {\n res.push(fn(arr[i], i));\n }\n return res;\n }\n\n function extend(a, b) {\n for (var i in b) {\n if (hasOwnProp(b, i)) {\n a[i] = b[i];\n }\n }\n\n if (hasOwnProp(b, 'toString')) {\n a.toString = b.toString;\n }\n\n if (hasOwnProp(b, 'valueOf')) {\n a.valueOf = b.valueOf;\n }\n\n return a;\n }\n\n function createUTC(input, format, locale, strict) {\n return createLocalOrUTC(input, format, locale, strict, true).utc();\n }\n\n function defaultParsingFlags() {\n // We need to deep clone this object.\n return {\n empty: false,\n unusedTokens: [],\n unusedInput: [],\n overflow: -2,\n charsLeftOver: 0,\n nullInput: false,\n invalidEra: null,\n invalidMonth: null,\n invalidFormat: false,\n userInvalidated: false,\n iso: false,\n parsedDateParts: [],\n era: null,\n meridiem: null,\n rfc2822: false,\n weekdayMismatch: false,\n };\n }\n\n function getParsingFlags(m) {\n if (m._pf == null) {\n m._pf = defaultParsingFlags();\n }\n return m._pf;\n }\n\n var some;\n if (Array.prototype.some) {\n some = Array.prototype.some;\n } else {\n some = function (fun) {\n var t = Object(this),\n len = t.length >>> 0,\n i;\n\n for (i = 0; i < len; i++) {\n if (i in t && fun.call(this, t[i], i, t)) {\n return true;\n }\n }\n\n return false;\n };\n }\n\n function isValid(m) {\n var flags = null,\n parsedParts = false,\n isNowValid = m._d && !isNaN(m._d.getTime());\n if (isNowValid) {\n flags = getParsingFlags(m);\n parsedParts = some.call(flags.parsedDateParts, function (i) {\n return i != null;\n });\n isNowValid =\n flags.overflow < 0 &&\n !flags.empty &&\n !flags.invalidEra &&\n !flags.invalidMonth &&\n !flags.invalidWeekday &&\n !flags.weekdayMismatch &&\n !flags.nullInput &&\n !flags.invalidFormat &&\n !flags.userInvalidated &&\n (!flags.meridiem || (flags.meridiem && parsedParts));\n if (m._strict) {\n isNowValid =\n isNowValid &&\n flags.charsLeftOver === 0 &&\n flags.unusedTokens.length === 0 &&\n flags.bigHour === undefined;\n }\n }\n if (Object.isFrozen == null || !Object.isFrozen(m)) {\n m._isValid = isNowValid;\n } else {\n return isNowValid;\n }\n return m._isValid;\n }\n\n function createInvalid(flags) {\n var m = createUTC(NaN);\n if (flags != null) {\n extend(getParsingFlags(m), flags);\n } else {\n getParsingFlags(m).userInvalidated = true;\n }\n\n return m;\n }\n\n // Plugins that add properties should also add the key here (null value),\n // so we can properly clone ourselves.\n var momentProperties = (hooks.momentProperties = []),\n updateInProgress = false;\n\n function copyConfig(to, from) {\n var i,\n prop,\n val,\n momentPropertiesLen = momentProperties.length;\n\n if (!isUndefined(from._isAMomentObject)) {\n to._isAMomentObject = from._isAMomentObject;\n }\n if (!isUndefined(from._i)) {\n to._i = from._i;\n }\n if (!isUndefined(from._f)) {\n to._f = from._f;\n }\n if (!isUndefined(from._l)) {\n to._l = from._l;\n }\n if (!isUndefined(from._strict)) {\n to._strict = from._strict;\n }\n if (!isUndefined(from._tzm)) {\n to._tzm = from._tzm;\n }\n if (!isUndefined(from._isUTC)) {\n to._isUTC = from._isUTC;\n }\n if (!isUndefined(from._offset)) {\n to._offset = from._offset;\n }\n if (!isUndefined(from._pf)) {\n to._pf = getParsingFlags(from);\n }\n if (!isUndefined(from._locale)) {\n to._locale = from._locale;\n }\n\n if (momentPropertiesLen > 0) {\n for (i = 0; i < momentPropertiesLen; i++) {\n prop = momentProperties[i];\n val = from[prop];\n if (!isUndefined(val)) {\n to[prop] = val;\n }\n }\n }\n\n return to;\n }\n\n // Moment prototype object\n function Moment(config) {\n copyConfig(this, config);\n this._d = new Date(config._d != null ? config._d.getTime() : NaN);\n if (!this.isValid()) {\n this._d = new Date(NaN);\n }\n // Prevent infinite loop in case updateOffset creates new moment\n // objects.\n if (updateInProgress === false) {\n updateInProgress = true;\n hooks.updateOffset(this);\n updateInProgress = false;\n }\n }\n\n function isMoment(obj) {\n return (\n obj instanceof Moment || (obj != null && obj._isAMomentObject != null)\n );\n }\n\n function warn(msg) {\n if (\n hooks.suppressDeprecationWarnings === false &&\n typeof console !== 'undefined' &&\n console.warn\n ) {\n console.warn('Deprecation warning: ' + msg);\n }\n }\n\n function deprecate(msg, fn) {\n var firstTime = true;\n\n return extend(function () {\n if (hooks.deprecationHandler != null) {\n hooks.deprecationHandler(null, msg);\n }\n if (firstTime) {\n var args = [],\n arg,\n i,\n key,\n argLen = arguments.length;\n for (i = 0; i < argLen; i++) {\n arg = '';\n if (typeof arguments[i] === 'object') {\n arg += '\\n[' + i + '] ';\n for (key in arguments[0]) {\n if (hasOwnProp(arguments[0], key)) {\n arg += key + ': ' + arguments[0][key] + ', ';\n }\n }\n arg = arg.slice(0, -2); // Remove trailing comma and space\n } else {\n arg = arguments[i];\n }\n args.push(arg);\n }\n warn(\n msg +\n '\\nArguments: ' +\n Array.prototype.slice.call(args).join('') +\n '\\n' +\n new Error().stack\n );\n firstTime = false;\n }\n return fn.apply(this, arguments);\n }, fn);\n }\n\n var deprecations = {};\n\n function deprecateSimple(name, msg) {\n if (hooks.deprecationHandler != null) {\n hooks.deprecationHandler(name, msg);\n }\n if (!deprecations[name]) {\n warn(msg);\n deprecations[name] = true;\n }\n }\n\n hooks.suppressDeprecationWarnings = false;\n hooks.deprecationHandler = null;\n\n function isFunction(input) {\n return (\n (typeof Function !== 'undefined' && input instanceof Function) ||\n Object.prototype.toString.call(input) === '[object Function]'\n );\n }\n\n function set(config) {\n var prop, i;\n for (i in config) {\n if (hasOwnProp(config, i)) {\n prop = config[i];\n if (isFunction(prop)) {\n this[i] = prop;\n } else {\n this['_' + i] = prop;\n }\n }\n }\n this._config = config;\n // Lenient ordinal parsing accepts just a number in addition to\n // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.\n // TODO: Remove \"ordinalParse\" fallback in next major release.\n this._dayOfMonthOrdinalParseLenient = new RegExp(\n (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +\n '|' +\n /\\d{1,2}/.source\n );\n }\n\n function mergeConfigs(parentConfig, childConfig) {\n var res = extend({}, parentConfig),\n prop;\n for (prop in childConfig) {\n if (hasOwnProp(childConfig, prop)) {\n if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {\n res[prop] = {};\n extend(res[prop], parentConfig[prop]);\n extend(res[prop], childConfig[prop]);\n } else if (childConfig[prop] != null) {\n res[prop] = childConfig[prop];\n } else {\n delete res[prop];\n }\n }\n }\n for (prop in parentConfig) {\n if (\n hasOwnProp(parentConfig, prop) &&\n !hasOwnProp(childConfig, prop) &&\n isObject(parentConfig[prop])\n ) {\n // make sure changes to properties don't modify parent config\n res[prop] = extend({}, res[prop]);\n }\n }\n return res;\n }\n\n function Locale(config) {\n if (config != null) {\n this.set(config);\n }\n }\n\n var keys;\n\n if (Object.keys) {\n keys = Object.keys;\n } else {\n keys = function (obj) {\n var i,\n res = [];\n for (i in obj) {\n if (hasOwnProp(obj, i)) {\n res.push(i);\n }\n }\n return res;\n };\n }\n\n var defaultCalendar = {\n sameDay: '[Today at] LT',\n nextDay: '[Tomorrow at] LT',\n nextWeek: 'dddd [at] LT',\n lastDay: '[Yesterday at] LT',\n lastWeek: '[Last] dddd [at] LT',\n sameElse: 'L',\n };\n\n function calendar(key, mom, now) {\n var output = this._calendar[key] || this._calendar['sameElse'];\n return isFunction(output) ? output.call(mom, now) : output;\n }\n\n function zeroFill(number, targetLength, forceSign) {\n var absNumber = '' + Math.abs(number),\n zerosToFill = targetLength - absNumber.length,\n sign = number >= 0;\n return (\n (sign ? (forceSign ? '+' : '') : '-') +\n Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) +\n absNumber\n );\n }\n\n var formattingTokens =\n /(\\[[^\\[]*\\])|(\\\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,\n localFormattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g,\n formatFunctions = {},\n formatTokenFunctions = {};\n\n // token: 'M'\n // padded: ['MM', 2]\n // ordinal: 'Mo'\n // callback: function () { this.month() + 1 }\n function addFormatToken(token, padded, ordinal, callback) {\n var func = callback;\n if (typeof callback === 'string') {\n func = function () {\n return this[callback]();\n };\n }\n if (token) {\n formatTokenFunctions[token] = func;\n }\n if (padded) {\n formatTokenFunctions[padded[0]] = function () {\n return zeroFill(func.apply(this, arguments), padded[1], padded[2]);\n };\n }\n if (ordinal) {\n formatTokenFunctions[ordinal] = function () {\n return this.localeData().ordinal(\n func.apply(this, arguments),\n token\n );\n };\n }\n }\n\n function removeFormattingTokens(input) {\n if (input.match(/\\[[\\s\\S]/)) {\n return input.replace(/^\\[|\\]$/g, '');\n }\n return input.replace(/\\\\/g, '');\n }\n\n function makeFormatFunction(format) {\n var array = format.match(formattingTokens),\n i,\n length;\n\n for (i = 0, length = array.length; i < length; i++) {\n if (formatTokenFunctions[array[i]]) {\n array[i] = formatTokenFunctions[array[i]];\n } else {\n array[i] = removeFormattingTokens(array[i]);\n }\n }\n\n return function (mom) {\n var output = '',\n i;\n for (i = 0; i < length; i++) {\n output += isFunction(array[i])\n ? array[i].call(mom, format)\n : array[i];\n }\n return output;\n };\n }\n\n // format date using native date object\n function formatMoment(m, format) {\n if (!m.isValid()) {\n return m.localeData().invalidDate();\n }\n\n format = expandFormat(format, m.localeData());\n formatFunctions[format] =\n formatFunctions[format] || makeFormatFunction(format);\n\n return formatFunctions[format](m);\n }\n\n function expandFormat(format, locale) {\n var i = 5;\n\n function replaceLongDateFormatTokens(input) {\n return locale.longDateFormat(input) || input;\n }\n\n localFormattingTokens.lastIndex = 0;\n while (i >= 0 && localFormattingTokens.test(format)) {\n format = format.replace(\n localFormattingTokens,\n replaceLongDateFormatTokens\n );\n localFormattingTokens.lastIndex = 0;\n i -= 1;\n }\n\n return format;\n }\n\n var defaultLongDateFormat = {\n LTS: 'h:mm:ss A',\n LT: 'h:mm A',\n L: 'MM/DD/YYYY',\n LL: 'MMMM D, YYYY',\n LLL: 'MMMM D, YYYY h:mm A',\n LLLL: 'dddd, MMMM D, YYYY h:mm A',\n };\n\n function longDateFormat(key) {\n var format = this._longDateFormat[key],\n formatUpper = this._longDateFormat[key.toUpperCase()];\n\n if (format || !formatUpper) {\n return format;\n }\n\n this._longDateFormat[key] = formatUpper\n .match(formattingTokens)\n .map(function (tok) {\n if (\n tok === 'MMMM' ||\n tok === 'MM' ||\n tok === 'DD' ||\n tok === 'dddd'\n ) {\n return tok.slice(1);\n }\n return tok;\n })\n .join('');\n\n return this._longDateFormat[key];\n }\n\n var defaultInvalidDate = 'Invalid date';\n\n function invalidDate() {\n return this._invalidDate;\n }\n\n var defaultOrdinal = '%d',\n defaultDayOfMonthOrdinalParse = /\\d{1,2}/;\n\n function ordinal(number) {\n return this._ordinal.replace('%d', number);\n }\n\n var defaultRelativeTime = {\n future: 'in %s',\n past: '%s ago',\n s: 'a few seconds',\n ss: '%d seconds',\n m: 'a minute',\n mm: '%d minutes',\n h: 'an hour',\n hh: '%d hours',\n d: 'a day',\n dd: '%d days',\n w: 'a week',\n ww: '%d weeks',\n M: 'a month',\n MM: '%d months',\n y: 'a year',\n yy: '%d years',\n };\n\n function relativeTime(number, withoutSuffix, string, isFuture) {\n var output = this._relativeTime[string];\n return isFunction(output)\n ? output(number, withoutSuffix, string, isFuture)\n : output.replace(/%d/i, number);\n }\n\n function pastFuture(diff, output) {\n var format = this._relativeTime[diff > 0 ? 'future' : 'past'];\n return isFunction(format) ? format(output) : format.replace(/%s/i, output);\n }\n\n var aliases = {\n D: 'date',\n dates: 'date',\n date: 'date',\n d: 'day',\n days: 'day',\n day: 'day',\n e: 'weekday',\n weekdays: 'weekday',\n weekday: 'weekday',\n E: 'isoWeekday',\n isoweekdays: 'isoWeekday',\n isoweekday: 'isoWeekday',\n DDD: 'dayOfYear',\n dayofyears: 'dayOfYear',\n dayofyear: 'dayOfYear',\n h: 'hour',\n hours: 'hour',\n hour: 'hour',\n ms: 'millisecond',\n milliseconds: 'millisecond',\n millisecond: 'millisecond',\n m: 'minute',\n minutes: 'minute',\n minute: 'minute',\n M: 'month',\n months: 'month',\n month: 'month',\n Q: 'quarter',\n quarters: 'quarter',\n quarter: 'quarter',\n s: 'second',\n seconds: 'second',\n second: 'second',\n gg: 'weekYear',\n weekyears: 'weekYear',\n weekyear: 'weekYear',\n GG: 'isoWeekYear',\n isoweekyears: 'isoWeekYear',\n isoweekyear: 'isoWeekYear',\n w: 'week',\n weeks: 'week',\n week: 'week',\n W: 'isoWeek',\n isoweeks: 'isoWeek',\n isoweek: 'isoWeek',\n y: 'year',\n years: 'year',\n year: 'year',\n };\n\n function normalizeUnits(units) {\n return typeof units === 'string'\n ? aliases[units] || aliases[units.toLowerCase()]\n : undefined;\n }\n\n function normalizeObjectUnits(inputObject) {\n var normalizedInput = {},\n normalizedProp,\n prop;\n\n for (prop in inputObject) {\n if (hasOwnProp(inputObject, prop)) {\n normalizedProp = normalizeUnits(prop);\n if (normalizedProp) {\n normalizedInput[normalizedProp] = inputObject[prop];\n }\n }\n }\n\n return normalizedInput;\n }\n\n var priorities = {\n date: 9,\n day: 11,\n weekday: 11,\n isoWeekday: 11,\n dayOfYear: 4,\n hour: 13,\n millisecond: 16,\n minute: 14,\n month: 8,\n quarter: 7,\n second: 15,\n weekYear: 1,\n isoWeekYear: 1,\n week: 5,\n isoWeek: 5,\n year: 1,\n };\n\n function getPrioritizedUnits(unitsObj) {\n var units = [],\n u;\n for (u in unitsObj) {\n if (hasOwnProp(unitsObj, u)) {\n units.push({ unit: u, priority: priorities[u] });\n }\n }\n units.sort(function (a, b) {\n return a.priority - b.priority;\n });\n return units;\n }\n\n var match1 = /\\d/, // 0 - 9\n match2 = /\\d\\d/, // 00 - 99\n match3 = /\\d{3}/, // 000 - 999\n match4 = /\\d{4}/, // 0000 - 9999\n match6 = /[+-]?\\d{6}/, // -999999 - 999999\n match1to2 = /\\d\\d?/, // 0 - 99\n match3to4 = /\\d\\d\\d\\d?/, // 999 - 9999\n match5to6 = /\\d\\d\\d\\d\\d\\d?/, // 99999 - 999999\n match1to3 = /\\d{1,3}/, // 0 - 999\n match1to4 = /\\d{1,4}/, // 0 - 9999\n match1to6 = /[+-]?\\d{1,6}/, // -999999 - 999999\n matchUnsigned = /\\d+/, // 0 - inf\n matchSigned = /[+-]?\\d+/, // -inf - inf\n matchOffset = /Z|[+-]\\d\\d:?\\d\\d/gi, // +00:00 -00:00 +0000 -0000 or Z\n matchShortOffset = /Z|[+-]\\d\\d(?::?\\d\\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z\n matchTimestamp = /[+-]?\\d+(\\.\\d{1,3})?/, // 123456789 123456789.123\n // any word (or two) characters or numbers including two/three word month in arabic.\n // includes scottish gaelic two word and hyphenated months\n matchWord =\n /[0-9]{0,256}['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF07\\uFF10-\\uFFEF]{1,256}|[\\u0600-\\u06FF\\/]{1,256}(\\s*?[\\u0600-\\u06FF]{1,256}){1,2}/i,\n match1to2NoLeadingZero = /^[1-9]\\d?/, // 1-99\n match1to2HasZero = /^([1-9]\\d|\\d)/, // 0-99\n regexes;\n\n regexes = {};\n\n function addRegexToken(token, regex, strictRegex) {\n regexes[token] = isFunction(regex)\n ? regex\n : function (isStrict, localeData) {\n return isStrict && strictRegex ? strictRegex : regex;\n };\n }\n\n function getParseRegexForToken(token, config) {\n if (!hasOwnProp(regexes, token)) {\n return new RegExp(unescapeFormat(token));\n }\n\n return regexes[token](config._strict, config._locale);\n }\n\n // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript\n function unescapeFormat(s) {\n return regexEscape(\n s\n .replace('\\\\', '')\n .replace(\n /\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g,\n function (matched, p1, p2, p3, p4) {\n return p1 || p2 || p3 || p4;\n }\n )\n );\n }\n\n function regexEscape(s) {\n return s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n\n function absFloor(number) {\n if (number < 0) {\n // -0 -> 0\n return Math.ceil(number) || 0;\n } else {\n return Math.floor(number);\n }\n }\n\n function toInt(argumentForCoercion) {\n var coercedNumber = +argumentForCoercion,\n value = 0;\n\n if (coercedNumber !== 0 && isFinite(coercedNumber)) {\n value = absFloor(coercedNumber);\n }\n\n return value;\n }\n\n var tokens = {};\n\n function addParseToken(token, callback) {\n var i,\n func = callback,\n tokenLen;\n if (typeof token === 'string') {\n token = [token];\n }\n if (isNumber(callback)) {\n func = function (input, array) {\n array[callback] = toInt(input);\n };\n }\n tokenLen = token.length;\n for (i = 0; i < tokenLen; i++) {\n tokens[token[i]] = func;\n }\n }\n\n function addWeekParseToken(token, callback) {\n addParseToken(token, function (input, array, config, token) {\n config._w = config._w || {};\n callback(input, config._w, config, token);\n });\n }\n\n function addTimeToArrayFromToken(token, input, config) {\n if (input != null && hasOwnProp(tokens, token)) {\n tokens[token](input, config._a, config, token);\n }\n }\n\n function isLeapYear(year) {\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n }\n\n var YEAR = 0,\n MONTH = 1,\n DATE = 2,\n HOUR = 3,\n MINUTE = 4,\n SECOND = 5,\n MILLISECOND = 6,\n WEEK = 7,\n WEEKDAY = 8;\n\n // FORMATTING\n\n addFormatToken('Y', 0, 0, function () {\n var y = this.year();\n return y <= 9999 ? zeroFill(y, 4) : '+' + y;\n });\n\n addFormatToken(0, ['YY', 2], 0, function () {\n return this.year() % 100;\n });\n\n addFormatToken(0, ['YYYY', 4], 0, 'year');\n addFormatToken(0, ['YYYYY', 5], 0, 'year');\n addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');\n\n // PARSING\n\n addRegexToken('Y', matchSigned);\n addRegexToken('YY', match1to2, match2);\n addRegexToken('YYYY', match1to4, match4);\n addRegexToken('YYYYY', match1to6, match6);\n addRegexToken('YYYYYY', match1to6, match6);\n\n addParseToken(['YYYYY', 'YYYYYY'], YEAR);\n addParseToken('YYYY', function (input, array) {\n array[YEAR] =\n input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);\n });\n addParseToken('YY', function (input, array) {\n array[YEAR] = hooks.parseTwoDigitYear(input);\n });\n addParseToken('Y', function (input, array) {\n array[YEAR] = parseInt(input, 10);\n });\n\n // HELPERS\n\n function daysInYear(year) {\n return isLeapYear(year) ? 366 : 365;\n }\n\n // HOOKS\n\n hooks.parseTwoDigitYear = function (input) {\n return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);\n };\n\n // MOMENTS\n\n var getSetYear = makeGetSet('FullYear', true);\n\n function getIsLeapYear() {\n return isLeapYear(this.year());\n }\n\n function makeGetSet(unit, keepTime) {\n return function (value) {\n if (value != null) {\n set$1(this, unit, value);\n hooks.updateOffset(this, keepTime);\n return this;\n } else {\n return get(this, unit);\n }\n };\n }\n\n function get(mom, unit) {\n if (!mom.isValid()) {\n return NaN;\n }\n\n var d = mom._d,\n isUTC = mom._isUTC;\n\n switch (unit) {\n case 'Milliseconds':\n return isUTC ? d.getUTCMilliseconds() : d.getMilliseconds();\n case 'Seconds':\n return isUTC ? d.getUTCSeconds() : d.getSeconds();\n case 'Minutes':\n return isUTC ? d.getUTCMinutes() : d.getMinutes();\n case 'Hours':\n return isUTC ? d.getUTCHours() : d.getHours();\n case 'Date':\n return isUTC ? d.getUTCDate() : d.getDate();\n case 'Day':\n return isUTC ? d.getUTCDay() : d.getDay();\n case 'Month':\n return isUTC ? d.getUTCMonth() : d.getMonth();\n case 'FullYear':\n return isUTC ? d.getUTCFullYear() : d.getFullYear();\n default:\n return NaN; // Just in case\n }\n }\n\n function set$1(mom, unit, value) {\n var d, isUTC, year, month, date;\n\n if (!mom.isValid() || isNaN(value)) {\n return;\n }\n\n d = mom._d;\n isUTC = mom._isUTC;\n\n switch (unit) {\n case 'Milliseconds':\n return void (isUTC\n ? d.setUTCMilliseconds(value)\n : d.setMilliseconds(value));\n case 'Seconds':\n return void (isUTC ? d.setUTCSeconds(value) : d.setSeconds(value));\n case 'Minutes':\n return void (isUTC ? d.setUTCMinutes(value) : d.setMinutes(value));\n case 'Hours':\n return void (isUTC ? d.setUTCHours(value) : d.setHours(value));\n case 'Date':\n return void (isUTC ? d.setUTCDate(value) : d.setDate(value));\n // case 'Day': // Not real\n // return void (isUTC ? d.setUTCDay(value) : d.setDay(value));\n // case 'Month': // Not used because we need to pass two variables\n // return void (isUTC ? d.setUTCMonth(value) : d.setMonth(value));\n case 'FullYear':\n break; // See below ...\n default:\n return; // Just in case\n }\n\n year = value;\n month = mom.month();\n date = mom.date();\n date = date === 29 && month === 1 && !isLeapYear(year) ? 28 : date;\n void (isUTC\n ? d.setUTCFullYear(year, month, date)\n : d.setFullYear(year, month, date));\n }\n\n // MOMENTS\n\n function stringGet(units) {\n units = normalizeUnits(units);\n if (isFunction(this[units])) {\n return this[units]();\n }\n return this;\n }\n\n function stringSet(units, value) {\n if (typeof units === 'object') {\n units = normalizeObjectUnits(units);\n var prioritized = getPrioritizedUnits(units),\n i,\n prioritizedLen = prioritized.length;\n for (i = 0; i < prioritizedLen; i++) {\n this[prioritized[i].unit](units[prioritized[i].unit]);\n }\n } else {\n units = normalizeUnits(units);\n if (isFunction(this[units])) {\n return this[units](value);\n }\n }\n return this;\n }\n\n function mod(n, x) {\n return ((n % x) + x) % x;\n }\n\n var indexOf;\n\n if (Array.prototype.indexOf) {\n indexOf = Array.prototype.indexOf;\n } else {\n indexOf = function (o) {\n // I know\n var i;\n for (i = 0; i < this.length; ++i) {\n if (this[i] === o) {\n return i;\n }\n }\n return -1;\n };\n }\n\n function daysInMonth(year, month) {\n if (isNaN(year) || isNaN(month)) {\n return NaN;\n }\n var modMonth = mod(month, 12);\n year += (month - modMonth) / 12;\n return modMonth === 1\n ? isLeapYear(year)\n ? 29\n : 28\n : 31 - ((modMonth % 7) % 2);\n }\n\n // FORMATTING\n\n addFormatToken('M', ['MM', 2], 'Mo', function () {\n return this.month() + 1;\n });\n\n addFormatToken('MMM', 0, 0, function (format) {\n return this.localeData().monthsShort(this, format);\n });\n\n addFormatToken('MMMM', 0, 0, function (format) {\n return this.localeData().months(this, format);\n });\n\n // PARSING\n\n addRegexToken('M', match1to2, match1to2NoLeadingZero);\n addRegexToken('MM', match1to2, match2);\n addRegexToken('MMM', function (isStrict, locale) {\n return locale.monthsShortRegex(isStrict);\n });\n addRegexToken('MMMM', function (isStrict, locale) {\n return locale.monthsRegex(isStrict);\n });\n\n addParseToken(['M', 'MM'], function (input, array) {\n array[MONTH] = toInt(input) - 1;\n });\n\n addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {\n var month = config._locale.monthsParse(input, token, config._strict);\n // if we didn't find a month name, mark the date as invalid.\n if (month != null) {\n array[MONTH] = month;\n } else {\n getParsingFlags(config).invalidMonth = input;\n }\n });\n\n // LOCALES\n\n var defaultLocaleMonths =\n 'January_February_March_April_May_June_July_August_September_October_November_December'.split(\n '_'\n ),\n defaultLocaleMonthsShort =\n 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),\n MONTHS_IN_FORMAT = /D[oD]?(\\[[^\\[\\]]*\\]|\\s)+MMMM?/,\n defaultMonthsShortRegex = matchWord,\n defaultMonthsRegex = matchWord;\n\n function localeMonths(m, format) {\n if (!m) {\n return isArray(this._months)\n ? this._months\n : this._months['standalone'];\n }\n return isArray(this._months)\n ? this._months[m.month()]\n : this._months[\n (this._months.isFormat || MONTHS_IN_FORMAT).test(format)\n ? 'format'\n : 'standalone'\n ][m.month()];\n }\n\n function localeMonthsShort(m, format) {\n if (!m) {\n return isArray(this._monthsShort)\n ? this._monthsShort\n : this._monthsShort['standalone'];\n }\n return isArray(this._monthsShort)\n ? this._monthsShort[m.month()]\n : this._monthsShort[\n MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'\n ][m.month()];\n }\n\n function handleStrictParse(monthName, format, strict) {\n var i,\n ii,\n mom,\n llc = monthName.toLocaleLowerCase();\n if (!this._monthsParse) {\n // this is not used\n this._monthsParse = [];\n this._longMonthsParse = [];\n this._shortMonthsParse = [];\n for (i = 0; i < 12; ++i) {\n mom = createUTC([2000, i]);\n this._shortMonthsParse[i] = this.monthsShort(\n mom,\n ''\n ).toLocaleLowerCase();\n this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();\n }\n }\n\n if (strict) {\n if (format === 'MMM') {\n ii = indexOf.call(this._shortMonthsParse, llc);\n return ii !== -1 ? ii : null;\n } else {\n ii = indexOf.call(this._longMonthsParse, llc);\n return ii !== -1 ? ii : null;\n }\n } else {\n if (format === 'MMM') {\n ii = indexOf.call(this._shortMonthsParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._longMonthsParse, llc);\n return ii !== -1 ? ii : null;\n } else {\n ii = indexOf.call(this._longMonthsParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._shortMonthsParse, llc);\n return ii !== -1 ? ii : null;\n }\n }\n }\n\n function localeMonthsParse(monthName, format, strict) {\n var i, mom, regex;\n\n if (this._monthsParseExact) {\n return handleStrictParse.call(this, monthName, format, strict);\n }\n\n if (!this._monthsParse) {\n this._monthsParse = [];\n this._longMonthsParse = [];\n this._shortMonthsParse = [];\n }\n\n // TODO: add sorting\n // Sorting makes sure if one month (or abbr) is a prefix of another\n // see sorting in computeMonthsParse\n for (i = 0; i < 12; i++) {\n // make the regex if we don't have it already\n mom = createUTC([2000, i]);\n if (strict && !this._longMonthsParse[i]) {\n this._longMonthsParse[i] = new RegExp(\n '^' + this.months(mom, '').replace('.', '') + '$',\n 'i'\n );\n this._shortMonthsParse[i] = new RegExp(\n '^' + this.monthsShort(mom, '').replace('.', '') + '$',\n 'i'\n );\n }\n if (!strict && !this._monthsParse[i]) {\n regex =\n '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');\n this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (\n strict &&\n format === 'MMMM' &&\n this._longMonthsParse[i].test(monthName)\n ) {\n return i;\n } else if (\n strict &&\n format === 'MMM' &&\n this._shortMonthsParse[i].test(monthName)\n ) {\n return i;\n } else if (!strict && this._monthsParse[i].test(monthName)) {\n return i;\n }\n }\n }\n\n // MOMENTS\n\n function setMonth(mom, value) {\n if (!mom.isValid()) {\n // No op\n return mom;\n }\n\n if (typeof value === 'string') {\n if (/^\\d+$/.test(value)) {\n value = toInt(value);\n } else {\n value = mom.localeData().monthsParse(value);\n // TODO: Another silent failure?\n if (!isNumber(value)) {\n return mom;\n }\n }\n }\n\n var month = value,\n date = mom.date();\n\n date = date < 29 ? date : Math.min(date, daysInMonth(mom.year(), month));\n void (mom._isUTC\n ? mom._d.setUTCMonth(month, date)\n : mom._d.setMonth(month, date));\n return mom;\n }\n\n function getSetMonth(value) {\n if (value != null) {\n setMonth(this, value);\n hooks.updateOffset(this, true);\n return this;\n } else {\n return get(this, 'Month');\n }\n }\n\n function getDaysInMonth() {\n return daysInMonth(this.year(), this.month());\n }\n\n function monthsShortRegex(isStrict) {\n if (this._monthsParseExact) {\n if (!hasOwnProp(this, '_monthsRegex')) {\n computeMonthsParse.call(this);\n }\n if (isStrict) {\n return this._monthsShortStrictRegex;\n } else {\n return this._monthsShortRegex;\n }\n } else {\n if (!hasOwnProp(this, '_monthsShortRegex')) {\n this._monthsShortRegex = defaultMonthsShortRegex;\n }\n return this._monthsShortStrictRegex && isStrict\n ? this._monthsShortStrictRegex\n : this._monthsShortRegex;\n }\n }\n\n function monthsRegex(isStrict) {\n if (this._monthsParseExact) {\n if (!hasOwnProp(this, '_monthsRegex')) {\n computeMonthsParse.call(this);\n }\n if (isStrict) {\n return this._monthsStrictRegex;\n } else {\n return this._monthsRegex;\n }\n } else {\n if (!hasOwnProp(this, '_monthsRegex')) {\n this._monthsRegex = defaultMonthsRegex;\n }\n return this._monthsStrictRegex && isStrict\n ? this._monthsStrictRegex\n : this._monthsRegex;\n }\n }\n\n function computeMonthsParse() {\n function cmpLenRev(a, b) {\n return b.length - a.length;\n }\n\n var shortPieces = [],\n longPieces = [],\n mixedPieces = [],\n i,\n mom,\n shortP,\n longP;\n for (i = 0; i < 12; i++) {\n // make the regex if we don't have it already\n mom = createUTC([2000, i]);\n shortP = regexEscape(this.monthsShort(mom, ''));\n longP = regexEscape(this.months(mom, ''));\n shortPieces.push(shortP);\n longPieces.push(longP);\n mixedPieces.push(longP);\n mixedPieces.push(shortP);\n }\n // Sorting makes sure if one month (or abbr) is a prefix of another it\n // will match the longer piece.\n shortPieces.sort(cmpLenRev);\n longPieces.sort(cmpLenRev);\n mixedPieces.sort(cmpLenRev);\n\n this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');\n this._monthsShortRegex = this._monthsRegex;\n this._monthsStrictRegex = new RegExp(\n '^(' + longPieces.join('|') + ')',\n 'i'\n );\n this._monthsShortStrictRegex = new RegExp(\n '^(' + shortPieces.join('|') + ')',\n 'i'\n );\n }\n\n function createDate(y, m, d, h, M, s, ms) {\n // can't just apply() to create a date:\n // https://stackoverflow.com/q/181348\n var date;\n // the date constructor remaps years 0-99 to 1900-1999\n if (y < 100 && y >= 0) {\n // preserve leap years using a full 400 year cycle, then reset\n date = new Date(y + 400, m, d, h, M, s, ms);\n if (isFinite(date.getFullYear())) {\n date.setFullYear(y);\n }\n } else {\n date = new Date(y, m, d, h, M, s, ms);\n }\n\n return date;\n }\n\n function createUTCDate(y) {\n var date, args;\n // the Date.UTC function remaps years 0-99 to 1900-1999\n if (y < 100 && y >= 0) {\n args = Array.prototype.slice.call(arguments);\n // preserve leap years using a full 400 year cycle, then reset\n args[0] = y + 400;\n date = new Date(Date.UTC.apply(null, args));\n if (isFinite(date.getUTCFullYear())) {\n date.setUTCFullYear(y);\n }\n } else {\n date = new Date(Date.UTC.apply(null, arguments));\n }\n\n return date;\n }\n\n // start-of-first-week - start-of-year\n function firstWeekOffset(year, dow, doy) {\n var // first-week day -- which january is always in the first week (4 for iso, 1 for other)\n fwd = 7 + dow - doy,\n // first-week day local weekday -- which local weekday is fwd\n fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;\n\n return -fwdlw + fwd - 1;\n }\n\n // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday\n function dayOfYearFromWeeks(year, week, weekday, dow, doy) {\n var localWeekday = (7 + weekday - dow) % 7,\n weekOffset = firstWeekOffset(year, dow, doy),\n dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,\n resYear,\n resDayOfYear;\n\n if (dayOfYear <= 0) {\n resYear = year - 1;\n resDayOfYear = daysInYear(resYear) + dayOfYear;\n } else if (dayOfYear > daysInYear(year)) {\n resYear = year + 1;\n resDayOfYear = dayOfYear - daysInYear(year);\n } else {\n resYear = year;\n resDayOfYear = dayOfYear;\n }\n\n return {\n year: resYear,\n dayOfYear: resDayOfYear,\n };\n }\n\n function weekOfYear(mom, dow, doy) {\n var weekOffset = firstWeekOffset(mom.year(), dow, doy),\n week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,\n resWeek,\n resYear;\n\n if (week < 1) {\n resYear = mom.year() - 1;\n resWeek = week + weeksInYear(resYear, dow, doy);\n } else if (week > weeksInYear(mom.year(), dow, doy)) {\n resWeek = week - weeksInYear(mom.year(), dow, doy);\n resYear = mom.year() + 1;\n } else {\n resYear = mom.year();\n resWeek = week;\n }\n\n return {\n week: resWeek,\n year: resYear,\n };\n }\n\n function weeksInYear(year, dow, doy) {\n var weekOffset = firstWeekOffset(year, dow, doy),\n weekOffsetNext = firstWeekOffset(year + 1, dow, doy);\n return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;\n }\n\n // FORMATTING\n\n addFormatToken('w', ['ww', 2], 'wo', 'week');\n addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');\n\n // PARSING\n\n addRegexToken('w', match1to2, match1to2NoLeadingZero);\n addRegexToken('ww', match1to2, match2);\n addRegexToken('W', match1to2, match1to2NoLeadingZero);\n addRegexToken('WW', match1to2, match2);\n\n addWeekParseToken(\n ['w', 'ww', 'W', 'WW'],\n function (input, week, config, token) {\n week[token.substr(0, 1)] = toInt(input);\n }\n );\n\n // HELPERS\n\n // LOCALES\n\n function localeWeek(mom) {\n return weekOfYear(mom, this._week.dow, this._week.doy).week;\n }\n\n var defaultLocaleWeek = {\n dow: 0, // Sunday is the first day of the week.\n doy: 6, // The week that contains Jan 6th is the first week of the year.\n };\n\n function localeFirstDayOfWeek() {\n return this._week.dow;\n }\n\n function localeFirstDayOfYear() {\n return this._week.doy;\n }\n\n // MOMENTS\n\n function getSetWeek(input) {\n var week = this.localeData().week(this);\n return input == null ? week : this.add((input - week) * 7, 'd');\n }\n\n function getSetISOWeek(input) {\n var week = weekOfYear(this, 1, 4).week;\n return input == null ? week : this.add((input - week) * 7, 'd');\n }\n\n // FORMATTING\n\n addFormatToken('d', 0, 'do', 'day');\n\n addFormatToken('dd', 0, 0, function (format) {\n return this.localeData().weekdaysMin(this, format);\n });\n\n addFormatToken('ddd', 0, 0, function (format) {\n return this.localeData().weekdaysShort(this, format);\n });\n\n addFormatToken('dddd', 0, 0, function (format) {\n return this.localeData().weekdays(this, format);\n });\n\n addFormatToken('e', 0, 0, 'weekday');\n addFormatToken('E', 0, 0, 'isoWeekday');\n\n // PARSING\n\n addRegexToken('d', match1to2);\n addRegexToken('e', match1to2);\n addRegexToken('E', match1to2);\n addRegexToken('dd', function (isStrict, locale) {\n return locale.weekdaysMinRegex(isStrict);\n });\n addRegexToken('ddd', function (isStrict, locale) {\n return locale.weekdaysShortRegex(isStrict);\n });\n addRegexToken('dddd', function (isStrict, locale) {\n return locale.weekdaysRegex(isStrict);\n });\n\n addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {\n var weekday = config._locale.weekdaysParse(input, token, config._strict);\n // if we didn't get a weekday name, mark the date as invalid\n if (weekday != null) {\n week.d = weekday;\n } else {\n getParsingFlags(config).invalidWeekday = input;\n }\n });\n\n addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {\n week[token] = toInt(input);\n });\n\n // HELPERS\n\n function parseWeekday(input, locale) {\n if (typeof input !== 'string') {\n return input;\n }\n\n if (!isNaN(input)) {\n return parseInt(input, 10);\n }\n\n input = locale.weekdaysParse(input);\n if (typeof input === 'number') {\n return input;\n }\n\n return null;\n }\n\n function parseIsoWeekday(input, locale) {\n if (typeof input === 'string') {\n return locale.weekdaysParse(input) % 7 || 7;\n }\n return isNaN(input) ? null : input;\n }\n\n // LOCALES\n function shiftWeekdays(ws, n) {\n return ws.slice(n, 7).concat(ws.slice(0, n));\n }\n\n var defaultLocaleWeekdays =\n 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),\n defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),\n defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),\n defaultWeekdaysRegex = matchWord,\n defaultWeekdaysShortRegex = matchWord,\n defaultWeekdaysMinRegex = matchWord;\n\n function localeWeekdays(m, format) {\n var weekdays = isArray(this._weekdays)\n ? this._weekdays\n : this._weekdays[\n m && m !== true && this._weekdays.isFormat.test(format)\n ? 'format'\n : 'standalone'\n ];\n return m === true\n ? shiftWeekdays(weekdays, this._week.dow)\n : m\n ? weekdays[m.day()]\n : weekdays;\n }\n\n function localeWeekdaysShort(m) {\n return m === true\n ? shiftWeekdays(this._weekdaysShort, this._week.dow)\n : m\n ? this._weekdaysShort[m.day()]\n : this._weekdaysShort;\n }\n\n function localeWeekdaysMin(m) {\n return m === true\n ? shiftWeekdays(this._weekdaysMin, this._week.dow)\n : m\n ? this._weekdaysMin[m.day()]\n : this._weekdaysMin;\n }\n\n function handleStrictParse$1(weekdayName, format, strict) {\n var i,\n ii,\n mom,\n llc = weekdayName.toLocaleLowerCase();\n if (!this._weekdaysParse) {\n this._weekdaysParse = [];\n this._shortWeekdaysParse = [];\n this._minWeekdaysParse = [];\n\n for (i = 0; i < 7; ++i) {\n mom = createUTC([2000, 1]).day(i);\n this._minWeekdaysParse[i] = this.weekdaysMin(\n mom,\n ''\n ).toLocaleLowerCase();\n this._shortWeekdaysParse[i] = this.weekdaysShort(\n mom,\n ''\n ).toLocaleLowerCase();\n this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();\n }\n }\n\n if (strict) {\n if (format === 'dddd') {\n ii = indexOf.call(this._weekdaysParse, llc);\n return ii !== -1 ? ii : null;\n } else if (format === 'ddd') {\n ii = indexOf.call(this._shortWeekdaysParse, llc);\n return ii !== -1 ? ii : null;\n } else {\n ii = indexOf.call(this._minWeekdaysParse, llc);\n return ii !== -1 ? ii : null;\n }\n } else {\n if (format === 'dddd') {\n ii = indexOf.call(this._weekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._shortWeekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._minWeekdaysParse, llc);\n return ii !== -1 ? ii : null;\n } else if (format === 'ddd') {\n ii = indexOf.call(this._shortWeekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._weekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._minWeekdaysParse, llc);\n return ii !== -1 ? ii : null;\n } else {\n ii = indexOf.call(this._minWeekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._weekdaysParse, llc);\n if (ii !== -1) {\n return ii;\n }\n ii = indexOf.call(this._shortWeekdaysParse, llc);\n return ii !== -1 ? ii : null;\n }\n }\n }\n\n function localeWeekdaysParse(weekdayName, format, strict) {\n var i, mom, regex;\n\n if (this._weekdaysParseExact) {\n return handleStrictParse$1.call(this, weekdayName, format, strict);\n }\n\n if (!this._weekdaysParse) {\n this._weekdaysParse = [];\n this._minWeekdaysParse = [];\n this._shortWeekdaysParse = [];\n this._fullWeekdaysParse = [];\n }\n\n for (i = 0; i < 7; i++) {\n // make the regex if we don't have it already\n\n mom = createUTC([2000, 1]).day(i);\n if (strict && !this._fullWeekdaysParse[i]) {\n this._fullWeekdaysParse[i] = new RegExp(\n '^' + this.weekdays(mom, '').replace('.', '\\\\.?') + '$',\n 'i'\n );\n this._shortWeekdaysParse[i] = new RegExp(\n '^' + this.weekdaysShort(mom, '').replace('.', '\\\\.?') + '$',\n 'i'\n );\n this._minWeekdaysParse[i] = new RegExp(\n '^' + this.weekdaysMin(mom, '').replace('.', '\\\\.?') + '$',\n 'i'\n );\n }\n if (!this._weekdaysParse[i]) {\n regex =\n '^' +\n this.weekdays(mom, '') +\n '|^' +\n this.weekdaysShort(mom, '') +\n '|^' +\n this.weekdaysMin(mom, '');\n this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (\n strict &&\n format === 'dddd' &&\n this._fullWeekdaysParse[i].test(weekdayName)\n ) {\n return i;\n } else if (\n strict &&\n format === 'ddd' &&\n this._shortWeekdaysParse[i].test(weekdayName)\n ) {\n return i;\n } else if (\n strict &&\n format === 'dd' &&\n this._minWeekdaysParse[i].test(weekdayName)\n ) {\n return i;\n } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {\n return i;\n }\n }\n }\n\n // MOMENTS\n\n function getSetDayOfWeek(input) {\n if (!this.isValid()) {\n return input != null ? this : NaN;\n }\n\n var day = get(this, 'Day');\n if (input != null) {\n input = parseWeekday(input, this.localeData());\n return this.add(input - day, 'd');\n } else {\n return day;\n }\n }\n\n function getSetLocaleDayOfWeek(input) {\n if (!this.isValid()) {\n return input != null ? this : NaN;\n }\n var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;\n return input == null ? weekday : this.add(input - weekday, 'd');\n }\n\n function getSetISODayOfWeek(input) {\n if (!this.isValid()) {\n return input != null ? this : NaN;\n }\n\n // behaves the same as moment#day except\n // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)\n // as a setter, sunday should belong to the previous week.\n\n if (input != null) {\n var weekday = parseIsoWeekday(input, this.localeData());\n return this.day(this.day() % 7 ? weekday : weekday - 7);\n } else {\n return this.day() || 7;\n }\n }\n\n function weekdaysRegex(isStrict) {\n if (this._weekdaysParseExact) {\n if (!hasOwnProp(this, '_weekdaysRegex')) {\n computeWeekdaysParse.call(this);\n }\n if (isStrict) {\n return this._weekdaysStrictRegex;\n } else {\n return this._weekdaysRegex;\n }\n } else {\n if (!hasOwnProp(this, '_weekdaysRegex')) {\n this._weekdaysRegex = defaultWeekdaysRegex;\n }\n return this._weekdaysStrictRegex && isStrict\n ? this._weekdaysStrictRegex\n : this._weekdaysRegex;\n }\n }\n\n function weekdaysShortRegex(isStrict) {\n if (this._weekdaysParseExact) {\n if (!hasOwnProp(this, '_weekdaysRegex')) {\n computeWeekdaysParse.call(this);\n }\n if (isStrict) {\n return this._weekdaysShortStrictRegex;\n } else {\n return this._weekdaysShortRegex;\n }\n } else {\n if (!hasOwnProp(this, '_weekdaysShortRegex')) {\n this._weekdaysShortRegex = defaultWeekdaysShortRegex;\n }\n return this._weekdaysShortStrictRegex && isStrict\n ? this._weekdaysShortStrictRegex\n : this._weekdaysShortRegex;\n }\n }\n\n function weekdaysMinRegex(isStrict) {\n if (this._weekdaysParseExact) {\n if (!hasOwnProp(this, '_weekdaysRegex')) {\n computeWeekdaysParse.call(this);\n }\n if (isStrict) {\n return this._weekdaysMinStrictRegex;\n } else {\n return this._weekdaysMinRegex;\n }\n } else {\n if (!hasOwnProp(this, '_weekdaysMinRegex')) {\n this._weekdaysMinRegex = defaultWeekdaysMinRegex;\n }\n return this._weekdaysMinStrictRegex && isStrict\n ? this._weekdaysMinStrictRegex\n : this._weekdaysMinRegex;\n }\n }\n\n function computeWeekdaysParse() {\n function cmpLenRev(a, b) {\n return b.length - a.length;\n }\n\n var minPieces = [],\n shortPieces = [],\n longPieces = [],\n mixedPieces = [],\n i,\n mom,\n minp,\n shortp,\n longp;\n for (i = 0; i < 7; i++) {\n // make the regex if we don't have it already\n mom = createUTC([2000, 1]).day(i);\n minp = regexEscape(this.weekdaysMin(mom, ''));\n shortp = regexEscape(this.weekdaysShort(mom, ''));\n longp = regexEscape(this.weekdays(mom, ''));\n minPieces.push(minp);\n shortPieces.push(shortp);\n longPieces.push(longp);\n mixedPieces.push(minp);\n mixedPieces.push(shortp);\n mixedPieces.push(longp);\n }\n // Sorting makes sure if one weekday (or abbr) is a prefix of another it\n // will match the longer piece.\n minPieces.sort(cmpLenRev);\n shortPieces.sort(cmpLenRev);\n longPieces.sort(cmpLenRev);\n mixedPieces.sort(cmpLenRev);\n\n this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');\n this._weekdaysShortRegex = this._weekdaysRegex;\n this._weekdaysMinRegex = this._weekdaysRegex;\n\n this._weekdaysStrictRegex = new RegExp(\n '^(' + longPieces.join('|') + ')',\n 'i'\n );\n this._weekdaysShortStrictRegex = new RegExp(\n '^(' + shortPieces.join('|') + ')',\n 'i'\n );\n this._weekdaysMinStrictRegex = new RegExp(\n '^(' + minPieces.join('|') + ')',\n 'i'\n );\n }\n\n // FORMATTING\n\n function hFormat() {\n return this.hours() % 12 || 12;\n }\n\n function kFormat() {\n return this.hours() || 24;\n }\n\n addFormatToken('H', ['HH', 2], 0, 'hour');\n addFormatToken('h', ['hh', 2], 0, hFormat);\n addFormatToken('k', ['kk', 2], 0, kFormat);\n\n addFormatToken('hmm', 0, 0, function () {\n return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);\n });\n\n addFormatToken('hmmss', 0, 0, function () {\n return (\n '' +\n hFormat.apply(this) +\n zeroFill(this.minutes(), 2) +\n zeroFill(this.seconds(), 2)\n );\n });\n\n addFormatToken('Hmm', 0, 0, function () {\n return '' + this.hours() + zeroFill(this.minutes(), 2);\n });\n\n addFormatToken('Hmmss', 0, 0, function () {\n return (\n '' +\n this.hours() +\n zeroFill(this.minutes(), 2) +\n zeroFill(this.seconds(), 2)\n );\n });\n\n function meridiem(token, lowercase) {\n addFormatToken(token, 0, 0, function () {\n return this.localeData().meridiem(\n this.hours(),\n this.minutes(),\n lowercase\n );\n });\n }\n\n meridiem('a', true);\n meridiem('A', false);\n\n // PARSING\n\n function matchMeridiem(isStrict, locale) {\n return locale._meridiemParse;\n }\n\n addRegexToken('a', matchMeridiem);\n addRegexToken('A', matchMeridiem);\n addRegexToken('H', match1to2, match1to2HasZero);\n addRegexToken('h', match1to2, match1to2NoLeadingZero);\n addRegexToken('k', match1to2, match1to2NoLeadingZero);\n addRegexToken('HH', match1to2, match2);\n addRegexToken('hh', match1to2, match2);\n addRegexToken('kk', match1to2, match2);\n\n addRegexToken('hmm', match3to4);\n addRegexToken('hmmss', match5to6);\n addRegexToken('Hmm', match3to4);\n addRegexToken('Hmmss', match5to6);\n\n addParseToken(['H', 'HH'], HOUR);\n addParseToken(['k', 'kk'], function (input, array, config) {\n var kInput = toInt(input);\n array[HOUR] = kInput === 24 ? 0 : kInput;\n });\n addParseToken(['a', 'A'], function (input, array, config) {\n config._isPm = config._locale.isPM(input);\n config._meridiem = input;\n });\n addParseToken(['h', 'hh'], function (input, array, config) {\n array[HOUR] = toInt(input);\n getParsingFlags(config).bigHour = true;\n });\n addParseToken('hmm', function (input, array, config) {\n var pos = input.length - 2;\n array[HOUR] = toInt(input.substr(0, pos));\n array[MINUTE] = toInt(input.substr(pos));\n getParsingFlags(config).bigHour = true;\n });\n addParseToken('hmmss', function (input, array, config) {\n var pos1 = input.length - 4,\n pos2 = input.length - 2;\n array[HOUR] = toInt(input.substr(0, pos1));\n array[MINUTE] = toInt(input.substr(pos1, 2));\n array[SECOND] = toInt(input.substr(pos2));\n getParsingFlags(config).bigHour = true;\n });\n addParseToken('Hmm', function (input, array, config) {\n var pos = input.length - 2;\n array[HOUR] = toInt(input.substr(0, pos));\n array[MINUTE] = toInt(input.substr(pos));\n });\n addParseToken('Hmmss', function (input, array, config) {\n var pos1 = input.length - 4,\n pos2 = input.length - 2;\n array[HOUR] = toInt(input.substr(0, pos1));\n array[MINUTE] = toInt(input.substr(pos1, 2));\n array[SECOND] = toInt(input.substr(pos2));\n });\n\n // LOCALES\n\n function localeIsPM(input) {\n // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays\n // Using charAt should be more compatible.\n return (input + '').toLowerCase().charAt(0) === 'p';\n }\n\n var defaultLocaleMeridiemParse = /[ap]\\.?m?\\.?/i,\n // Setting the hour should keep the time, because the user explicitly\n // specified which hour they want. So trying to maintain the same hour (in\n // a new timezone) makes sense. Adding/subtracting hours does not follow\n // this rule.\n getSetHour = makeGetSet('Hours', true);\n\n function localeMeridiem(hours, minutes, isLower) {\n if (hours > 11) {\n return isLower ? 'pm' : 'PM';\n } else {\n return isLower ? 'am' : 'AM';\n }\n }\n\n var baseConfig = {\n calendar: defaultCalendar,\n longDateFormat: defaultLongDateFormat,\n invalidDate: defaultInvalidDate,\n ordinal: defaultOrdinal,\n dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,\n relativeTime: defaultRelativeTime,\n\n months: defaultLocaleMonths,\n monthsShort: defaultLocaleMonthsShort,\n\n week: defaultLocaleWeek,\n\n weekdays: defaultLocaleWeekdays,\n weekdaysMin: defaultLocaleWeekdaysMin,\n weekdaysShort: defaultLocaleWeekdaysShort,\n\n meridiemParse: defaultLocaleMeridiemParse,\n };\n\n // internal storage for locale config files\n var locales = {},\n localeFamilies = {},\n globalLocale;\n\n function commonPrefix(arr1, arr2) {\n var i,\n minl = Math.min(arr1.length, arr2.length);\n for (i = 0; i < minl; i += 1) {\n if (arr1[i] !== arr2[i]) {\n return i;\n }\n }\n return minl;\n }\n\n function normalizeLocale(key) {\n return key ? key.toLowerCase().replace('_', '-') : key;\n }\n\n // pick the locale from the array\n // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each\n // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root\n function chooseLocale(names) {\n var i = 0,\n j,\n next,\n locale,\n split;\n\n while (i < names.length) {\n split = normalizeLocale(names[i]).split('-');\n j = split.length;\n next = normalizeLocale(names[i + 1]);\n next = next ? next.split('-') : null;\n while (j > 0) {\n locale = loadLocale(split.slice(0, j).join('-'));\n if (locale) {\n return locale;\n }\n if (\n next &&\n next.length >= j &&\n commonPrefix(split, next) >= j - 1\n ) {\n //the next array item is better than a shallower substring of this one\n break;\n }\n j--;\n }\n i++;\n }\n return globalLocale;\n }\n\n function isLocaleNameSane(name) {\n // Prevent names that look like filesystem paths, i.e contain '/' or '\\'\n // Ensure name is available and function returns boolean\n return !!(name && name.match('^[^/\\\\\\\\]*$'));\n }\n\n function loadLocale(name) {\n var oldLocale = null,\n aliasedRequire;\n // TODO: Find a better way to register and load all the locales in Node\n if (\n locales[name] === undefined &&\n typeof module !== 'undefined' &&\n module &&\n module.exports &&\n isLocaleNameSane(name)\n ) {\n try {\n oldLocale = globalLocale._abbr;\n aliasedRequire = require;\n aliasedRequire('./locale/' + name);\n getSetGlobalLocale(oldLocale);\n } catch (e) {\n // mark as not found to avoid repeating expensive file require call causing high CPU\n // when trying to find en-US, en_US, en-us for every format call\n locales[name] = null; // null means not found\n }\n }\n return locales[name];\n }\n\n // This function will load locale and then set the global locale. If\n // no arguments are passed in, it will simply return the current global\n // locale key.\n function getSetGlobalLocale(key, values) {\n var data;\n if (key) {\n if (isUndefined(values)) {\n data = getLocale(key);\n } else {\n data = defineLocale(key, values);\n }\n\n if (data) {\n // moment.duration._locale = moment._locale = data;\n globalLocale = data;\n } else {\n if (typeof console !== 'undefined' && console.warn) {\n //warn user if arguments are passed but the locale could not be set\n console.warn(\n 'Locale ' + key + ' not found. Did you forget to load it?'\n );\n }\n }\n }\n\n return globalLocale._abbr;\n }\n\n function defineLocale(name, config) {\n if (config !== null) {\n var locale,\n parentConfig = baseConfig;\n config.abbr = name;\n if (locales[name] != null) {\n deprecateSimple(\n 'defineLocaleOverride',\n 'use moment.updateLocale(localeName, config) to change ' +\n 'an existing locale. moment.defineLocale(localeName, ' +\n 'config) should only be used for creating a new locale ' +\n 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'\n );\n parentConfig = locales[name]._config;\n } else if (config.parentLocale != null) {\n if (locales[config.parentLocale] != null) {\n parentConfig = locales[config.parentLocale]._config;\n } else {\n locale = loadLocale(config.parentLocale);\n if (locale != null) {\n parentConfig = locale._config;\n } else {\n if (!localeFamilies[config.parentLocale]) {\n localeFamilies[config.parentLocale] = [];\n }\n localeFamilies[config.parentLocale].push({\n name: name,\n config: config,\n });\n return null;\n }\n }\n }\n locales[name] = new Locale(mergeConfigs(parentConfig, config));\n\n if (localeFamilies[name]) {\n localeFamilies[name].forEach(function (x) {\n defineLocale(x.name, x.config);\n });\n }\n\n // backwards compat for now: also set the locale\n // make sure we set the locale AFTER all child locales have been\n // created, so we won't end up with the child locale set.\n getSetGlobalLocale(name);\n\n return locales[name];\n } else {\n // useful for testing\n delete locales[name];\n return null;\n }\n }\n\n function updateLocale(name, config) {\n if (config != null) {\n var locale,\n tmpLocale,\n parentConfig = baseConfig;\n\n if (locales[name] != null && locales[name].parentLocale != null) {\n // Update existing child locale in-place to avoid memory-leaks\n locales[name].set(mergeConfigs(locales[name]._config, config));\n } else {\n // MERGE\n tmpLocale = loadLocale(name);\n if (tmpLocale != null) {\n parentConfig = tmpLocale._config;\n }\n config = mergeConfigs(parentConfig, config);\n if (tmpLocale == null) {\n // updateLocale is called for creating a new locale\n // Set abbr so it will have a name (getters return\n // undefined otherwise).\n config.abbr = name;\n }\n locale = new Locale(config);\n locale.parentLocale = locales[name];\n locales[name] = locale;\n }\n\n // backwards compat for now: also set the locale\n getSetGlobalLocale(name);\n } else {\n // pass null for config to unupdate, useful for tests\n if (locales[name] != null) {\n if (locales[name].parentLocale != null) {\n locales[name] = locales[name].parentLocale;\n if (name === getSetGlobalLocale()) {\n getSetGlobalLocale(name);\n }\n } else if (locales[name] != null) {\n delete locales[name];\n }\n }\n }\n return locales[name];\n }\n\n // returns locale data\n function getLocale(key) {\n var locale;\n\n if (key && key._locale && key._locale._abbr) {\n key = key._locale._abbr;\n }\n\n if (!key) {\n return globalLocale;\n }\n\n if (!isArray(key)) {\n //short-circuit everything else\n locale = loadLocale(key);\n if (locale) {\n return locale;\n }\n key = [key];\n }\n\n return chooseLocale(key);\n }\n\n function listLocales() {\n return keys(locales);\n }\n\n function checkOverflow(m) {\n var overflow,\n a = m._a;\n\n if (a && getParsingFlags(m).overflow === -2) {\n overflow =\n a[MONTH] < 0 || a[MONTH] > 11\n ? MONTH\n : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])\n ? DATE\n : a[HOUR] < 0 ||\n a[HOUR] > 24 ||\n (a[HOUR] === 24 &&\n (a[MINUTE] !== 0 ||\n a[SECOND] !== 0 ||\n a[MILLISECOND] !== 0))\n ? HOUR\n : a[MINUTE] < 0 || a[MINUTE] > 59\n ? MINUTE\n : a[SECOND] < 0 || a[SECOND] > 59\n ? SECOND\n : a[MILLISECOND] < 0 || a[MILLISECOND] > 999\n ? MILLISECOND\n : -1;\n\n if (\n getParsingFlags(m)._overflowDayOfYear &&\n (overflow < YEAR || overflow > DATE)\n ) {\n overflow = DATE;\n }\n if (getParsingFlags(m)._overflowWeeks && overflow === -1) {\n overflow = WEEK;\n }\n if (getParsingFlags(m)._overflowWeekday && overflow === -1) {\n overflow = WEEKDAY;\n }\n\n getParsingFlags(m).overflow = overflow;\n }\n\n return m;\n }\n\n // iso 8601 regex\n // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)\n var extendedIsoRegex =\n /^\\s*((?:[+-]\\d{6}|\\d{4})-(?:\\d\\d-\\d\\d|W\\d\\d-\\d|W\\d\\d|\\d\\d\\d|\\d\\d))(?:(T| )(\\d\\d(?::\\d\\d(?::\\d\\d(?:[.,]\\d+)?)?)?)([+-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,\n basicIsoRegex =\n /^\\s*((?:[+-]\\d{6}|\\d{4})(?:\\d\\d\\d\\d|W\\d\\d\\d|W\\d\\d|\\d\\d\\d|\\d\\d|))(?:(T| )(\\d\\d(?:\\d\\d(?:\\d\\d(?:[.,]\\d+)?)?)?)([+-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,\n tzRegex = /Z|[+-]\\d\\d(?::?\\d\\d)?/,\n isoDates = [\n ['YYYYYY-MM-DD', /[+-]\\d{6}-\\d\\d-\\d\\d/],\n ['YYYY-MM-DD', /\\d{4}-\\d\\d-\\d\\d/],\n ['GGGG-[W]WW-E', /\\d{4}-W\\d\\d-\\d/],\n ['GGGG-[W]WW', /\\d{4}-W\\d\\d/, false],\n ['YYYY-DDD', /\\d{4}-\\d{3}/],\n ['YYYY-MM', /\\d{4}-\\d\\d/, false],\n ['YYYYYYMMDD', /[+-]\\d{10}/],\n ['YYYYMMDD', /\\d{8}/],\n ['GGGG[W]WWE', /\\d{4}W\\d{3}/],\n ['GGGG[W]WW', /\\d{4}W\\d{2}/, false],\n ['YYYYDDD', /\\d{7}/],\n ['YYYYMM', /\\d{6}/, false],\n ['YYYY', /\\d{4}/, false],\n ],\n // iso time formats and regexes\n isoTimes = [\n ['HH:mm:ss.SSSS', /\\d\\d:\\d\\d:\\d\\d\\.\\d+/],\n ['HH:mm:ss,SSSS', /\\d\\d:\\d\\d:\\d\\d,\\d+/],\n ['HH:mm:ss', /\\d\\d:\\d\\d:\\d\\d/],\n ['HH:mm', /\\d\\d:\\d\\d/],\n ['HHmmss.SSSS', /\\d\\d\\d\\d\\d\\d\\.\\d+/],\n ['HHmmss,SSSS', /\\d\\d\\d\\d\\d\\d,\\d+/],\n ['HHmmss', /\\d\\d\\d\\d\\d\\d/],\n ['HHmm', /\\d\\d\\d\\d/],\n ['HH', /\\d\\d/],\n ],\n aspNetJsonRegex = /^\\/?Date\\((-?\\d+)/i,\n // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3\n rfc2822 =\n /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\\s)?(\\d{1,2})\\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\s(\\d{2,4})\\s(\\d\\d):(\\d\\d)(?::(\\d\\d))?\\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\\d{4}))$/,\n obsOffsets = {\n UT: 0,\n GMT: 0,\n EDT: -4 * 60,\n EST: -5 * 60,\n CDT: -5 * 60,\n CST: -6 * 60,\n MDT: -6 * 60,\n MST: -7 * 60,\n PDT: -7 * 60,\n PST: -8 * 60,\n };\n\n // date from iso format\n function configFromISO(config) {\n var i,\n l,\n string = config._i,\n match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),\n allowTime,\n dateFormat,\n timeFormat,\n tzFormat,\n isoDatesLen = isoDates.length,\n isoTimesLen = isoTimes.length;\n\n if (match) {\n getParsingFlags(config).iso = true;\n for (i = 0, l = isoDatesLen; i < l; i++) {\n if (isoDates[i][1].exec(match[1])) {\n dateFormat = isoDates[i][0];\n allowTime = isoDates[i][2] !== false;\n break;\n }\n }\n if (dateFormat == null) {\n config._isValid = false;\n return;\n }\n if (match[3]) {\n for (i = 0, l = isoTimesLen; i < l; i++) {\n if (isoTimes[i][1].exec(match[3])) {\n // match[2] should be 'T' or space\n timeFormat = (match[2] || ' ') + isoTimes[i][0];\n break;\n }\n }\n if (timeFormat == null) {\n config._isValid = false;\n return;\n }\n }\n if (!allowTime && timeFormat != null) {\n config._isValid = false;\n return;\n }\n if (match[4]) {\n if (tzRegex.exec(match[4])) {\n tzFormat = 'Z';\n } else {\n config._isValid = false;\n return;\n }\n }\n config._f = dateFormat + (timeFormat || '') + (tzFormat || '');\n configFromStringAndFormat(config);\n } else {\n config._isValid = false;\n }\n }\n\n function extractFromRFC2822Strings(\n yearStr,\n monthStr,\n dayStr,\n hourStr,\n minuteStr,\n secondStr\n ) {\n var result = [\n untruncateYear(yearStr),\n defaultLocaleMonthsShort.indexOf(monthStr),\n parseInt(dayStr, 10),\n parseInt(hourStr, 10),\n parseInt(minuteStr, 10),\n ];\n\n if (secondStr) {\n result.push(parseInt(secondStr, 10));\n }\n\n return result;\n }\n\n function untruncateYear(yearStr) {\n var year = parseInt(yearStr, 10);\n if (year <= 49) {\n return 2000 + year;\n } else if (year <= 999) {\n return 1900 + year;\n }\n return year;\n }\n\n function preprocessRFC2822(s) {\n // Remove comments and folding whitespace and replace multiple-spaces with a single space\n return s\n .replace(/\\([^()]*\\)|[\\n\\t]/g, ' ')\n .replace(/(\\s\\s+)/g, ' ')\n .replace(/^\\s\\s*/, '')\n .replace(/\\s\\s*$/, '');\n }\n\n function checkWeekday(weekdayStr, parsedInput, config) {\n if (weekdayStr) {\n // TODO: Replace the vanilla JS Date object with an independent day-of-week check.\n var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),\n weekdayActual = new Date(\n parsedInput[0],\n parsedInput[1],\n parsedInput[2]\n ).getDay();\n if (weekdayProvided !== weekdayActual) {\n getParsingFlags(config).weekdayMismatch = true;\n config._isValid = false;\n return false;\n }\n }\n return true;\n }\n\n function calculateOffset(obsOffset, militaryOffset, numOffset) {\n if (obsOffset) {\n return obsOffsets[obsOffset];\n } else if (militaryOffset) {\n // the only allowed military tz is Z\n return 0;\n } else {\n var hm = parseInt(numOffset, 10),\n m = hm % 100,\n h = (hm - m) / 100;\n return h * 60 + m;\n }\n }\n\n // date and time from ref 2822 format\n function configFromRFC2822(config) {\n var match = rfc2822.exec(preprocessRFC2822(config._i)),\n parsedArray;\n if (match) {\n parsedArray = extractFromRFC2822Strings(\n match[4],\n match[3],\n match[2],\n match[5],\n match[6],\n match[7]\n );\n if (!checkWeekday(match[1], parsedArray, config)) {\n return;\n }\n\n config._a = parsedArray;\n config._tzm = calculateOffset(match[8], match[9], match[10]);\n\n config._d = createUTCDate.apply(null, config._a);\n config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);\n\n getParsingFlags(config).rfc2822 = true;\n } else {\n config._isValid = false;\n }\n }\n\n // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict\n function configFromString(config) {\n var matched = aspNetJsonRegex.exec(config._i);\n if (matched !== null) {\n config._d = new Date(+matched[1]);\n return;\n }\n\n configFromISO(config);\n if (config._isValid === false) {\n delete config._isValid;\n } else {\n return;\n }\n\n configFromRFC2822(config);\n if (config._isValid === false) {\n delete config._isValid;\n } else {\n return;\n }\n\n if (config._strict) {\n config._isValid = false;\n } else {\n // Final attempt, use Input Fallback\n hooks.createFromInputFallback(config);\n }\n }\n\n hooks.createFromInputFallback = deprecate(\n 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +\n 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +\n 'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',\n function (config) {\n config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));\n }\n );\n\n // Pick the first defined of two or three arguments.\n function defaults(a, b, c) {\n if (a != null) {\n return a;\n }\n if (b != null) {\n return b;\n }\n return c;\n }\n\n function currentDateArray(config) {\n // hooks is actually the exported moment object\n var nowValue = new Date(hooks.now());\n if (config._useUTC) {\n return [\n nowValue.getUTCFullYear(),\n nowValue.getUTCMonth(),\n nowValue.getUTCDate(),\n ];\n }\n return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];\n }\n\n // convert an array to a date.\n // the array should mirror the parameters below\n // note: all values past the year are optional and will default to the lowest possible value.\n // [year, month, day , hour, minute, second, millisecond]\n function configFromArray(config) {\n var i,\n date,\n input = [],\n currentDate,\n expectedWeekday,\n yearToUse;\n\n if (config._d) {\n return;\n }\n\n currentDate = currentDateArray(config);\n\n //compute day of the year from weeks and weekdays\n if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {\n dayOfYearFromWeekInfo(config);\n }\n\n //if the day of the year is set, figure out what it is\n if (config._dayOfYear != null) {\n yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);\n\n if (\n config._dayOfYear > daysInYear(yearToUse) ||\n config._dayOfYear === 0\n ) {\n getParsingFlags(config)._overflowDayOfYear = true;\n }\n\n date = createUTCDate(yearToUse, 0, config._dayOfYear);\n config._a[MONTH] = date.getUTCMonth();\n config._a[DATE] = date.getUTCDate();\n }\n\n // Default to current date.\n // * if no year, month, day of month are given, default to today\n // * if day of month is given, default month and year\n // * if month is given, default only year\n // * if year is given, don't default anything\n for (i = 0; i < 3 && config._a[i] == null; ++i) {\n config._a[i] = input[i] = currentDate[i];\n }\n\n // Zero out whatever was not defaulted, including time\n for (; i < 7; i++) {\n config._a[i] = input[i] =\n config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];\n }\n\n // Check for 24:00:00.000\n if (\n config._a[HOUR] === 24 &&\n config._a[MINUTE] === 0 &&\n config._a[SECOND] === 0 &&\n config._a[MILLISECOND] === 0\n ) {\n config._nextDay = true;\n config._a[HOUR] = 0;\n }\n\n config._d = (config._useUTC ? createUTCDate : createDate).apply(\n null,\n input\n );\n expectedWeekday = config._useUTC\n ? config._d.getUTCDay()\n : config._d.getDay();\n\n // Apply timezone offset from input. The actual utcOffset can be changed\n // with parseZone.\n if (config._tzm != null) {\n config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);\n }\n\n if (config._nextDay) {\n config._a[HOUR] = 24;\n }\n\n // check for mismatching day of week\n if (\n config._w &&\n typeof config._w.d !== 'undefined' &&\n config._w.d !== expectedWeekday\n ) {\n getParsingFlags(config).weekdayMismatch = true;\n }\n }\n\n function dayOfYearFromWeekInfo(config) {\n var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;\n\n w = config._w;\n if (w.GG != null || w.W != null || w.E != null) {\n dow = 1;\n doy = 4;\n\n // TODO: We need to take the current isoWeekYear, but that depends on\n // how we interpret now (local, utc, fixed offset). So create\n // a now version of current config (take local/utc/offset flags, and\n // create now).\n weekYear = defaults(\n w.GG,\n config._a[YEAR],\n weekOfYear(createLocal(), 1, 4).year\n );\n week = defaults(w.W, 1);\n weekday = defaults(w.E, 1);\n if (weekday < 1 || weekday > 7) {\n weekdayOverflow = true;\n }\n } else {\n dow = config._locale._week.dow;\n doy = config._locale._week.doy;\n\n curWeek = weekOfYear(createLocal(), dow, doy);\n\n weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);\n\n // Default to current week.\n week = defaults(w.w, curWeek.week);\n\n if (w.d != null) {\n // weekday -- low day numbers are considered next week\n weekday = w.d;\n if (weekday < 0 || weekday > 6) {\n weekdayOverflow = true;\n }\n } else if (w.e != null) {\n // local weekday -- counting starts from beginning of week\n weekday = w.e + dow;\n if (w.e < 0 || w.e > 6) {\n weekdayOverflow = true;\n }\n } else {\n // default to beginning of week\n weekday = dow;\n }\n }\n if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {\n getParsingFlags(config)._overflowWeeks = true;\n } else if (weekdayOverflow != null) {\n getParsingFlags(config)._overflowWeekday = true;\n } else {\n temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);\n config._a[YEAR] = temp.year;\n config._dayOfYear = temp.dayOfYear;\n }\n }\n\n // constant that refers to the ISO standard\n hooks.ISO_8601 = function () {};\n\n // constant that refers to the RFC 2822 form\n hooks.RFC_2822 = function () {};\n\n // date from string and format string\n function configFromStringAndFormat(config) {\n // TODO: Move this to another part of the creation flow to prevent circular deps\n if (config._f === hooks.ISO_8601) {\n configFromISO(config);\n return;\n }\n if (config._f === hooks.RFC_2822) {\n configFromRFC2822(config);\n return;\n }\n config._a = [];\n getParsingFlags(config).empty = true;\n\n // This array is used to make a Date, either with `new Date` or `Date.UTC`\n var string = '' + config._i,\n i,\n parsedInput,\n tokens,\n token,\n skipped,\n stringLength = string.length,\n totalParsedInputLength = 0,\n era,\n tokenLen;\n\n tokens =\n expandFormat(config._f, config._locale).match(formattingTokens) || [];\n tokenLen = tokens.length;\n for (i = 0; i < tokenLen; i++) {\n token = tokens[i];\n parsedInput = (string.match(getParseRegexForToken(token, config)) ||\n [])[0];\n if (parsedInput) {\n skipped = string.substr(0, string.indexOf(parsedInput));\n if (skipped.length > 0) {\n getParsingFlags(config).unusedInput.push(skipped);\n }\n string = string.slice(\n string.indexOf(parsedInput) + parsedInput.length\n );\n totalParsedInputLength += parsedInput.length;\n }\n // don't parse if it's not a known token\n if (formatTokenFunctions[token]) {\n if (parsedInput) {\n getParsingFlags(config).empty = false;\n } else {\n getParsingFlags(config).unusedTokens.push(token);\n }\n addTimeToArrayFromToken(token, parsedInput, config);\n } else if (config._strict && !parsedInput) {\n getParsingFlags(config).unusedTokens.push(token);\n }\n }\n\n // add remaining unparsed input length to the string\n getParsingFlags(config).charsLeftOver =\n stringLength - totalParsedInputLength;\n if (string.length > 0) {\n getParsingFlags(config).unusedInput.push(string);\n }\n\n // clear _12h flag if hour is <= 12\n if (\n config._a[HOUR] <= 12 &&\n getParsingFlags(config).bigHour === true &&\n config._a[HOUR] > 0\n ) {\n getParsingFlags(config).bigHour = undefined;\n }\n\n getParsingFlags(config).parsedDateParts = config._a.slice(0);\n getParsingFlags(config).meridiem = config._meridiem;\n // handle meridiem\n config._a[HOUR] = meridiemFixWrap(\n config._locale,\n config._a[HOUR],\n config._meridiem\n );\n\n // handle era\n era = getParsingFlags(config).era;\n if (era !== null) {\n config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);\n }\n\n configFromArray(config);\n checkOverflow(config);\n }\n\n function meridiemFixWrap(locale, hour, meridiem) {\n var isPm;\n\n if (meridiem == null) {\n // nothing to do\n return hour;\n }\n if (locale.meridiemHour != null) {\n return locale.meridiemHour(hour, meridiem);\n } else if (locale.isPM != null) {\n // Fallback\n isPm = locale.isPM(meridiem);\n if (isPm && hour < 12) {\n hour += 12;\n }\n if (!isPm && hour === 12) {\n hour = 0;\n }\n return hour;\n } else {\n // this is not supposed to happen\n return hour;\n }\n }\n\n // date from string and array of format strings\n function configFromStringAndArray(config) {\n var tempConfig,\n bestMoment,\n scoreToBeat,\n i,\n currentScore,\n validFormatFound,\n bestFormatIsValid = false,\n configfLen = config._f.length;\n\n if (configfLen === 0) {\n getParsingFlags(config).invalidFormat = true;\n config._d = new Date(NaN);\n return;\n }\n\n for (i = 0; i < configfLen; i++) {\n currentScore = 0;\n validFormatFound = false;\n tempConfig = copyConfig({}, config);\n if (config._useUTC != null) {\n tempConfig._useUTC = config._useUTC;\n }\n tempConfig._f = config._f[i];\n configFromStringAndFormat(tempConfig);\n\n if (isValid(tempConfig)) {\n validFormatFound = true;\n }\n\n // if there is any input that was not parsed add a penalty for that format\n currentScore += getParsingFlags(tempConfig).charsLeftOver;\n\n //or tokens\n currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;\n\n getParsingFlags(tempConfig).score = currentScore;\n\n if (!bestFormatIsValid) {\n if (\n scoreToBeat == null ||\n currentScore < scoreToBeat ||\n validFormatFound\n ) {\n scoreToBeat = currentScore;\n bestMoment = tempConfig;\n if (validFormatFound) {\n bestFormatIsValid = true;\n }\n }\n } else {\n if (currentScore < scoreToBeat) {\n scoreToBeat = currentScore;\n bestMoment = tempConfig;\n }\n }\n }\n\n extend(config, bestMoment || tempConfig);\n }\n\n function configFromObject(config) {\n if (config._d) {\n return;\n }\n\n var i = normalizeObjectUnits(config._i),\n dayOrDate = i.day === undefined ? i.date : i.day;\n config._a = map(\n [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],\n function (obj) {\n return obj && parseInt(obj, 10);\n }\n );\n\n configFromArray(config);\n }\n\n function createFromConfig(config) {\n var res = new Moment(checkOverflow(prepareConfig(config)));\n if (res._nextDay) {\n // Adding is smart enough around DST\n res.add(1, 'd');\n res._nextDay = undefined;\n }\n\n return res;\n }\n\n function prepareConfig(config) {\n var input = config._i,\n format = config._f;\n\n config._locale = config._locale || getLocale(config._l);\n\n if (input === null || (format === undefined && input === '')) {\n return createInvalid({ nullInput: true });\n }\n\n if (typeof input === 'string') {\n config._i = input = config._locale.preparse(input);\n }\n\n if (isMoment(input)) {\n return new Moment(checkOverflow(input));\n } else if (isDate(input)) {\n config._d = input;\n } else if (isArray(format)) {\n configFromStringAndArray(config);\n } else if (format) {\n configFromStringAndFormat(config);\n } else {\n configFromInput(config);\n }\n\n if (!isValid(config)) {\n config._d = null;\n }\n\n return config;\n }\n\n function configFromInput(config) {\n var input = config._i;\n if (isUndefined(input)) {\n config._d = new Date(hooks.now());\n } else if (isDate(input)) {\n config._d = new Date(input.valueOf());\n } else if (typeof input === 'string') {\n configFromString(config);\n } else if (isArray(input)) {\n config._a = map(input.slice(0), function (obj) {\n return parseInt(obj, 10);\n });\n configFromArray(config);\n } else if (isObject(input)) {\n configFromObject(config);\n } else if (isNumber(input)) {\n // from milliseconds\n config._d = new Date(input);\n } else {\n hooks.createFromInputFallback(config);\n }\n }\n\n function createLocalOrUTC(input, format, locale, strict, isUTC) {\n var c = {};\n\n if (format === true || format === false) {\n strict = format;\n format = undefined;\n }\n\n if (locale === true || locale === false) {\n strict = locale;\n locale = undefined;\n }\n\n if (\n (isObject(input) && isObjectEmpty(input)) ||\n (isArray(input) && input.length === 0)\n ) {\n input = undefined;\n }\n // object construction must be done this way.\n // https://github.com/moment/moment/issues/1423\n c._isAMomentObject = true;\n c._useUTC = c._isUTC = isUTC;\n c._l = locale;\n c._i = input;\n c._f = format;\n c._strict = strict;\n\n return createFromConfig(c);\n }\n\n function createLocal(input, format, locale, strict) {\n return createLocalOrUTC(input, format, locale, strict, false);\n }\n\n var prototypeMin = deprecate(\n 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',\n function () {\n var other = createLocal.apply(null, arguments);\n if (this.isValid() && other.isValid()) {\n return other < this ? this : other;\n } else {\n return createInvalid();\n }\n }\n ),\n prototypeMax = deprecate(\n 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',\n function () {\n var other = createLocal.apply(null, arguments);\n if (this.isValid() && other.isValid()) {\n return other > this ? this : other;\n } else {\n return createInvalid();\n }\n }\n );\n\n // Pick a moment m from moments so that m[fn](other) is true for all\n // other. This relies on the function fn to be transitive.\n //\n // moments should either be an array of moment objects or an array, whose\n // first element is an array of moment objects.\n function pickBy(fn, moments) {\n var res, i;\n if (moments.length === 1 && isArray(moments[0])) {\n moments = moments[0];\n }\n if (!moments.length) {\n return createLocal();\n }\n res = moments[0];\n for (i = 1; i < moments.length; ++i) {\n if (!moments[i].isValid() || moments[i][fn](res)) {\n res = moments[i];\n }\n }\n return res;\n }\n\n // TODO: Use [].sort instead?\n function min() {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isBefore', args);\n }\n\n function max() {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isAfter', args);\n }\n\n var now = function () {\n return Date.now ? Date.now() : +new Date();\n };\n\n var ordering = [\n 'year',\n 'quarter',\n 'month',\n 'week',\n 'day',\n 'hour',\n 'minute',\n 'second',\n 'millisecond',\n ];\n\n function isDurationValid(m) {\n var key,\n unitHasDecimal = false,\n i,\n orderLen = ordering.length;\n for (key in m) {\n if (\n hasOwnProp(m, key) &&\n !(\n indexOf.call(ordering, key) !== -1 &&\n (m[key] == null || !isNaN(m[key]))\n )\n ) {\n return false;\n }\n }\n\n for (i = 0; i < orderLen; ++i) {\n if (m[ordering[i]]) {\n if (unitHasDecimal) {\n return false; // only allow non-integers for smallest unit\n }\n if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {\n unitHasDecimal = true;\n }\n }\n }\n\n return true;\n }\n\n function isValid$1() {\n return this._isValid;\n }\n\n function createInvalid$1() {\n return createDuration(NaN);\n }\n\n function Duration(duration) {\n var normalizedInput = normalizeObjectUnits(duration),\n years = normalizedInput.year || 0,\n quarters = normalizedInput.quarter || 0,\n months = normalizedInput.month || 0,\n weeks = normalizedInput.week || normalizedInput.isoWeek || 0,\n days = normalizedInput.day || 0,\n hours = normalizedInput.hour || 0,\n minutes = normalizedInput.minute || 0,\n seconds = normalizedInput.second || 0,\n milliseconds = normalizedInput.millisecond || 0;\n\n this._isValid = isDurationValid(normalizedInput);\n\n // representation for dateAddRemove\n this._milliseconds =\n +milliseconds +\n seconds * 1e3 + // 1000\n minutes * 6e4 + // 1000 * 60\n hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978\n // Because of dateAddRemove treats 24 hours as different from a\n // day when working around DST, we need to store them separately\n this._days = +days + weeks * 7;\n // It is impossible to translate months into days without knowing\n // which months you are are talking about, so we have to store\n // it separately.\n this._months = +months + quarters * 3 + years * 12;\n\n this._data = {};\n\n this._locale = getLocale();\n\n this._bubble();\n }\n\n function isDuration(obj) {\n return obj instanceof Duration;\n }\n\n function absRound(number) {\n if (number < 0) {\n return Math.round(-1 * number) * -1;\n } else {\n return Math.round(number);\n }\n }\n\n // compare two arrays, return the number of differences\n function compareArrays(array1, array2, dontConvert) {\n var len = Math.min(array1.length, array2.length),\n lengthDiff = Math.abs(array1.length - array2.length),\n diffs = 0,\n i;\n for (i = 0; i < len; i++) {\n if (\n (dontConvert && array1[i] !== array2[i]) ||\n (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))\n ) {\n diffs++;\n }\n }\n return diffs + lengthDiff;\n }\n\n // FORMATTING\n\n function offset(token, separator) {\n addFormatToken(token, 0, 0, function () {\n var offset = this.utcOffset(),\n sign = '+';\n if (offset < 0) {\n offset = -offset;\n sign = '-';\n }\n return (\n sign +\n zeroFill(~~(offset / 60), 2) +\n separator +\n zeroFill(~~offset % 60, 2)\n );\n });\n }\n\n offset('Z', ':');\n offset('ZZ', '');\n\n // PARSING\n\n addRegexToken('Z', matchShortOffset);\n addRegexToken('ZZ', matchShortOffset);\n addParseToken(['Z', 'ZZ'], function (input, array, config) {\n config._useUTC = true;\n config._tzm = offsetFromString(matchShortOffset, input);\n });\n\n // HELPERS\n\n // timezone chunker\n // '+10:00' > ['10', '00']\n // '-1530' > ['-15', '30']\n var chunkOffset = /([\\+\\-]|\\d\\d)/gi;\n\n function offsetFromString(matcher, string) {\n var matches = (string || '').match(matcher),\n chunk,\n parts,\n minutes;\n\n if (matches === null) {\n return null;\n }\n\n chunk = matches[matches.length - 1] || [];\n parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];\n minutes = +(parts[1] * 60) + toInt(parts[2]);\n\n return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;\n }\n\n // Return a moment from input, that is local/utc/zone equivalent to model.\n function cloneWithOffset(input, model) {\n var res, diff;\n if (model._isUTC) {\n res = model.clone();\n diff =\n (isMoment(input) || isDate(input)\n ? input.valueOf()\n : createLocal(input).valueOf()) - res.valueOf();\n // Use low-level api, because this fn is low-level api.\n res._d.setTime(res._d.valueOf() + diff);\n hooks.updateOffset(res, false);\n return res;\n } else {\n return createLocal(input).local();\n }\n }\n\n function getDateOffset(m) {\n // On Firefox.24 Date#getTimezoneOffset returns a floating point.\n // https://github.com/moment/moment/pull/1871\n return -Math.round(m._d.getTimezoneOffset());\n }\n\n // HOOKS\n\n // This function will be called whenever a moment is mutated.\n // It is intended to keep the offset in sync with the timezone.\n hooks.updateOffset = function () {};\n\n // MOMENTS\n\n // keepLocalTime = true means only change the timezone, without\n // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->\n // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset\n // +0200, so we adjust the time as needed, to be valid.\n //\n // Keeping the time actually adds/subtracts (one hour)\n // from the actual represented time. That is why we call updateOffset\n // a second time. In case it wants us to change the offset again\n // _changeInProgress == true case, then we have to adjust, because\n // there is no such time in the given timezone.\n function getSetOffset(input, keepLocalTime, keepMinutes) {\n var offset = this._offset || 0,\n localAdjust;\n if (!this.isValid()) {\n return input != null ? this : NaN;\n }\n if (input != null) {\n if (typeof input === 'string') {\n input = offsetFromString(matchShortOffset, input);\n if (input === null) {\n return this;\n }\n } else if (Math.abs(input) < 16 && !keepMinutes) {\n input = input * 60;\n }\n if (!this._isUTC && keepLocalTime) {\n localAdjust = getDateOffset(this);\n }\n this._offset = input;\n this._isUTC = true;\n if (localAdjust != null) {\n this.add(localAdjust, 'm');\n }\n if (offset !== input) {\n if (!keepLocalTime || this._changeInProgress) {\n addSubtract(\n this,\n createDuration(input - offset, 'm'),\n 1,\n false\n );\n } else if (!this._changeInProgress) {\n this._changeInProgress = true;\n hooks.updateOffset(this, true);\n this._changeInProgress = null;\n }\n }\n return this;\n } else {\n return this._isUTC ? offset : getDateOffset(this);\n }\n }\n\n function getSetZone(input, keepLocalTime) {\n if (input != null) {\n if (typeof input !== 'string') {\n input = -input;\n }\n\n this.utcOffset(input, keepLocalTime);\n\n return this;\n } else {\n return -this.utcOffset();\n }\n }\n\n function setOffsetToUTC(keepLocalTime) {\n return this.utcOffset(0, keepLocalTime);\n }\n\n function setOffsetToLocal(keepLocalTime) {\n if (this._isUTC) {\n this.utcOffset(0, keepLocalTime);\n this._isUTC = false;\n\n if (keepLocalTime) {\n this.subtract(getDateOffset(this), 'm');\n }\n }\n return this;\n }\n\n function setOffsetToParsedOffset() {\n if (this._tzm != null) {\n this.utcOffset(this._tzm, false, true);\n } else if (typeof this._i === 'string') {\n var tZone = offsetFromString(matchOffset, this._i);\n if (tZone != null) {\n this.utcOffset(tZone);\n } else {\n this.utcOffset(0, true);\n }\n }\n return this;\n }\n\n function hasAlignedHourOffset(input) {\n if (!this.isValid()) {\n return false;\n }\n input = input ? createLocal(input).utcOffset() : 0;\n\n return (this.utcOffset() - input) % 60 === 0;\n }\n\n function isDaylightSavingTime() {\n return (\n this.utcOffset() > this.clone().month(0).utcOffset() ||\n this.utcOffset() > this.clone().month(5).utcOffset()\n );\n }\n\n function isDaylightSavingTimeShifted() {\n if (!isUndefined(this._isDSTShifted)) {\n return this._isDSTShifted;\n }\n\n var c = {},\n other;\n\n copyConfig(c, this);\n c = prepareConfig(c);\n\n if (c._a) {\n other = c._isUTC ? createUTC(c._a) : createLocal(c._a);\n this._isDSTShifted =\n this.isValid() && compareArrays(c._a, other.toArray()) > 0;\n } else {\n this._isDSTShifted = false;\n }\n\n return this._isDSTShifted;\n }\n\n function isLocal() {\n return this.isValid() ? !this._isUTC : false;\n }\n\n function isUtcOffset() {\n return this.isValid() ? this._isUTC : false;\n }\n\n function isUtc() {\n return this.isValid() ? this._isUTC && this._offset === 0 : false;\n }\n\n // ASP.NET json date format regex\n var aspNetRegex = /^(-|\\+)?(?:(\\d*)[. ])?(\\d+):(\\d+)(?::(\\d+)(\\.\\d*)?)?$/,\n // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html\n // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere\n // and further modified to allow for strings containing both week and day\n isoRegex =\n /^(-|\\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;\n\n function createDuration(input, key) {\n var duration = input,\n // matching against regexp is expensive, do it on demand\n match = null,\n sign,\n ret,\n diffRes;\n\n if (isDuration(input)) {\n duration = {\n ms: input._milliseconds,\n d: input._days,\n M: input._months,\n };\n } else if (isNumber(input) || !isNaN(+input)) {\n duration = {};\n if (key) {\n duration[key] = +input;\n } else {\n duration.milliseconds = +input;\n }\n } else if ((match = aspNetRegex.exec(input))) {\n sign = match[1] === '-' ? -1 : 1;\n duration = {\n y: 0,\n d: toInt(match[DATE]) * sign,\n h: toInt(match[HOUR]) * sign,\n m: toInt(match[MINUTE]) * sign,\n s: toInt(match[SECOND]) * sign,\n ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match\n };\n } else if ((match = isoRegex.exec(input))) {\n sign = match[1] === '-' ? -1 : 1;\n duration = {\n y: parseIso(match[2], sign),\n M: parseIso(match[3], sign),\n w: parseIso(match[4], sign),\n d: parseIso(match[5], sign),\n h: parseIso(match[6], sign),\n m: parseIso(match[7], sign),\n s: parseIso(match[8], sign),\n };\n } else if (duration == null) {\n // checks for null or undefined\n duration = {};\n } else if (\n typeof duration === 'object' &&\n ('from' in duration || 'to' in duration)\n ) {\n diffRes = momentsDifference(\n createLocal(duration.from),\n createLocal(duration.to)\n );\n\n duration = {};\n duration.ms = diffRes.milliseconds;\n duration.M = diffRes.months;\n }\n\n ret = new Duration(duration);\n\n if (isDuration(input) && hasOwnProp(input, '_locale')) {\n ret._locale = input._locale;\n }\n\n if (isDuration(input) && hasOwnProp(input, '_isValid')) {\n ret._isValid = input._isValid;\n }\n\n return ret;\n }\n\n createDuration.fn = Duration.prototype;\n createDuration.invalid = createInvalid$1;\n\n function parseIso(inp, sign) {\n // We'd normally use ~~inp for this, but unfortunately it also\n // converts floats to ints.\n // inp may be undefined, so careful calling replace on it.\n var res = inp && parseFloat(inp.replace(',', '.'));\n // apply sign while we're at it\n return (isNaN(res) ? 0 : res) * sign;\n }\n\n function positiveMomentsDifference(base, other) {\n var res = {};\n\n res.months =\n other.month() - base.month() + (other.year() - base.year()) * 12;\n if (base.clone().add(res.months, 'M').isAfter(other)) {\n --res.months;\n }\n\n res.milliseconds = +other - +base.clone().add(res.months, 'M');\n\n return res;\n }\n\n function momentsDifference(base, other) {\n var res;\n if (!(base.isValid() && other.isValid())) {\n return { milliseconds: 0, months: 0 };\n }\n\n other = cloneWithOffset(other, base);\n if (base.isBefore(other)) {\n res = positiveMomentsDifference(base, other);\n } else {\n res = positiveMomentsDifference(other, base);\n res.milliseconds = -res.milliseconds;\n res.months = -res.months;\n }\n\n return res;\n }\n\n // TODO: remove 'name' arg after deprecation is removed\n function createAdder(direction, name) {\n return function (val, period) {\n var dur, tmp;\n //invert the arguments, but complain about it\n if (period !== null && !isNaN(+period)) {\n deprecateSimple(\n name,\n 'moment().' +\n name +\n '(period, number) is deprecated. Please use moment().' +\n name +\n '(number, period). ' +\n 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'\n );\n tmp = val;\n val = period;\n period = tmp;\n }\n\n dur = createDuration(val, period);\n addSubtract(this, dur, direction);\n return this;\n };\n }\n\n function addSubtract(mom, duration, isAdding, updateOffset) {\n var milliseconds = duration._milliseconds,\n days = absRound(duration._days),\n months = absRound(duration._months);\n\n if (!mom.isValid()) {\n // No op\n return;\n }\n\n updateOffset = updateOffset == null ? true : updateOffset;\n\n if (months) {\n setMonth(mom, get(mom, 'Month') + months * isAdding);\n }\n if (days) {\n set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);\n }\n if (milliseconds) {\n mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);\n }\n if (updateOffset) {\n hooks.updateOffset(mom, days || months);\n }\n }\n\n var add = createAdder(1, 'add'),\n subtract = createAdder(-1, 'subtract');\n\n function isString(input) {\n return typeof input === 'string' || input instanceof String;\n }\n\n // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined\n function isMomentInput(input) {\n return (\n isMoment(input) ||\n isDate(input) ||\n isString(input) ||\n isNumber(input) ||\n isNumberOrStringArray(input) ||\n isMomentInputObject(input) ||\n input === null ||\n input === undefined\n );\n }\n\n function isMomentInputObject(input) {\n var objectTest = isObject(input) && !isObjectEmpty(input),\n propertyTest = false,\n properties = [\n 'years',\n 'year',\n 'y',\n 'months',\n 'month',\n 'M',\n 'days',\n 'day',\n 'd',\n 'dates',\n 'date',\n 'D',\n 'hours',\n 'hour',\n 'h',\n 'minutes',\n 'minute',\n 'm',\n 'seconds',\n 'second',\n 's',\n 'milliseconds',\n 'millisecond',\n 'ms',\n ],\n i,\n property,\n propertyLen = properties.length;\n\n for (i = 0; i < propertyLen; i += 1) {\n property = properties[i];\n propertyTest = propertyTest || hasOwnProp(input, property);\n }\n\n return objectTest && propertyTest;\n }\n\n function isNumberOrStringArray(input) {\n var arrayTest = isArray(input),\n dataTypeTest = false;\n if (arrayTest) {\n dataTypeTest =\n input.filter(function (item) {\n return !isNumber(item) && isString(input);\n }).length === 0;\n }\n return arrayTest && dataTypeTest;\n }\n\n function isCalendarSpec(input) {\n var objectTest = isObject(input) && !isObjectEmpty(input),\n propertyTest = false,\n properties = [\n 'sameDay',\n 'nextDay',\n 'lastDay',\n 'nextWeek',\n 'lastWeek',\n 'sameElse',\n ],\n i,\n property;\n\n for (i = 0; i < properties.length; i += 1) {\n property = properties[i];\n propertyTest = propertyTest || hasOwnProp(input, property);\n }\n\n return objectTest && propertyTest;\n }\n\n function getCalendarFormat(myMoment, now) {\n var diff = myMoment.diff(now, 'days', true);\n return diff < -6\n ? 'sameElse'\n : diff < -1\n ? 'lastWeek'\n : diff < 0\n ? 'lastDay'\n : diff < 1\n ? 'sameDay'\n : diff < 2\n ? 'nextDay'\n : diff < 7\n ? 'nextWeek'\n : 'sameElse';\n }\n\n function calendar$1(time, formats) {\n // Support for single parameter, formats only overload to the calendar function\n if (arguments.length === 1) {\n if (!arguments[0]) {\n time = undefined;\n formats = undefined;\n } else if (isMomentInput(arguments[0])) {\n time = arguments[0];\n formats = undefined;\n } else if (isCalendarSpec(arguments[0])) {\n formats = arguments[0];\n time = undefined;\n }\n }\n // We want to compare the start of today, vs this.\n // Getting start-of-today depends on whether we're local/utc/offset or not.\n var now = time || createLocal(),\n sod = cloneWithOffset(now, this).startOf('day'),\n format = hooks.calendarFormat(this, sod) || 'sameElse',\n output =\n formats &&\n (isFunction(formats[format])\n ? formats[format].call(this, now)\n : formats[format]);\n\n return this.format(\n output || this.localeData().calendar(format, this, createLocal(now))\n );\n }\n\n function clone() {\n return new Moment(this);\n }\n\n function isAfter(input, units) {\n var localInput = isMoment(input) ? input : createLocal(input);\n if (!(this.isValid() && localInput.isValid())) {\n return false;\n }\n units = normalizeUnits(units) || 'millisecond';\n if (units === 'millisecond') {\n return this.valueOf() > localInput.valueOf();\n } else {\n return localInput.valueOf() < this.clone().startOf(units).valueOf();\n }\n }\n\n function isBefore(input, units) {\n var localInput = isMoment(input) ? input : createLocal(input);\n if (!(this.isValid() && localInput.isValid())) {\n return false;\n }\n units = normalizeUnits(units) || 'millisecond';\n if (units === 'millisecond') {\n return this.valueOf() < localInput.valueOf();\n } else {\n return this.clone().endOf(units).valueOf() < localInput.valueOf();\n }\n }\n\n function isBetween(from, to, units, inclusivity) {\n var localFrom = isMoment(from) ? from : createLocal(from),\n localTo = isMoment(to) ? to : createLocal(to);\n if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {\n return false;\n }\n inclusivity = inclusivity || '()';\n return (\n (inclusivity[0] === '('\n ? this.isAfter(localFrom, units)\n : !this.isBefore(localFrom, units)) &&\n (inclusivity[1] === ')'\n ? this.isBefore(localTo, units)\n : !this.isAfter(localTo, units))\n );\n }\n\n function isSame(input, units) {\n var localInput = isMoment(input) ? input : createLocal(input),\n inputMs;\n if (!(this.isValid() && localInput.isValid())) {\n return false;\n }\n units = normalizeUnits(units) || 'millisecond';\n if (units === 'millisecond') {\n return this.valueOf() === localInput.valueOf();\n } else {\n inputMs = localInput.valueOf();\n return (\n this.clone().startOf(units).valueOf() <= inputMs &&\n inputMs <= this.clone().endOf(units).valueOf()\n );\n }\n }\n\n function isSameOrAfter(input, units) {\n return this.isSame(input, units) || this.isAfter(input, units);\n }\n\n function isSameOrBefore(input, units) {\n return this.isSame(input, units) || this.isBefore(input, units);\n }\n\n function diff(input, units, asFloat) {\n var that, zoneDelta, output;\n\n if (!this.isValid()) {\n return NaN;\n }\n\n that = cloneWithOffset(input, this);\n\n if (!that.isValid()) {\n return NaN;\n }\n\n zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;\n\n units = normalizeUnits(units);\n\n switch (units) {\n case 'year':\n output = monthDiff(this, that) / 12;\n break;\n case 'month':\n output = monthDiff(this, that);\n break;\n case 'quarter':\n output = monthDiff(this, that) / 3;\n break;\n case 'second':\n output = (this - that) / 1e3;\n break; // 1000\n case 'minute':\n output = (this - that) / 6e4;\n break; // 1000 * 60\n case 'hour':\n output = (this - that) / 36e5;\n break; // 1000 * 60 * 60\n case 'day':\n output = (this - that - zoneDelta) / 864e5;\n break; // 1000 * 60 * 60 * 24, negate dst\n case 'week':\n output = (this - that - zoneDelta) / 6048e5;\n break; // 1000 * 60 * 60 * 24 * 7, negate dst\n default:\n output = this - that;\n }\n\n return asFloat ? output : absFloor(output);\n }\n\n function monthDiff(a, b) {\n if (a.date() < b.date()) {\n // end-of-month calculations work correct when the start month has more\n // days than the end month.\n return -monthDiff(b, a);\n }\n // difference in months\n var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),\n // b is in (anchor - 1 month, anchor + 1 month)\n anchor = a.clone().add(wholeMonthDiff, 'months'),\n anchor2,\n adjust;\n\n if (b - anchor < 0) {\n anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor - anchor2);\n } else {\n anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor2 - anchor);\n }\n\n //check for negative zero, return zero if negative zero\n return -(wholeMonthDiff + adjust) || 0;\n }\n\n hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';\n hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';\n\n function toString() {\n return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');\n }\n\n function toISOString(keepOffset) {\n if (!this.isValid()) {\n return null;\n }\n var utc = keepOffset !== true,\n m = utc ? this.clone().utc() : this;\n if (m.year() < 0 || m.year() > 9999) {\n return formatMoment(\n m,\n utc\n ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'\n : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'\n );\n }\n if (isFunction(Date.prototype.toISOString)) {\n // native implementation is ~50x faster, use it when we can\n if (utc) {\n return this.toDate().toISOString();\n } else {\n return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)\n .toISOString()\n .replace('Z', formatMoment(m, 'Z'));\n }\n }\n return formatMoment(\n m,\n utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'\n );\n }\n\n /**\n * Return a human readable representation of a moment that can\n * also be evaluated to get a new moment which is the same\n *\n * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects\n */\n function inspect() {\n if (!this.isValid()) {\n return 'moment.invalid(/* ' + this._i + ' */)';\n }\n var func = 'moment',\n zone = '',\n prefix,\n year,\n datetime,\n suffix;\n if (!this.isLocal()) {\n func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';\n zone = 'Z';\n }\n prefix = '[' + func + '(\"]';\n year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';\n datetime = '-MM-DD[T]HH:mm:ss.SSS';\n suffix = zone + '[\")]';\n\n return this.format(prefix + year + datetime + suffix);\n }\n\n function format(inputString) {\n if (!inputString) {\n inputString = this.isUtc()\n ? hooks.defaultFormatUtc\n : hooks.defaultFormat;\n }\n var output = formatMoment(this, inputString);\n return this.localeData().postformat(output);\n }\n\n function from(time, withoutSuffix) {\n if (\n this.isValid() &&\n ((isMoment(time) && time.isValid()) || createLocal(time).isValid())\n ) {\n return createDuration({ to: this, from: time })\n .locale(this.locale())\n .humanize(!withoutSuffix);\n } else {\n return this.localeData().invalidDate();\n }\n }\n\n function fromNow(withoutSuffix) {\n return this.from(createLocal(), withoutSuffix);\n }\n\n function to(time, withoutSuffix) {\n if (\n this.isValid() &&\n ((isMoment(time) && time.isValid()) || createLocal(time).isValid())\n ) {\n return createDuration({ from: this, to: time })\n .locale(this.locale())\n .humanize(!withoutSuffix);\n } else {\n return this.localeData().invalidDate();\n }\n }\n\n function toNow(withoutSuffix) {\n return this.to(createLocal(), withoutSuffix);\n }\n\n // If passed a locale key, it will set the locale for this\n // instance. Otherwise, it will return the locale configuration\n // variables for this instance.\n function locale(key) {\n var newLocaleData;\n\n if (key === undefined) {\n return this._locale._abbr;\n } else {\n newLocaleData = getLocale(key);\n if (newLocaleData != null) {\n this._locale = newLocaleData;\n }\n return this;\n }\n }\n\n var lang = deprecate(\n 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',\n function (key) {\n if (key === undefined) {\n return this.localeData();\n } else {\n return this.locale(key);\n }\n }\n );\n\n function localeData() {\n return this._locale;\n }\n\n var MS_PER_SECOND = 1000,\n MS_PER_MINUTE = 60 * MS_PER_SECOND,\n MS_PER_HOUR = 60 * MS_PER_MINUTE,\n MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;\n\n // actual modulo - handles negative numbers (for dates before 1970):\n function mod$1(dividend, divisor) {\n return ((dividend % divisor) + divisor) % divisor;\n }\n\n function localStartOfDate(y, m, d) {\n // the date constructor remaps years 0-99 to 1900-1999\n if (y < 100 && y >= 0) {\n // preserve leap years using a full 400 year cycle, then reset\n return new Date(y + 400, m, d) - MS_PER_400_YEARS;\n } else {\n return new Date(y, m, d).valueOf();\n }\n }\n\n function utcStartOfDate(y, m, d) {\n // Date.UTC remaps years 0-99 to 1900-1999\n if (y < 100 && y >= 0) {\n // preserve leap years using a full 400 year cycle, then reset\n return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;\n } else {\n return Date.UTC(y, m, d);\n }\n }\n\n function startOf(units) {\n var time, startOfDate;\n units = normalizeUnits(units);\n if (units === undefined || units === 'millisecond' || !this.isValid()) {\n return this;\n }\n\n startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;\n\n switch (units) {\n case 'year':\n time = startOfDate(this.year(), 0, 1);\n break;\n case 'quarter':\n time = startOfDate(\n this.year(),\n this.month() - (this.month() % 3),\n 1\n );\n break;\n case 'month':\n time = startOfDate(this.year(), this.month(), 1);\n break;\n case 'week':\n time = startOfDate(\n this.year(),\n this.month(),\n this.date() - this.weekday()\n );\n break;\n case 'isoWeek':\n time = startOfDate(\n this.year(),\n this.month(),\n this.date() - (this.isoWeekday() - 1)\n );\n break;\n case 'day':\n case 'date':\n time = startOfDate(this.year(), this.month(), this.date());\n break;\n case 'hour':\n time = this._d.valueOf();\n time -= mod$1(\n time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),\n MS_PER_HOUR\n );\n break;\n case 'minute':\n time = this._d.valueOf();\n time -= mod$1(time, MS_PER_MINUTE);\n break;\n case 'second':\n time = this._d.valueOf();\n time -= mod$1(time, MS_PER_SECOND);\n break;\n }\n\n this._d.setTime(time);\n hooks.updateOffset(this, true);\n return this;\n }\n\n function endOf(units) {\n var time, startOfDate;\n units = normalizeUnits(units);\n if (units === undefined || units === 'millisecond' || !this.isValid()) {\n return this;\n }\n\n startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;\n\n switch (units) {\n case 'year':\n time = startOfDate(this.year() + 1, 0, 1) - 1;\n break;\n case 'quarter':\n time =\n startOfDate(\n this.year(),\n this.month() - (this.month() % 3) + 3,\n 1\n ) - 1;\n break;\n case 'month':\n time = startOfDate(this.year(), this.month() + 1, 1) - 1;\n break;\n case 'week':\n time =\n startOfDate(\n this.year(),\n this.month(),\n this.date() - this.weekday() + 7\n ) - 1;\n break;\n case 'isoWeek':\n time =\n startOfDate(\n this.year(),\n this.month(),\n this.date() - (this.isoWeekday() - 1) + 7\n ) - 1;\n break;\n case 'day':\n case 'date':\n time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;\n break;\n case 'hour':\n time = this._d.valueOf();\n time +=\n MS_PER_HOUR -\n mod$1(\n time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),\n MS_PER_HOUR\n ) -\n 1;\n break;\n case 'minute':\n time = this._d.valueOf();\n time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;\n break;\n case 'second':\n time = this._d.valueOf();\n time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;\n break;\n }\n\n this._d.setTime(time);\n hooks.updateOffset(this, true);\n return this;\n }\n\n function valueOf() {\n return this._d.valueOf() - (this._offset || 0) * 60000;\n }\n\n function unix() {\n return Math.floor(this.valueOf() / 1000);\n }\n\n function toDate() {\n return new Date(this.valueOf());\n }\n\n function toArray() {\n var m = this;\n return [\n m.year(),\n m.month(),\n m.date(),\n m.hour(),\n m.minute(),\n m.second(),\n m.millisecond(),\n ];\n }\n\n function toObject() {\n var m = this;\n return {\n years: m.year(),\n months: m.month(),\n date: m.date(),\n hours: m.hours(),\n minutes: m.minutes(),\n seconds: m.seconds(),\n milliseconds: m.milliseconds(),\n };\n }\n\n function toJSON() {\n // new Date(NaN).toJSON() === null\n return this.isValid() ? this.toISOString() : null;\n }\n\n function isValid$2() {\n return isValid(this);\n }\n\n function parsingFlags() {\n return extend({}, getParsingFlags(this));\n }\n\n function invalidAt() {\n return getParsingFlags(this).overflow;\n }\n\n function creationData() {\n return {\n input: this._i,\n format: this._f,\n locale: this._locale,\n isUTC: this._isUTC,\n strict: this._strict,\n };\n }\n\n addFormatToken('N', 0, 0, 'eraAbbr');\n addFormatToken('NN', 0, 0, 'eraAbbr');\n addFormatToken('NNN', 0, 0, 'eraAbbr');\n addFormatToken('NNNN', 0, 0, 'eraName');\n addFormatToken('NNNNN', 0, 0, 'eraNarrow');\n\n addFormatToken('y', ['y', 1], 'yo', 'eraYear');\n addFormatToken('y', ['yy', 2], 0, 'eraYear');\n addFormatToken('y', ['yyy', 3], 0, 'eraYear');\n addFormatToken('y', ['yyyy', 4], 0, 'eraYear');\n\n addRegexToken('N', matchEraAbbr);\n addRegexToken('NN', matchEraAbbr);\n addRegexToken('NNN', matchEraAbbr);\n addRegexToken('NNNN', matchEraName);\n addRegexToken('NNNNN', matchEraNarrow);\n\n addParseToken(\n ['N', 'NN', 'NNN', 'NNNN', 'NNNNN'],\n function (input, array, config, token) {\n var era = config._locale.erasParse(input, token, config._strict);\n if (era) {\n getParsingFlags(config).era = era;\n } else {\n getParsingFlags(config).invalidEra = input;\n }\n }\n );\n\n addRegexToken('y', matchUnsigned);\n addRegexToken('yy', matchUnsigned);\n addRegexToken('yyy', matchUnsigned);\n addRegexToken('yyyy', matchUnsigned);\n addRegexToken('yo', matchEraYearOrdinal);\n\n addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);\n addParseToken(['yo'], function (input, array, config, token) {\n var match;\n if (config._locale._eraYearOrdinalRegex) {\n match = input.match(config._locale._eraYearOrdinalRegex);\n }\n\n if (config._locale.eraYearOrdinalParse) {\n array[YEAR] = config._locale.eraYearOrdinalParse(input, match);\n } else {\n array[YEAR] = parseInt(input, 10);\n }\n });\n\n function localeEras(m, format) {\n var i,\n l,\n date,\n eras = this._eras || getLocale('en')._eras;\n for (i = 0, l = eras.length; i < l; ++i) {\n switch (typeof eras[i].since) {\n case 'string':\n // truncate time\n date = hooks(eras[i].since).startOf('day');\n eras[i].since = date.valueOf();\n break;\n }\n\n switch (typeof eras[i].until) {\n case 'undefined':\n eras[i].until = +Infinity;\n break;\n case 'string':\n // truncate time\n date = hooks(eras[i].until).startOf('day').valueOf();\n eras[i].until = date.valueOf();\n break;\n }\n }\n return eras;\n }\n\n function localeErasParse(eraName, format, strict) {\n var i,\n l,\n eras = this.eras(),\n name,\n abbr,\n narrow;\n eraName = eraName.toUpperCase();\n\n for (i = 0, l = eras.length; i < l; ++i) {\n name = eras[i].name.toUpperCase();\n abbr = eras[i].abbr.toUpperCase();\n narrow = eras[i].narrow.toUpperCase();\n\n if (strict) {\n switch (format) {\n case 'N':\n case 'NN':\n case 'NNN':\n if (abbr === eraName) {\n return eras[i];\n }\n break;\n\n case 'NNNN':\n if (name === eraName) {\n return eras[i];\n }\n break;\n\n case 'NNNNN':\n if (narrow === eraName) {\n return eras[i];\n }\n break;\n }\n } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {\n return eras[i];\n }\n }\n }\n\n function localeErasConvertYear(era, year) {\n var dir = era.since <= era.until ? +1 : -1;\n if (year === undefined) {\n return hooks(era.since).year();\n } else {\n return hooks(era.since).year() + (year - era.offset) * dir;\n }\n }\n\n function getEraName() {\n var i,\n l,\n val,\n eras = this.localeData().eras();\n for (i = 0, l = eras.length; i < l; ++i) {\n // truncate time\n val = this.clone().startOf('day').valueOf();\n\n if (eras[i].since <= val && val <= eras[i].until) {\n return eras[i].name;\n }\n if (eras[i].until <= val && val <= eras[i].since) {\n return eras[i].name;\n }\n }\n\n return '';\n }\n\n function getEraNarrow() {\n var i,\n l,\n val,\n eras = this.localeData().eras();\n for (i = 0, l = eras.length; i < l; ++i) {\n // truncate time\n val = this.clone().startOf('day').valueOf();\n\n if (eras[i].since <= val && val <= eras[i].until) {\n return eras[i].narrow;\n }\n if (eras[i].until <= val && val <= eras[i].since) {\n return eras[i].narrow;\n }\n }\n\n return '';\n }\n\n function getEraAbbr() {\n var i,\n l,\n val,\n eras = this.localeData().eras();\n for (i = 0, l = eras.length; i < l; ++i) {\n // truncate time\n val = this.clone().startOf('day').valueOf();\n\n if (eras[i].since <= val && val <= eras[i].until) {\n return eras[i].abbr;\n }\n if (eras[i].until <= val && val <= eras[i].since) {\n return eras[i].abbr;\n }\n }\n\n return '';\n }\n\n function getEraYear() {\n var i,\n l,\n dir,\n val,\n eras = this.localeData().eras();\n for (i = 0, l = eras.length; i < l; ++i) {\n dir = eras[i].since <= eras[i].until ? +1 : -1;\n\n // truncate time\n val = this.clone().startOf('day').valueOf();\n\n if (\n (eras[i].since <= val && val <= eras[i].until) ||\n (eras[i].until <= val && val <= eras[i].since)\n ) {\n return (\n (this.year() - hooks(eras[i].since).year()) * dir +\n eras[i].offset\n );\n }\n }\n\n return this.year();\n }\n\n function erasNameRegex(isStrict) {\n if (!hasOwnProp(this, '_erasNameRegex')) {\n computeErasParse.call(this);\n }\n return isStrict ? this._erasNameRegex : this._erasRegex;\n }\n\n function erasAbbrRegex(isStrict) {\n if (!hasOwnProp(this, '_erasAbbrRegex')) {\n computeErasParse.call(this);\n }\n return isStrict ? this._erasAbbrRegex : this._erasRegex;\n }\n\n function erasNarrowRegex(isStrict) {\n if (!hasOwnProp(this, '_erasNarrowRegex')) {\n computeErasParse.call(this);\n }\n return isStrict ? this._erasNarrowRegex : this._erasRegex;\n }\n\n function matchEraAbbr(isStrict, locale) {\n return locale.erasAbbrRegex(isStrict);\n }\n\n function matchEraName(isStrict, locale) {\n return locale.erasNameRegex(isStrict);\n }\n\n function matchEraNarrow(isStrict, locale) {\n return locale.erasNarrowRegex(isStrict);\n }\n\n function matchEraYearOrdinal(isStrict, locale) {\n return locale._eraYearOrdinalRegex || matchUnsigned;\n }\n\n function computeErasParse() {\n var abbrPieces = [],\n namePieces = [],\n narrowPieces = [],\n mixedPieces = [],\n i,\n l,\n erasName,\n erasAbbr,\n erasNarrow,\n eras = this.eras();\n\n for (i = 0, l = eras.length; i < l; ++i) {\n erasName = regexEscape(eras[i].name);\n erasAbbr = regexEscape(eras[i].abbr);\n erasNarrow = regexEscape(eras[i].narrow);\n\n namePieces.push(erasName);\n abbrPieces.push(erasAbbr);\n narrowPieces.push(erasNarrow);\n mixedPieces.push(erasName);\n mixedPieces.push(erasAbbr);\n mixedPieces.push(erasNarrow);\n }\n\n this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');\n this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');\n this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');\n this._erasNarrowRegex = new RegExp(\n '^(' + narrowPieces.join('|') + ')',\n 'i'\n );\n }\n\n // FORMATTING\n\n addFormatToken(0, ['gg', 2], 0, function () {\n return this.weekYear() % 100;\n });\n\n addFormatToken(0, ['GG', 2], 0, function () {\n return this.isoWeekYear() % 100;\n });\n\n function addWeekYearFormatToken(token, getter) {\n addFormatToken(0, [token, token.length], 0, getter);\n }\n\n addWeekYearFormatToken('gggg', 'weekYear');\n addWeekYearFormatToken('ggggg', 'weekYear');\n addWeekYearFormatToken('GGGG', 'isoWeekYear');\n addWeekYearFormatToken('GGGGG', 'isoWeekYear');\n\n // ALIASES\n\n // PARSING\n\n addRegexToken('G', matchSigned);\n addRegexToken('g', matchSigned);\n addRegexToken('GG', match1to2, match2);\n addRegexToken('gg', match1to2, match2);\n addRegexToken('GGGG', match1to4, match4);\n addRegexToken('gggg', match1to4, match4);\n addRegexToken('GGGGG', match1to6, match6);\n addRegexToken('ggggg', match1to6, match6);\n\n addWeekParseToken(\n ['gggg', 'ggggg', 'GGGG', 'GGGGG'],\n function (input, week, config, token) {\n week[token.substr(0, 2)] = toInt(input);\n }\n );\n\n addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {\n week[token] = hooks.parseTwoDigitYear(input);\n });\n\n // MOMENTS\n\n function getSetWeekYear(input) {\n return getSetWeekYearHelper.call(\n this,\n input,\n this.week(),\n this.weekday() + this.localeData()._week.dow,\n this.localeData()._week.dow,\n this.localeData()._week.doy\n );\n }\n\n function getSetISOWeekYear(input) {\n return getSetWeekYearHelper.call(\n this,\n input,\n this.isoWeek(),\n this.isoWeekday(),\n 1,\n 4\n );\n }\n\n function getISOWeeksInYear() {\n return weeksInYear(this.year(), 1, 4);\n }\n\n function getISOWeeksInISOWeekYear() {\n return weeksInYear(this.isoWeekYear(), 1, 4);\n }\n\n function getWeeksInYear() {\n var weekInfo = this.localeData()._week;\n return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);\n }\n\n function getWeeksInWeekYear() {\n var weekInfo = this.localeData()._week;\n return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);\n }\n\n function getSetWeekYearHelper(input, week, weekday, dow, doy) {\n var weeksTarget;\n if (input == null) {\n return weekOfYear(this, dow, doy).year;\n } else {\n weeksTarget = weeksInYear(input, dow, doy);\n if (week > weeksTarget) {\n week = weeksTarget;\n }\n return setWeekAll.call(this, input, week, weekday, dow, doy);\n }\n }\n\n function setWeekAll(weekYear, week, weekday, dow, doy) {\n var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),\n date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);\n\n this.year(date.getUTCFullYear());\n this.month(date.getUTCMonth());\n this.date(date.getUTCDate());\n return this;\n }\n\n // FORMATTING\n\n addFormatToken('Q', 0, 'Qo', 'quarter');\n\n // PARSING\n\n addRegexToken('Q', match1);\n addParseToken('Q', function (input, array) {\n array[MONTH] = (toInt(input) - 1) * 3;\n });\n\n // MOMENTS\n\n function getSetQuarter(input) {\n return input == null\n ? Math.ceil((this.month() + 1) / 3)\n : this.month((input - 1) * 3 + (this.month() % 3));\n }\n\n // FORMATTING\n\n addFormatToken('D', ['DD', 2], 'Do', 'date');\n\n // PARSING\n\n addRegexToken('D', match1to2, match1to2NoLeadingZero);\n addRegexToken('DD', match1to2, match2);\n addRegexToken('Do', function (isStrict, locale) {\n // TODO: Remove \"ordinalParse\" fallback in next major release.\n return isStrict\n ? locale._dayOfMonthOrdinalParse || locale._ordinalParse\n : locale._dayOfMonthOrdinalParseLenient;\n });\n\n addParseToken(['D', 'DD'], DATE);\n addParseToken('Do', function (input, array) {\n array[DATE] = toInt(input.match(match1to2)[0]);\n });\n\n // MOMENTS\n\n var getSetDayOfMonth = makeGetSet('Date', true);\n\n // FORMATTING\n\n addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');\n\n // PARSING\n\n addRegexToken('DDD', match1to3);\n addRegexToken('DDDD', match3);\n addParseToken(['DDD', 'DDDD'], function (input, array, config) {\n config._dayOfYear = toInt(input);\n });\n\n // HELPERS\n\n // MOMENTS\n\n function getSetDayOfYear(input) {\n var dayOfYear =\n Math.round(\n (this.clone().startOf('day') - this.clone().startOf('year')) / 864e5\n ) + 1;\n return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');\n }\n\n // FORMATTING\n\n addFormatToken('m', ['mm', 2], 0, 'minute');\n\n // PARSING\n\n addRegexToken('m', match1to2, match1to2HasZero);\n addRegexToken('mm', match1to2, match2);\n addParseToken(['m', 'mm'], MINUTE);\n\n // MOMENTS\n\n var getSetMinute = makeGetSet('Minutes', false);\n\n // FORMATTING\n\n addFormatToken('s', ['ss', 2], 0, 'second');\n\n // PARSING\n\n addRegexToken('s', match1to2, match1to2HasZero);\n addRegexToken('ss', match1to2, match2);\n addParseToken(['s', 'ss'], SECOND);\n\n // MOMENTS\n\n var getSetSecond = makeGetSet('Seconds', false);\n\n // FORMATTING\n\n addFormatToken('S', 0, 0, function () {\n return ~~(this.millisecond() / 100);\n });\n\n addFormatToken(0, ['SS', 2], 0, function () {\n return ~~(this.millisecond() / 10);\n });\n\n addFormatToken(0, ['SSS', 3], 0, 'millisecond');\n addFormatToken(0, ['SSSS', 4], 0, function () {\n return this.millisecond() * 10;\n });\n addFormatToken(0, ['SSSSS', 5], 0, function () {\n return this.millisecond() * 100;\n });\n addFormatToken(0, ['SSSSSS', 6], 0, function () {\n return this.millisecond() * 1000;\n });\n addFormatToken(0, ['SSSSSSS', 7], 0, function () {\n return this.millisecond() * 10000;\n });\n addFormatToken(0, ['SSSSSSSS', 8], 0, function () {\n return this.millisecond() * 100000;\n });\n addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {\n return this.millisecond() * 1000000;\n });\n\n // PARSING\n\n addRegexToken('S', match1to3, match1);\n addRegexToken('SS', match1to3, match2);\n addRegexToken('SSS', match1to3, match3);\n\n var token, getSetMillisecond;\n for (token = 'SSSS'; token.length <= 9; token += 'S') {\n addRegexToken(token, matchUnsigned);\n }\n\n function parseMs(input, array) {\n array[MILLISECOND] = toInt(('0.' + input) * 1000);\n }\n\n for (token = 'S'; token.length <= 9; token += 'S') {\n addParseToken(token, parseMs);\n }\n\n getSetMillisecond = makeGetSet('Milliseconds', false);\n\n // FORMATTING\n\n addFormatToken('z', 0, 0, 'zoneAbbr');\n addFormatToken('zz', 0, 0, 'zoneName');\n\n // MOMENTS\n\n function getZoneAbbr() {\n return this._isUTC ? 'UTC' : '';\n }\n\n function getZoneName() {\n return this._isUTC ? 'Coordinated Universal Time' : '';\n }\n\n var proto = Moment.prototype;\n\n proto.add = add;\n proto.calendar = calendar$1;\n proto.clone = clone;\n proto.diff = diff;\n proto.endOf = endOf;\n proto.format = format;\n proto.from = from;\n proto.fromNow = fromNow;\n proto.to = to;\n proto.toNow = toNow;\n proto.get = stringGet;\n proto.invalidAt = invalidAt;\n proto.isAfter = isAfter;\n proto.isBefore = isBefore;\n proto.isBetween = isBetween;\n proto.isSame = isSame;\n proto.isSameOrAfter = isSameOrAfter;\n proto.isSameOrBefore = isSameOrBefore;\n proto.isValid = isValid$2;\n proto.lang = lang;\n proto.locale = locale;\n proto.localeData = localeData;\n proto.max = prototypeMax;\n proto.min = prototypeMin;\n proto.parsingFlags = parsingFlags;\n proto.set = stringSet;\n proto.startOf = startOf;\n proto.subtract = subtract;\n proto.toArray = toArray;\n proto.toObject = toObject;\n proto.toDate = toDate;\n proto.toISOString = toISOString;\n proto.inspect = inspect;\n if (typeof Symbol !== 'undefined' && Symbol.for != null) {\n proto[Symbol.for('nodejs.util.inspect.custom')] = function () {\n return 'Moment<' + this.format() + '>';\n };\n }\n proto.toJSON = toJSON;\n proto.toString = toString;\n proto.unix = unix;\n proto.valueOf = valueOf;\n proto.creationData = creationData;\n proto.eraName = getEraName;\n proto.eraNarrow = getEraNarrow;\n proto.eraAbbr = getEraAbbr;\n proto.eraYear = getEraYear;\n proto.year = getSetYear;\n proto.isLeapYear = getIsLeapYear;\n proto.weekYear = getSetWeekYear;\n proto.isoWeekYear = getSetISOWeekYear;\n proto.quarter = proto.quarters = getSetQuarter;\n proto.month = getSetMonth;\n proto.daysInMonth = getDaysInMonth;\n proto.week = proto.weeks = getSetWeek;\n proto.isoWeek = proto.isoWeeks = getSetISOWeek;\n proto.weeksInYear = getWeeksInYear;\n proto.weeksInWeekYear = getWeeksInWeekYear;\n proto.isoWeeksInYear = getISOWeeksInYear;\n proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;\n proto.date = getSetDayOfMonth;\n proto.day = proto.days = getSetDayOfWeek;\n proto.weekday = getSetLocaleDayOfWeek;\n proto.isoWeekday = getSetISODayOfWeek;\n proto.dayOfYear = getSetDayOfYear;\n proto.hour = proto.hours = getSetHour;\n proto.minute = proto.minutes = getSetMinute;\n proto.second = proto.seconds = getSetSecond;\n proto.millisecond = proto.milliseconds = getSetMillisecond;\n proto.utcOffset = getSetOffset;\n proto.utc = setOffsetToUTC;\n proto.local = setOffsetToLocal;\n proto.parseZone = setOffsetToParsedOffset;\n proto.hasAlignedHourOffset = hasAlignedHourOffset;\n proto.isDST = isDaylightSavingTime;\n proto.isLocal = isLocal;\n proto.isUtcOffset = isUtcOffset;\n proto.isUtc = isUtc;\n proto.isUTC = isUtc;\n proto.zoneAbbr = getZoneAbbr;\n proto.zoneName = getZoneName;\n proto.dates = deprecate(\n 'dates accessor is deprecated. Use date instead.',\n getSetDayOfMonth\n );\n proto.months = deprecate(\n 'months accessor is deprecated. Use month instead',\n getSetMonth\n );\n proto.years = deprecate(\n 'years accessor is deprecated. Use year instead',\n getSetYear\n );\n proto.zone = deprecate(\n 'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/',\n getSetZone\n );\n proto.isDSTShifted = deprecate(\n 'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information',\n isDaylightSavingTimeShifted\n );\n\n function createUnix(input) {\n return createLocal(input * 1000);\n }\n\n function createInZone() {\n return createLocal.apply(null, arguments).parseZone();\n }\n\n function preParsePostFormat(string) {\n return string;\n }\n\n var proto$1 = Locale.prototype;\n\n proto$1.calendar = calendar;\n proto$1.longDateFormat = longDateFormat;\n proto$1.invalidDate = invalidDate;\n proto$1.ordinal = ordinal;\n proto$1.preparse = preParsePostFormat;\n proto$1.postformat = preParsePostFormat;\n proto$1.relativeTime = relativeTime;\n proto$1.pastFuture = pastFuture;\n proto$1.set = set;\n proto$1.eras = localeEras;\n proto$1.erasParse = localeErasParse;\n proto$1.erasConvertYear = localeErasConvertYear;\n proto$1.erasAbbrRegex = erasAbbrRegex;\n proto$1.erasNameRegex = erasNameRegex;\n proto$1.erasNarrowRegex = erasNarrowRegex;\n\n proto$1.months = localeMonths;\n proto$1.monthsShort = localeMonthsShort;\n proto$1.monthsParse = localeMonthsParse;\n proto$1.monthsRegex = monthsRegex;\n proto$1.monthsShortRegex = monthsShortRegex;\n proto$1.week = localeWeek;\n proto$1.firstDayOfYear = localeFirstDayOfYear;\n proto$1.firstDayOfWeek = localeFirstDayOfWeek;\n\n proto$1.weekdays = localeWeekdays;\n proto$1.weekdaysMin = localeWeekdaysMin;\n proto$1.weekdaysShort = localeWeekdaysShort;\n proto$1.weekdaysParse = localeWeekdaysParse;\n\n proto$1.weekdaysRegex = weekdaysRegex;\n proto$1.weekdaysShortRegex = weekdaysShortRegex;\n proto$1.weekdaysMinRegex = weekdaysMinRegex;\n\n proto$1.isPM = localeIsPM;\n proto$1.meridiem = localeMeridiem;\n\n function get$1(format, index, field, setter) {\n var locale = getLocale(),\n utc = createUTC().set(setter, index);\n return locale[field](utc, format);\n }\n\n function listMonthsImpl(format, index, field) {\n if (isNumber(format)) {\n index = format;\n format = undefined;\n }\n\n format = format || '';\n\n if (index != null) {\n return get$1(format, index, field, 'month');\n }\n\n var i,\n out = [];\n for (i = 0; i < 12; i++) {\n out[i] = get$1(format, i, field, 'month');\n }\n return out;\n }\n\n // ()\n // (5)\n // (fmt, 5)\n // (fmt)\n // (true)\n // (true, 5)\n // (true, fmt, 5)\n // (true, fmt)\n function listWeekdaysImpl(localeSorted, format, index, field) {\n if (typeof localeSorted === 'boolean') {\n if (isNumber(format)) {\n index = format;\n format = undefined;\n }\n\n format = format || '';\n } else {\n format = localeSorted;\n index = format;\n localeSorted = false;\n\n if (isNumber(format)) {\n index = format;\n format = undefined;\n }\n\n format = format || '';\n }\n\n var locale = getLocale(),\n shift = localeSorted ? locale._week.dow : 0,\n i,\n out = [];\n\n if (index != null) {\n return get$1(format, (index + shift) % 7, field, 'day');\n }\n\n for (i = 0; i < 7; i++) {\n out[i] = get$1(format, (i + shift) % 7, field, 'day');\n }\n return out;\n }\n\n function listMonths(format, index) {\n return listMonthsImpl(format, index, 'months');\n }\n\n function listMonthsShort(format, index) {\n return listMonthsImpl(format, index, 'monthsShort');\n }\n\n function listWeekdays(localeSorted, format, index) {\n return listWeekdaysImpl(localeSorted, format, index, 'weekdays');\n }\n\n function listWeekdaysShort(localeSorted, format, index) {\n return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');\n }\n\n function listWeekdaysMin(localeSorted, format, index) {\n return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');\n }\n\n getSetGlobalLocale('en', {\n eras: [\n {\n since: '0001-01-01',\n until: +Infinity,\n offset: 1,\n name: 'Anno Domini',\n narrow: 'AD',\n abbr: 'AD',\n },\n {\n since: '0000-12-31',\n until: -Infinity,\n offset: 1,\n name: 'Before Christ',\n narrow: 'BC',\n abbr: 'BC',\n },\n ],\n dayOfMonthOrdinalParse: /\\d{1,2}(th|st|nd|rd)/,\n ordinal: function (number) {\n var b = number % 10,\n output =\n toInt((number % 100) / 10) === 1\n ? 'th'\n : b === 1\n ? 'st'\n : b === 2\n ? 'nd'\n : b === 3\n ? 'rd'\n : 'th';\n return number + output;\n },\n });\n\n // Side effect imports\n\n hooks.lang = deprecate(\n 'moment.lang is deprecated. Use moment.locale instead.',\n getSetGlobalLocale\n );\n hooks.langData = deprecate(\n 'moment.langData is deprecated. Use moment.localeData instead.',\n getLocale\n );\n\n var mathAbs = Math.abs;\n\n function abs() {\n var data = this._data;\n\n this._milliseconds = mathAbs(this._milliseconds);\n this._days = mathAbs(this._days);\n this._months = mathAbs(this._months);\n\n data.milliseconds = mathAbs(data.milliseconds);\n data.seconds = mathAbs(data.seconds);\n data.minutes = mathAbs(data.minutes);\n data.hours = mathAbs(data.hours);\n data.months = mathAbs(data.months);\n data.years = mathAbs(data.years);\n\n return this;\n }\n\n function addSubtract$1(duration, input, value, direction) {\n var other = createDuration(input, value);\n\n duration._milliseconds += direction * other._milliseconds;\n duration._days += direction * other._days;\n duration._months += direction * other._months;\n\n return duration._bubble();\n }\n\n // supports only 2.0-style add(1, 's') or add(duration)\n function add$1(input, value) {\n return addSubtract$1(this, input, value, 1);\n }\n\n // supports only 2.0-style subtract(1, 's') or subtract(duration)\n function subtract$1(input, value) {\n return addSubtract$1(this, input, value, -1);\n }\n\n function absCeil(number) {\n if (number < 0) {\n return Math.floor(number);\n } else {\n return Math.ceil(number);\n }\n }\n\n function bubble() {\n var milliseconds = this._milliseconds,\n days = this._days,\n months = this._months,\n data = this._data,\n seconds,\n minutes,\n hours,\n years,\n monthsFromDays;\n\n // if we have a mix of positive and negative values, bubble down first\n // check: https://github.com/moment/moment/issues/2166\n if (\n !(\n (milliseconds >= 0 && days >= 0 && months >= 0) ||\n (milliseconds <= 0 && days <= 0 && months <= 0)\n )\n ) {\n milliseconds += absCeil(monthsToDays(months) + days) * 864e5;\n days = 0;\n months = 0;\n }\n\n // The following code bubbles up values, see the tests for\n // examples of what that means.\n data.milliseconds = milliseconds % 1000;\n\n seconds = absFloor(milliseconds / 1000);\n data.seconds = seconds % 60;\n\n minutes = absFloor(seconds / 60);\n data.minutes = minutes % 60;\n\n hours = absFloor(minutes / 60);\n data.hours = hours % 24;\n\n days += absFloor(hours / 24);\n\n // convert days to months\n monthsFromDays = absFloor(daysToMonths(days));\n months += monthsFromDays;\n days -= absCeil(monthsToDays(monthsFromDays));\n\n // 12 months -> 1 year\n years = absFloor(months / 12);\n months %= 12;\n\n data.days = days;\n data.months = months;\n data.years = years;\n\n return this;\n }\n\n function daysToMonths(days) {\n // 400 years have 146097 days (taking into account leap year rules)\n // 400 years have 12 months === 4800\n return (days * 4800) / 146097;\n }\n\n function monthsToDays(months) {\n // the reverse of daysToMonths\n return (months * 146097) / 4800;\n }\n\n function as(units) {\n if (!this.isValid()) {\n return NaN;\n }\n var days,\n months,\n milliseconds = this._milliseconds;\n\n units = normalizeUnits(units);\n\n if (units === 'month' || units === 'quarter' || units === 'year') {\n days = this._days + milliseconds / 864e5;\n months = this._months + daysToMonths(days);\n switch (units) {\n case 'month':\n return months;\n case 'quarter':\n return months / 3;\n case 'year':\n return months / 12;\n }\n } else {\n // handle milliseconds separately because of floating point math errors (issue #1867)\n days = this._days + Math.round(monthsToDays(this._months));\n switch (units) {\n case 'week':\n return days / 7 + milliseconds / 6048e5;\n case 'day':\n return days + milliseconds / 864e5;\n case 'hour':\n return days * 24 + milliseconds / 36e5;\n case 'minute':\n return days * 1440 + milliseconds / 6e4;\n case 'second':\n return days * 86400 + milliseconds / 1000;\n // Math.floor prevents floating point math errors here\n case 'millisecond':\n return Math.floor(days * 864e5) + milliseconds;\n default:\n throw new Error('Unknown unit ' + units);\n }\n }\n }\n\n function makeAs(alias) {\n return function () {\n return this.as(alias);\n };\n }\n\n var asMilliseconds = makeAs('ms'),\n asSeconds = makeAs('s'),\n asMinutes = makeAs('m'),\n asHours = makeAs('h'),\n asDays = makeAs('d'),\n asWeeks = makeAs('w'),\n asMonths = makeAs('M'),\n asQuarters = makeAs('Q'),\n asYears = makeAs('y'),\n valueOf$1 = asMilliseconds;\n\n function clone$1() {\n return createDuration(this);\n }\n\n function get$2(units) {\n units = normalizeUnits(units);\n return this.isValid() ? this[units + 's']() : NaN;\n }\n\n function makeGetter(name) {\n return function () {\n return this.isValid() ? this._data[name] : NaN;\n };\n }\n\n var milliseconds = makeGetter('milliseconds'),\n seconds = makeGetter('seconds'),\n minutes = makeGetter('minutes'),\n hours = makeGetter('hours'),\n days = makeGetter('days'),\n months = makeGetter('months'),\n years = makeGetter('years');\n\n function weeks() {\n return absFloor(this.days() / 7);\n }\n\n var round = Math.round,\n thresholds = {\n ss: 44, // a few seconds to seconds\n s: 45, // seconds to minute\n m: 45, // minutes to hour\n h: 22, // hours to day\n d: 26, // days to month/week\n w: null, // weeks to month\n M: 11, // months to year\n };\n\n // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize\n function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {\n return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);\n }\n\n function relativeTime$1(posNegDuration, withoutSuffix, thresholds, locale) {\n var duration = createDuration(posNegDuration).abs(),\n seconds = round(duration.as('s')),\n minutes = round(duration.as('m')),\n hours = round(duration.as('h')),\n days = round(duration.as('d')),\n months = round(duration.as('M')),\n weeks = round(duration.as('w')),\n years = round(duration.as('y')),\n a =\n (seconds <= thresholds.ss && ['s', seconds]) ||\n (seconds < thresholds.s && ['ss', seconds]) ||\n (minutes <= 1 && ['m']) ||\n (minutes < thresholds.m && ['mm', minutes]) ||\n (hours <= 1 && ['h']) ||\n (hours < thresholds.h && ['hh', hours]) ||\n (days <= 1 && ['d']) ||\n (days < thresholds.d && ['dd', days]);\n\n if (thresholds.w != null) {\n a =\n a ||\n (weeks <= 1 && ['w']) ||\n (weeks < thresholds.w && ['ww', weeks]);\n }\n a = a ||\n (months <= 1 && ['M']) ||\n (months < thresholds.M && ['MM', months]) ||\n (years <= 1 && ['y']) || ['yy', years];\n\n a[2] = withoutSuffix;\n a[3] = +posNegDuration > 0;\n a[4] = locale;\n return substituteTimeAgo.apply(null, a);\n }\n\n // This function allows you to set the rounding function for relative time strings\n function getSetRelativeTimeRounding(roundingFunction) {\n if (roundingFunction === undefined) {\n return round;\n }\n if (typeof roundingFunction === 'function') {\n round = roundingFunction;\n return true;\n }\n return false;\n }\n\n // This function allows you to set a threshold for relative time strings\n function getSetRelativeTimeThreshold(threshold, limit) {\n if (thresholds[threshold] === undefined) {\n return false;\n }\n if (limit === undefined) {\n return thresholds[threshold];\n }\n thresholds[threshold] = limit;\n if (threshold === 's') {\n thresholds.ss = limit - 1;\n }\n return true;\n }\n\n function humanize(argWithSuffix, argThresholds) {\n if (!this.isValid()) {\n return this.localeData().invalidDate();\n }\n\n var withSuffix = false,\n th = thresholds,\n locale,\n output;\n\n if (typeof argWithSuffix === 'object') {\n argThresholds = argWithSuffix;\n argWithSuffix = false;\n }\n if (typeof argWithSuffix === 'boolean') {\n withSuffix = argWithSuffix;\n }\n if (typeof argThresholds === 'object') {\n th = Object.assign({}, thresholds, argThresholds);\n if (argThresholds.s != null && argThresholds.ss == null) {\n th.ss = argThresholds.s - 1;\n }\n }\n\n locale = this.localeData();\n output = relativeTime$1(this, !withSuffix, th, locale);\n\n if (withSuffix) {\n output = locale.pastFuture(+this, output);\n }\n\n return locale.postformat(output);\n }\n\n var abs$1 = Math.abs;\n\n function sign(x) {\n return (x > 0) - (x < 0) || +x;\n }\n\n function toISOString$1() {\n // for ISO strings we do not use the normal bubbling rules:\n // * milliseconds bubble up until they become hours\n // * days do not bubble at all\n // * months bubble up until they become years\n // This is because there is no context-free conversion between hours and days\n // (think of clock changes)\n // and also not between days and months (28-31 days per month)\n if (!this.isValid()) {\n return this.localeData().invalidDate();\n }\n\n var seconds = abs$1(this._milliseconds) / 1000,\n days = abs$1(this._days),\n months = abs$1(this._months),\n minutes,\n hours,\n years,\n s,\n total = this.asSeconds(),\n totalSign,\n ymSign,\n daysSign,\n hmsSign;\n\n if (!total) {\n // this is the same as C#'s (Noda) and python (isodate)...\n // but not other JS (goog.date)\n return 'P0D';\n }\n\n // 3600 seconds -> 60 minutes -> 1 hour\n minutes = absFloor(seconds / 60);\n hours = absFloor(minutes / 60);\n seconds %= 60;\n minutes %= 60;\n\n // 12 months -> 1 year\n years = absFloor(months / 12);\n months %= 12;\n\n // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js\n s = seconds ? seconds.toFixed(3).replace(/\\.?0+$/, '') : '';\n\n totalSign = total < 0 ? '-' : '';\n ymSign = sign(this._months) !== sign(total) ? '-' : '';\n daysSign = sign(this._days) !== sign(total) ? '-' : '';\n hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';\n\n return (\n totalSign +\n 'P' +\n (years ? ymSign + years + 'Y' : '') +\n (months ? ymSign + months + 'M' : '') +\n (days ? daysSign + days + 'D' : '') +\n (hours || minutes || seconds ? 'T' : '') +\n (hours ? hmsSign + hours + 'H' : '') +\n (minutes ? hmsSign + minutes + 'M' : '') +\n (seconds ? hmsSign + s + 'S' : '')\n );\n }\n\n var proto$2 = Duration.prototype;\n\n proto$2.isValid = isValid$1;\n proto$2.abs = abs;\n proto$2.add = add$1;\n proto$2.subtract = subtract$1;\n proto$2.as = as;\n proto$2.asMilliseconds = asMilliseconds;\n proto$2.asSeconds = asSeconds;\n proto$2.asMinutes = asMinutes;\n proto$2.asHours = asHours;\n proto$2.asDays = asDays;\n proto$2.asWeeks = asWeeks;\n proto$2.asMonths = asMonths;\n proto$2.asQuarters = asQuarters;\n proto$2.asYears = asYears;\n proto$2.valueOf = valueOf$1;\n proto$2._bubble = bubble;\n proto$2.clone = clone$1;\n proto$2.get = get$2;\n proto$2.milliseconds = milliseconds;\n proto$2.seconds = seconds;\n proto$2.minutes = minutes;\n proto$2.hours = hours;\n proto$2.days = days;\n proto$2.weeks = weeks;\n proto$2.months = months;\n proto$2.years = years;\n proto$2.humanize = humanize;\n proto$2.toISOString = toISOString$1;\n proto$2.toString = toISOString$1;\n proto$2.toJSON = toISOString$1;\n proto$2.locale = locale;\n proto$2.localeData = localeData;\n\n proto$2.toIsoString = deprecate(\n 'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',\n toISOString$1\n );\n proto$2.lang = lang;\n\n // FORMATTING\n\n addFormatToken('X', 0, 0, 'unix');\n addFormatToken('x', 0, 0, 'valueOf');\n\n // PARSING\n\n addRegexToken('x', matchSigned);\n addRegexToken('X', matchTimestamp);\n addParseToken('X', function (input, array, config) {\n config._d = new Date(parseFloat(input) * 1000);\n });\n addParseToken('x', function (input, array, config) {\n config._d = new Date(toInt(input));\n });\n\n //! moment.js\n\n hooks.version = '2.30.1';\n\n setHookCallback(createLocal);\n\n hooks.fn = proto;\n hooks.min = min;\n hooks.max = max;\n hooks.now = now;\n hooks.utc = createUTC;\n hooks.unix = createUnix;\n hooks.months = listMonths;\n hooks.isDate = isDate;\n hooks.locale = getSetGlobalLocale;\n hooks.invalid = createInvalid;\n hooks.duration = createDuration;\n hooks.isMoment = isMoment;\n hooks.weekdays = listWeekdays;\n hooks.parseZone = createInZone;\n hooks.localeData = getLocale;\n hooks.isDuration = isDuration;\n hooks.monthsShort = listMonthsShort;\n hooks.weekdaysMin = listWeekdaysMin;\n hooks.defineLocale = defineLocale;\n hooks.updateLocale = updateLocale;\n hooks.locales = listLocales;\n hooks.weekdaysShort = listWeekdaysShort;\n hooks.normalizeUnits = normalizeUnits;\n hooks.relativeTimeRounding = getSetRelativeTimeRounding;\n hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;\n hooks.calendarFormat = getCalendarFormat;\n hooks.prototype = proto;\n\n // currently HTML5 input type only supports 24-hour formats\n hooks.HTML5_FMT = {\n DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // \n DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // \n DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // \n DATE: 'YYYY-MM-DD', // \n TIME: 'HH:mm', // \n TIME_SECONDS: 'HH:mm:ss', // \n TIME_MS: 'HH:mm:ss.SSS', // \n WEEK: 'GGGG-[W]WW', // \n MONTH: 'YYYY-MM', // \n };\n\n return hooks;\n\n})));\n","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar isArray = require('../internals/is-array');\nvar isCallable = require('../internals/is-callable');\nvar classof = require('../internals/classof-raw');\nvar toString = require('../internals/to-string');\n\nvar push = uncurryThis([].push);\n\nmodule.exports = function (replacer) {\n if (isCallable(replacer)) return replacer;\n if (!isArray(replacer)) return;\n var rawLength = replacer.length;\n var keys = [];\n for (var i = 0; i < rawLength; i++) {\n var element = replacer[i];\n if (typeof element == 'string') push(keys, element);\n else if (typeof element == 'number' || classof(element) === 'Number' || classof(element) === 'String') push(keys, toString(element));\n }\n var keysLength = keys.length;\n var root = true;\n return function (key, value) {\n if (root) {\n root = false;\n return value;\n }\n if (isArray(this)) return value;\n for (var j = 0; j < keysLength; j++) if (keys[j] === key) return value;\n };\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar getBuiltIn = require('../internals/get-built-in');\nvar apply = require('../internals/function-apply');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar fails = require('../internals/fails');\nvar isCallable = require('../internals/is-callable');\nvar isSymbol = require('../internals/is-symbol');\nvar arraySlice = require('../internals/array-slice');\nvar getReplacerFunction = require('../internals/get-json-replacer-function');\nvar NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');\n\nvar $String = String;\nvar $stringify = getBuiltIn('JSON', 'stringify');\nvar exec = uncurryThis(/./.exec);\nvar charAt = uncurryThis(''.charAt);\nvar charCodeAt = uncurryThis(''.charCodeAt);\nvar replace = uncurryThis(''.replace);\nvar numberToString = uncurryThis(1.0.toString);\n\nvar tester = /[\\uD800-\\uDFFF]/g;\nvar low = /^[\\uD800-\\uDBFF]$/;\nvar hi = /^[\\uDC00-\\uDFFF]$/;\n\nvar WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL || fails(function () {\n var symbol = getBuiltIn('Symbol')('stringify detection');\n // MS Edge converts symbol values to JSON as {}\n return $stringify([symbol]) !== '[null]'\n // WebKit converts symbol values to JSON as null\n || $stringify({ a: symbol }) !== '{}'\n // V8 throws on boxed symbols\n || $stringify(Object(symbol)) !== '{}';\n});\n\n// https://github.com/tc39/proposal-well-formed-stringify\nvar ILL_FORMED_UNICODE = fails(function () {\n return $stringify('\\uDF06\\uD834') !== '\"\\\\udf06\\\\ud834\"'\n || $stringify('\\uDEAD') !== '\"\\\\udead\"';\n});\n\nvar stringifyWithSymbolsFix = function (it, replacer) {\n var args = arraySlice(arguments);\n var $replacer = getReplacerFunction(replacer);\n if (!isCallable($replacer) && (it === undefined || isSymbol(it))) return; // IE8 returns string on undefined\n args[1] = function (key, value) {\n // some old implementations (like WebKit) could pass numbers as keys\n if (isCallable($replacer)) value = call($replacer, this, $String(key), value);\n if (!isSymbol(value)) return value;\n };\n return apply($stringify, null, args);\n};\n\nvar fixIllFormed = function (match, offset, string) {\n var prev = charAt(string, offset - 1);\n var next = charAt(string, offset + 1);\n if ((exec(low, match) && !exec(hi, next)) || (exec(hi, match) && !exec(low, prev))) {\n return '\\\\u' + numberToString(charCodeAt(match, 0), 16);\n } return match;\n};\n\nif ($stringify) {\n // `JSON.stringify` method\n // https://tc39.es/ecma262/#sec-json.stringify\n $({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, {\n // eslint-disable-next-line no-unused-vars -- required for `.length`\n stringify: function stringify(it, replacer, space) {\n var args = arraySlice(arguments);\n var result = apply(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args);\n return ILL_FORMED_UNICODE && typeof result == 'string' ? replace(result, tester, fixIllFormed) : result;\n }\n });\n}\n","'use strict';\n// this method was added to unscopables after implementation\n// in popular engines, so it's moved to a separate module\nvar addToUnscopables = require('../internals/add-to-unscopables');\n\n// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables\naddToUnscopables('flatMap');\n","'use strict';\nvar $ = require('../internals/export');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar isCallable = require('../internals/is-callable');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar isRegExp = require('../internals/is-regexp');\nvar toString = require('../internals/to-string');\nvar getMethod = require('../internals/get-method');\nvar getRegExpFlags = require('../internals/regexp-get-flags');\nvar getSubstitution = require('../internals/get-substitution');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar IS_PURE = require('../internals/is-pure');\n\nvar REPLACE = wellKnownSymbol('replace');\nvar $TypeError = TypeError;\nvar indexOf = uncurryThis(''.indexOf);\nvar replace = uncurryThis(''.replace);\nvar stringSlice = uncurryThis(''.slice);\nvar max = Math.max;\n\n// `String.prototype.replaceAll` method\n// https://tc39.es/ecma262/#sec-string.prototype.replaceall\n$({ target: 'String', proto: true }, {\n replaceAll: function replaceAll(searchValue, replaceValue) {\n var O = requireObjectCoercible(this);\n var IS_REG_EXP, flags, replacer, string, searchString, functionalReplace, searchLength, advanceBy, position, replacement;\n var endOfLastMatch = 0;\n var result = '';\n if (!isNullOrUndefined(searchValue)) {\n IS_REG_EXP = isRegExp(searchValue);\n if (IS_REG_EXP) {\n flags = toString(requireObjectCoercible(getRegExpFlags(searchValue)));\n if (!~indexOf(flags, 'g')) throw new $TypeError('`.replaceAll` does not allow non-global regexes');\n }\n replacer = getMethod(searchValue, REPLACE);\n if (replacer) return call(replacer, searchValue, O, replaceValue);\n if (IS_PURE && IS_REG_EXP) return replace(toString(O), searchValue, replaceValue);\n }\n string = toString(O);\n searchString = toString(searchValue);\n functionalReplace = isCallable(replaceValue);\n if (!functionalReplace) replaceValue = toString(replaceValue);\n searchLength = searchString.length;\n advanceBy = max(1, searchLength);\n position = indexOf(string, searchString);\n while (position !== -1) {\n replacement = functionalReplace\n ? toString(replaceValue(searchString, position, string))\n : getSubstitution(searchString, string, position, [], undefined, replaceValue);\n result += stringSlice(string, endOfLastMatch, position) + replacement;\n endOfLastMatch = position + searchLength;\n position = position + advanceBy > string.length ? -1 : indexOf(string, searchString, position + advanceBy);\n }\n if (endOfLastMatch < string.length) {\n result += stringSlice(string, endOfLastMatch);\n }\n return result;\n }\n});\n","'use strict';\nvar $ = require('../internals/export');\nvar toObject = require('../internals/to-object');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar addToUnscopables = require('../internals/add-to-unscopables');\n\n// `Array.prototype.at` method\n// https://tc39.es/ecma262/#sec-array.prototype.at\n$({ target: 'Array', proto: true }, {\n at: function at(index) {\n var O = toObject(this);\n var len = lengthOfArrayLike(O);\n var relativeIndex = toIntegerOrInfinity(index);\n var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;\n return (k < 0 || k >= len) ? undefined : O[k];\n }\n});\n\naddToUnscopables('at');\n","'use strict';\nvar $ = require('../internals/export');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar toString = require('../internals/to-string');\nvar fails = require('../internals/fails');\n\nvar charAt = uncurryThis(''.charAt);\n\nvar FORCED = fails(function () {\n // eslint-disable-next-line es/no-string-prototype-at -- safe\n return '𠮷'.at(-2) !== '\\uD842';\n});\n\n// `String.prototype.at` method\n// https://tc39.es/ecma262/#sec-string.prototype.at\n$({ target: 'String', proto: true, forced: FORCED }, {\n at: function at(index) {\n var S = toString(requireObjectCoercible(this));\n var len = S.length;\n var relativeIndex = toIntegerOrInfinity(index);\n var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;\n return (k < 0 || k >= len) ? undefined : charAt(S, k);\n }\n});\n","'use strict';\n// this method was added to unscopables after implementation\n// in popular engines, so it's moved to a separate module\nvar addToUnscopables = require('../internals/add-to-unscopables');\n\n// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables\naddToUnscopables('flat');\n","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nimport \"core-js/modules/web.immediate.js\";\nimport { addClass, empty, observeVisibilityChangeOnce, removeClass } from \"./helpers/dom/element.mjs\";\nimport { isFunction } from \"./helpers/function.mjs\";\nimport { isDefined, isUndefined, isRegExp, _injectProductInfo, isEmpty } from \"./helpers/mixed.mjs\";\nimport { isMobileBrowser, isIpadOS } from \"./helpers/browser.mjs\";\nimport EditorManager from \"./editorManager.mjs\";\nimport EventManager from \"./eventManager.mjs\";\nimport { deepClone, duckSchema, isObjectEqual, isObject, deepObjectSize, hasOwnProperty, createObjectPropListener, objectEach } from \"./helpers/object.mjs\";\nimport { FocusManager } from \"./focusManager.mjs\";\nimport { arrayMap, arrayEach, arrayReduce, getDifferenceOfArrays, stringToArray, pivot } from \"./helpers/array.mjs\";\nimport { instanceToHTML } from \"./utils/parseTable.mjs\";\nimport { getPlugin, getPluginsNames } from \"./plugins/registry.mjs\";\nimport { getRenderer } from \"./renderers/registry.mjs\";\nimport { getEditor } from \"./editors/registry.mjs\";\nimport { getValidator } from \"./validators/registry.mjs\";\nimport { randomString, toUpperCaseFirst } from \"./helpers/string.mjs\";\nimport { rangeEach, rangeEachReverse, isNumericLike } from \"./helpers/number.mjs\";\nimport TableView from \"./tableView.mjs\";\nimport DataSource from \"./dataMap/dataSource.mjs\";\nimport { spreadsheetColumnLabel } from \"./helpers/data.mjs\";\nimport { IndexMapper } from \"./translations/index.mjs\";\nimport { registerAsRootInstance, hasValidParameter, isRootInstance } from \"./utils/rootInstance.mjs\";\nimport { DEFAULT_COLUMN_WIDTH } from \"./3rdparty/walkontable/src/index.mjs\";\nimport Hooks from \"./pluginHooks.mjs\";\nimport { hasLanguageDictionary, getValidLanguageCode, getTranslatedPhrase } from \"./i18n/registry.mjs\";\nimport { warnUserAboutLanguageRegistration, normalizeLanguageCode } from \"./i18n/utils.mjs\";\nimport { Selection } from \"./selection/index.mjs\";\nimport { MetaManager, DynamicCellMetaMod, ExtendMetaPropertiesMod, replaceData } from \"./dataMap/index.mjs\";\nimport { installFocusCatcher, createViewportScroller } from \"./core/index.mjs\";\nimport { createUniqueMap } from \"./utils/dataStructures/uniqueMap.mjs\";\nimport { createShortcutManager } from \"./shortcuts/index.mjs\";\nimport { registerAllShortcutContexts } from \"./shortcutContexts/index.mjs\";\nlet activeGuid = null;\n\n/**\n * Keeps the collection of the all Handsontable instances created on the same page. The\n * list is then used to trigger the \"afterUnlisten\" hook when the \"listen()\" method was\n * called on another instance.\n *\n * @type {Map}\n */\nconst foreignHotInstances = new Map();\n\n/**\n * A set of deprecated feature names.\n *\n * @type {Set}\n */\n// eslint-disable-next-line no-unused-vars\nconst deprecationWarns = new Set();\n\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * Handsontable constructor.\n *\n * @core\n * @class Core\n * @description\n *\n * The `Handsontable` class (known as the `Core`) lets you modify the grid's behavior by using Handsontable's public API methods.\n *\n * ::: only-for react\n * To use these methods, associate a Handsontable instance with your instance\n * of the [`HotTable` component](@/guides/getting-started/installation/installation.md#_4-use-the-hottable-component),\n * by using React's `ref` feature (read more on the [Instance methods](@/guides/getting-started/react-methods/react-methods.md) page).\n * :::\n *\n * ## How to call a method\n *\n * ::: only-for javascript\n * ```js\n * // create a Handsontable instance\n * const hot = new Handsontable(document.getElementById('example'), options);\n *\n * // call a method\n * hot.setDataAtCell(0, 0, 'new value');\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * import { useRef } from 'react';\n *\n * const hotTableComponent = useRef(null);\n *\n * \n *\n * // access the Handsontable instance, under the `.current.hotInstance` property\n * // call a method\n * hotTableComponent.current.hotInstance.setDataAtCell(0, 0, 'new value');\n * ```\n * :::\n *\n * @param {HTMLElement} rootElement The element to which the Handsontable instance is injected.\n * @param {object} userSettings The user defined options.\n * @param {boolean} [rootInstanceSymbol=false] Indicates if the instance is root of all later instances created.\n */\nexport default function Core(rootElement, userSettings) {\n var _userSettings$layoutD,\n _this = this;\n let rootInstanceSymbol = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let instance = this;\n const eventManager = new EventManager(instance);\n let datamap;\n let dataSource;\n let grid;\n let editorManager;\n let focusManager;\n let viewportScroller;\n let firstRun = true;\n if (hasValidParameter(rootInstanceSymbol)) {\n registerAsRootInstance(this);\n }\n\n // TODO: check if references to DOM elements should be move to UI layer (Walkontable)\n /**\n * Reference to the container element.\n *\n * @private\n * @type {HTMLElement}\n */\n this.rootElement = rootElement;\n /**\n * The nearest document over container.\n *\n * @private\n * @type {Document}\n */\n this.rootDocument = rootElement.ownerDocument;\n /**\n * Window object over container's document.\n *\n * @private\n * @type {Window}\n */\n this.rootWindow = this.rootDocument.defaultView;\n /**\n * A boolean to tell if the Handsontable has been fully destroyed. This is set to `true`\n * after `afterDestroy` hook is called.\n *\n * @memberof Core#\n * @member isDestroyed\n * @type {boolean}\n */\n this.isDestroyed = false;\n /**\n * The counter determines how many times the render suspending was called. It allows\n * tracking the nested suspending calls. For each render suspend resuming call the\n * counter is decremented. The value equal to 0 means the render suspending feature\n * is disabled.\n *\n * @private\n * @type {number}\n */\n this.renderSuspendedCounter = 0;\n /**\n * The counter determines how many times the execution suspending was called. It allows\n * tracking the nested suspending calls. For each execution suspend resuming call the\n * counter is decremented. The value equal to 0 means the execution suspending feature\n * is disabled.\n *\n * @private\n * @type {number}\n */\n this.executionSuspendedCounter = 0;\n const layoutDirection = (_userSettings$layoutD = userSettings === null || userSettings === void 0 ? void 0 : userSettings.layoutDirection) !== null && _userSettings$layoutD !== void 0 ? _userSettings$layoutD : 'inherit';\n const rootElementDirection = ['rtl', 'ltr'].includes(layoutDirection) ? layoutDirection : this.rootWindow.getComputedStyle(this.rootElement).direction;\n this.rootElement.setAttribute('dir', rootElementDirection);\n\n /**\n * Checks if the grid is rendered using the right-to-left layout direction.\n *\n * @since 12.0.0\n * @memberof Core#\n * @function isRtl\n * @returns {boolean} True if RTL.\n */\n this.isRtl = function () {\n return rootElementDirection === 'rtl';\n };\n\n /**\n * Checks if the grid is rendered using the left-to-right layout direction.\n *\n * @since 12.0.0\n * @memberof Core#\n * @function isLtr\n * @returns {boolean} True if LTR.\n */\n this.isLtr = function () {\n return !instance.isRtl();\n };\n\n /**\n * Returns 1 for LTR; -1 for RTL. Useful for calculations.\n *\n * @since 12.0.0\n * @memberof Core#\n * @function getDirectionFactor\n * @returns {number} Returns 1 for LTR; -1 for RTL.\n */\n this.getDirectionFactor = function () {\n return instance.isLtr() ? 1 : -1;\n };\n userSettings.language = getValidLanguageCode(userSettings.language);\n const metaManager = new MetaManager(instance, userSettings, [DynamicCellMetaMod, ExtendMetaPropertiesMod]);\n const tableMeta = metaManager.getTableMeta();\n const globalMeta = metaManager.getGlobalMeta();\n const pluginsRegistry = createUniqueMap();\n this.container = this.rootDocument.createElement('div');\n this.renderCall = false;\n rootElement.insertBefore(this.container, rootElement.firstChild);\n if (isRootInstance(this)) {\n _injectProductInfo(userSettings.licenseKey, rootElement);\n }\n this.guid = `ht_${randomString()}`; // this is the namespace for global events\n\n foreignHotInstances.set(this.guid, this);\n\n /**\n * Instance of index mapper which is responsible for managing the column indexes.\n *\n * @memberof Core#\n * @member columnIndexMapper\n * @type {IndexMapper}\n */\n this.columnIndexMapper = new IndexMapper();\n /**\n * Instance of index mapper which is responsible for managing the row indexes.\n *\n * @memberof Core#\n * @member rowIndexMapper\n * @type {IndexMapper}\n */\n this.rowIndexMapper = new IndexMapper();\n this.columnIndexMapper.addLocalHook('indexesSequenceChange', source => {\n instance.runHooks('afterColumnSequenceChange', source);\n });\n this.rowIndexMapper.addLocalHook('indexesSequenceChange', source => {\n instance.runHooks('afterRowSequenceChange', source);\n });\n dataSource = new DataSource(instance);\n if (!this.rootElement.id || this.rootElement.id.substring(0, 3) === 'ht_') {\n this.rootElement.id = this.guid; // if root element does not have an id, assign a random id\n }\n const visualToRenderableCoords = coords => {\n const {\n row: visualRow,\n col: visualColumn\n } = coords;\n return instance._createCellCoords(\n // We just store indexes for rows and columns without headers.\n visualRow >= 0 ? instance.rowIndexMapper.getRenderableFromVisualIndex(visualRow) : visualRow, visualColumn >= 0 ? instance.columnIndexMapper.getRenderableFromVisualIndex(visualColumn) : visualColumn);\n };\n const renderableToVisualCoords = coords => {\n const {\n row: renderableRow,\n col: renderableColumn\n } = coords;\n return instance._createCellCoords(\n // We just store indexes for rows and columns without headers.\n renderableRow >= 0 ? instance.rowIndexMapper.getVisualFromRenderableIndex(renderableRow) : renderableRow, renderableColumn >= 0 ? instance.columnIndexMapper.getVisualFromRenderableIndex(renderableColumn) : renderableColumn // eslint-disable-line max-len\n );\n };\n const findFirstNonHiddenRenderableRow = (visualRowFrom, visualRowTo) => {\n const dir = visualRowTo > visualRowFrom ? 1 : -1;\n const minIndex = Math.min(visualRowFrom, visualRowTo);\n const maxIndex = Math.max(visualRowFrom, visualRowTo);\n const rowIndex = instance.rowIndexMapper.getNearestNotHiddenIndex(visualRowFrom, dir);\n if (rowIndex === null || dir === 1 && rowIndex > maxIndex || dir === -1 && rowIndex < minIndex) {\n return null;\n }\n return rowIndex >= 0 ? instance.rowIndexMapper.getRenderableFromVisualIndex(rowIndex) : rowIndex;\n };\n const findFirstNonHiddenRenderableColumn = (visualColumnFrom, visualColumnTo) => {\n const dir = visualColumnTo > visualColumnFrom ? 1 : -1;\n const minIndex = Math.min(visualColumnFrom, visualColumnTo);\n const maxIndex = Math.max(visualColumnFrom, visualColumnTo);\n const columnIndex = instance.columnIndexMapper.getNearestNotHiddenIndex(visualColumnFrom, dir);\n if (columnIndex === null || dir === 1 && columnIndex > maxIndex || dir === -1 && columnIndex < minIndex) {\n return null;\n }\n return columnIndex >= 0 ? instance.columnIndexMapper.getRenderableFromVisualIndex(columnIndex) : columnIndex;\n };\n let selection = new Selection(tableMeta, {\n rowIndexMapper: instance.rowIndexMapper,\n columnIndexMapper: instance.columnIndexMapper,\n countCols: () => instance.countCols(),\n countRows: () => instance.countRows(),\n propToCol: prop => datamap.propToCol(prop),\n isEditorOpened: () => instance.getActiveEditor() ? instance.getActiveEditor().isOpened() : false,\n countRenderableColumns: () => this.view.countRenderableColumns(),\n countRenderableRows: () => this.view.countRenderableRows(),\n countRowHeaders: () => this.countRowHeaders(),\n countColHeaders: () => this.countColHeaders(),\n countRenderableRowsInRange: function () {\n return _this.view.countRenderableRowsInRange(...arguments);\n },\n countRenderableColumnsInRange: function () {\n return _this.view.countRenderableColumnsInRange(...arguments);\n },\n getShortcutManager: () => instance.getShortcutManager(),\n createCellCoords: (row, column) => instance._createCellCoords(row, column),\n createCellRange: (highlight, from, to) => instance._createCellRange(highlight, from, to),\n visualToRenderableCoords,\n renderableToVisualCoords,\n findFirstNonHiddenRenderableRow,\n findFirstNonHiddenRenderableColumn,\n isDisabledCellSelection: (visualRow, visualColumn) => {\n if (visualRow < 0 || visualColumn < 0) {\n return instance.getSettings().disableVisualSelection;\n }\n return instance.getCellMeta(visualRow, visualColumn).disableVisualSelection;\n }\n });\n this.selection = selection;\n const onIndexMapperCacheUpdate = _ref => {\n let {\n hiddenIndexesChanged\n } = _ref;\n if (hiddenIndexesChanged) {\n this.selection.commit();\n }\n };\n this.columnIndexMapper.addLocalHook('cacheUpdated', onIndexMapperCacheUpdate);\n this.rowIndexMapper.addLocalHook('cacheUpdated', onIndexMapperCacheUpdate);\n this.selection.addLocalHook('afterSetRangeEnd', (cellCoords, isLastSelectionLayer) => {\n const preventScrolling = createObjectPropListener(false);\n const selectionRange = this.selection.getSelectedRange();\n const {\n from,\n to\n } = selectionRange.current();\n const selectionLayerLevel = selectionRange.size() - 1;\n this.runHooks('afterSelection', from.row, from.col, to.row, to.col, preventScrolling, selectionLayerLevel);\n this.runHooks('afterSelectionByProp', from.row, instance.colToProp(from.col), to.row, instance.colToProp(to.col), preventScrolling, selectionLayerLevel);\n if (isLastSelectionLayer && (!preventScrolling.isTouched() || preventScrolling.isTouched() && !preventScrolling.value)) {\n viewportScroller.scrollTo(cellCoords);\n }\n const isSelectedByRowHeader = selection.isSelectedByRowHeader();\n const isSelectedByColumnHeader = selection.isSelectedByColumnHeader();\n\n // @TODO: These CSS classes are no longer needed anymore. They are used only as a indicator of the selected\n // rows/columns in the MergedCells plugin (via border.js#L520 in the walkontable module). After fixing\n // the Border class this should be removed.\n if (isSelectedByRowHeader && isSelectedByColumnHeader) {\n addClass(this.rootElement, ['ht__selection--rows', 'ht__selection--columns']);\n } else if (isSelectedByRowHeader) {\n removeClass(this.rootElement, 'ht__selection--columns');\n addClass(this.rootElement, 'ht__selection--rows');\n } else if (isSelectedByColumnHeader) {\n removeClass(this.rootElement, 'ht__selection--rows');\n addClass(this.rootElement, 'ht__selection--columns');\n } else {\n removeClass(this.rootElement, ['ht__selection--rows', 'ht__selection--columns']);\n }\n if (selection.getSelectionSource() !== 'shift') {\n editorManager.closeEditor(null);\n }\n instance.view.render();\n editorManager.prepareEditor();\n });\n this.selection.addLocalHook('beforeSetFocus', cellCoords => {\n this.runHooks('beforeSelectionFocusSet', cellCoords.row, cellCoords.col);\n });\n this.selection.addLocalHook('afterSetFocus', cellCoords => {\n const preventScrolling = createObjectPropListener(false);\n this.runHooks('afterSelectionFocusSet', cellCoords.row, cellCoords.col, preventScrolling);\n if (!preventScrolling.isTouched() || preventScrolling.isTouched() && !preventScrolling.value) {\n viewportScroller.scrollTo(cellCoords);\n }\n editorManager.closeEditor();\n instance.view.render();\n editorManager.prepareEditor();\n });\n this.selection.addLocalHook('afterSelectionFinished', cellRanges => {\n const selectionLayerLevel = cellRanges.length - 1;\n const {\n from,\n to\n } = cellRanges[selectionLayerLevel];\n this.runHooks('afterSelectionEnd', from.row, from.col, to.row, to.col, selectionLayerLevel);\n this.runHooks('afterSelectionEndByProp', from.row, instance.colToProp(from.col), to.row, instance.colToProp(to.col), selectionLayerLevel);\n });\n this.selection.addLocalHook('afterIsMultipleSelection', isMultiple => {\n const changedIsMultiple = this.runHooks('afterIsMultipleSelection', isMultiple.value);\n if (isMultiple.value) {\n isMultiple.value = changedIsMultiple;\n }\n });\n this.selection.addLocalHook('afterDeselect', () => {\n editorManager.closeEditor();\n instance.view.render();\n removeClass(this.rootElement, ['ht__selection--rows', 'ht__selection--columns']);\n this.runHooks('afterDeselect');\n });\n this.selection.addLocalHook('beforeHighlightSet', () => this.runHooks('beforeSelectionHighlightSet')).addLocalHook('beforeSetRangeStart', function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return _this.runHooks('beforeSetRangeStart', ...args);\n }).addLocalHook('beforeSetRangeStartOnly', function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return _this.runHooks('beforeSetRangeStartOnly', ...args);\n }).addLocalHook('beforeSetRangeEnd', function () {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n return _this.runHooks('beforeSetRangeEnd', ...args);\n }).addLocalHook('beforeSelectColumns', function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return _this.runHooks('beforeSelectColumns', ...args);\n }).addLocalHook('afterSelectColumns', function () {\n for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {\n args[_key5] = arguments[_key5];\n }\n return _this.runHooks('afterSelectColumns', ...args);\n }).addLocalHook('beforeSelectRows', function () {\n for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n return _this.runHooks('beforeSelectRows', ...args);\n }).addLocalHook('afterSelectRows', function () {\n for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {\n args[_key7] = arguments[_key7];\n }\n return _this.runHooks('afterSelectRows', ...args);\n }).addLocalHook('beforeModifyTransformStart', function () {\n for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {\n args[_key8] = arguments[_key8];\n }\n return _this.runHooks('modifyTransformStart', ...args);\n }).addLocalHook('afterModifyTransformStart', function () {\n for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {\n args[_key9] = arguments[_key9];\n }\n return _this.runHooks('afterModifyTransformStart', ...args);\n }).addLocalHook('beforeModifyTransformFocus', function () {\n for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {\n args[_key10] = arguments[_key10];\n }\n return _this.runHooks('modifyTransformFocus', ...args);\n }).addLocalHook('afterModifyTransformFocus', function () {\n for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) {\n args[_key11] = arguments[_key11];\n }\n return _this.runHooks('afterModifyTransformFocus', ...args);\n }).addLocalHook('beforeModifyTransformEnd', function () {\n for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) {\n args[_key12] = arguments[_key12];\n }\n return _this.runHooks('modifyTransformEnd', ...args);\n }).addLocalHook('afterModifyTransformEnd', function () {\n for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) {\n args[_key13] = arguments[_key13];\n }\n return _this.runHooks('afterModifyTransformEnd', ...args);\n }).addLocalHook('beforeRowWrap', function () {\n for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) {\n args[_key14] = arguments[_key14];\n }\n return _this.runHooks('beforeRowWrap', ...args);\n }).addLocalHook('beforeColumnWrap', function () {\n for (var _len15 = arguments.length, args = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) {\n args[_key15] = arguments[_key15];\n }\n return _this.runHooks('beforeColumnWrap', ...args);\n }).addLocalHook('insertRowRequire', totalRows => this.alter('insert_row_above', totalRows, 1, 'auto')).addLocalHook('insertColRequire', totalCols => this.alter('insert_col_start', totalCols, 1, 'auto'));\n grid = {\n /**\n * Inserts or removes rows and columns.\n *\n * @private\n * @param {string} action Possible values: \"insert_row_above\", \"insert_row_below\", \"insert_col_start\", \"insert_col_end\",\n * \"remove_row\", \"remove_col\".\n * @param {number|Array} index Row or column visual index which from the alter action will be triggered.\n * Alter actions such as \"remove_row\" and \"remove_col\" support array indexes in the\n * format `[[index, amount], [index, amount]...]` this can be used to remove\n * non-consecutive columns or rows in one call.\n * @param {number} [amount=1] Amount of rows or columns to remove.\n * @param {string} [source] Optional. Source of hook runner.\n * @param {boolean} [keepEmptyRows] Optional. Flag for preventing deletion of empty rows.\n */\n alter(action, index) {\n var _index, _index2;\n let amount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n let source = arguments.length > 3 ? arguments[3] : undefined;\n let keepEmptyRows = arguments.length > 4 ? arguments[4] : undefined;\n const normalizeIndexesGroup = indexes => {\n if (indexes.length === 0) {\n return [];\n }\n const sortedIndexes = [...indexes];\n\n // Sort the indexes in ascending order.\n sortedIndexes.sort((_ref2, _ref3) => {\n let [indexA] = _ref2;\n let [indexB] = _ref3;\n if (indexA === indexB) {\n return 0;\n }\n return indexA > indexB ? 1 : -1;\n });\n\n // Normalize the {index, amount} groups into bigger groups.\n const normalizedIndexes = arrayReduce(sortedIndexes, (acc, _ref4) => {\n let [groupIndex, groupAmount] = _ref4;\n const previousItem = acc[acc.length - 1];\n const [prevIndex, prevAmount] = previousItem;\n const prevLastIndex = prevIndex + prevAmount;\n if (groupIndex <= prevLastIndex) {\n const amountToAdd = Math.max(groupAmount - (prevLastIndex - groupIndex), 0);\n previousItem[1] += amountToAdd;\n } else {\n acc.push([groupIndex, groupAmount]);\n }\n return acc;\n }, [sortedIndexes[0]]);\n return normalizedIndexes;\n };\n\n /* eslint-disable no-case-declarations */\n switch (action) {\n case 'insert_row_below':\n case 'insert_row_above':\n const numberOfSourceRows = instance.countSourceRows();\n if (tableMeta.maxRows === numberOfSourceRows) {\n return;\n }\n\n // `above` is the default behavior for creating new rows\n const insertRowMode = action === 'insert_row_below' ? 'below' : 'above';\n\n // Calling the `insert_row_above` action adds a new row at the beginning of the data set.\n // eslint-disable-next-line no-param-reassign\n index = (_index = index) !== null && _index !== void 0 ? _index : insertRowMode === 'below' ? numberOfSourceRows : 0;\n const {\n delta: rowDelta,\n startPhysicalIndex: startRowPhysicalIndex\n } = datamap.createRow(index, amount, {\n source,\n mode: insertRowMode\n });\n selection.shiftRows(instance.toVisualRow(startRowPhysicalIndex), rowDelta);\n break;\n case 'insert_col_start':\n case 'insert_col_end':\n // \"start\" is a default behavior for creating new columns\n const insertColumnMode = action === 'insert_col_end' ? 'end' : 'start';\n\n // Calling the `insert_col_start` action adds a new column to the left of the data set.\n // eslint-disable-next-line no-param-reassign\n index = (_index2 = index) !== null && _index2 !== void 0 ? _index2 : insertColumnMode === 'end' ? instance.countSourceCols() : 0;\n const {\n delta: colDelta,\n startPhysicalIndex: startColumnPhysicalIndex\n } = datamap.createCol(index, amount, {\n source,\n mode: insertColumnMode\n });\n if (colDelta) {\n if (Array.isArray(tableMeta.colHeaders)) {\n const spliceArray = [instance.toVisualColumn(startColumnPhysicalIndex), 0];\n spliceArray.length += colDelta; // inserts empty (undefined) elements at the end of an array\n Array.prototype.splice.apply(tableMeta.colHeaders, spliceArray); // inserts empty (undefined) elements into the colHeader array\n }\n selection.shiftColumns(instance.toVisualColumn(startColumnPhysicalIndex), colDelta);\n }\n break;\n case 'remove_row':\n const removeRow = indexes => {\n let offset = 0;\n\n // Normalize the {index, amount} groups into bigger groups.\n arrayEach(indexes, _ref5 => {\n let [groupIndex, groupAmount] = _ref5;\n const calcIndex = isEmpty(groupIndex) ? instance.countRows() - 1 : Math.max(groupIndex - offset, 0);\n\n // If the 'index' is an integer decrease it by 'offset' otherwise pass it through to make the value\n // compatible with datamap.removeCol method.\n if (Number.isInteger(groupIndex)) {\n // eslint-disable-next-line no-param-reassign\n groupIndex = Math.max(groupIndex - offset, 0);\n }\n\n // TODO: for datamap.removeRow index should be passed as it is (with undefined and null values). If not, the logic\n // inside the datamap.removeRow breaks the removing functionality.\n const wasRemoved = datamap.removeRow(groupIndex, groupAmount, source);\n if (!wasRemoved) {\n return;\n }\n if (selection.isSelected()) {\n const {\n row\n } = instance.getSelectedRangeLast().highlight;\n if (row >= groupIndex && row <= groupIndex + groupAmount - 1) {\n editorManager.closeEditor(true);\n }\n }\n const totalRows = instance.countRows();\n if (totalRows === 0) {\n selection.deselect();\n } else if (source === 'ContextMenu.removeRow') {\n selection.refresh();\n } else {\n selection.shiftRows(groupIndex, -groupAmount);\n }\n const fixedRowsTop = tableMeta.fixedRowsTop;\n if (fixedRowsTop >= calcIndex + 1) {\n tableMeta.fixedRowsTop -= Math.min(groupAmount, fixedRowsTop - calcIndex);\n }\n const fixedRowsBottom = tableMeta.fixedRowsBottom;\n if (fixedRowsBottom && calcIndex >= totalRows - fixedRowsBottom) {\n tableMeta.fixedRowsBottom -= Math.min(groupAmount, fixedRowsBottom);\n }\n offset += groupAmount;\n });\n };\n if (Array.isArray(index)) {\n removeRow(normalizeIndexesGroup(index));\n } else {\n removeRow([[index, amount]]);\n }\n break;\n case 'remove_col':\n const removeCol = indexes => {\n let offset = 0;\n\n // Normalize the {index, amount} groups into bigger groups.\n arrayEach(indexes, _ref6 => {\n let [groupIndex, groupAmount] = _ref6;\n const calcIndex = isEmpty(groupIndex) ? instance.countCols() - 1 : Math.max(groupIndex - offset, 0);\n let physicalColumnIndex = instance.toPhysicalColumn(calcIndex);\n\n // If the 'index' is an integer decrease it by 'offset' otherwise pass it through to make the value\n // compatible with datamap.removeCol method.\n if (Number.isInteger(groupIndex)) {\n // eslint-disable-next-line no-param-reassign\n groupIndex = Math.max(groupIndex - offset, 0);\n }\n\n // TODO: for datamap.removeCol index should be passed as it is (with undefined and null values). If not, the logic\n // inside the datamap.removeCol breaks the removing functionality.\n const wasRemoved = datamap.removeCol(groupIndex, groupAmount, source);\n if (!wasRemoved) {\n return;\n }\n if (selection.isSelected()) {\n const {\n col\n } = instance.getSelectedRangeLast().highlight;\n if (col >= groupIndex && col <= groupIndex + groupAmount - 1) {\n editorManager.closeEditor(true);\n }\n }\n const totalColumns = instance.countCols();\n if (totalColumns === 0) {\n selection.deselect();\n } else if (source === 'ContextMenu.removeColumn') {\n selection.refresh();\n } else {\n selection.shiftColumns(groupIndex, -groupAmount);\n }\n const fixedColumnsStart = tableMeta.fixedColumnsStart;\n if (fixedColumnsStart >= calcIndex + 1) {\n tableMeta.fixedColumnsStart -= Math.min(groupAmount, fixedColumnsStart - calcIndex);\n }\n if (Array.isArray(tableMeta.colHeaders)) {\n if (typeof physicalColumnIndex === 'undefined') {\n physicalColumnIndex = -1;\n }\n tableMeta.colHeaders.splice(physicalColumnIndex, groupAmount);\n }\n offset += groupAmount;\n });\n };\n if (Array.isArray(index)) {\n removeCol(normalizeIndexesGroup(index));\n } else {\n removeCol([[index, amount]]);\n }\n break;\n default:\n throw new Error(`There is no such action \"${action}\"`);\n }\n instance.view.render();\n if (!keepEmptyRows) {\n grid.adjustRowsAndCols(); // makes sure that we did not add rows that will be removed in next refresh\n }\n },\n /**\n * Makes sure there are empty rows at the bottom of the table.\n *\n * @private\n */\n adjustRowsAndCols() {\n const minRows = tableMeta.minRows;\n const minSpareRows = tableMeta.minSpareRows;\n const minCols = tableMeta.minCols;\n const minSpareCols = tableMeta.minSpareCols;\n if (minRows) {\n // should I add empty rows to data source to meet minRows?\n const nrOfRows = instance.countRows();\n if (nrOfRows < minRows) {\n // The synchronization with cell meta is not desired here. For `minRows` option,\n // we don't want to touch/shift cell meta objects.\n datamap.createRow(nrOfRows, minRows - nrOfRows, {\n source: 'auto'\n });\n }\n }\n if (minSpareRows) {\n const emptyRows = instance.countEmptyRows(true);\n\n // should I add empty rows to meet minSpareRows?\n if (emptyRows < minSpareRows) {\n const emptyRowsMissing = minSpareRows - emptyRows;\n const rowsToCreate = Math.min(emptyRowsMissing, tableMeta.maxRows - instance.countSourceRows());\n\n // The synchronization with cell meta is not desired here. For `minSpareRows` option,\n // we don't want to touch/shift cell meta objects.\n datamap.createRow(instance.countRows(), rowsToCreate, {\n source: 'auto'\n });\n }\n }\n {\n let emptyCols;\n\n // count currently empty cols\n if (minCols || minSpareCols) {\n emptyCols = instance.countEmptyCols(true);\n }\n let nrOfColumns = instance.countCols();\n\n // should I add empty cols to meet minCols?\n if (minCols && !tableMeta.columns && nrOfColumns < minCols) {\n // The synchronization with cell meta is not desired here. For `minSpareRows` option,\n // we don't want to touch/shift cell meta objects.\n const colsToCreate = minCols - nrOfColumns;\n emptyCols += colsToCreate;\n datamap.createCol(nrOfColumns, colsToCreate, {\n source: 'auto'\n });\n }\n // should I add empty cols to meet minSpareCols?\n if (minSpareCols && !tableMeta.columns && instance.dataType === 'array' && emptyCols < minSpareCols) {\n nrOfColumns = instance.countCols();\n const emptyColsMissing = minSpareCols - emptyCols;\n const colsToCreate = Math.min(emptyColsMissing, tableMeta.maxCols - nrOfColumns);\n\n // The synchronization with cell meta is not desired here. For `minSpareRows` option,\n // we don't want to touch/shift cell meta objects.\n datamap.createCol(nrOfColumns, colsToCreate, {\n source: 'auto'\n });\n }\n }\n if (instance.view) {\n instance.view.adjustElementsSize();\n }\n },\n /**\n * Populate the data from the provided 2d array from the given cell coordinates.\n *\n * @private\n * @param {object} start Start selection position. Visual indexes.\n * @param {Array} input 2d data array.\n * @param {object} [end] End selection position (only for drag-down mode). Visual indexes.\n * @param {string} [source=\"populateFromArray\"] Source information string.\n * @param {string} [method=\"overwrite\"] Populate method. Possible options: `shift_down`, `shift_right`, `overwrite`.\n * @returns {object|undefined} Ending td in pasted area (only if any cell was changed).\n */\n populateFromArray(start, input, end, source, method) {\n let r;\n let rlen;\n let c;\n let clen;\n const setData = [];\n const current = {};\n const newDataByColumns = [];\n const startRow = start.row;\n const startColumn = start.col;\n rlen = input.length;\n if (rlen === 0) {\n return false;\n }\n let columnsPopulationEnd = 0;\n let rowsPopulationEnd = 0;\n if (isObject(end)) {\n columnsPopulationEnd = end.col - startColumn + 1;\n rowsPopulationEnd = end.row - startRow + 1;\n }\n\n // insert data with specified pasteMode method\n switch (method) {\n case 'shift_down':\n // translate data from a list of rows to a list of columns\n const populatedDataByColumns = pivot(input);\n const numberOfDataColumns = populatedDataByColumns.length;\n // method's argument can extend the range of data population (data would be repeated)\n const numberOfColumnsToPopulate = Math.max(numberOfDataColumns, columnsPopulationEnd);\n const pushedDownDataByRows = instance.getData().slice(startRow);\n\n // translate data from a list of rows to a list of columns\n const pushedDownDataByColumns = pivot(pushedDownDataByRows).slice(startColumn, startColumn + numberOfColumnsToPopulate);\n for (c = 0; c < numberOfColumnsToPopulate; c += 1) {\n if (c < numberOfDataColumns) {\n for (r = 0, rlen = populatedDataByColumns[c].length; r < rowsPopulationEnd - rlen; r += 1) {\n // repeating data for rows\n populatedDataByColumns[c].push(populatedDataByColumns[c][r % rlen]);\n }\n if (c < pushedDownDataByColumns.length) {\n newDataByColumns.push(populatedDataByColumns[c].concat(pushedDownDataByColumns[c]));\n } else {\n // if before data population, there was no data in the column\n // we fill the required rows' newly-created cells with `null` values\n newDataByColumns.push(populatedDataByColumns[c].concat(new Array(pushedDownDataByRows.length).fill(null)));\n }\n } else {\n // Repeating data for columns.\n newDataByColumns.push(populatedDataByColumns[c % numberOfDataColumns].concat(pushedDownDataByColumns[c]));\n }\n }\n instance.populateFromArray(startRow, startColumn, pivot(newDataByColumns));\n break;\n case 'shift_right':\n const numberOfDataRows = input.length;\n // method's argument can extend the range of data population (data would be repeated)\n const numberOfRowsToPopulate = Math.max(numberOfDataRows, rowsPopulationEnd);\n const pushedRightDataByRows = instance.getData().slice(startRow).map(rowData => rowData.slice(startColumn));\n for (r = 0; r < numberOfRowsToPopulate; r += 1) {\n if (r < numberOfDataRows) {\n for (c = 0, clen = input[r].length; c < columnsPopulationEnd - clen; c += 1) {\n // repeating data for rows\n input[r].push(input[r][c % clen]);\n }\n if (r < pushedRightDataByRows.length) {\n for (let i = 0; i < pushedRightDataByRows[r].length; i += 1) {\n input[r].push(pushedRightDataByRows[r][i]);\n }\n } else {\n // if before data population, there was no data in the row\n // we fill the required columns' newly-created cells with `null` values\n input[r].push(...new Array(pushedRightDataByRows[0].length).fill(null));\n }\n } else {\n // Repeating data for columns.\n input.push(input[r % rlen].slice(0, numberOfRowsToPopulate).concat(pushedRightDataByRows[r]));\n }\n }\n instance.populateFromArray(startRow, startColumn, input);\n break;\n case 'overwrite':\n default:\n // overwrite and other not specified options\n current.row = start.row;\n current.col = start.col;\n let skippedRow = 0;\n let skippedColumn = 0;\n let pushData = true;\n let cellMeta;\n const getInputValue = function getInputValue(row) {\n let col = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n const rowValue = input[row % input.length];\n if (col !== null) {\n return rowValue[col % rowValue.length];\n }\n return rowValue;\n };\n const rowInputLength = input.length;\n const rowSelectionLength = end ? end.row - start.row + 1 : 0;\n if (end) {\n rlen = rowSelectionLength;\n } else {\n rlen = Math.max(rowInputLength, rowSelectionLength);\n }\n for (r = 0; r < rlen; r++) {\n if (end && current.row > end.row && rowSelectionLength > rowInputLength || !tableMeta.allowInsertRow && current.row > instance.countRows() - 1 || current.row >= tableMeta.maxRows) {\n break;\n }\n const visualRow = r - skippedRow;\n const colInputLength = getInputValue(visualRow).length;\n const colSelectionLength = end ? end.col - start.col + 1 : 0;\n if (end) {\n clen = colSelectionLength;\n } else {\n clen = Math.max(colInputLength, colSelectionLength);\n }\n current.col = start.col;\n cellMeta = instance.getCellMeta(current.row, current.col);\n if ((source === 'CopyPaste.paste' || source === 'Autofill.fill') && cellMeta.skipRowOnPaste) {\n skippedRow += 1;\n current.row += 1;\n rlen += 1;\n /* eslint-disable no-continue */\n continue;\n }\n skippedColumn = 0;\n for (c = 0; c < clen; c++) {\n if (end && current.col > end.col && colSelectionLength > colInputLength || !tableMeta.allowInsertColumn && current.col > instance.countCols() - 1 || current.col >= tableMeta.maxCols) {\n break;\n }\n cellMeta = instance.getCellMeta(current.row, current.col);\n if ((source === 'CopyPaste.paste' || source === 'Autofill.fill') && cellMeta.skipColumnOnPaste) {\n skippedColumn += 1;\n current.col += 1;\n clen += 1;\n continue;\n }\n if (cellMeta.readOnly && source !== 'UndoRedo.undo') {\n current.col += 1;\n /* eslint-disable no-continue */\n continue;\n }\n const visualColumn = c - skippedColumn;\n let value = getInputValue(visualRow, visualColumn);\n let orgValue = instance.getDataAtCell(current.row, current.col);\n if (value !== null && typeof value === 'object') {\n // when 'value' is array and 'orgValue' is null, set 'orgValue' to\n // an empty array so that the null value can be compared to 'value'\n // as an empty value for the array context\n if (Array.isArray(value) && orgValue === null) orgValue = [];\n if (orgValue === null || typeof orgValue !== 'object') {\n pushData = false;\n } else {\n const orgValueSchema = duckSchema(Array.isArray(orgValue) ? orgValue : orgValue[0] || orgValue);\n const valueSchema = duckSchema(Array.isArray(value) ? value : value[0] || value);\n\n // Allow overwriting values with the same object-based schema or any array-based schema.\n if (isObjectEqual(orgValueSchema, valueSchema) || Array.isArray(orgValueSchema) && Array.isArray(valueSchema)) {\n value = deepClone(value);\n } else {\n pushData = false;\n }\n }\n } else if (orgValue !== null && typeof orgValue === 'object') {\n pushData = false;\n }\n if (pushData) {\n setData.push([current.row, current.col, value]);\n }\n pushData = true;\n current.col += 1;\n }\n current.row += 1;\n }\n instance.setDataAtCell(setData, null, null, source || 'populateFromArray');\n break;\n }\n }\n };\n\n /**\n * Internal function to set `language` key of settings.\n *\n * @private\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n * @fires Hooks#afterLanguageChange\n */\n function setLanguage(languageCode) {\n const normalizedLanguageCode = normalizeLanguageCode(languageCode);\n if (hasLanguageDictionary(normalizedLanguageCode)) {\n instance.runHooks('beforeLanguageChange', normalizedLanguageCode);\n globalMeta.language = normalizedLanguageCode;\n instance.runHooks('afterLanguageChange', normalizedLanguageCode);\n } else {\n warnUserAboutLanguageRegistration(languageCode);\n }\n }\n\n /**\n * Internal function to set `className` or `tableClassName`, depending on the key from the settings object.\n *\n * @private\n * @param {string} className `className` or `tableClassName` from the key in the settings object.\n * @param {string|string[]} classSettings String or array of strings. Contains class name(s) from settings object.\n */\n function setClassName(className, classSettings) {\n const element = className === 'className' ? instance.rootElement : instance.table;\n if (firstRun) {\n addClass(element, classSettings);\n } else {\n let globalMetaSettingsArray = [];\n let settingsArray = [];\n if (globalMeta[className]) {\n globalMetaSettingsArray = Array.isArray(globalMeta[className]) ? globalMeta[className] : stringToArray(globalMeta[className]);\n }\n if (classSettings) {\n settingsArray = Array.isArray(classSettings) ? classSettings : stringToArray(classSettings);\n }\n const classNameToRemove = getDifferenceOfArrays(globalMetaSettingsArray, settingsArray);\n const classNameToAdd = getDifferenceOfArrays(settingsArray, globalMetaSettingsArray);\n if (classNameToRemove.length) {\n removeClass(element, classNameToRemove);\n }\n if (classNameToAdd.length) {\n addClass(element, classNameToAdd);\n }\n }\n globalMeta[className] = classSettings;\n }\n this.init = function () {\n dataSource.setData(tableMeta.data);\n instance.runHooks('beforeInit');\n if (isMobileBrowser() || isIpadOS()) {\n addClass(instance.rootElement, 'mobile');\n }\n this.updateSettings(tableMeta, true);\n this.view = new TableView(this);\n editorManager = EditorManager.getInstance(instance, tableMeta, selection);\n viewportScroller = createViewportScroller(instance);\n focusManager = new FocusManager(instance);\n if (isRootInstance(this)) {\n installFocusCatcher(instance);\n }\n instance.runHooks('init');\n this.forceFullRender = true; // used when data was changed\n this.view.render();\n\n // Run the logic only if it's the table's initialization and the root element is not visible.\n if (!!firstRun && instance.rootElement.offsetParent === null) {\n observeVisibilityChangeOnce(instance.rootElement, () => {\n // Update the spreader size cache before rendering.\n instance.view._wt.wtOverlays.updateLastSpreaderSize();\n instance.render();\n instance.view.adjustElementsSize();\n });\n }\n if (typeof firstRun === 'object') {\n instance.runHooks('afterChange', firstRun[0], firstRun[1]);\n firstRun = false;\n }\n instance.runHooks('afterInit');\n };\n\n /**\n * @ignore\n * @returns {object}\n */\n function ValidatorsQueue() {\n // moved this one level up so it can be used in any function here. Probably this should be moved to a separate file\n let resolved = false;\n return {\n validatorsInQueue: 0,\n valid: true,\n addValidatorToQueue() {\n this.validatorsInQueue += 1;\n resolved = false;\n },\n removeValidatorFormQueue() {\n this.validatorsInQueue = this.validatorsInQueue - 1 < 0 ? 0 : this.validatorsInQueue - 1;\n this.checkIfQueueIsEmpty();\n },\n onQueueEmpty() {},\n checkIfQueueIsEmpty() {\n if (this.validatorsInQueue === 0 && resolved === false) {\n resolved = true;\n this.onQueueEmpty(this.valid);\n }\n }\n };\n }\n\n /**\n * Get parsed number from numeric string.\n *\n * @private\n * @param {string} numericData Float (separated by a dot or a comma) or integer.\n * @returns {number} Number if we get data in parsable format, not changed value otherwise.\n */\n function getParsedNumber(numericData) {\n // Unifying \"float like\" string. Change from value with comma determiner to value with dot determiner,\n // for example from `450,65` to `450.65`.\n const unifiedNumericData = numericData.replace(',', '.');\n if (isNaN(parseFloat(unifiedNumericData)) === false) {\n return parseFloat(unifiedNumericData);\n }\n return numericData;\n }\n\n /**\n * @ignore\n * @param {Array} changes The 2D array containing information about each of the edited cells.\n * @param {string} source The string that identifies source of validation.\n * @param {Function} callback The callback function fot async validation.\n */\n function validateChanges(changes, source, callback) {\n if (!changes.length) {\n callback();\n return;\n }\n const activeEditor = instance.getActiveEditor();\n const waitingForValidator = new ValidatorsQueue();\n let shouldBeCanceled = true;\n waitingForValidator.onQueueEmpty = () => {\n if (activeEditor && shouldBeCanceled) {\n activeEditor.cancelChanges();\n }\n callback(); // called when async validators are resolved and beforeChange was not async\n };\n for (let i = changes.length - 1; i >= 0; i--) {\n const [row, prop,, newValue] = changes[i];\n const visualCol = datamap.propToCol(prop);\n let cellProperties;\n if (Number.isInteger(visualCol)) {\n cellProperties = instance.getCellMeta(row, visualCol);\n } else {\n // If there's no requested visual column, we can use the table meta as the cell properties when retrieving\n // the cell validator.\n cellProperties = {\n ...Object.getPrototypeOf(tableMeta),\n ...tableMeta\n };\n }\n if (cellProperties.type === 'numeric' && typeof newValue === 'string' && isNumericLike(newValue)) {\n changes[i][3] = getParsedNumber(newValue);\n }\n\n /* eslint-disable no-loop-func */\n if (instance.getCellValidator(cellProperties)) {\n waitingForValidator.addValidatorToQueue();\n instance.validateCell(changes[i][3], cellProperties, function (index, cellPropertiesReference) {\n return function (result) {\n if (typeof result !== 'boolean') {\n throw new Error('Validation error: result is not boolean');\n }\n if (result === false && cellPropertiesReference.allowInvalid === false) {\n shouldBeCanceled = false;\n changes.splice(index, 1); // cancel the change\n cellPropertiesReference.valid = true; // we cancelled the change, so cell value is still valid\n }\n waitingForValidator.removeValidatorFormQueue();\n };\n }(i, cellProperties), source);\n }\n }\n waitingForValidator.checkIfQueueIsEmpty();\n }\n\n /**\n * Internal function to apply changes. Called after validateChanges.\n *\n * @private\n * @param {Array} changes Array in form of [row, prop, oldValue, newValue].\n * @param {string} source String that identifies how this change will be described in changes array (useful in onChange callback).\n * @fires Hooks#beforeChangeRender\n * @fires Hooks#afterChange\n */\n function applyChanges(changes, source) {\n for (let i = changes.length - 1; i >= 0; i--) {\n let skipThisChange = false;\n if (changes[i] === null) {\n changes.splice(i, 1);\n /* eslint-disable no-continue */\n continue;\n }\n if ((changes[i][2] === null || changes[i][2] === undefined) && (changes[i][3] === null || changes[i][3] === undefined)) {\n /* eslint-disable no-continue */\n continue;\n }\n if (tableMeta.allowInsertRow) {\n while (changes[i][0] > instance.countRows() - 1) {\n const {\n delta: numberOfCreatedRows\n } = datamap.createRow(undefined, undefined, {\n source\n });\n if (numberOfCreatedRows === 0) {\n skipThisChange = true;\n break;\n }\n }\n }\n if (instance.dataType === 'array' && (!tableMeta.columns || tableMeta.columns.length === 0) && tableMeta.allowInsertColumn) {\n while (datamap.propToCol(changes[i][1]) > instance.countCols() - 1) {\n const {\n delta: numberOfCreatedColumns\n } = datamap.createCol(undefined, undefined, {\n source\n });\n if (numberOfCreatedColumns === 0) {\n skipThisChange = true;\n break;\n }\n }\n }\n if (skipThisChange) {\n /* eslint-disable no-continue */\n continue;\n }\n datamap.set(changes[i][0], changes[i][1], changes[i][3]);\n }\n const hasChanges = changes.length > 0;\n instance.forceFullRender = true; // used when data was changed or when all cells need to be re-rendered\n\n if (hasChanges) {\n grid.adjustRowsAndCols();\n instance.runHooks('beforeChangeRender', changes, source);\n editorManager.closeEditor();\n instance.view.render();\n editorManager.prepareEditor();\n instance.view.adjustElementsSize();\n instance.runHooks('afterChange', changes, source || 'edit');\n const activeEditor = instance.getActiveEditor();\n if (activeEditor && isDefined(activeEditor.refreshValue)) {\n activeEditor.refreshValue();\n }\n } else {\n instance.view.render();\n }\n }\n\n /**\n * Creates and returns the CellCoords object.\n *\n * @private\n * @memberof Core#\n * @function _createCellCoords\n * @param {number} row The row index.\n * @param {number} column The column index.\n * @returns {CellCoords}\n */\n this._createCellCoords = function (row, column) {\n return instance.view._wt.createCellCoords(row, column);\n };\n\n /**\n * Creates and returns the CellRange object.\n *\n * @private\n * @memberof Core#\n * @function _createCellRange\n * @param {CellCoords} highlight Defines the border around a cell where selection was started and to edit the cell\n * when you press Enter. The highlight cannot point to headers (negative values).\n * @param {CellCoords} from Initial coordinates.\n * @param {CellCoords} to Final coordinates.\n * @returns {CellRange}\n */\n this._createCellRange = function (highlight, from, to) {\n return instance.view._wt.createCellRange(highlight, from, to);\n };\n\n /**\n * Validate a single cell.\n *\n * @memberof Core#\n * @function validateCell\n * @param {string|number} value The value to validate.\n * @param {object} cellProperties The cell meta which corresponds with the value.\n * @param {Function} callback The callback function.\n * @param {string} source The string that identifies source of the validation.\n */\n this.validateCell = function (value, cellProperties, callback, source) {\n let validator = instance.getCellValidator(cellProperties);\n\n // the `canBeValidated = false` argument suggests, that the cell passes validation by default.\n /**\n * @private\n * @function done\n * @param {boolean} valid Indicates if the validation was successful.\n * @param {boolean} [canBeValidated=true] Flag which controls the validation process.\n */\n function done(valid) {\n let canBeValidated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n // Fixes GH#3903\n if (!canBeValidated || cellProperties.hidden === true) {\n callback(valid);\n return;\n }\n const col = cellProperties.visualCol;\n const row = cellProperties.visualRow;\n const td = instance.getCell(row, col, true);\n if (td && td.nodeName !== 'TH') {\n const renderableRow = instance.rowIndexMapper.getRenderableFromVisualIndex(row);\n const renderableColumn = instance.columnIndexMapper.getRenderableFromVisualIndex(col);\n instance.view._wt.getSetting('cellRenderer', renderableRow, renderableColumn, td);\n }\n callback(valid);\n }\n if (isRegExp(validator)) {\n validator = function (expression) {\n return function (cellValue, validatorCallback) {\n validatorCallback(expression.test(cellValue));\n };\n }(validator);\n }\n if (isFunction(validator)) {\n // eslint-disable-next-line no-param-reassign\n value = instance.runHooks('beforeValidate', value, cellProperties.visualRow, cellProperties.prop, source);\n\n // To provide consistent behaviour, validation should be always asynchronous\n instance._registerImmediate(() => {\n validator.call(cellProperties, value, valid => {\n if (!instance) {\n return;\n }\n // eslint-disable-next-line no-param-reassign\n valid = instance.runHooks('afterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);\n cellProperties.valid = valid;\n done(valid);\n instance.runHooks('postAfterValidate', valid, value, cellProperties.visualRow, cellProperties.prop, source);\n });\n });\n } else {\n // resolve callback even if validator function was not found\n instance._registerImmediate(() => {\n cellProperties.valid = true;\n done(cellProperties.valid, false);\n });\n }\n };\n\n /**\n * @ignore\n * @param {number} row The visual row index.\n * @param {string|number} propOrCol The visual prop or column index.\n * @param {*} value The cell value.\n * @returns {Array}\n */\n function setDataInputToArray(row, propOrCol, value) {\n if (Array.isArray(row)) {\n // it's an array of changes\n return row;\n }\n return [[row, propOrCol, value]];\n }\n\n /**\n * Process changes prepared for applying to the dataset (unifying list of changes, closing an editor - when needed,\n * calling a hook).\n *\n * @private\n * @param {Array} changes Array of changes in format `[[row, col, value],...]`.\n * @param {string} [source] String that identifies how this change will be described in the changes array (useful in afterChange or beforeChange callback). Set to 'edit' if left empty.\n * @returns {Array} List of changes finally applied to the dataset.\n */\n function processChanges(changes, source) {\n const activeEditor = instance.getActiveEditor();\n const beforeChangeResult = instance.runHooks('beforeChange', changes, source || 'edit');\n // The `beforeChange` hook could add a `null` for purpose of cancelling some dataset's change.\n const filteredChanges = changes.filter(change => change !== null);\n if (beforeChangeResult === false || filteredChanges.length === 0) {\n if (activeEditor) {\n activeEditor.cancelChanges();\n }\n return [];\n }\n return filteredChanges;\n }\n\n /**\n * @description\n * Set new value to a cell. To change many cells at once (recommended way), pass an array of `changes` in format\n * `[[row, col, value],...]` as the first argument.\n *\n * @memberof Core#\n * @function setDataAtCell\n * @param {number|Array} row Visual row index or array of changes in format `[[row, col, value],...]`.\n * @param {number} [column] Visual column index.\n * @param {string} [value] New value.\n * @param {string} [source] String that identifies how this change will be described in the changes array (useful in afterChange or beforeChange callback). Set to 'edit' if left empty.\n */\n this.setDataAtCell = function (row, column, value, source) {\n const input = setDataInputToArray(row, column, value);\n const changes = [];\n let changeSource = source;\n let i;\n let ilen;\n let prop;\n for (i = 0, ilen = input.length; i < ilen; i++) {\n if (typeof input[i] !== 'object') {\n throw new Error('Method `setDataAtCell` accepts row number or changes array of arrays as its first parameter');\n }\n if (typeof input[i][1] !== 'number') {\n throw new Error('Method `setDataAtCell` accepts row and column number as its parameters. If you want to use object property name, use method `setDataAtRowProp`'); // eslint-disable-line max-len\n }\n if (input[i][1] >= this.countCols()) {\n prop = input[i][1];\n } else {\n prop = datamap.colToProp(input[i][1]);\n }\n changes.push([input[i][0], prop, dataSource.getAtCell(this.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);\n }\n if (!changeSource && typeof row === 'object') {\n changeSource = column;\n }\n const processedChanges = processChanges(changes, source);\n instance.runHooks('afterSetDataAtCell', processedChanges, changeSource);\n validateChanges(processedChanges, changeSource, () => {\n applyChanges(processedChanges, changeSource);\n });\n };\n\n /**\n * @description\n * Set new value to a cell. To change many cells at once (recommended way), pass an array of `changes` in format\n * `[[row, prop, value],...]` as the first argument.\n *\n * @memberof Core#\n * @function setDataAtRowProp\n * @param {number|Array} row Visual row index or array of changes in format `[[row, prop, value], ...]`.\n * @param {string} prop Property name or the source string (e.g. `'first.name'` or `'0'`).\n * @param {string} value Value to be set.\n * @param {string} [source] String that identifies how this change will be described in changes array (useful in onChange callback).\n */\n this.setDataAtRowProp = function (row, prop, value, source) {\n const input = setDataInputToArray(row, prop, value);\n const changes = [];\n let changeSource = source;\n let i;\n let ilen;\n for (i = 0, ilen = input.length; i < ilen; i++) {\n changes.push([input[i][0], input[i][1], dataSource.getAtCell(this.toPhysicalRow(input[i][0]), input[i][1]), input[i][2]]);\n }\n\n // TODO: I don't think `prop` should be used as `changeSource` here, but removing it would be a breaking change.\n // We should remove it with the next major release.\n if (!changeSource && typeof row === 'object') {\n changeSource = prop;\n }\n const processedChanges = processChanges(changes, source);\n instance.runHooks('afterSetDataAtRowProp', processedChanges, changeSource);\n validateChanges(processedChanges, changeSource, () => {\n applyChanges(processedChanges, changeSource);\n });\n };\n\n /**\n * Listen to the keyboard input on document body. This allows Handsontable to capture keyboard events and respond\n * in the right way.\n *\n * @memberof Core#\n * @function listen\n * @fires Hooks#afterListen\n */\n this.listen = function () {\n if (instance && !instance.isListening()) {\n foreignHotInstances.forEach(foreignHot => {\n if (instance !== foreignHot) {\n foreignHot.unlisten();\n }\n });\n activeGuid = instance.guid;\n instance.runHooks('afterListen');\n }\n };\n\n /**\n * Stop listening to keyboard input on the document body. Calling this method makes the Handsontable inactive for\n * any keyboard events.\n *\n * @memberof Core#\n * @function unlisten\n */\n this.unlisten = function () {\n if (this.isListening()) {\n activeGuid = null;\n instance.runHooks('afterUnlisten');\n }\n };\n\n /**\n * Returns `true` if the current Handsontable instance is listening to keyboard input on document body.\n *\n * @memberof Core#\n * @function isListening\n * @returns {boolean} `true` if the instance is listening, `false` otherwise.\n */\n this.isListening = function () {\n return activeGuid === instance.guid;\n };\n\n /**\n * Destroys the current editor, render the table and prepares the editor of the newly selected cell.\n *\n * @memberof Core#\n * @function destroyEditor\n * @param {boolean} [revertOriginal=false] If `true`, the previous value will be restored. Otherwise, the edited value will be saved.\n * @param {boolean} [prepareEditorIfNeeded=true] If `true` the editor under the selected cell will be prepared to open.\n */\n this.destroyEditor = function () {\n let revertOriginal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n let prepareEditorIfNeeded = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n editorManager.closeEditor(revertOriginal);\n instance.view.render();\n if (prepareEditorIfNeeded && selection.isSelected()) {\n editorManager.prepareEditor();\n }\n };\n\n /**\n * Populates cells at position with 2D input array (e.g. `[[1, 2], [3, 4]]`). Use `endRow`, `endCol` when you\n * want to cut input when a certain row is reached.\n *\n * The `populateFromArray()` method can't change [`readOnly`](@/api/options.md#readonly) cells.\n *\n * Optional `method` argument has the same effect as pasteMode option (see {@link Options#pasteMode}).\n *\n * @memberof Core#\n * @function populateFromArray\n * @param {number} row Start visual row index.\n * @param {number} column Start visual column index.\n * @param {Array} input 2d array.\n * @param {number} [endRow] End visual row index (use when you want to cut input when certain row is reached).\n * @param {number} [endCol] End visual column index (use when you want to cut input when certain column is reached).\n * @param {string} [source=populateFromArray] Used to identify this call in the resulting events (beforeChange, afterChange).\n * @param {string} [method=overwrite] Populate method, possible values: `'shift_down'`, `'shift_right'`, `'overwrite'`.\n * @returns {object|undefined} Ending td in pasted area (only if any cell was changed).\n */\n this.populateFromArray = function (row, column, input, endRow, endCol, source, method) {\n if (!(typeof input === 'object' && typeof input[0] === 'object')) {\n throw new Error('populateFromArray parameter `input` must be an array of arrays'); // API changed in 0.9-beta2, let's check if you use it correctly\n }\n const c = typeof endRow === 'number' ? instance._createCellCoords(endRow, endCol) : null;\n return grid.populateFromArray(instance._createCellCoords(row, column), input, c, source, method);\n };\n\n /**\n * Adds/removes data from the column. This method works the same as Array.splice for arrays.\n *\n * @memberof Core#\n * @function spliceCol\n * @param {number} column Index of the column in which do you want to do splice.\n * @param {number} index Index at which to start changing the array. If negative, will begin that many elements from the end.\n * @param {number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.\n * @param {...number} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.\n * @returns {Array} Returns removed portion of columns.\n */\n this.spliceCol = function (column, index, amount) {\n for (var _len16 = arguments.length, elements = new Array(_len16 > 3 ? _len16 - 3 : 0), _key16 = 3; _key16 < _len16; _key16++) {\n elements[_key16 - 3] = arguments[_key16];\n }\n return datamap.spliceCol(column, index, amount, ...elements);\n };\n\n /**\n * Adds/removes data from the row. This method works the same as Array.splice for arrays.\n *\n * @memberof Core#\n * @function spliceRow\n * @param {number} row Index of column in which do you want to do splice.\n * @param {number} index Index at which to start changing the array. If negative, will begin that many elements from the end.\n * @param {number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.\n * @param {...number} [elements] The elements to add to the array. If you don't specify any elements, spliceCol simply removes elements from the array.\n * @returns {Array} Returns removed portion of rows.\n */\n this.spliceRow = function (row, index, amount) {\n for (var _len17 = arguments.length, elements = new Array(_len17 > 3 ? _len17 - 3 : 0), _key17 = 3; _key17 < _len17; _key17++) {\n elements[_key17 - 3] = arguments[_key17];\n }\n return datamap.spliceRow(row, index, amount, ...elements);\n };\n\n /**\n * Returns indexes of the currently selected cells as an array of arrays `[[startRow, startCol, endRow, endCol],...]`.\n *\n * Start row and start column are the coordinates of the active cell (where the selection was started).\n *\n * The version 0.36.0 adds a non-consecutive selection feature. Since this version, the method returns an array of arrays.\n * Additionally to collect the coordinates of the currently selected area (as it was previously done by the method)\n * you need to use `getSelectedLast` method.\n *\n * @memberof Core#\n * @function getSelected\n * @returns {Array[]|undefined} An array of arrays of the selection's coordinates.\n */\n this.getSelected = function () {\n // https://github.com/handsontable/handsontable/issues/44 //cjl\n if (selection.isSelected()) {\n return arrayMap(selection.getSelectedRange(), _ref7 => {\n let {\n from,\n to\n } = _ref7;\n return [from.row, from.col, to.row, to.col];\n });\n }\n };\n\n /**\n * Returns the last coordinates applied to the table as a an array `[startRow, startCol, endRow, endCol]`.\n *\n * @since 0.36.0\n * @memberof Core#\n * @function getSelectedLast\n * @returns {Array|undefined} An array of the selection's coordinates.\n */\n this.getSelectedLast = function () {\n const selected = this.getSelected();\n let result;\n if (selected && selected.length > 0) {\n result = selected[selected.length - 1];\n }\n return result;\n };\n\n /**\n * Returns the current selection as an array of CellRange objects.\n *\n * The version 0.36.0 adds a non-consecutive selection feature. Since this version, the method returns an array of arrays.\n * Additionally to collect the coordinates of the currently selected area (as it was previously done by the method)\n * you need to use `getSelectedRangeLast` method.\n *\n * @memberof Core#\n * @function getSelectedRange\n * @returns {CellRange[]|undefined} Selected range object or undefined if there is no selection.\n */\n this.getSelectedRange = function () {\n // https://github.com/handsontable/handsontable/issues/44 //cjl\n if (selection.isSelected()) {\n return Array.from(selection.getSelectedRange());\n }\n };\n\n /**\n * Returns the last coordinates applied to the table as a CellRange object.\n *\n * @memberof Core#\n * @function getSelectedRangeLast\n * @since 0.36.0\n * @returns {CellRange|undefined} Selected range object or undefined` if there is no selection.\n */\n this.getSelectedRangeLast = function () {\n const selectedRange = this.getSelectedRange();\n let result;\n if (selectedRange && selectedRange.length > 0) {\n result = selectedRange[selectedRange.length - 1];\n }\n return result;\n };\n\n /**\n * Erases content from cells that have been selected in the table.\n *\n * @memberof Core#\n * @function emptySelectedCells\n * @param {string} [source] String that identifies how this change will be described in the changes array (useful in afterChange or beforeChange callback). Set to 'edit' if left empty.\n * @since 0.36.0\n */\n this.emptySelectedCells = function (source) {\n if (!selection.isSelected() || this.countRows() === 0 || this.countCols() === 0) {\n return;\n }\n const changes = [];\n arrayEach(selection.getSelectedRange(), cellRange => {\n if (cellRange.isSingleHeader()) {\n return;\n }\n const topStart = cellRange.getTopStartCorner();\n const bottomEnd = cellRange.getBottomEndCorner();\n rangeEach(topStart.row, bottomEnd.row, row => {\n rangeEach(topStart.col, bottomEnd.col, column => {\n if (!this.getCellMeta(row, column).readOnly) {\n changes.push([row, column, null]);\n }\n });\n });\n });\n if (changes.length > 0) {\n this.setDataAtCell(changes, source);\n }\n };\n\n /**\n * Checks if the table rendering process was suspended. See explanation in {@link Core#suspendRender}.\n *\n * @memberof Core#\n * @function isRenderSuspended\n * @since 8.3.0\n * @returns {boolean}\n */\n this.isRenderSuspended = function () {\n return this.renderSuspendedCounter > 0;\n };\n\n /**\n * Suspends the rendering process. It's helpful to wrap the table render\n * cycles triggered by API calls or UI actions (or both) and call the \"render\"\n * once in the end. As a result, it improves the performance of wrapped operations.\n * When the table is in the suspend state, most operations will have no visual\n * effect until the rendering state is resumed. Resuming the state automatically\n * invokes the table rendering. To make sure that after executing all operations,\n * the table will be rendered, it's highly recommended to use the {@link Core#batchRender}\n * method or {@link Core#batch}, which additionally aggregates the logic execution\n * that happens behind the table.\n *\n * The method is intended to be used by advanced users. Suspending the rendering\n * process could cause visual glitches when wrongly implemented.\n *\n * Every [`suspendRender()`](@/api/core.md#suspendrender) call needs to correspond with one [`resumeRender()`](@/api/core.md#resumerender) call.\n * For example, if you call [`suspendRender()`](@/api/core.md#suspendrender) 5 times, you need to call [`resumeRender()`](@/api/core.md#resumerender) 5 times as well.\n *\n * @memberof Core#\n * @function suspendRender\n * @since 8.3.0\n * @example\n * ```js\n * hot.suspendRender();\n * hot.alter('insert_row_above', 5, 45);\n * hot.alter('insert_col_start', 10, 40);\n * hot.setDataAtCell(1, 1, 'John');\n * hot.setDataAtCell(2, 2, 'Mark');\n * hot.setDataAtCell(3, 3, 'Ann');\n * hot.setDataAtCell(4, 4, 'Sophia');\n * hot.setDataAtCell(5, 5, 'Mia');\n * hot.selectCell(0, 0);\n * hot.resumeRender(); // It re-renders the table internally\n * ```\n */\n this.suspendRender = function () {\n this.renderSuspendedCounter += 1;\n };\n\n /**\n * Resumes the rendering process. In combination with the {@link Core#suspendRender}\n * method it allows aggregating the table render cycles triggered by API calls or UI\n * actions (or both) and calls the \"render\" once in the end. When the table is in\n * the suspend state, most operations will have no visual effect until the rendering\n * state is resumed. Resuming the state automatically invokes the table rendering.\n *\n * The method is intended to be used by advanced users. Suspending the rendering\n * process could cause visual glitches when wrongly implemented.\n *\n * Every [`suspendRender()`](@/api/core.md#suspendrender) call needs to correspond with one [`resumeRender()`](@/api/core.md#resumerender) call.\n * For example, if you call [`suspendRender()`](@/api/core.md#suspendrender) 5 times, you need to call [`resumeRender()`](@/api/core.md#resumerender) 5 times as well.\n *\n * @memberof Core#\n * @function resumeRender\n * @since 8.3.0\n * @example\n * ```js\n * hot.suspendRender();\n * hot.alter('insert_row_above', 5, 45);\n * hot.alter('insert_col_start', 10, 40);\n * hot.setDataAtCell(1, 1, 'John');\n * hot.setDataAtCell(2, 2, 'Mark');\n * hot.setDataAtCell(3, 3, 'Ann');\n * hot.setDataAtCell(4, 4, 'Sophia');\n * hot.setDataAtCell(5, 5, 'Mia');\n * hot.selectCell(0, 0);\n * hot.resumeRender(); // It re-renders the table internally\n * ```\n */\n this.resumeRender = function () {\n const nextValue = this.renderSuspendedCounter - 1;\n this.renderSuspendedCounter = Math.max(nextValue, 0);\n if (!this.isRenderSuspended() && nextValue === this.renderSuspendedCounter) {\n if (this.renderCall) {\n this.render();\n } else {\n instance.view.render();\n }\n }\n };\n\n /**\n * Rerender the table. Calling this method starts the process of recalculating, redrawing and applying the changes\n * to the DOM. While rendering the table all cell renderers are recalled.\n *\n * Calling this method manually is not recommended. Handsontable tries to render itself by choosing the most\n * optimal moments in its lifecycle.\n *\n * @memberof Core#\n * @function render\n */\n this.render = function () {\n if (this.view) {\n this.renderCall = true;\n this.forceFullRender = true; // used when data was changed or when all cells need to be re-rendered\n\n if (!this.isRenderSuspended()) {\n instance.view.render();\n }\n }\n };\n\n /**\n * The method aggregates multi-line API calls into a callback and postpones the\n * table rendering process. After the execution of the operations, the table is\n * rendered once. As a result, it improves the performance of wrapped operations.\n * Without batching, a similar case could trigger multiple table render calls.\n *\n * @memberof Core#\n * @function batchRender\n * @param {Function} wrappedOperations Batched operations wrapped in a function.\n * @returns {*} Returns result from the wrappedOperations callback.\n * @since 8.3.0\n * @example\n * ```js\n * hot.batchRender(() => {\n * hot.alter('insert_row_above', 5, 45);\n * hot.alter('insert_col_start', 10, 40);\n * hot.setDataAtCell(1, 1, 'John');\n * hot.setDataAtCell(2, 2, 'Mark');\n * hot.setDataAtCell(3, 3, 'Ann');\n * hot.setDataAtCell(4, 4, 'Sophia');\n * hot.setDataAtCell(5, 5, 'Mia');\n * hot.selectCell(0, 0);\n * // The table will be rendered once after executing the callback\n * });\n * ```\n */\n this.batchRender = function (wrappedOperations) {\n this.suspendRender();\n const result = wrappedOperations();\n this.resumeRender();\n return result;\n };\n\n /**\n * Checks if the table indexes recalculation process was suspended. See explanation\n * in {@link Core#suspendExecution}.\n *\n * @memberof Core#\n * @function isExecutionSuspended\n * @since 8.3.0\n * @returns {boolean}\n */\n this.isExecutionSuspended = function () {\n return this.executionSuspendedCounter > 0;\n };\n\n /**\n * Suspends the execution process. It's helpful to wrap the table logic changes\n * such as index changes into one call after which the cache is updated. As a result,\n * it improves the performance of wrapped operations.\n *\n * The method is intended to be used by advanced users. Suspending the execution\n * process could cause visual glitches caused by not updated the internal table cache.\n *\n * @memberof Core#\n * @function suspendExecution\n * @since 8.3.0\n * @example\n * ```js\n * hot.suspendExecution();\n * const filters = hot.getPlugin('filters');\n *\n * filters.addCondition(2, 'contains', ['3']);\n * filters.filter();\n * hot.getPlugin('columnSorting').sort({ column: 1, sortOrder: 'desc' });\n * hot.resumeExecution(); // It updates the cache internally\n * ```\n */\n this.suspendExecution = function () {\n this.executionSuspendedCounter += 1;\n this.columnIndexMapper.suspendOperations();\n this.rowIndexMapper.suspendOperations();\n };\n\n /**\n * Resumes the execution process. In combination with the {@link Core#suspendExecution}\n * method it allows aggregating the table logic changes after which the cache is\n * updated. Resuming the state automatically invokes the table cache updating process.\n *\n * The method is intended to be used by advanced users. Suspending the execution\n * process could cause visual glitches caused by not updated the internal table cache.\n *\n * @memberof Core#\n * @function resumeExecution\n * @param {boolean} [forceFlushChanges=false] If `true`, the table internal data cache\n * is recalculated after the execution of the batched operations. For nested\n * {@link Core#batchExecution} calls, it can be desire to recalculate the table\n * after each batch.\n * @since 8.3.0\n * @example\n * ```js\n * hot.suspendExecution();\n * const filters = hot.getPlugin('filters');\n *\n * filters.addCondition(2, 'contains', ['3']);\n * filters.filter();\n * hot.getPlugin('columnSorting').sort({ column: 1, sortOrder: 'desc' });\n * hot.resumeExecution(); // It updates the cache internally\n * ```\n */\n this.resumeExecution = function () {\n let forceFlushChanges = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const nextValue = this.executionSuspendedCounter - 1;\n this.executionSuspendedCounter = Math.max(nextValue, 0);\n if (!this.isExecutionSuspended() && nextValue === this.executionSuspendedCounter || forceFlushChanges) {\n this.columnIndexMapper.resumeOperations();\n this.rowIndexMapper.resumeOperations();\n }\n };\n\n /**\n * The method aggregates multi-line API calls into a callback and postpones the\n * table execution process. After the execution of the operations, the internal table\n * cache is recalculated once. As a result, it improves the performance of wrapped\n * operations. Without batching, a similar case could trigger multiple table cache rebuilds.\n *\n * @memberof Core#\n * @function batchExecution\n * @param {Function} wrappedOperations Batched operations wrapped in a function.\n * @param {boolean} [forceFlushChanges=false] If `true`, the table internal data cache\n * is recalculated after the execution of the batched operations. For nested calls,\n * it can be a desire to recalculate the table after each batch.\n * @returns {*} Returns result from the wrappedOperations callback.\n * @since 8.3.0\n * @example\n * ```js\n * hot.batchExecution(() => {\n * const filters = hot.getPlugin('filters');\n *\n * filters.addCondition(2, 'contains', ['3']);\n * filters.filter();\n * hot.getPlugin('columnSorting').sort({ column: 1, sortOrder: 'desc' });\n * // The table cache will be recalculated once after executing the callback\n * });\n * ```\n */\n this.batchExecution = function (wrappedOperations) {\n let forceFlushChanges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n this.suspendExecution();\n const result = wrappedOperations();\n this.resumeExecution(forceFlushChanges);\n return result;\n };\n\n /**\n * It batches the rendering process and index recalculations. The method aggregates\n * multi-line API calls into a callback and postpones the table rendering process\n * as well aggregates the table logic changes such as index changes into one call\n * after which the cache is updated. After the execution of the operations, the\n * table is rendered, and the cache is updated once. As a result, it improves the\n * performance of wrapped operations.\n *\n * @memberof Core#\n * @function batch\n * @param {Function} wrappedOperations Batched operations wrapped in a function.\n * @returns {*} Returns result from the wrappedOperations callback.\n * @since 8.3.0\n * @example\n * ```js\n * hot.batch(() => {\n * hot.alter('insert_row_above', 5, 45);\n * hot.alter('insert_col_start', 10, 40);\n * hot.setDataAtCell(1, 1, 'x');\n * hot.setDataAtCell(2, 2, 'c');\n * hot.setDataAtCell(3, 3, 'v');\n * hot.setDataAtCell(4, 4, 'b');\n * hot.setDataAtCell(5, 5, 'n');\n * hot.selectCell(0, 0);\n *\n * const filters = hot.getPlugin('filters');\n *\n * filters.addCondition(2, 'contains', ['3']);\n * filters.filter();\n * hot.getPlugin('columnSorting').sort({ column: 1, sortOrder: 'desc' });\n * // The table will be re-rendered and cache will be recalculated once after executing the callback\n * });\n * ```\n */\n this.batch = function (wrappedOperations) {\n this.suspendRender();\n this.suspendExecution();\n const result = wrappedOperations();\n this.resumeExecution();\n this.resumeRender();\n return result;\n };\n\n /**\n * Updates dimensions of the table. The method compares previous dimensions with the current ones and updates accordingly.\n *\n * @memberof Core#\n * @function refreshDimensions\n * @fires Hooks#beforeRefreshDimensions\n * @fires Hooks#afterRefreshDimensions\n */\n this.refreshDimensions = function () {\n if (!instance.view) {\n return;\n }\n const {\n width: lastWidth,\n height: lastHeight\n } = instance.view.getLastSize();\n const {\n width,\n height\n } = instance.rootElement.getBoundingClientRect();\n const isSizeChanged = width !== lastWidth || height !== lastHeight;\n const isResizeBlocked = instance.runHooks('beforeRefreshDimensions', {\n width: lastWidth,\n height: lastHeight\n }, {\n width,\n height\n }, isSizeChanged) === false;\n if (isResizeBlocked) {\n return;\n }\n if (isSizeChanged || instance.view._wt.wtOverlays.scrollableElement === instance.rootWindow) {\n instance.view.setLastSize(width, height);\n instance.render();\n }\n instance.runHooks('afterRefreshDimensions', {\n width: lastWidth,\n height: lastHeight\n }, {\n width,\n height\n }, isSizeChanged);\n };\n\n /**\n * The `updateData()` method replaces Handsontable's [`data`](@/api/options.md#data) with a new dataset.\n *\n * The `updateData()` method:\n * - Keeps cells' states (e.g. cells' [formatting](@/guides/cell-features/formatting-cells/formatting-cells.md) and cells' [`readOnly`](@/api/options.md#readonly) states)\n * - Keeps rows' states (e.g. row order)\n * - Keeps columns' states (e.g. column order)\n *\n * To replace Handsontable's [`data`](@/api/options.md#data) and reset states, use the [`loadData()`](#loaddata) method.\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @memberof Core#\n * @function updateData\n * @since 11.1.0\n * @param {Array} data An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {string} [source] The source of the `updateData()` call\n * @fires Hooks#beforeUpdateData\n * @fires Hooks#afterUpdateData\n * @fires Hooks#afterChange\n */\n this.updateData = function (data, source) {\n replaceData(data, newDataMap => {\n datamap = newDataMap;\n }, newDataMap => {\n datamap = newDataMap;\n instance.columnIndexMapper.fitToLength(this.getInitialColumnCount());\n instance.rowIndexMapper.fitToLength(this.countSourceRows());\n grid.adjustRowsAndCols();\n selection.refresh();\n }, {\n hotInstance: instance,\n dataMap: datamap,\n dataSource,\n internalSource: 'updateData',\n source,\n metaManager,\n firstRun\n });\n };\n\n /**\n * The `loadData()` method replaces Handsontable's [`data`](@/api/options.md#data) with a new dataset.\n *\n * Additionally, the `loadData()` method:\n * - Resets cells' states (e.g. cells' [formatting](@/guides/cell-features/formatting-cells/formatting-cells.md) and cells' [`readOnly`](@/api/options.md#readonly) states)\n * - Resets rows' states (e.g. row order)\n * - Resets columns' states (e.g. column order)\n *\n * To replace Handsontable's [`data`](@/api/options.md#data) without resetting states, use the [`updateData()`](#updatedata) method.\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @memberof Core#\n * @function loadData\n * @param {Array} data An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {string} [source] The source of the `loadData()` call\n * @fires Hooks#beforeLoadData\n * @fires Hooks#afterLoadData\n * @fires Hooks#afterChange\n */\n this.loadData = function (data, source) {\n replaceData(data, newDataMap => {\n datamap = newDataMap;\n }, () => {\n metaManager.clearCellsCache();\n instance.initIndexMappers();\n grid.adjustRowsAndCols();\n selection.refresh();\n if (firstRun) {\n firstRun = [null, 'loadData'];\n }\n }, {\n hotInstance: instance,\n dataMap: datamap,\n dataSource,\n internalSource: 'loadData',\n source,\n metaManager,\n firstRun\n });\n };\n\n /**\n * Gets the initial column count, calculated based on the `columns` setting.\n *\n * @private\n * @returns {number} The calculated number of columns.\n */\n this.getInitialColumnCount = function () {\n const columnsSettings = tableMeta.columns;\n let finalNrOfColumns = 0;\n\n // We will check number of columns when the `columns` property was defined as an array. Columns option may\n // narrow down or expand displayed dataset in that case.\n if (Array.isArray(columnsSettings)) {\n finalNrOfColumns = columnsSettings.length;\n } else if (isFunction(columnsSettings)) {\n if (instance.dataType === 'array') {\n const nrOfSourceColumns = this.countSourceCols();\n for (let columnIndex = 0; columnIndex < nrOfSourceColumns; columnIndex += 1) {\n if (columnsSettings(columnIndex)) {\n finalNrOfColumns += 1;\n }\n }\n\n // Extended dataset by the `columns` property? Moved code right from the refactored `countCols` method.\n } else if (instance.dataType === 'object' || instance.dataType === 'function') {\n finalNrOfColumns = datamap.colToPropCache.length;\n }\n\n // In some cases we need to check columns length from the schema, i.e. `data` may be empty.\n } else if (isDefined(tableMeta.dataSchema)) {\n const schema = datamap.getSchema();\n\n // Schema may be defined as an array of objects. Each object will define column.\n finalNrOfColumns = Array.isArray(schema) ? schema.length : deepObjectSize(schema);\n } else {\n // We init index mappers by length of source data to provide indexes also for skipped indexes.\n finalNrOfColumns = this.countSourceCols();\n }\n return finalNrOfColumns;\n };\n\n /**\n * Init index mapper which manage indexes assigned to the data.\n *\n * @private\n */\n this.initIndexMappers = function () {\n this.columnIndexMapper.initToLength(this.getInitialColumnCount());\n this.rowIndexMapper.initToLength(this.countSourceRows());\n };\n\n /**\n * Returns the current data object (the same one that was passed by `data` configuration option or `loadData` method,\n * unless some modifications have been applied (i.e. Sequence of rows/columns was changed, some row/column was skipped).\n * If that's the case - use the {@link Core#getSourceData} method.).\n *\n * Optionally you can provide cell range by defining `row`, `column`, `row2`, `column2` to get only a fragment of table data.\n *\n * @memberof Core#\n * @function getData\n * @param {number} [row] From visual row index.\n * @param {number} [column] From visual column index.\n * @param {number} [row2] To visual row index.\n * @param {number} [column2] To visual column index.\n * @returns {Array[]} Array with the data.\n * @example\n * ```js\n * // Get all data (in order how it is rendered in the table).\n * hot.getData();\n * // Get data fragment (from top-left 0, 0 to bottom-right 3, 3).\n * hot.getData(3, 3);\n * // Get data fragment (from top-left 2, 1 to bottom-right 3, 3).\n * hot.getData(2, 1, 3, 3);\n * ```\n */\n this.getData = function (row, column, row2, column2) {\n if (isUndefined(row)) {\n return datamap.getAll();\n }\n return datamap.getRange(instance._createCellCoords(row, column), instance._createCellCoords(row2, column2), datamap.DESTINATION_RENDERER);\n };\n\n /**\n * Returns a string value of the selected range. Each column is separated by tab, each row is separated by a new\n * line character.\n *\n * @memberof Core#\n * @function getCopyableText\n * @param {number} startRow From visual row index.\n * @param {number} startCol From visual column index.\n * @param {number} endRow To visual row index.\n * @param {number} endCol To visual column index.\n * @returns {string}\n */\n this.getCopyableText = function (startRow, startCol, endRow, endCol) {\n return datamap.getCopyableText(instance._createCellCoords(startRow, startCol), instance._createCellCoords(endRow, endCol));\n };\n\n /**\n * Returns the data's copyable value at specified `row` and `column` index.\n *\n * @memberof Core#\n * @function getCopyableData\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @returns {string}\n */\n this.getCopyableData = function (row, column) {\n return datamap.getCopyable(row, datamap.colToProp(column));\n };\n\n /**\n * Returns schema provided by constructor settings. If it doesn't exist then it returns the schema based on the data\n * structure in the first row.\n *\n * @memberof Core#\n * @function getSchema\n * @returns {object} Schema object.\n */\n this.getSchema = function () {\n return datamap.getSchema();\n };\n\n /**\n * Use it if you need to change configuration after initialization. The `settings` argument is an object containing the changed\n * settings, declared the same way as in the initial settings object.\n *\n * __Note__, that although the `updateSettings` method doesn't overwrite the previously declared settings, it might reset\n * the settings made post-initialization. (for example - ignore changes made using the columnResize feature).\n *\n * Since 8.0.0 passing `columns` or `data` inside `settings` objects will result in resetting states corresponding to rows and columns\n * (for example, row/column sequence, column width, row height, frozen columns etc.).\n *\n * Since 12.0.0 passing `data` inside `settings` objects no longer results in resetting states corresponding to rows and columns\n * (for example, row/column sequence, column width, row height, frozen columns etc.).\n *\n * @memberof Core#\n * @function updateSettings\n * @param {object} settings A settings object (see {@link Options}). Only provide the settings that are changed, not the whole settings object that was used for initialization.\n * @param {boolean} [init=false] Internally used for in initialization mode.\n * @example\n * ```js\n * hot.updateSettings({\n * contextMenu: true,\n * colHeaders: true,\n * fixedRowsTop: 2\n * });\n * ```\n * @fires Hooks#afterCellMetaReset\n * @fires Hooks#afterUpdateSettings\n */\n this.updateSettings = function (settings) {\n let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n const dataUpdateFunction = (firstRun ? instance.loadData : instance.updateData).bind(this);\n let columnsAsFunc = false;\n let i;\n let j;\n if (isDefined(settings.rows)) {\n throw new Error('The \"rows\" setting is no longer supported. Do you mean startRows, minRows or maxRows?');\n }\n if (isDefined(settings.cols)) {\n throw new Error('The \"cols\" setting is no longer supported. Do you mean startCols, minCols or maxCols?');\n }\n if (isDefined(settings.ganttChart)) {\n throw new Error('Since 8.0.0 the \"ganttChart\" setting is no longer supported.');\n }\n\n // eslint-disable-next-line no-restricted-syntax\n for (i in settings) {\n if (i === 'data') {\n // Do nothing. loadData will be triggered later\n } else if (i === 'language') {\n setLanguage(settings.language);\n } else if (i === 'className') {\n setClassName('className', settings.className);\n } else if (i === 'tableClassName' && instance.table) {\n setClassName('tableClassName', settings.tableClassName);\n instance.view._wt.wtOverlays.syncOverlayTableClassNames();\n } else if (Hooks.getSingleton().isRegistered(i) || Hooks.getSingleton().isDeprecated(i)) {\n if (isFunction(settings[i]) || Array.isArray(settings[i])) {\n settings[i].initialHook = true;\n instance.addHook(i, settings[i]);\n }\n } else if (!init && hasOwnProperty(settings, i)) {\n // Update settings\n globalMeta[i] = settings[i];\n }\n }\n\n // Load data or create data map\n if (settings.data === undefined && tableMeta.data === undefined) {\n dataUpdateFunction(null, 'updateSettings'); // data source created just now\n } else if (settings.data !== undefined) {\n dataUpdateFunction(settings.data, 'updateSettings'); // data source given as option\n } else if (settings.columns !== undefined) {\n datamap.createMap();\n\n // The `column` property has changed - dataset may be expanded or narrowed down. The `loadData` do the same.\n instance.initIndexMappers();\n }\n const clen = instance.countCols();\n const columnSetting = tableMeta.columns;\n\n // Init columns constructors configuration\n if (columnSetting && isFunction(columnSetting)) {\n columnsAsFunc = true;\n }\n\n // Clear cell meta cache\n if (settings.cell !== undefined || settings.cells !== undefined || settings.columns !== undefined) {\n metaManager.clearCache();\n }\n if (clen > 0) {\n for (i = 0, j = 0; i < clen; i++) {\n // Use settings provided by user\n if (columnSetting) {\n const column = columnsAsFunc ? columnSetting(i) : columnSetting[j];\n if (column) {\n metaManager.updateColumnMeta(j, column);\n }\n }\n j += 1;\n }\n }\n if (isDefined(settings.cell)) {\n objectEach(settings.cell, cell => {\n instance.setCellMetaObject(cell.row, cell.col, cell);\n });\n }\n instance.runHooks('afterCellMetaReset');\n let currentHeight = instance.rootElement.style.height;\n if (currentHeight !== '') {\n currentHeight = parseInt(instance.rootElement.style.height, 10);\n }\n let height = settings.height;\n if (isFunction(height)) {\n height = height();\n }\n if (init) {\n const initialStyle = instance.rootElement.getAttribute('style');\n if (initialStyle) {\n instance.rootElement.setAttribute('data-initialstyle', instance.rootElement.getAttribute('style'));\n }\n }\n if (height === null) {\n const initialStyle = instance.rootElement.getAttribute('data-initialstyle');\n if (initialStyle && (initialStyle.indexOf('height') > -1 || initialStyle.indexOf('overflow') > -1)) {\n instance.rootElement.setAttribute('style', initialStyle);\n } else {\n instance.rootElement.style.height = '';\n instance.rootElement.style.overflow = '';\n }\n } else if (height !== undefined) {\n instance.rootElement.style.height = isNaN(height) ? `${height}` : `${height}px`;\n instance.rootElement.style.overflow = 'hidden';\n }\n if (typeof settings.width !== 'undefined') {\n let width = settings.width;\n if (isFunction(width)) {\n width = width();\n }\n instance.rootElement.style.width = isNaN(width) ? `${width}` : `${width}px`;\n }\n if (!init) {\n if (instance.view) {\n instance.view._wt.wtViewport.resetHasOversizedColumnHeadersMarked();\n instance.view._wt.exportSettingsAsClassNames();\n }\n instance.runHooks('afterUpdateSettings', settings);\n }\n grid.adjustRowsAndCols();\n if (instance.view && !firstRun) {\n instance.forceFullRender = true; // used when data was changed\n instance.view.render();\n instance.view._wt.wtOverlays.adjustElementsSize();\n }\n if (!init && instance.view && (currentHeight === '' || height === '' || height === undefined) && currentHeight !== height) {\n instance.view._wt.wtOverlays.updateMainScrollableElements();\n }\n };\n\n /**\n * Gets the value of the currently focused cell.\n *\n * For column headers and row headers, returns `null`.\n *\n * @memberof Core#\n * @function getValue\n * @returns {*} The value of the focused cell.\n */\n this.getValue = function () {\n const sel = instance.getSelectedLast();\n if (tableMeta.getValue) {\n if (isFunction(tableMeta.getValue)) {\n return tableMeta.getValue.call(instance);\n } else if (sel) {\n return instance.getData()[sel[0][0]][tableMeta.getValue];\n }\n } else if (sel) {\n return instance.getDataAtCell(sel[0], sel[1]);\n }\n };\n\n /**\n * Returns the object settings.\n *\n * @memberof Core#\n * @function getSettings\n * @returns {TableMeta} Object containing the current table settings.\n */\n this.getSettings = function () {\n return tableMeta;\n };\n\n /**\n * Clears the data from the table (the table settings remain intact).\n *\n * @memberof Core#\n * @function clear\n */\n this.clear = function () {\n this.selectAll();\n this.emptySelectedCells();\n };\n\n /**\n * The `alter()` method lets you alter the grid's structure\n * by adding or removing rows and columns at specified positions.\n *\n * ::: tip\n * The `alter()` method works only when your [`data`](@/api/options.md#data)\n * is an [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays).\n * :::\n *\n * ```js\n * // above row 10 (by visual index), insert 1 new row\n * hot.alter('insert_row_above', 10);\n * ```\n *\n * | Action | With `index` | Without `index` |\n * | -------------------- | ------------ | --------------- |\n * | `'insert_row_above'` | Inserts rows above the `index` row. | Inserts rows above the first row. |\n * | `'insert_row_below'` | Inserts rows below the `index` row. | Inserts rows below the last row. |\n * | `'remove_row'` | Removes rows, starting from the `index` row. | Removes rows, starting from the last row. |\n * | `'insert_col_start'` | Inserts columns before the `index` column. | Inserts columns before the first column. |\n * | `'insert_col_end'` | Inserts columns after the `index` column. | Inserts columns after the last column. |\n * | `'remove_col'` | Removes columns, starting from the `index` column. | Removes columns, starting from the last column. |\n *\n * Additional information about `'insert_col_start'` and `'insert_col_end'`:\n * - Their behavior depends on your [`layoutDirection`](@/api/options.md#layoutdirection).\n * - If the provided `index` is higher than the actual number of columns, Handsontable doesn't generate\n * the columns missing in between. Instead, the new columns are inserted next to the last column.\n *\n * @memberof Core#\n * @function alter\n * @param {string} action Available operations:\n *
\n *
`'insert_row_above'`
\n *
`'insert_row_below'`
\n *
`'remove_row'`
\n *
`'insert_col_start'`
\n *
`'insert_col_end'`
\n *
`'remove_col'`
\n *
\n * @param {number|number[]} [index] A visual index of the row/column before or after which the new row/column will be\n * inserted or removed. Can also be an array of arrays, in format `[[index, amount],...]`.\n * @param {number} [amount] The amount of rows or columns to be inserted or removed (default: `1`).\n * @param {string} [source] Source indicator.\n * @param {boolean} [keepEmptyRows] If set to `true`: prevents removing empty rows.\n * @example\n * ```js\n * // above row 10 (by visual index), insert 1 new row\n * hot.alter('insert_row_above', 10);\n *\n * // below row 10 (by visual index), insert 3 new rows\n * hot.alter('insert_row_below', 10, 3);\n *\n * // in the LTR layout direction: to the left of column 10 (by visual index), insert 3 new columns\n * // in the RTL layout direction: to the right of column 10 (by visual index), insert 3 new columns\n * hot.alter('insert_col_start', 10, 3);\n *\n * // in the LTR layout direction: to the right of column 10 (by visual index), insert 1 new column\n * // in the RTL layout direction: to the left of column 10 (by visual index), insert 1 new column\n * hot.alter('insert_col_end', 10);\n *\n * // remove 2 rows, starting from row 10 (by visual index)\n * hot.alter('remove_row', 10, 2);\n *\n * // remove 3 rows, starting from row 1 (by visual index)\n * // remove 2 rows, starting from row 5 (by visual index)\n * hot.alter('remove_row', [[1, 3], [5, 2]]);\n * ```\n */\n this.alter = function (action, index, amount, source, keepEmptyRows) {\n grid.alter(action, index, amount, source, keepEmptyRows);\n };\n\n /**\n * Returns a TD element for the given `row` and `column` arguments, if it is rendered on screen.\n * Returns `null` if the TD is not rendered on screen (probably because that part of the table is not visible).\n *\n * @memberof Core#\n * @function getCell\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {boolean} [topmost=false] If set to `true`, it returns the TD element from the topmost overlay. For example,\n * if the wanted cell is in the range of fixed rows, it will return a TD element from the `top` overlay.\n * @returns {HTMLTableCellElement|null} The cell's TD element.\n */\n this.getCell = function (row, column) {\n let topmost = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let renderableColumnIndex = column; // Handling also column headers.\n let renderableRowIndex = row; // Handling also row headers.\n\n if (column >= 0) {\n if (this.columnIndexMapper.isHidden(this.toPhysicalColumn(column))) {\n return null;\n }\n renderableColumnIndex = this.columnIndexMapper.getRenderableFromVisualIndex(column);\n }\n if (row >= 0) {\n if (this.rowIndexMapper.isHidden(this.toPhysicalRow(row))) {\n return null;\n }\n renderableRowIndex = this.rowIndexMapper.getRenderableFromVisualIndex(row);\n }\n if (renderableRowIndex === null || renderableColumnIndex === null || renderableRowIndex === undefined || renderableColumnIndex === undefined) {\n return null;\n }\n return instance.view.getCellAtCoords(instance._createCellCoords(renderableRowIndex, renderableColumnIndex), topmost);\n };\n\n /**\n * Returns the coordinates of the cell, provided as a HTML table cell element.\n *\n * @memberof Core#\n * @function getCoords\n * @param {HTMLTableCellElement} element The HTML Element representing the cell.\n * @returns {CellCoords|null} Visual coordinates object.\n * @example\n * ```js\n * hot.getCoords(hot.getCell(1, 1));\n * // it returns CellCoords object instance with props row: 1 and col: 1.\n * ```\n */\n this.getCoords = function (element) {\n const renderableCoords = this.view._wt.wtTable.getCoords(element);\n if (renderableCoords === null) {\n return null;\n }\n const {\n row: renderableRow,\n col: renderableColumn\n } = renderableCoords;\n let visualRow = renderableRow;\n let visualColumn = renderableColumn;\n if (renderableRow >= 0) {\n visualRow = this.rowIndexMapper.getVisualFromRenderableIndex(renderableRow);\n }\n if (renderableColumn >= 0) {\n visualColumn = this.columnIndexMapper.getVisualFromRenderableIndex(renderableColumn);\n }\n return instance._createCellCoords(visualRow, visualColumn);\n };\n\n /**\n * Returns the property name that corresponds with the given column index.\n * If the data source is an array of arrays, it returns the columns index.\n *\n * @memberof Core#\n * @function colToProp\n * @param {number} column Visual column index.\n * @returns {string|number} Column property or physical column index.\n */\n this.colToProp = function (column) {\n return datamap.colToProp(column);\n };\n\n /**\n * Returns column index that corresponds with the given property.\n *\n * @memberof Core#\n * @function propToCol\n * @param {string|number} prop Property name or physical column index.\n * @returns {number} Visual column index.\n */\n this.propToCol = function (prop) {\n return datamap.propToCol(prop);\n };\n\n /**\n * Translate physical row index into visual.\n *\n * This method is useful when you want to retrieve visual row index which can be reordered, moved or trimmed\n * based on a physical index.\n *\n * @memberof Core#\n * @function toVisualRow\n * @param {number} row Physical row index.\n * @returns {number} Returns visual row index.\n */\n this.toVisualRow = row => this.rowIndexMapper.getVisualFromPhysicalIndex(row);\n\n /**\n * Translate physical column index into visual.\n *\n * This method is useful when you want to retrieve visual column index which can be reordered, moved or trimmed\n * based on a physical index.\n *\n * @memberof Core#\n * @function toVisualColumn\n * @param {number} column Physical column index.\n * @returns {number} Returns visual column index.\n */\n this.toVisualColumn = column => this.columnIndexMapper.getVisualFromPhysicalIndex(column);\n\n /**\n * Translate visual row index into physical.\n *\n * This method is useful when you want to retrieve physical row index based on a visual index which can be\n * reordered, moved or trimmed.\n *\n * @memberof Core#\n * @function toPhysicalRow\n * @param {number} row Visual row index.\n * @returns {number} Returns physical row index.\n */\n this.toPhysicalRow = row => this.rowIndexMapper.getPhysicalFromVisualIndex(row);\n\n /**\n * Translate visual column index into physical.\n *\n * This method is useful when you want to retrieve physical column index based on a visual index which can be\n * reordered, moved or trimmed.\n *\n * @memberof Core#\n * @function toPhysicalColumn\n * @param {number} column Visual column index.\n * @returns {number} Returns physical column index.\n */\n this.toPhysicalColumn = column => this.columnIndexMapper.getPhysicalFromVisualIndex(column);\n\n /**\n * @description\n * Returns the cell value at `row`, `column`.\n *\n * __Note__: If data is reordered, sorted or trimmed, the currently visible order will be used.\n *\n * @memberof Core#\n * @function getDataAtCell\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @returns {*} Data at cell.\n */\n this.getDataAtCell = function (row, column) {\n return datamap.get(row, datamap.colToProp(column));\n };\n\n /**\n * Returns value at visual `row` and `prop` indexes.\n *\n * __Note__: If data is reordered, sorted or trimmed, the currently visible order will be used.\n *\n * @memberof Core#\n * @function getDataAtRowProp\n * @param {number} row Visual row index.\n * @param {string} prop Property name.\n * @returns {*} Cell value.\n */\n this.getDataAtRowProp = function (row, prop) {\n return datamap.get(row, prop);\n };\n\n /**\n * @description\n * Returns array of column values from the data source.\n *\n * __Note__: If columns were reordered or sorted, the currently visible order will be used.\n *\n * @memberof Core#\n * @function getDataAtCol\n * @param {number} column Visual column index.\n * @returns {Array} Array of cell values.\n */\n this.getDataAtCol = function (column) {\n const columnData = [];\n const dataByRows = datamap.getRange(instance._createCellCoords(0, column), instance._createCellCoords(tableMeta.data.length - 1, column), datamap.DESTINATION_RENDERER);\n for (let i = 0; i < dataByRows.length; i += 1) {\n for (let j = 0; j < dataByRows[i].length; j += 1) {\n columnData.push(dataByRows[i][j]);\n }\n }\n return columnData;\n };\n\n /**\n * Given the object property name (e.g. `'first.name'` or `'0'`), returns an array of column's values from the table data.\n * You can also provide a column index as the first argument.\n *\n * @memberof Core#\n * @function getDataAtProp\n * @param {string|number} prop Property name or physical column index.\n * @returns {Array} Array of cell values.\n */\n // TODO: Getting data from `datamap` should work on visual indexes.\n this.getDataAtProp = function (prop) {\n const columnData = [];\n const dataByRows = datamap.getRange(instance._createCellCoords(0, datamap.propToCol(prop)), instance._createCellCoords(tableMeta.data.length - 1, datamap.propToCol(prop)), datamap.DESTINATION_RENDERER);\n for (let i = 0; i < dataByRows.length; i += 1) {\n for (let j = 0; j < dataByRows[i].length; j += 1) {\n columnData.push(dataByRows[i][j]);\n }\n }\n return columnData;\n };\n\n /**\n * Returns a clone of the source data object.\n * Optionally you can provide a cell range by using the `row`, `column`, `row2`, `column2` arguments, to get only a\n * fragment of the table data.\n *\n * __Note__: This method does not participate in data transformation. If the visual data of the table is reordered,\n * sorted or trimmed only physical indexes are correct.\n *\n * __Note__: This method may return incorrect values for cells that contain\n * [formulas](@/guides/formulas/formula-calculation/formula-calculation.md). This is because `getSourceData()`\n * operates on source data ([physical indexes](@/api/indexMapper.md)),\n * whereas formulas operate on visual data (visual indexes).\n *\n * @memberof Core#\n * @function getSourceData\n * @param {number} [row] From physical row index.\n * @param {number} [column] From physical column index (or visual index, if data type is an array of objects).\n * @param {number} [row2] To physical row index.\n * @param {number} [column2] To physical column index (or visual index, if data type is an array of objects).\n * @returns {Array[]|object[]} The table data.\n */\n this.getSourceData = function (row, column, row2, column2) {\n let data;\n if (row === undefined) {\n data = dataSource.getData();\n } else {\n data = dataSource.getByRange(instance._createCellCoords(row, column), instance._createCellCoords(row2, column2));\n }\n return data;\n };\n\n /**\n * Returns the source data object as an arrays of arrays format even when source data was provided in another format.\n * Optionally you can provide a cell range by using the `row`, `column`, `row2`, `column2` arguments, to get only a\n * fragment of the table data.\n *\n * __Note__: This method does not participate in data transformation. If the visual data of the table is reordered,\n * sorted or trimmed only physical indexes are correct.\n *\n * @memberof Core#\n * @function getSourceDataArray\n * @param {number} [row] From physical row index.\n * @param {number} [column] From physical column index (or visual index, if data type is an array of objects).\n * @param {number} [row2] To physical row index.\n * @param {number} [column2] To physical column index (or visual index, if data type is an array of objects).\n * @returns {Array} An array of arrays.\n */\n this.getSourceDataArray = function (row, column, row2, column2) {\n let data;\n if (row === undefined) {\n data = dataSource.getData(true);\n } else {\n data = dataSource.getByRange(instance._createCellCoords(row, column), instance._createCellCoords(row2, column2), true);\n }\n return data;\n };\n\n /**\n * Returns an array of column values from the data source.\n *\n * @memberof Core#\n * @function getSourceDataAtCol\n * @param {number} column Visual column index.\n * @returns {Array} Array of the column's cell values.\n */\n // TODO: Getting data from `sourceData` should work always on physical indexes.\n this.getSourceDataAtCol = function (column) {\n return dataSource.getAtColumn(column);\n };\n\n /* eslint-disable jsdoc/require-param */\n /**\n * Set the provided value in the source data set at the provided coordinates.\n *\n * @memberof Core#\n * @function setSourceDataAtCell\n * @param {number|Array} row Physical row index or array of changes in format `[[row, prop, value], ...]`.\n * @param {number|string} column Physical column index / prop name.\n * @param {*} value The value to be set at the provided coordinates.\n * @param {string} [source] Source of the change as a string.\n */\n /* eslint-enable jsdoc/require-param */\n this.setSourceDataAtCell = function (row, column, value, source) {\n const input = setDataInputToArray(row, column, value);\n const isThereAnySetSourceListener = this.hasHook('afterSetSourceDataAtCell');\n const changesForHook = [];\n if (isThereAnySetSourceListener) {\n arrayEach(input, _ref8 => {\n let [changeRow, changeProp, changeValue] = _ref8;\n changesForHook.push([changeRow, changeProp, dataSource.getAtCell(changeRow, changeProp),\n // The previous value.\n changeValue]);\n });\n }\n arrayEach(input, _ref9 => {\n let [changeRow, changeProp, changeValue] = _ref9;\n dataSource.setAtCell(changeRow, changeProp, changeValue);\n });\n if (isThereAnySetSourceListener) {\n this.runHooks('afterSetSourceDataAtCell', changesForHook, source);\n }\n this.render();\n const activeEditor = instance.getActiveEditor();\n if (activeEditor && isDefined(activeEditor.refreshValue)) {\n activeEditor.refreshValue();\n }\n };\n\n /**\n * Returns a single row of the data (array or object, depending on what data format you use).\n *\n * __Note__: This method does not participate in data transformation. If the visual data of the table is reordered,\n * sorted or trimmed only physical indexes are correct.\n *\n * @memberof Core#\n * @function getSourceDataAtRow\n * @param {number} row Physical row index.\n * @returns {Array|object} Single row of data.\n */\n this.getSourceDataAtRow = function (row) {\n return dataSource.getAtRow(row);\n };\n\n /**\n * Returns a single value from the data source.\n *\n * @memberof Core#\n * @function getSourceDataAtCell\n * @param {number} row Physical row index.\n * @param {number} column Visual column index.\n * @returns {*} Cell data.\n */\n // TODO: Getting data from `sourceData` should work always on physical indexes.\n this.getSourceDataAtCell = function (row, column) {\n return dataSource.getAtCell(row, column);\n };\n\n /**\n * @description\n * Returns a single row of the data.\n *\n * __Note__: If rows were reordered, sorted or trimmed, the currently visible order will be used.\n *\n * @memberof Core#\n * @function getDataAtRow\n * @param {number} row Visual row index.\n * @returns {Array} Array of row's cell data.\n */\n this.getDataAtRow = function (row) {\n const data = datamap.getRange(instance._createCellCoords(row, 0), instance._createCellCoords(row, this.countCols() - 1), datamap.DESTINATION_RENDERER);\n return data[0] || [];\n };\n\n /**\n * @description\n * Returns a data type defined in the Handsontable settings under the `type` key ({@link Options#type}).\n * If there are cells with different types in the selected range, it returns `'mixed'`.\n *\n * __Note__: If data is reordered, sorted or trimmed, the currently visible order will be used.\n *\n * @memberof Core#\n * @function getDataType\n * @param {number} rowFrom From visual row index.\n * @param {number} columnFrom From visual column index.\n * @param {number} rowTo To visual row index.\n * @param {number} columnTo To visual column index.\n * @returns {string} Cell type (e.q: `'mixed'`, `'text'`, `'numeric'`, `'autocomplete'`).\n */\n this.getDataType = function (rowFrom, columnFrom, rowTo, columnTo) {\n const coords = rowFrom === undefined ? [0, 0, this.countRows(), this.countCols()] : [rowFrom, columnFrom, rowTo, columnTo];\n const [rowStart, columnStart] = coords;\n let [,, rowEnd, columnEnd] = coords;\n let previousType = null;\n let currentType = null;\n if (rowEnd === undefined) {\n rowEnd = rowStart;\n }\n if (columnEnd === undefined) {\n columnEnd = columnStart;\n }\n let type = 'mixed';\n rangeEach(Math.max(Math.min(rowStart, rowEnd), 0), Math.max(rowStart, rowEnd), row => {\n let isTypeEqual = true;\n rangeEach(Math.max(Math.min(columnStart, columnEnd), 0), Math.max(columnStart, columnEnd), column => {\n const cellType = this.getCellMeta(row, column);\n currentType = cellType.type;\n if (previousType) {\n isTypeEqual = previousType === currentType;\n } else {\n previousType = currentType;\n }\n return isTypeEqual;\n });\n type = isTypeEqual ? currentType : 'mixed';\n return isTypeEqual;\n });\n return type;\n };\n\n /**\n * Remove a property defined by the `key` argument from the cell meta object for the provided `row` and `column` coordinates.\n *\n * @memberof Core#\n * @function removeCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key Property name.\n * @fires Hooks#beforeRemoveCellMeta\n * @fires Hooks#afterRemoveCellMeta\n */\n this.removeCellMeta = function (row, column, key) {\n const [physicalRow, physicalColumn] = [this.toPhysicalRow(row), this.toPhysicalColumn(column)];\n let cachedValue = metaManager.getCellMetaKeyValue(physicalRow, physicalColumn, key);\n const hookResult = instance.runHooks('beforeRemoveCellMeta', row, column, key, cachedValue);\n if (hookResult !== false) {\n metaManager.removeCellMeta(physicalRow, physicalColumn, key);\n instance.runHooks('afterRemoveCellMeta', row, column, key, cachedValue);\n }\n cachedValue = null;\n };\n\n /**\n * Removes or adds one or more rows of the cell meta objects to the cell meta collections.\n *\n * @since 0.30.0\n * @memberof Core#\n * @function spliceCellsMeta\n * @param {number} visualIndex A visual index that specifies at what position to add/remove items.\n * @param {number} [deleteAmount=0] The number of items to be removed. If set to 0, no cell meta objects will be removed.\n * @param {...object} [cellMetaRows] The new cell meta row objects to be added to the cell meta collection.\n */\n this.spliceCellsMeta = function (visualIndex) {\n let deleteAmount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n for (var _len18 = arguments.length, cellMetaRows = new Array(_len18 > 2 ? _len18 - 2 : 0), _key18 = 2; _key18 < _len18; _key18++) {\n cellMetaRows[_key18 - 2] = arguments[_key18];\n }\n if (cellMetaRows.length > 0 && !Array.isArray(cellMetaRows[0])) {\n throw new Error('The 3rd argument (cellMetaRows) has to be passed as an array of cell meta objects array.');\n }\n if (deleteAmount > 0) {\n metaManager.removeRow(this.toPhysicalRow(visualIndex), deleteAmount);\n }\n if (cellMetaRows.length > 0) {\n arrayEach(cellMetaRows.reverse(), cellMetaRow => {\n metaManager.createRow(this.toPhysicalRow(visualIndex));\n arrayEach(cellMetaRow, (cellMeta, columnIndex) => this.setCellMetaObject(visualIndex, columnIndex, cellMeta));\n });\n }\n instance.render();\n };\n\n /**\n * Set cell meta data object defined by `prop` to the corresponding params `row` and `column`.\n *\n * @memberof Core#\n * @function setCellMetaObject\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {object} prop Meta object.\n */\n this.setCellMetaObject = function (row, column, prop) {\n if (typeof prop === 'object') {\n objectEach(prop, (value, key) => {\n this.setCellMeta(row, column, key, value);\n });\n }\n };\n\n /**\n * Sets a property defined by the `key` property to the meta object of a cell corresponding to params `row` and `column`.\n *\n * @memberof Core#\n * @function setCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key Property name.\n * @param {string} value Property value.\n * @fires Hooks#beforeSetCellMeta\n * @fires Hooks#afterSetCellMeta\n */\n this.setCellMeta = function (row, column, key, value) {\n const allowSetCellMeta = instance.runHooks('beforeSetCellMeta', row, column, key, value);\n if (allowSetCellMeta === false) {\n return;\n }\n let physicalRow = row;\n let physicalColumn = column;\n if (row < this.countRows()) {\n physicalRow = this.toPhysicalRow(row);\n }\n if (column < this.countCols()) {\n physicalColumn = this.toPhysicalColumn(column);\n }\n metaManager.setCellMeta(physicalRow, physicalColumn, key, value);\n instance.runHooks('afterSetCellMeta', row, column, key, value);\n };\n\n /**\n * Get all the cells meta settings at least once generated in the table (in order of cell initialization).\n *\n * @memberof Core#\n * @function getCellsMeta\n * @returns {Array} Returns an array of ColumnSettings object instances.\n */\n this.getCellsMeta = function () {\n return metaManager.getCellsMeta();\n };\n\n /**\n * Returns the cell properties object for the given `row` and `column` coordinates.\n *\n * @memberof Core#\n * @function getCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @returns {object} The cell properties object.\n * @fires Hooks#beforeGetCellMeta\n * @fires Hooks#afterGetCellMeta\n */\n this.getCellMeta = function (row, column) {\n let physicalRow = this.toPhysicalRow(row);\n let physicalColumn = this.toPhysicalColumn(column);\n if (physicalRow === null) {\n physicalRow = row;\n }\n if (physicalColumn === null) {\n physicalColumn = column;\n }\n return metaManager.getCellMeta(physicalRow, physicalColumn, {\n visualRow: row,\n visualColumn: column\n });\n };\n\n /**\n * Returns the meta information for the provided column.\n *\n * @since 14.5.0\n * @memberof Core#\n * @function getColumnMeta\n * @param {number} column Visual column index.\n * @returns {object}\n */\n this.getColumnMeta = function (column) {\n return metaManager.getColumnMeta(this.toPhysicalColumn(column));\n };\n\n /**\n * Returns an array of cell meta objects for specified physical row index.\n *\n * @memberof Core#\n * @function getCellMetaAtRow\n * @param {number} row Physical row index.\n * @returns {Array}\n */\n this.getCellMetaAtRow = function (row) {\n return metaManager.getCellsMetaAtRow(row);\n };\n\n /**\n * Checks if your [data format](@/guides/getting-started/binding-to-data/binding-to-data.md#compatible-data-types)\n * and [configuration options](@/guides/getting-started/configuration-options/configuration-options.md)\n * allow for changing the number of columns.\n *\n * Returns `false` when your data is an array of objects,\n * or when you use the [`columns`](@/api/options.md#columns) option.\n * Otherwise, returns `true`.\n *\n * @memberof Core#\n * @function isColumnModificationAllowed\n * @returns {boolean}\n */\n this.isColumnModificationAllowed = function () {\n return !(instance.dataType === 'object' || tableMeta.columns);\n };\n\n /**\n * Returns the cell renderer function by given `row` and `column` arguments.\n *\n * @memberof Core#\n * @function getCellRenderer\n * @param {number|object} rowOrMeta Visual row index or cell meta object (see {@link Core#getCellMeta}).\n * @param {number} column Visual column index.\n * @returns {Function} Returns the renderer function.\n * @example\n * ```js\n * // Get cell renderer using `row` and `column` coordinates.\n * hot.getCellRenderer(1, 1);\n * // Get cell renderer using cell meta object.\n * hot.getCellRenderer(hot.getCellMeta(1, 1));\n * ```\n */\n this.getCellRenderer = function (rowOrMeta, column) {\n const cellRenderer = typeof rowOrMeta === 'number' ? instance.getCellMeta(rowOrMeta, column).renderer : rowOrMeta.renderer;\n if (typeof cellRenderer === 'string') {\n return getRenderer(cellRenderer);\n }\n return isUndefined(cellRenderer) ? getRenderer('text') : cellRenderer;\n };\n\n /**\n * Returns the cell editor class by the provided `row` and `column` arguments.\n *\n * @memberof Core#\n * @function getCellEditor\n * @param {number} rowOrMeta Visual row index or cell meta object (see {@link Core#getCellMeta}).\n * @param {number} column Visual column index.\n * @returns {Function|boolean} Returns the editor class or `false` is cell editor is disabled.\n * @example\n * ```js\n * // Get cell editor class using `row` and `column` coordinates.\n * hot.getCellEditor(1, 1);\n * // Get cell editor class using cell meta object.\n * hot.getCellEditor(hot.getCellMeta(1, 1));\n * ```\n */\n this.getCellEditor = function (rowOrMeta, column) {\n const cellEditor = typeof rowOrMeta === 'number' ? instance.getCellMeta(rowOrMeta, column).editor : rowOrMeta.editor;\n if (typeof cellEditor === 'string') {\n return getEditor(cellEditor);\n }\n return isUndefined(cellEditor) ? getEditor('text') : cellEditor;\n };\n\n /**\n * Returns the cell validator by `row` and `column`.\n *\n * @memberof Core#\n * @function getCellValidator\n * @param {number|object} rowOrMeta Visual row index or cell meta object (see {@link Core#getCellMeta}).\n * @param {number} column Visual column index.\n * @returns {Function|RegExp|undefined} The validator function.\n * @example\n * ```js\n * // Get cell validator using `row` and `column` coordinates.\n * hot.getCellValidator(1, 1);\n * // Get cell validator using cell meta object.\n * hot.getCellValidator(hot.getCellMeta(1, 1));\n * ```\n */\n this.getCellValidator = function (rowOrMeta, column) {\n const cellValidator = typeof rowOrMeta === 'number' ? instance.getCellMeta(rowOrMeta, column).validator : rowOrMeta.validator;\n if (typeof cellValidator === 'string') {\n return getValidator(cellValidator);\n }\n return cellValidator;\n };\n\n /**\n * Validates every cell in the data set,\n * using a [validator function](@/guides/cell-functions/cell-validator/cell-validator.md) configured for each cell.\n *\n * Doesn't validate cells that are currently [trimmed](@/guides/rows/row-trimming/row-trimming.md),\n * [hidden](@/guides/rows/row-hiding/row-hiding.md), or [filtered](@/guides/columns/column-filter/column-filter.md),\n * as such cells are not included in the data set until you bring them back again.\n *\n * After the validation, the `callback` function is fired, with the `valid` argument set to:\n * - `true` for valid cells\n * - `false` for invalid cells\n *\n * @memberof Core#\n * @function validateCells\n * @param {Function} [callback] The callback function.\n * @example\n * ```js\n * hot.validateCells((valid) => {\n * if (valid) {\n * // ... code for validated cells\n * }\n * })\n * ```\n */\n this.validateCells = function (callback) {\n this._validateCells(callback);\n };\n\n /**\n * Validates rows using their validator functions and calls callback when finished.\n *\n * If one of the cells is invalid, the callback will be fired with `'valid'` arguments as `false` - otherwise it\n * would equal `true`.\n *\n * @memberof Core#\n * @function validateRows\n * @param {Array} [rows] Array of validation target visual row indexes.\n * @param {Function} [callback] The callback function.\n * @example\n * ```js\n * hot.validateRows([3, 4, 5], (valid) => {\n * if (valid) {\n * // ... code for validated rows\n * }\n * })\n * ```\n */\n this.validateRows = function (rows, callback) {\n if (!Array.isArray(rows)) {\n throw new Error('validateRows parameter `rows` must be an array');\n }\n this._validateCells(callback, rows);\n };\n\n /**\n * Validates columns using their validator functions and calls callback when finished.\n *\n * If one of the cells is invalid, the callback will be fired with `'valid'` arguments as `false` - otherwise it\n * would equal `true`.\n *\n * @memberof Core#\n * @function validateColumns\n * @param {Array} [columns] Array of validation target visual columns indexes.\n * @param {Function} [callback] The callback function.\n * @example\n * ```js\n * hot.validateColumns([3, 4, 5], (valid) => {\n * if (valid) {\n * // ... code for validated columns\n * }\n * })\n * ```\n */\n this.validateColumns = function (columns, callback) {\n if (!Array.isArray(columns)) {\n throw new Error('validateColumns parameter `columns` must be an array');\n }\n this._validateCells(callback, undefined, columns);\n };\n\n /**\n * Validates all cells using their validator functions and calls callback when finished.\n *\n * If one of the cells is invalid, the callback will be fired with `'valid'` arguments as `false` - otherwise it would equal `true`.\n *\n * Private use intended.\n *\n * @private\n * @memberof Core#\n * @function _validateCells\n * @param {Function} [callback] The callback function.\n * @param {Array} [rows] An array of validation target visual row indexes.\n * @param {Array} [columns] An array of validation target visual column indexes.\n */\n this._validateCells = function (callback, rows, columns) {\n const waitingForValidator = new ValidatorsQueue();\n if (callback) {\n waitingForValidator.onQueueEmpty = callback;\n }\n let i = instance.countRows() - 1;\n while (i >= 0) {\n if (rows !== undefined && rows.indexOf(i) === -1) {\n i -= 1;\n continue;\n }\n let j = instance.countCols() - 1;\n while (j >= 0) {\n if (columns !== undefined && columns.indexOf(j) === -1) {\n j -= 1;\n continue;\n }\n waitingForValidator.addValidatorToQueue();\n instance.validateCell(instance.getDataAtCell(i, j), instance.getCellMeta(i, j), result => {\n if (typeof result !== 'boolean') {\n throw new Error('Validation error: result is not boolean');\n }\n if (result === false) {\n waitingForValidator.valid = false;\n }\n waitingForValidator.removeValidatorFormQueue();\n }, 'validateCells');\n j -= 1;\n }\n i -= 1;\n }\n waitingForValidator.checkIfQueueIsEmpty();\n };\n\n /**\n * Returns an array of row headers' values (if they are enabled). If param `row` was given, it returns the header of the given row as a string.\n *\n * @memberof Core#\n * @function getRowHeader\n * @param {number} [row] Visual row index.\n * @fires Hooks#modifyRowHeader\n * @returns {Array|string|number} Array of header values / single header value.\n */\n this.getRowHeader = function (row) {\n let rowHeader = tableMeta.rowHeaders;\n let physicalRow = row;\n if (physicalRow !== undefined) {\n physicalRow = instance.runHooks('modifyRowHeader', physicalRow);\n }\n if (physicalRow === undefined) {\n rowHeader = [];\n rangeEach(instance.countRows() - 1, i => {\n rowHeader.push(instance.getRowHeader(i));\n });\n } else if (Array.isArray(rowHeader) && rowHeader[physicalRow] !== undefined) {\n rowHeader = rowHeader[physicalRow];\n } else if (isFunction(rowHeader)) {\n rowHeader = rowHeader(physicalRow);\n } else if (rowHeader && typeof rowHeader !== 'string' && typeof rowHeader !== 'number') {\n rowHeader = physicalRow + 1;\n }\n return rowHeader;\n };\n\n /**\n * Returns information about if this table is configured to display row headers.\n *\n * @memberof Core#\n * @function hasRowHeaders\n * @returns {boolean} `true` if the instance has the row headers enabled, `false` otherwise.\n */\n this.hasRowHeaders = function () {\n return !!tableMeta.rowHeaders;\n };\n\n /**\n * Returns information about if this table is configured to display column headers.\n *\n * @memberof Core#\n * @function hasColHeaders\n * @returns {boolean} `true` if the instance has the column headers enabled, `false` otherwise.\n */\n this.hasColHeaders = function () {\n if (tableMeta.colHeaders !== undefined && tableMeta.colHeaders !== null) {\n // Polymer has empty value = null\n return !!tableMeta.colHeaders;\n }\n for (let i = 0, ilen = instance.countCols(); i < ilen; i++) {\n if (instance.getColHeader(i)) {\n return true;\n }\n }\n return false;\n };\n\n /**\n * Gets the values of column headers (if column headers are [enabled](@/api/options.md#colheaders)).\n *\n * To get an array with the values of all\n * [bottom-most](@/guides/cell-features/clipboard/clipboard.md#copy-with-headers) column headers,\n * call `getColHeader()` with no arguments.\n *\n * To get the value of the bottom-most header of a specific column, use the `column` parameter.\n *\n * To get the value of a [specific-level](@/guides/columns/column-groups/column-groups.md) header\n * of a specific column, use the `column` and `headerLevel` parameters.\n *\n * Read more:\n * - [Guides: Column groups](@/guides/columns/column-groups/column-groups.md)\n * - [Options: `colHeaders`](@/api/options.md#colheaders)\n * - [Guides: Copy with headers](@/guides/cell-features/clipboard/clipboard.md#copy-with-headers)\n *\n * ```js\n * // get the contents of all bottom-most column headers\n * hot.getColHeader();\n *\n * // get the contents of the bottom-most header of a specific column\n * hot.getColHeader(5);\n *\n * // get the contents of a specific column header at a specific level\n * hot.getColHeader(5, -2);\n * ```\n *\n * @memberof Core#\n * @function getColHeader\n * @param {number} [column] A visual column index.\n * @param {number} [headerLevel=-1] (Since 12.3.0) Header level index. Accepts positive (0 to n)\n * and negative (-1 to -n) values. For positive values, 0 points to the\n * topmost header. For negative values, -1 points to the bottom-most\n * header (the header closest to the cells).\n * @fires Hooks#modifyColHeader\n * @fires Hooks#modifyColumnHeaderValue\n * @returns {Array|string|number} Column header values.\n */\n this.getColHeader = function (column) {\n let headerLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;\n const columnIndex = instance.runHooks('modifyColHeader', column);\n if (columnIndex === undefined) {\n const out = [];\n const ilen = instance.countCols();\n for (let i = 0; i < ilen; i++) {\n out.push(instance.getColHeader(i));\n }\n return out;\n }\n let result = tableMeta.colHeaders;\n const translateVisualIndexToColumns = function (visualColumnIndex) {\n const arr = [];\n const columnsLen = instance.countCols();\n let index = 0;\n for (; index < columnsLen; index++) {\n if (isFunction(tableMeta.columns) && tableMeta.columns(index)) {\n arr.push(index);\n }\n }\n return arr[visualColumnIndex];\n };\n const physicalColumn = instance.toPhysicalColumn(columnIndex);\n const prop = translateVisualIndexToColumns(physicalColumn);\n if (tableMeta.colHeaders === false) {\n result = null;\n } else if (tableMeta.columns && isFunction(tableMeta.columns) && tableMeta.columns(prop) && tableMeta.columns(prop).title) {\n result = tableMeta.columns(prop).title;\n } else if (tableMeta.columns && tableMeta.columns[physicalColumn] && tableMeta.columns[physicalColumn].title) {\n result = tableMeta.columns[physicalColumn].title;\n } else if (Array.isArray(tableMeta.colHeaders) && tableMeta.colHeaders[physicalColumn] !== undefined) {\n result = tableMeta.colHeaders[physicalColumn];\n } else if (isFunction(tableMeta.colHeaders)) {\n result = tableMeta.colHeaders(physicalColumn);\n } else if (tableMeta.colHeaders && typeof tableMeta.colHeaders !== 'string' && typeof tableMeta.colHeaders !== 'number') {\n result = spreadsheetColumnLabel(columnIndex); // see #1458\n }\n result = instance.runHooks('modifyColumnHeaderValue', result, column, headerLevel);\n return result;\n };\n\n /**\n * Return column width from settings (no guessing). Private use intended.\n *\n * @private\n * @memberof Core#\n * @function _getColWidthFromSettings\n * @param {number} col Visual col index.\n * @returns {number}\n */\n this._getColWidthFromSettings = function (col) {\n let width;\n\n // We currently don't support cell meta objects for headers (negative values)\n if (col >= 0) {\n const cellProperties = instance.getCellMeta(0, col);\n width = cellProperties.width;\n }\n if (width === undefined || width === tableMeta.width) {\n width = tableMeta.colWidths;\n }\n if (width !== undefined && width !== null) {\n switch (typeof width) {\n case 'object':\n // array\n width = width[col];\n break;\n case 'function':\n width = width(col);\n break;\n default:\n break;\n }\n if (typeof width === 'string') {\n width = parseInt(width, 10);\n }\n }\n return width;\n };\n\n /**\n * Returns the width of the requested column.\n *\n * @memberof Core#\n * @function getColWidth\n * @param {number} column Visual column index.\n * @returns {number} Column width.\n * @fires Hooks#modifyColWidth\n */\n this.getColWidth = function (column) {\n let width = instance._getColWidthFromSettings(column);\n width = instance.runHooks('modifyColWidth', width, column);\n if (width === undefined) {\n width = DEFAULT_COLUMN_WIDTH;\n }\n return width;\n };\n\n /**\n * Return row height from settings (no guessing). Private use intended.\n *\n * @private\n * @memberof Core#\n * @function _getRowHeightFromSettings\n * @param {number} row Visual row index.\n * @returns {number}\n */\n this._getRowHeightFromSettings = function (row) {\n let height = tableMeta.rowHeights;\n if (height !== undefined && height !== null) {\n switch (typeof height) {\n case 'object':\n // array\n height = height[row];\n break;\n case 'function':\n height = height(row);\n break;\n default:\n break;\n }\n if (typeof height === 'string') {\n height = parseInt(height, 10);\n }\n }\n return height;\n };\n\n /**\n * Returns a row's height, as recognized by Handsontable.\n *\n * Depending on your configuration, the method returns (in order of priority):\n * 1. The row height set by the [`ManualRowResize`](@/api/manualRowResize.md) plugin\n * (if the plugin is enabled).\n * 2. The row height set by the [`rowHeights`](@/api/options.md#rowheights) configuration option\n * (if the option is set).\n * 3. The row height as measured in the DOM by the [`AutoRowSize`](@/api/autoRowSize.md) plugin\n * (if the plugin is enabled).\n * 4. `undefined`, if neither [`ManualRowResize`](@/api/manualRowResize.md),\n * nor [`rowHeights`](@/api/options.md#rowheights),\n * nor [`AutoRowSize`](@/api/autoRowSize.md) is used.\n *\n * The height returned includes 1 px of the row's bottom border.\n *\n * Mind that this method is different from the\n * [`getRowHeight()`](@/api/autoRowSize.md#getrowheight) method\n * of the [`AutoRowSize`](@/api/autoRowSize.md) plugin.\n *\n * @memberof Core#\n * @function getRowHeight\n * @param {number} row A visual row index.\n * @returns {number|undefined} The height of the specified row, in pixels.\n * @fires Hooks#modifyRowHeight\n */\n this.getRowHeight = function (row) {\n let height = instance._getRowHeightFromSettings(row);\n height = instance.runHooks('modifyRowHeight', height, row);\n return height;\n };\n\n /**\n * Returns the total number of rows in the data source.\n *\n * @memberof Core#\n * @function countSourceRows\n * @returns {number} Total number of rows.\n */\n this.countSourceRows = function () {\n return dataSource.countRows();\n };\n\n /**\n * Returns the total number of columns in the data source.\n *\n * @memberof Core#\n * @function countSourceCols\n * @returns {number} Total number of columns.\n */\n this.countSourceCols = function () {\n return dataSource.countFirstRowKeys();\n };\n\n /**\n * Returns the total number of visual rows in the table.\n *\n * @memberof Core#\n * @function countRows\n * @returns {number} Total number of rows.\n */\n this.countRows = function () {\n return datamap.getLength();\n };\n\n /**\n * Returns the total number of visible columns in the table.\n *\n * @memberof Core#\n * @function countCols\n * @returns {number} Total number of columns.\n */\n this.countCols = function () {\n const maxCols = tableMeta.maxCols;\n const dataLen = this.columnIndexMapper.getNotTrimmedIndexesLength();\n return Math.min(maxCols, dataLen);\n };\n\n /**\n * Returns the number of rendered rows including rows that are partially or fully rendered\n * outside the table viewport.\n *\n * @memberof Core#\n * @function countRenderedRows\n * @returns {number} Returns -1 if table is not visible.\n */\n this.countRenderedRows = function () {\n return instance.view._wt.drawn ? instance.view._wt.wtTable.getRenderedRowsCount() : -1;\n };\n\n /**\n * Returns the number of rendered rows that are only visible in the table viewport.\n * The rows that are partially visible are not counted.\n *\n * @memberof Core#\n * @function countVisibleRows\n * @returns {number} Number of visible rows or -1.\n */\n this.countVisibleRows = function () {\n return instance.view._wt.drawn ? instance.view._wt.wtTable.getVisibleRowsCount() : -1;\n };\n\n /**\n * Returns the number of rendered rows including columns that are partially or fully rendered\n * outside the table viewport.\n *\n * @memberof Core#\n * @function countRenderedCols\n * @returns {number} Returns -1 if table is not visible.\n */\n this.countRenderedCols = function () {\n return instance.view._wt.drawn ? instance.view._wt.wtTable.getRenderedColumnsCount() : -1;\n };\n\n /**\n * Returns the number of rendered columns that are only visible in the table viewport.\n * The columns that are partially visible are not counted.\n *\n * @memberof Core#\n * @function countVisibleCols\n * @returns {number} Number of visible columns or -1.\n */\n this.countVisibleCols = function () {\n return instance.view._wt.drawn ? instance.view._wt.wtTable.getVisibleColumnsCount() : -1;\n };\n\n /**\n * Returns the number of rendered row headers.\n *\n * @since 14.0.0\n * @memberof Core#\n * @function countRowHeaders\n * @returns {number} Number of row headers.\n */\n this.countRowHeaders = function () {\n return this.view.getRowHeadersCount();\n };\n\n /**\n * Returns the number of rendered column headers.\n *\n * @since 14.0.0\n * @memberof Core#\n * @function countColHeaders\n * @returns {number} Number of column headers.\n */\n this.countColHeaders = function () {\n return this.view.getColumnHeadersCount();\n };\n\n /**\n * Returns the number of empty rows. If the optional ending parameter is `true`, returns the\n * number of empty rows at the bottom of the table.\n *\n * @memberof Core#\n * @function countEmptyRows\n * @param {boolean} [ending=false] If `true`, will only count empty rows at the end of the data source.\n * @returns {number} Count empty rows.\n */\n this.countEmptyRows = function () {\n let ending = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n let emptyRows = 0;\n rangeEachReverse(instance.countRows() - 1, visualIndex => {\n if (instance.isEmptyRow(visualIndex)) {\n emptyRows += 1;\n } else if (ending === true) {\n return false;\n }\n });\n return emptyRows;\n };\n\n /**\n * Returns the number of empty columns. If the optional ending parameter is `true`, returns the number of empty\n * columns at right hand edge of the table.\n *\n * @memberof Core#\n * @function countEmptyCols\n * @param {boolean} [ending=false] If `true`, will only count empty columns at the end of the data source row.\n * @returns {number} Count empty cols.\n */\n this.countEmptyCols = function () {\n let ending = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n let emptyColumns = 0;\n rangeEachReverse(instance.countCols() - 1, visualIndex => {\n if (instance.isEmptyCol(visualIndex)) {\n emptyColumns += 1;\n } else if (ending === true) {\n return false;\n }\n });\n return emptyColumns;\n };\n\n /**\n * Check if all cells in the row declared by the `row` argument are empty.\n *\n * @memberof Core#\n * @function isEmptyRow\n * @param {number} row Visual row index.\n * @returns {boolean} `true` if the row at the given `row` is empty, `false` otherwise.\n */\n this.isEmptyRow = function (row) {\n return tableMeta.isEmptyRow.call(instance, row);\n };\n\n /**\n * Check if all cells in the the column declared by the `column` argument are empty.\n *\n * @memberof Core#\n * @function isEmptyCol\n * @param {number} column Column index.\n * @returns {boolean} `true` if the column at the given `col` is empty, `false` otherwise.\n */\n this.isEmptyCol = function (column) {\n return tableMeta.isEmptyCol.call(instance, column);\n };\n\n /**\n * Select a single cell, or a single range of adjacent cells.\n *\n * To select a cell, pass its visual row and column indexes, for example: `selectCell(2, 4)`.\n *\n * To select a range, pass the visual indexes of the first and last cell in the range, for example: `selectCell(2, 4, 3, 5)`.\n *\n * If your columns have properties, you can pass those properties' values instead of column indexes, for example: `selectCell(2, 'first_name')`.\n *\n * By default, `selectCell()` also:\n * - Scrolls the viewport to the newly-selected cells.\n * - Switches the keyboard focus to Handsontable (by calling Handsontable's [`listen()`](#listen) method).\n *\n * @example\n * ```js\n * // select a single cell\n * hot.selectCell(2, 4);\n *\n * // select a range of cells\n * hot.selectCell(2, 4, 3, 5);\n *\n * // select a single cell, using a column property\n * hot.selectCell(2, 'first_name');\n *\n * // select a range of cells, using column properties\n * hot.selectCell(2, 'first_name', 3, 'last_name');\n *\n * // select a range of cells, without scrolling to them\n * hot.selectCell(2, 4, 3, 5, false);\n *\n * // select a range of cells, without switching the keyboard focus to Handsontable\n * hot.selectCell(2, 4, 3, 5, null, false);\n * ```\n *\n * @memberof Core#\n * @function selectCell\n * @param {number} row A visual row index.\n * @param {number|string} column A visual column index (`number`), or a column property's value (`string`).\n * @param {number} [endRow] If selecting a range: the visual row index of the last cell in the range.\n * @param {number|string} [endColumn] If selecting a range: the visual column index (or a column property's value) of the last cell in the range.\n * @param {boolean} [scrollToCell=true] `true`: scroll the viewport to the newly-selected cells. `false`: keep the previous viewport.\n * @param {boolean} [changeListener=true] `true`: switch the keyboard focus to Handsontable. `false`: keep the previous keyboard focus.\n * @returns {boolean} `true`: the selection was successful, `false`: the selection failed.\n */\n this.selectCell = function (row, column, endRow, endColumn) {\n let scrollToCell = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n let changeListener = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;\n if (isUndefined(row) || isUndefined(column)) {\n return false;\n }\n return this.selectCells([[row, column, endRow, endColumn]], scrollToCell, changeListener);\n };\n\n /**\n * Select multiple cells or ranges of cells, adjacent or non-adjacent.\n *\n * You can pass one of the below:\n * - An array of arrays (which matches the output of Handsontable's [`getSelected()`](#getselected) method).\n * - An array of [`CellRange`](@/api/cellRange.md) objects (which matches the output of Handsontable's [`getSelectedRange()`](#getselectedrange) method).\n *\n * To select multiple cells, pass the visual row and column indexes of each cell, for example: `hot.selectCells([[1, 1], [5, 5]])`.\n *\n * To select multiple ranges, pass the visual indexes of the first and last cell in each range, for example: `hot.selectCells([[1, 1, 2, 2], [6, 2, 0, 2]])`.\n *\n * If your columns have properties, you can pass those properties' values instead of column indexes, for example: `hot.selectCells([[1, 'first_name'], [5, 'last_name']])`.\n *\n * By default, `selectCell()` also:\n * - Scrolls the viewport to the newly-selected cells.\n * - Switches the keyboard focus to Handsontable (by calling Handsontable's [`listen()`](#listen) method).\n *\n * @example\n * ```js\n * // select non-adjacent cells\n * hot.selectCells([[1, 1], [5, 5], [10, 10]]);\n *\n * // select non-adjacent ranges of cells\n * hot.selectCells([[1, 1, 2, 2], [10, 10, 20, 20]]);\n *\n * // select cells and ranges of cells\n * hot.selectCells([[1, 1, 2, 2], [3, 3], [6, 2, 0, 2]]);\n *\n * // select cells, using column properties\n * hot.selectCells([[1, 'id', 2, 'first_name'], [3, 'full_name'], [6, 'last_name', 0, 'first_name']]);\n *\n * // select multiple ranges, using an array of `CellRange` objects\n * const selected = hot.getSelectedRange();\n *\n * selected[0].from.row = 0;\n * selected[0].from.col = 0;\n * selected[0].to.row = 5;\n * selected[0].to.col = 5;\n *\n * selected[1].from.row = 10;\n * selected[1].from.col = 10;\n * selected[1].to.row = 20;\n * selected[1].to.col = 20;\n *\n * hot.selectCells(selected);\n * ```\n *\n * @memberof Core#\n * @since 0.38.0\n * @function selectCells\n * @param {Array[]|CellRange[]} coords Visual coordinates,\n * passed either as an array of arrays (`[[rowStart, columnStart, rowEnd, columnEnd], ...]`)\n * or as an array of [`CellRange`](@/api/cellRange.md) objects.\n * @param {boolean} [scrollToCell=true] `true`: scroll the viewport to the newly-selected cells. `false`: keep the previous viewport.\n * @param {boolean} [changeListener=true] `true`: switch the keyboard focus to Handsontable. `false`: keep the previous keyboard focus.\n * @returns {boolean} `true`: the selection was successful, `false`: the selection failed.\n */\n this.selectCells = function () {\n let coords = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [[]];\n let scrollToCell = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n let changeListener = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n if (scrollToCell === false) {\n viewportScroller.suspend();\n }\n const wasSelected = selection.selectCells(coords);\n if (wasSelected && changeListener) {\n instance.listen();\n }\n viewportScroller.resume();\n return wasSelected;\n };\n\n /**\n * Select column specified by `startColumn` visual index, column property or a range of columns finishing at `endColumn`.\n *\n * @example\n * ```js\n * // Select column using visual index.\n * hot.selectColumns(1);\n * // Select column using column property.\n * hot.selectColumns('id');\n * // Select range of columns using visual indexes.\n * hot.selectColumns(1, 4);\n * // Select range of columns using visual indexes and mark the first header as highlighted.\n * hot.selectColumns(1, 2, -1);\n * // Select range of columns using visual indexes and mark the second cell as highlighted.\n * hot.selectColumns(2, 1, 1);\n * // Select range of columns using visual indexes and move the focus position somewhere in the middle of the range.\n * hot.selectColumns(2, 5, { row: 2, col: 3 });\n * // Select range of columns using column properties.\n * hot.selectColumns('id', 'last_name');\n * ```\n *\n * @memberof Core#\n * @since 0.38.0\n * @function selectColumns\n * @param {number} startColumn The visual column index from which the selection starts.\n * @param {number} [endColumn=startColumn] The visual column index to which the selection finishes. If `endColumn`\n * is not defined the column defined by `startColumn` will be selected.\n * @param {number | { row: number, col: number } | CellCoords} [focusPosition=0] The argument allows changing the cell/header focus\n * position. The value can take visual row index from -N to N, where negative values point to the headers and positive\n * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus\n * position horizontally.\n * @returns {boolean} `true` if selection was successful, `false` otherwise.\n */\n this.selectColumns = function (startColumn) {\n let endColumn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startColumn;\n let focusPosition = arguments.length > 2 ? arguments[2] : undefined;\n return selection.selectColumns(startColumn, endColumn, focusPosition);\n };\n\n /**\n * Select row specified by `startRow` visual index or a range of rows finishing at `endRow`.\n *\n * @example\n * ```js\n * // Select row using visual index.\n * hot.selectRows(1);\n * // select a range of rows, using visual indexes.\n * hot.selectRows(1, 4);\n * // select a range of rows, using visual indexes, and mark the header as highlighted.\n * hot.selectRows(1, 2, -1);\n * // Select range of rows using visual indexes and mark the second cell as highlighted.\n * hot.selectRows(2, 1, 1);\n * // Select range of rows using visual indexes and move the focus position somewhere in the middle of the range.\n * hot.selectRows(2, 5, { row: 2, col: 3 });\n * ```\n *\n * @memberof Core#\n * @since 0.38.0\n * @function selectRows\n * @param {number} startRow The visual row index from which the selection starts.\n * @param {number} [endRow=startRow] The visual row index to which the selection finishes. If `endRow`\n * is not defined the row defined by `startRow` will be selected.\n * @param {number | { row: number, col: number } | CellCoords} [focusPosition=0] The argument allows changing the cell/header focus\n * position. The value can take visual row index from -N to N, where negative values point to the headers and positive\n * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus\n * position vertically.\n * @returns {boolean} `true` if selection was successful, `false` otherwise.\n */\n this.selectRows = function (startRow) {\n let endRow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startRow;\n let focusPosition = arguments.length > 2 ? arguments[2] : undefined;\n return selection.selectRows(startRow, endRow, focusPosition);\n };\n\n /**\n * Deselects the current cell selection on the table.\n *\n * @memberof Core#\n * @function deselectCell\n */\n this.deselectCell = function () {\n selection.deselect();\n };\n\n /**\n * Select all cells in the table excluding headers and corner elements.\n *\n * The previous selection is overwritten.\n *\n * ```js\n * // Select all cells in the table along with row headers, including all headers and the corner cell.\n * // Doesn't select column headers and corner elements.\n * hot.selectAll();\n *\n * // Select all cells in the table, including row headers but excluding the corner cell and column headers.\n * hot.selectAll(true, false);\n *\n * // Select all cells in the table, including all headers and the corner cell, but move the focus.\n * // highlight to position 2, 1\n * hot.selectAll(-2, -1, {\n * focusPosition: { row: 2, col: 1 }\n * });\n *\n * // Select all cells in the table, without headers and corner elements.\n * hot.selectAll(false);\n * ```\n *\n * @since 0.38.2\n * @memberof Core#\n * @function selectAll\n * @param {boolean} [includeRowHeaders=false] `true` If the selection should include the row headers,\n * `false` otherwise.\n * @param {boolean} [includeColumnHeaders=false] `true` If the selection should include the column\n * headers, `false` otherwise.\n *\n * @param {object} [options] Additional object with options. Since 14.0.0\n * @param {{row: number, col: number} | boolean} [options.focusPosition] The argument allows changing the cell/header\n * focus position. The value takes an object with a `row` and `col` properties from -N to N, where\n * negative values point to the headers and positive values point to the cell range. If `false`, the focus\n * position won't be changed. Example:\n * ```js\n * hot.selectAll(0, 0, {\n * focusPosition: { row: 0, col: 1 },\n * disableHeadersHighlight: true\n * })\n * ```\n *\n * @param {boolean} [options.disableHeadersHighlight] If `true`, disables highlighting the headers even when\n * the logical coordinates points on them.\n */\n this.selectAll = function () {\n let includeRowHeaders = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n let includeColumnHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : includeRowHeaders;\n let options = arguments.length > 2 ? arguments[2] : undefined;\n viewportScroller.skipNextScrollCycle();\n selection.selectAll(includeRowHeaders, includeColumnHeaders, options);\n };\n const getIndexToScroll = (indexMapper, visualIndex) => {\n // Looking for a visual index on the right and then (when not found) on the left.\n return indexMapper.getNearestNotHiddenIndex(visualIndex, 1, true);\n };\n\n /**\n * Scroll viewport to coordinates specified by the `row` and/or `col` object properties.\n *\n * ```js\n * // scroll the viewport to the visual row index (leave the horizontal scroll untouched)\n * hot.scrollViewportTo({ row: 50 });\n *\n * // scroll the viewport to the passed coordinates so that the cell at 50, 50 will be snapped to\n * // the bottom-end table's edge.\n * hot.scrollViewportTo({\n * row: 50,\n * col: 50,\n * verticalSnap: 'bottom',\n * horizontalSnap: 'end',\n * });\n * ```\n *\n * @memberof Core#\n * @function scrollViewportTo\n * @param {object} options A dictionary containing the following parameters:\n * @param {number} [options.row] Specifies the number of visual rows along the Y axis to scroll the viewport.\n * @param {number} [options.col] Specifies the number of visual columns along the X axis to scroll the viewport.\n * @param {'top' | 'bottom'} [options.verticalSnap] Determines to which edge of the table the viewport will be scrolled based on the passed coordinates.\n * This option is a string which must take one of the following values:\n * - `top`: The viewport will be scrolled to a row in such a way that it will be positioned on the top of the viewport;\n * - `bottom`: The viewport will be scrolled to a row in such a way that it will be positioned on the bottom of the viewport;\n * - If the property is not defined the vertical auto-snapping is enabled. Depending on where the viewport is scrolled from, a row will\n * be positioned at the top or bottom of the viewport.\n * @param {'start' | 'end'} [options.horizontalSnap] Determines to which edge of the table the viewport will be scrolled based on the passed coordinates.\n * This option is a string which must take one of the following values:\n * - `start`: The viewport will be scrolled to a column in such a way that it will be positioned on the start (left edge or right, if the layout direction is set to `rtl`) of the viewport;\n * - `end`: The viewport will be scrolled to a column in such a way that it will be positioned on the end (right edge or left, if the layout direction is set to `rtl`) of the viewport;\n * - If the property is not defined the horizontal auto-snapping is enabled. Depending on where the viewport is scrolled from, a column will\n * be positioned at the start or end of the viewport.\n * @param {boolean} [options.considerHiddenIndexes=true] If `true`, we handle visual indexes, otherwise we handle only indexes which\n * may be rendered when they are in the viewport (we don't consider hidden indexes as they aren't rendered).\n * @returns {boolean} `true` if viewport was scrolled, `false` otherwise.\n */\n this.scrollViewportTo = function (options) {\n var _options;\n // Support for backward compatibility arguments: (row, col, snapToBottom, snapToRight, considerHiddenIndexes)\n if (typeof options === 'number') {\n var _arguments$;\n /* eslint-disable prefer-rest-params */\n options = {\n row: arguments[0],\n col: arguments[1],\n verticalSnap: arguments[2] ? 'bottom' : 'top',\n horizontalSnap: arguments[3] ? 'end' : 'start',\n considerHiddenIndexes: (_arguments$ = arguments[4]) !== null && _arguments$ !== void 0 ? _arguments$ : true\n };\n /* eslint-enable prefer-rest-params */\n }\n const {\n row,\n col,\n verticalSnap,\n horizontalSnap,\n considerHiddenIndexes\n } = (_options = options) !== null && _options !== void 0 ? _options : {};\n let snapToTop;\n let snapToBottom;\n let snapToInlineStart;\n let snapToInlineEnd;\n if (verticalSnap !== undefined) {\n snapToTop = verticalSnap === 'top';\n snapToBottom = !snapToTop;\n }\n if (horizontalSnap !== undefined) {\n snapToInlineStart = horizontalSnap === 'start';\n snapToInlineEnd = !snapToInlineStart;\n }\n let renderableRow = row;\n let renderableColumn = col;\n if (considerHiddenIndexes === undefined || considerHiddenIndexes) {\n const isValidRowGrid = Number.isInteger(row) && row >= 0;\n const isValidColumnGrid = Number.isInteger(col) && col >= 0;\n const visualRowToScroll = isValidRowGrid ? getIndexToScroll(this.rowIndexMapper, row) : undefined;\n const visualColumnToScroll = isValidColumnGrid ? getIndexToScroll(this.columnIndexMapper, col) : undefined;\n if (visualRowToScroll === null || visualColumnToScroll === null) {\n return false;\n }\n renderableRow = isValidRowGrid ? instance.rowIndexMapper.getRenderableFromVisualIndex(visualRowToScroll) : row;\n renderableColumn = isValidColumnGrid ? instance.columnIndexMapper.getRenderableFromVisualIndex(visualColumnToScroll) : col;\n }\n const isRowInteger = Number.isInteger(renderableRow);\n const isColumnInteger = Number.isInteger(renderableColumn);\n if (isRowInteger && renderableRow >= 0 && isColumnInteger && renderableColumn >= 0) {\n return instance.view.scrollViewport(instance._createCellCoords(renderableRow, renderableColumn), snapToTop, snapToInlineEnd, snapToBottom, snapToInlineStart);\n }\n if (isRowInteger && renderableRow >= 0 && (isColumnInteger && renderableColumn < 0 || !isColumnInteger)) {\n return instance.view.scrollViewportVertically(renderableRow, snapToTop, snapToBottom);\n }\n if (isColumnInteger && renderableColumn >= 0 && (isRowInteger && renderableRow < 0 || !isRowInteger)) {\n return instance.view.scrollViewportHorizontally(renderableColumn, snapToInlineEnd, snapToInlineStart);\n }\n return false;\n };\n\n /**\n * Scrolls the viewport to coordinates specified by the currently focused cell.\n *\n * @since 14.0.0\n * @memberof Core#\n * @fires Hooks#afterScroll\n * @function scrollToFocusedCell\n * @param {Function} callback The callback function to call after the viewport is scrolled.\n */\n this.scrollToFocusedCell = function () {\n let callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : () => {};\n if (!this.selection.isSelected()) {\n return;\n }\n this.addHookOnce('afterScroll', callback);\n const {\n highlight\n } = this.getSelectedRangeLast();\n const isScrolled = this.scrollViewportTo(highlight.toObject());\n if (isScrolled) {\n this.view.render();\n } else {\n this.removeHook('afterScroll', callback);\n this._registerImmediate(() => callback());\n }\n };\n\n /**\n * Removes the table from the DOM and destroys the instance of the Handsontable.\n *\n * @memberof Core#\n * @function destroy\n * @fires Hooks#afterDestroy\n */\n this.destroy = function () {\n instance._clearTimeouts();\n instance._clearImmediates();\n if (instance.view) {\n // in case HT is destroyed before initialization has finished\n instance.view.destroy();\n }\n if (dataSource) {\n dataSource.destroy();\n }\n dataSource = null;\n this.getShortcutManager().destroy();\n metaManager.clearCache();\n foreignHotInstances.delete(this.guid);\n if (isRootInstance(instance)) {\n const licenseInfo = this.rootDocument.querySelector('.hot-display-license-info');\n if (licenseInfo) {\n licenseInfo.parentNode.removeChild(licenseInfo);\n }\n }\n empty(instance.rootElement);\n eventManager.destroy();\n if (editorManager) {\n editorManager.destroy();\n }\n\n // The plugin's `destroy` method is called as a consequence and it should handle\n // unregistration of plugin's maps. Some unregistered maps reset the cache.\n instance.batchExecution(() => {\n instance.rowIndexMapper.unregisterAll();\n instance.columnIndexMapper.unregisterAll();\n pluginsRegistry.getItems().forEach(_ref10 => {\n let [, plugin] = _ref10;\n plugin.destroy();\n });\n pluginsRegistry.clear();\n instance.runHooks('afterDestroy');\n }, true);\n Hooks.getSingleton().destroy(instance);\n objectEach(instance, (property, key, obj) => {\n // replace instance methods with post mortem\n if (isFunction(property)) {\n obj[key] = postMortem(key);\n } else if (key !== 'guid') {\n // replace instance properties with null (restores memory)\n // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests\n obj[key] = null;\n }\n });\n instance.isDestroyed = true;\n\n // replace private properties with null (restores memory)\n // it should not be necessary but this prevents a memory leak side effects that show itself in Jasmine tests\n if (datamap) {\n datamap.destroy();\n }\n datamap = null;\n grid = null;\n selection = null;\n editorManager = null;\n instance = null;\n };\n\n /**\n * Replacement for all methods after the Handsontable was destroyed.\n *\n * @private\n * @param {string} method The method name.\n * @returns {Function}\n */\n function postMortem(method) {\n return () => {\n throw new Error(`The \"${method}\" method cannot be called because this Handsontable instance has been destroyed`);\n };\n }\n\n /**\n * Returns the active editor class instance.\n *\n * @memberof Core#\n * @function getActiveEditor\n * @returns {BaseEditor} The active editor instance.\n */\n this.getActiveEditor = function () {\n return editorManager.getActiveEditor();\n };\n\n /**\n * Returns plugin instance by provided its name.\n *\n * @memberof Core#\n * @function getPlugin\n * @param {string} pluginName The plugin name.\n * @returns {BasePlugin|undefined} The plugin instance or undefined if there is no plugin.\n */\n this.getPlugin = function (pluginName) {\n const unifiedPluginName = toUpperCaseFirst(pluginName);\n\n // Workaround for the UndoRedo plugin which, currently doesn't follow the plugin architecture.\n if (unifiedPluginName === 'UndoRedo') {\n return this.undoRedo;\n }\n return pluginsRegistry.getItem(unifiedPluginName);\n };\n\n /**\n * Returns name of the passed plugin.\n *\n * @private\n * @memberof Core#\n * @param {BasePlugin} plugin The plugin instance.\n * @returns {string}\n */\n this.getPluginName = function (plugin) {\n // Workaround for the UndoRedo plugin which, currently doesn't follow the plugin architecture.\n if (plugin === this.undoRedo) {\n return this.undoRedo.constructor.PLUGIN_KEY;\n }\n return pluginsRegistry.getId(plugin);\n };\n\n /**\n * Returns the Handsontable instance.\n *\n * @memberof Core#\n * @function getInstance\n * @returns {Handsontable} The Handsontable instance.\n */\n this.getInstance = function () {\n return instance;\n };\n\n /**\n * Adds listener to the specified hook name (only for this Handsontable instance).\n *\n * @memberof Core#\n * @function addHook\n * @see Hooks#add\n * @param {string} key Hook name (see {@link Hooks}).\n * @param {Function|Array} callback Function or array of functions.\n * @param {number} [orderIndex] Order index of the callback.\n * If > 0, the callback will be added after the others, for example, with an index of 1, the callback will be added before the ones with an index of 2, 3, etc., but after the ones with an index of 0 and lower.\n * If < 0, the callback will be added before the others, for example, with an index of -1, the callback will be added after the ones with an index of -2, -3, etc., but before the ones with an index of 0 and higher.\n * If 0 or no order index is provided, the callback will be added between the \"negative\" and \"positive\" indexes.\n * @example\n * ```js\n * hot.addHook('beforeInit', myCallback);\n * ```\n */\n this.addHook = function (key, callback, orderIndex) {\n Hooks.getSingleton().add(key, callback, instance, orderIndex);\n };\n\n /**\n * Check if for a specified hook name there are added listeners (only for this Handsontable instance). All available\n * hooks you will find {@link Hooks}.\n *\n * @memberof Core#\n * @function hasHook\n * @see Hooks#has\n * @param {string} key Hook name.\n * @returns {boolean}\n *\n * @example\n * ```js\n * const hasBeforeInitListeners = hot.hasHook('beforeInit');\n * ```\n */\n this.hasHook = function (key) {\n return Hooks.getSingleton().has(key, instance) || Hooks.getSingleton().has(key);\n };\n\n /**\n * Adds listener to specified hook name (only for this Handsontable instance). After the listener is triggered,\n * it will be automatically removed.\n *\n * @memberof Core#\n * @function addHookOnce\n * @see Hooks#once\n * @param {string} key Hook name (see {@link Hooks}).\n * @param {Function|Array} callback Function or array of functions.\n * @param {number} [orderIndex] Order index of the callback.\n * If > 0, the callback will be added after the others, for example, with an index of 1, the callback will be added before the ones with an index of 2, 3, etc., but after the ones with an index of 0 and lower.\n * If < 0, the callback will be added before the others, for example, with an index of -1, the callback will be added after the ones with an index of -2, -3, etc., but before the ones with an index of 0 and higher.\n * If 0 or no order index is provided, the callback will be added between the \"negative\" and \"positive\" indexes.\n * @example\n * ```js\n * hot.addHookOnce('beforeInit', myCallback);\n * ```\n */\n this.addHookOnce = function (key, callback, orderIndex) {\n Hooks.getSingleton().once(key, callback, instance, orderIndex);\n };\n\n /**\n * Removes the hook listener previously registered with {@link Core#addHook}.\n *\n * @memberof Core#\n * @function removeHook\n * @see Hooks#remove\n * @param {string} key Hook name.\n * @param {Function} callback Reference to the function which has been registered using {@link Core#addHook}.\n *\n * @example\n * ```js\n * hot.removeHook('beforeInit', myCallback);\n * ```\n */\n this.removeHook = function (key, callback) {\n Hooks.getSingleton().remove(key, callback, instance);\n };\n\n /**\n * Run the callbacks for the hook provided in the `key` argument using the parameters given in the other arguments.\n *\n * @memberof Core#\n * @function runHooks\n * @see Hooks#run\n * @param {string} key Hook name.\n * @param {*} [p1] Argument passed to the callback.\n * @param {*} [p2] Argument passed to the callback.\n * @param {*} [p3] Argument passed to the callback.\n * @param {*} [p4] Argument passed to the callback.\n * @param {*} [p5] Argument passed to the callback.\n * @param {*} [p6] Argument passed to the callback.\n * @returns {*}\n *\n * @example\n * ```js\n * // Run built-in hook\n * hot.runHooks('beforeInit');\n * // Run custom hook\n * hot.runHooks('customAction', 10, 'foo');\n * ```\n */\n this.runHooks = function (key, p1, p2, p3, p4, p5, p6) {\n return Hooks.getSingleton().run(instance, key, p1, p2, p3, p4, p5, p6);\n };\n\n /**\n * Get language phrase for specified dictionary key.\n *\n * @memberof Core#\n * @function getTranslatedPhrase\n * @since 0.35.0\n * @param {string} dictionaryKey Constant which is dictionary key.\n * @param {*} extraArguments Arguments which will be handled by formatters.\n * @returns {string}\n */\n this.getTranslatedPhrase = function (dictionaryKey, extraArguments) {\n return getTranslatedPhrase(tableMeta.language, dictionaryKey, extraArguments);\n };\n\n /**\n * Converts instance into outerHTML of HTMLTableElement.\n *\n * @memberof Core#\n * @function toHTML\n * @since 7.1.0\n * @returns {string}\n */\n this.toHTML = () => instanceToHTML(this);\n\n /**\n * Converts instance into HTMLTableElement.\n *\n * @memberof Core#\n * @function toTableElement\n * @since 7.1.0\n * @returns {HTMLTableElement}\n */\n this.toTableElement = () => {\n const tempElement = this.rootDocument.createElement('div');\n tempElement.insertAdjacentHTML('afterbegin', instanceToHTML(this));\n return tempElement.firstElementChild;\n };\n this.timeouts = [];\n\n /**\n * Sets timeout. Purpose of this method is to clear all known timeouts when `destroy` method is called.\n *\n * @param {number|Function} handle Handler returned from setTimeout or function to execute (it will be automatically wraped\n * by setTimeout function).\n * @param {number} [delay=0] If first argument is passed as a function this argument set delay of the execution of that function.\n * @private\n */\n this._registerTimeout = function (handle) {\n let delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n let handleFunc = handle;\n if (typeof handleFunc === 'function') {\n handleFunc = setTimeout(handleFunc, delay);\n }\n this.timeouts.push(handleFunc);\n };\n\n /**\n * Clears all known timeouts.\n *\n * @private\n */\n this._clearTimeouts = function () {\n arrayEach(this.timeouts, handler => {\n clearTimeout(handler);\n });\n };\n this.immediates = [];\n\n /**\n * Execute function execution to the next event loop cycle. Purpose of this method is to clear all known timeouts when `destroy` method is called.\n *\n * @param {Function} callback Function to be delayed in execution.\n * @private\n */\n this._registerImmediate = function (callback) {\n this.immediates.push(setImmediate(callback));\n };\n\n /**\n * Clears all known timeouts.\n *\n * @private\n */\n this._clearImmediates = function () {\n arrayEach(this.immediates, handler => {\n clearImmediate(handler);\n });\n };\n\n /**\n * Gets the instance of the EditorManager.\n *\n * @private\n * @returns {EditorManager}\n */\n this._getEditorManager = function () {\n return editorManager;\n };\n\n /**\n * Check if currently it is RTL direction.\n *\n * @private\n * @memberof Core#\n * @function isRtl\n * @returns {boolean} True if RTL.\n */\n this.isRtl = function () {\n return instance.rootWindow.getComputedStyle(instance.rootElement).direction === 'rtl';\n };\n\n /**\n * Check if currently it is LTR direction.\n *\n * @private\n * @memberof Core#\n * @function isLtr\n * @returns {boolean} True if LTR.\n */\n this.isLtr = function () {\n return !instance.isRtl();\n };\n\n /**\n * Returns 1 for LTR; -1 for RTL. Useful for calculations.\n *\n * @private\n * @memberof Core#\n * @function getDirectionFactor\n * @returns {number} Returns 1 for LTR; -1 for RTL.\n */\n this.getDirectionFactor = function () {\n return instance.isLtr() ? 1 : -1;\n };\n const shortcutManager = createShortcutManager({\n handleEvent() {\n return instance.isListening();\n },\n beforeKeyDown: event => {\n return this.runHooks('beforeKeyDown', event);\n },\n afterKeyDown: event => {\n if (this.isDestroyed) {\n // Handsontable could be destroyed after performing action (executing a callback).\n return;\n }\n instance.runHooks('afterDocumentKeyDown', event);\n },\n ownerWindow: this.rootWindow\n });\n this.addHook('beforeOnCellMouseDown', event => {\n // Releasing keys as some browser/system shortcuts break events sequence (thus the `keyup` event isn't triggered).\n if (event.ctrlKey === false && event.metaKey === false) {\n shortcutManager.releasePressedKeys();\n }\n });\n\n /**\n * Returns instance of a manager responsible for handling shortcuts stored in some contexts. It run actions after\n * pressing key combination in active Handsontable instance.\n *\n * @memberof Core#\n * @since 12.0.0\n * @function getShortcutManager\n * @returns {ShortcutManager} Instance of {@link ShortcutManager}\n */\n this.getShortcutManager = function () {\n return shortcutManager;\n };\n\n /**\n * Return the Focus Manager responsible for managing the browser's focus in the table.\n *\n * @memberof Core#\n * @since 14.0.0\n * @function getFocusManager\n * @returns {FocusManager}\n */\n this.getFocusManager = function () {\n return focusManager;\n };\n getPluginsNames().forEach(pluginName => {\n const PluginClass = getPlugin(pluginName);\n pluginsRegistry.addItem(pluginName, new PluginClass(this));\n });\n registerAllShortcutContexts(instance);\n shortcutManager.setActiveContextName('grid');\n Hooks.getSingleton().run(instance, 'construct');\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport { sanitize } from \"../string.mjs\";\nimport { A11Y_HIDDEN } from \"../a11y.mjs\";\n/**\n * Get the parent of the specified node in the DOM tree.\n *\n * @param {HTMLElement} element Element from which traversing is started.\n * @param {number} [level=0] Traversing deep level.\n * @returns {HTMLElement|null}\n */\nexport function getParent(element) {\n let level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n let iteration = -1;\n let parent = null;\n let elementToCheck = element;\n while (elementToCheck !== null) {\n if (iteration === level) {\n parent = elementToCheck;\n break;\n }\n if (elementToCheck.host && elementToCheck.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n elementToCheck = elementToCheck.host;\n } else {\n iteration += 1;\n elementToCheck = elementToCheck.parentNode;\n }\n }\n return parent;\n}\n\n/**\n * Check if the provided element is a child of the provided Handsontable container.\n *\n * @param {HTMLElement} element Element to be analyzed.\n * @param {HTMLElement} thisHotContainer The Handsontable container.\n * @returns {boolean}\n */\nexport function isThisHotChild(element, thisHotContainer) {\n const closestHandsontableContainer = element.closest('.handsontable');\n return !!closestHandsontableContainer && (closestHandsontableContainer.parentNode === thisHotContainer || closestHandsontableContainer === thisHotContainer);\n}\n\n/**\n * Gets `frameElement` of the specified frame. Returns null if it is a top frame or if script has no access to read property.\n *\n * @param {Window} frame Frame from which should be get frameElement in safe way.\n * @returns {HTMLIFrameElement|null}\n */\nexport function getFrameElement(frame) {\n return Object.getPrototypeOf(frame.parent) && frame.frameElement;\n}\n\n/**\n * Gets parent frame of the specified frame. Returns null if it is a top frame or if script has no access to read property.\n *\n * @param {Window} frame Frame from which should get frameElement in a safe way.\n * @returns {Window|null}\n */\nexport function getParentWindow(frame) {\n return getFrameElement(frame) && frame.parent;\n}\n\n/**\n * Checks if script has access to read from parent frame of specified frame.\n *\n * @param {Window} frame Frame from which should get frameElement in a safe way.\n * @returns {boolean}\n */\nexport function hasAccessToParentWindow(frame) {\n return !!Object.getPrototypeOf(frame.parent);\n}\n\n/**\n * Goes up the DOM tree (including given element) until it finds an parent element that matches the nodes or nodes name.\n * This method goes up through web components.\n *\n * @param {Node} element Element from which traversing is started.\n * @param {Array} [nodes] Array of elements or Array of elements name (in uppercase form).\n * @param {Node} [until] The element until the traversing ends.\n * @returns {Node|null}\n */\nexport function closest(element) {\n let nodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n let until = arguments.length > 2 ? arguments[2] : undefined;\n const {\n ELEMENT_NODE,\n DOCUMENT_FRAGMENT_NODE\n } = Node;\n let elementToCheck = element;\n while (elementToCheck !== null && elementToCheck !== undefined && elementToCheck !== until) {\n const {\n nodeType,\n nodeName\n } = elementToCheck;\n if (nodeType === ELEMENT_NODE && (nodes.includes(nodeName) || nodes.includes(elementToCheck))) {\n return elementToCheck;\n }\n const {\n host\n } = elementToCheck;\n if (host && nodeType === DOCUMENT_FRAGMENT_NODE) {\n elementToCheck = host;\n } else {\n elementToCheck = elementToCheck.parentNode;\n }\n }\n return null;\n}\n\n/**\n * Goes \"down\" the DOM tree (including given element) until it finds an element that matches the nodes or nodes name.\n *\n * @param {HTMLElement} element Element from which traversing is started.\n * @param {Array} nodes Array of elements or Array of elements name.\n * @param {HTMLElement} [until] The list of elements until the traversing ends.\n * @returns {HTMLElement|null}\n */\nexport function closestDown(element, nodes, until) {\n const matched = [];\n let elementToCheck = element;\n while (elementToCheck) {\n elementToCheck = closest(elementToCheck, nodes, until);\n if (!elementToCheck || until && !until.contains(elementToCheck)) {\n break;\n }\n matched.push(elementToCheck);\n if (elementToCheck.host && elementToCheck.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n elementToCheck = elementToCheck.host;\n } else {\n elementToCheck = elementToCheck.parentNode;\n }\n }\n const length = matched.length;\n return length ? matched[length - 1] : null;\n}\n\n/**\n * Goes up the DOM tree and checks if element is child of another element.\n *\n * @param {HTMLElement} child Child element An element to check.\n * @param {object|string} parent Parent element OR selector of the parent element.\n * If string provided, function returns `true` for the first occurrence of element with that class.\n * @returns {boolean}\n */\nexport function isChildOf(child, parent) {\n let node = child.parentNode;\n let queriedParents = [];\n if (typeof parent === 'string') {\n if (child.defaultView) {\n queriedParents = Array.prototype.slice.call(child.querySelectorAll(parent), 0);\n } else {\n queriedParents = Array.prototype.slice.call(child.ownerDocument.querySelectorAll(parent), 0);\n }\n } else {\n queriedParents.push(parent);\n }\n while (node !== null) {\n if (queriedParents.indexOf(node) > -1) {\n return true;\n }\n node = node.parentNode;\n }\n return false;\n}\n\n/**\n * Counts index of element within its parent.\n * WARNING: for performance reasons, assumes there are only element nodes (no text nodes). This is true\n * for Walkotnable, otherwise would need to check for nodeType or use previousElementSibling.\n *\n * @see http://jsperf.com/sibling-index/10\n * @param {Element} element The element to check.\n * @returns {number}\n */\nexport function index(element) {\n let i = 0;\n let elementToCheck = element;\n if (elementToCheck.previousSibling) {\n /* eslint-disable no-cond-assign */\n while (elementToCheck = elementToCheck.previousSibling) {\n i += 1;\n }\n }\n return i;\n}\n\n/**\n * Check if the provided overlay contains the provided element.\n *\n * @param {string} overlayType The type of the overlay.\n * @param {HTMLElement} element An element to check.\n * @param {HTMLElement} root The root element.\n * @returns {boolean}\n */\nexport function overlayContainsElement(overlayType, element, root) {\n const overlayElement = root.parentElement.querySelector(`.ht_clone_${overlayType}`);\n return overlayElement ? overlayElement.contains(element) : null;\n}\n\n/**\n * @param {string[]} classNames The element \"class\" attribute string.\n * @returns {string[]}\n */\nfunction filterEmptyClassNames(classNames) {\n if (!classNames || !classNames.length) {\n return [];\n }\n return classNames.filter(x => !!x);\n}\n\n/**\n * Filter out the RegExp entries from an array.\n *\n * @param {(string|RegExp)[]} list Array of either strings, Regexes or a mix of both.\n * @param {boolean} [returnBoth] If `true`, both the array without regexes and an array of regexes will be returned.\n * @returns {string[]|{regexFree: string[], regexes: RegExp[]}}\n */\nfunction filterRegexes(list, returnBoth) {\n if (!list || !list.length) {\n return returnBoth ? {\n regexFree: [],\n regexes: []\n } : [];\n }\n const regexes = [];\n const regexFree = [];\n regexFree.push(...list.filter(entry => {\n const isRegex = entry instanceof RegExp;\n if (isRegex && returnBoth) {\n regexes.push(entry);\n }\n return !isRegex;\n }));\n return returnBoth ? {\n regexFree,\n regexes\n } : regexFree;\n}\n\n/**\n * Checks if element has class name.\n *\n * @param {HTMLElement} element An element to check.\n * @param {string} className Class name to check.\n * @returns {boolean}\n */\nexport function hasClass(element, className) {\n if (element.classList === undefined || typeof className !== 'string' || className === '') {\n return false;\n }\n return element.classList.contains(className);\n}\n\n/**\n * Add class name to an element.\n *\n * @param {HTMLElement} element An element to process.\n * @param {string|Array} className Class name as string or array of strings.\n */\nexport function addClass(element, className) {\n if (typeof className === 'string') {\n className = className.split(' ');\n }\n className = filterEmptyClassNames(className);\n if (className.length > 0) {\n element.classList.add(...className);\n }\n}\n\n/**\n * Remove class name from an element.\n *\n * @param {HTMLElement} element An element to process.\n * @param {string|Array} className Class name as string or array of strings.\n */\nexport function removeClass(element, className) {\n if (typeof className === 'string') {\n className = className.split(' ');\n } else if (className instanceof RegExp) {\n className = [className];\n }\n let {\n regexFree: stringClasses,\n // eslint-disable-next-line prefer-const\n regexes: regexClasses\n } = filterRegexes(className, true);\n stringClasses = filterEmptyClassNames(stringClasses);\n if (stringClasses.length > 0) {\n element.classList.remove(...stringClasses);\n }\n regexClasses.forEach(regexClassName => {\n element.classList.forEach(currentClassName => {\n if (regexClassName.test(currentClassName)) {\n element.classList.remove(currentClassName);\n }\n });\n });\n}\n\n/**\n * Set a single attribute or multiple attributes at once.\n *\n * @param {HTMLElement} domElement The HTML element to be modified.\n * @param {Array[]|string} attributes If setting multiple attributes at once, `attributes` holds an array containing the\n * attributes to be added. Each element of the array should be an array in a form of `[attributeName,\n * attributeValue]`. If setting a single attribute, `attributes` holds the name of the attribute.\n * @param {string|number|undefined} [attributeValue] If setting a single attribute, `attributeValue` holds the attribute\n * value.\n */\nexport function setAttribute(domElement) {\n let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n let attributeValue = arguments.length > 2 ? arguments[2] : undefined;\n if (!Array.isArray(attributes)) {\n attributes = [[attributes, attributeValue]];\n }\n attributes.forEach(attributeInfo => {\n if (Array.isArray(attributeInfo) && attributeInfo[0] !== '') {\n domElement.setAttribute(...attributeInfo);\n }\n });\n}\n\n/**\n * Remove a single attribute or multiple attributes from the provided element at once.\n *\n * @param {HTMLElement} domElement The HTML element to be processed.\n * @param {Array|string} attributesToRemove If removing multiple attributes, `attributesToRemove`\n * holds an array of attribute names to be removed from the provided element. If removing a single attribute, it\n * holds the attribute name.\n */\nexport function removeAttribute(domElement) {\n let attributesToRemove = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n if (typeof attributesToRemove === 'string') {\n attributesToRemove = attributesToRemove.split(' ');\n } else if (attributesToRemove instanceof RegExp) {\n attributesToRemove = [attributesToRemove];\n }\n const {\n regexFree: stringAttributes,\n regexes: regexAttributes\n } = filterRegexes(attributesToRemove, true);\n stringAttributes.forEach(attributeNameToRemove => {\n if (attributeNameToRemove !== '') {\n domElement.removeAttribute(attributeNameToRemove);\n }\n });\n regexAttributes.forEach(attributeRegex => {\n domElement.getAttributeNames().forEach(attributeName => {\n if (attributeRegex.test(attributeName)) {\n domElement.removeAttribute(attributeName);\n }\n });\n });\n}\n\n/**\n * @param {HTMLElement} element An element from the text is removed.\n */\nexport function removeTextNodes(element) {\n if (element.nodeType === 3) {\n element.parentNode.removeChild(element); // bye text nodes!\n } else if (['TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR'].indexOf(element.nodeName) > -1) {\n const childs = element.childNodes;\n for (let i = childs.length - 1; i >= 0; i--) {\n removeTextNodes(childs[i]);\n }\n }\n}\n\n/**\n * Remove children function\n * WARNING - this doesn't unload events and data attached by jQuery\n * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/9\n * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/11 - no siginificant improvement with Chrome remove() method.\n *\n * @param {HTMLElement} element An element to clear.\n */\nexport function empty(element) {\n let child;\n\n /* eslint-disable no-cond-assign */\n while (child = element.lastChild) {\n element.removeChild(child);\n }\n}\nexport const HTML_CHARACTERS = /(<(.*)>|&(.*);)/;\n\n/**\n * Insert content into element trying to avoid innerHTML method.\n *\n * @param {HTMLElement} element An element to write into.\n * @param {string} content The text to write.\n * @param {boolean} [sanitizeContent=true] If `true`, the content will be sanitized before writing to the element.\n */\nexport function fastInnerHTML(element, content) {\n let sanitizeContent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n if (HTML_CHARACTERS.test(content)) {\n element.innerHTML = sanitizeContent ? sanitize(content) : content;\n } else {\n fastInnerText(element, content);\n }\n}\n\n/**\n * Insert text content into element.\n *\n * @param {HTMLElement} element An element to write into.\n * @param {string} content The text to write.\n */\nexport function fastInnerText(element, content) {\n const child = element.firstChild;\n if (child && child.nodeType === 3 && child.nextSibling === null) {\n // fast lane - replace existing text node\n child.textContent = content;\n } else {\n // slow lane - empty element and insert a text node\n empty(element);\n element.appendChild(element.ownerDocument.createTextNode(content));\n }\n}\n\n/**\n * Returns true if element is attached to the DOM and visible, false otherwise.\n *\n * @param {HTMLElement} element An element to check.\n * @returns {boolean}\n */\nexport function isVisible(element) {\n const documentElement = element.ownerDocument.documentElement;\n let next = element;\n while (next !== documentElement) {\n // until reached\n if (next === null) {\n // parent detached from DOM\n return false;\n } else if (next.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n if (next.host) {\n // this is Web Components Shadow DOM\n // see: http://w3c.github.io/webcomponents/spec/shadow/#encapsulation\n // according to spec, should be if (next.ownerDocument !== window.document), but that doesn't work yet\n if (next.host.impl) {\n // Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features disabled\n return isVisible(next.host.impl);\n } else if (next.host) {\n // Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features enabled\n return isVisible(next.host);\n }\n throw new Error('Lost in Web Components world');\n } else {\n return false; // this is a node detached from document in IE8\n }\n } else if (getComputedStyle(next).display === 'none') {\n return false;\n }\n next = next.parentNode;\n }\n return true;\n}\n\n/**\n * Returns elements top and left offset relative to the document. Function is not compatible with jQuery offset.\n *\n * @param {HTMLElement} element An element to get the offset position from.\n * @returns {object} Returns object with `top` and `left` props.\n */\nexport function offset(element) {\n const rootDocument = element.ownerDocument;\n const rootWindow = rootDocument.defaultView;\n const documentElement = rootDocument.documentElement;\n let elementToCheck = element;\n let offsetLeft;\n let offsetTop;\n let lastElem;\n offsetLeft = elementToCheck.offsetLeft;\n offsetTop = elementToCheck.offsetTop;\n lastElem = elementToCheck;\n\n /* eslint-disable no-cond-assign */\n while (elementToCheck = elementToCheck.offsetParent) {\n // from my observation, document.body always has scrollLeft/scrollTop == 0\n if (elementToCheck === rootDocument.body) {\n break;\n }\n // If the element is inside an SVG context, the `offsetParent` can be\n // a that does not have properties `offsetLeft` and `offsetTop` defined.\n if (!('offsetLeft' in elementToCheck)) {\n break;\n }\n offsetLeft += elementToCheck.offsetLeft;\n offsetTop += elementToCheck.offsetTop;\n lastElem = elementToCheck;\n }\n\n // slow - http://jsperf.com/offset-vs-getboundingclientrect/6\n if (lastElem && lastElem.style.position === 'fixed') {\n // if(lastElem !== document.body) { //faster but does gives false positive in Firefox\n offsetLeft += rootWindow.pageXOffset || documentElement.scrollLeft;\n offsetTop += rootWindow.pageYOffset || documentElement.scrollTop;\n }\n return {\n left: offsetLeft,\n top: offsetTop\n };\n}\n\n/**\n * Returns the document's scrollTop property.\n *\n * @param {Window} [rootWindow] The document window owner.\n * @returns {number}\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getWindowScrollTop() {\n let rootWindow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;\n return rootWindow.scrollY;\n}\n\n/**\n * Returns the document's scrollLeft property.\n *\n * @param {Window} [rootWindow] The document window owner.\n * @returns {number}\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getWindowScrollLeft() {\n let rootWindow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;\n return rootWindow.scrollX;\n}\n\n/**\n * Returns the provided element's scrollTop property.\n *\n * @param {HTMLElement} element An element to get the scroll top position from.\n * @param {Window} [rootWindow] The document window owner.\n * @returns {number}\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getScrollTop(element) {\n let rootWindow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window;\n if (element === rootWindow) {\n return getWindowScrollTop(rootWindow);\n }\n return element.scrollTop;\n}\n\n/**\n * Returns the provided element's scrollLeft property.\n *\n * @param {HTMLElement} element An element to get the scroll left position from.\n * @param {Window} [rootWindow] The document window owner.\n * @returns {number}\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getScrollLeft(element) {\n let rootWindow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window;\n if (element === rootWindow) {\n return getWindowScrollLeft(rootWindow);\n }\n return element.scrollLeft;\n}\n\n/**\n * Returns a DOM element responsible for scrolling of the provided element.\n *\n * @param {HTMLElement} element An element to get the scrollable element from.\n * @returns {HTMLElement} Element's scrollable parent.\n */\nexport function getScrollableElement(element) {\n let rootDocument = element.ownerDocument;\n let rootWindow = rootDocument ? rootDocument.defaultView : undefined;\n if (!rootDocument) {\n rootDocument = element.document ? element.document : element;\n rootWindow = rootDocument.defaultView;\n }\n const props = ['auto', 'scroll'];\n let el = element.parentNode;\n while (el && el.style && rootDocument.body !== el) {\n let {\n overflow,\n overflowX,\n overflowY\n } = el.style;\n if ([overflow, overflowX, overflowY].includes('scroll')) {\n return el;\n } else {\n ({\n overflow,\n overflowX,\n overflowY\n } = rootWindow.getComputedStyle(el));\n if (props.includes(overflow) || props.includes(overflowX) || props.includes(overflowY)) {\n return el;\n }\n }\n\n // The '+ 1' after the scrollHeight/scrollWidth is to prevent problems with zoomed out Chrome.\n if (el.clientHeight <= el.scrollHeight + 1 && (props.includes(overflowY) || props.includes(overflow))) {\n return el;\n }\n if (el.clientWidth <= el.scrollWidth + 1 && (props.includes(overflowX) || props.includes(overflow))) {\n return el;\n }\n el = el.parentNode;\n }\n return rootWindow;\n}\n\n/**\n * Get the maximum available `scrollTop` value for the provided element.\n *\n * @param {HTMLElement} element The element to get the maximum scroll top value from.\n * @returns {number} The maximum scroll top value.\n */\nexport function getMaximumScrollTop(element) {\n return element.scrollHeight - element.clientHeight;\n}\n\n/**\n * Get the maximum available `scrollLeft` value for the provided element.\n *\n * @param {HTMLElement} element The element to get the maximum scroll left value from.\n * @returns {number} The maximum scroll left value.\n */\nexport function getMaximumScrollLeft(element) {\n return element.scrollWidth - element.clientWidth;\n}\n\n/**\n * Returns a DOM element responsible for trimming the provided element.\n *\n * @param {HTMLElement} base Base element.\n * @returns {HTMLElement} Base element's trimming parent.\n */\nexport function getTrimmingContainer(base) {\n const rootDocument = base.ownerDocument;\n const rootWindow = rootDocument.defaultView;\n let el = base.parentNode;\n while (el && el.style && rootDocument.body !== el) {\n if (el.style.overflow !== 'visible' && el.style.overflow !== '') {\n return el;\n }\n const computedStyle = getComputedStyle(el, rootWindow);\n const allowedProperties = ['scroll', 'hidden', 'auto'];\n const property = computedStyle.getPropertyValue('overflow');\n const propertyY = computedStyle.getPropertyValue('overflow-y');\n const propertyX = computedStyle.getPropertyValue('overflow-x');\n if (allowedProperties.includes(property) || allowedProperties.includes(propertyY) || allowedProperties.includes(propertyX)) {\n return el;\n }\n el = el.parentNode;\n }\n return rootWindow;\n}\n\n/**\n * Returns a style property for the provided element. (Be it an inline or external style).\n *\n * @param {HTMLElement} element An element to get the style from.\n * @param {string} prop Wanted property.\n * @param {Window} [rootWindow] The document window owner.\n * @returns {string|undefined} Element's style property.\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getStyle(element, prop) {\n let rootWindow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window;\n if (!element) {\n return;\n } else if (element === rootWindow) {\n if (prop === 'width') {\n return `${rootWindow.innerWidth}px`;\n } else if (prop === 'height') {\n return `${rootWindow.innerHeight}px`;\n }\n return;\n }\n const styleProp = element.style[prop];\n if (styleProp !== '' && styleProp !== undefined) {\n return styleProp;\n }\n const computedStyle = getComputedStyle(element, rootWindow);\n if (computedStyle[prop] !== '' && computedStyle[prop] !== undefined) {\n return computedStyle[prop];\n }\n}\n\n/**\n * Verifies if element fit to provided CSSRule.\n *\n * @param {Element} element Element to verify with selector text.\n * @param {CSSRule} rule Selector text from CSSRule.\n * @returns {boolean}\n */\nexport function matchesCSSRules(element, rule) {\n const {\n selectorText\n } = rule;\n let result = false;\n if (rule.type === CSSRule.STYLE_RULE && selectorText) {\n if (element.msMatchesSelector) {\n result = element.msMatchesSelector(selectorText);\n } else if (element.matches) {\n result = element.matches(selectorText);\n }\n }\n return result;\n}\n\n/**\n * Returns a computed style object for the provided element. (Needed if style is declared in external stylesheet).\n *\n * @param {HTMLElement} element An element to get style from.\n * @param {Window} [rootWindow] The document window owner.\n * @returns {IEElementStyle|CssStyle} Elements computed style object.\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getComputedStyle(element) {\n let rootWindow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window;\n return element.currentStyle || rootWindow.getComputedStyle(element);\n}\n\n/**\n * Returns the element's outer width.\n *\n * @param {HTMLElement} element An element to get the width from.\n * @returns {number} Element's outer width.\n */\nexport function outerWidth(element) {\n return element.offsetWidth;\n}\n\n/**\n * Returns the element's outer height.\n *\n * @param {HTMLElement} element An element to get the height from.\n * @returns {number} Element's outer height.\n */\nexport function outerHeight(element) {\n return element.offsetHeight;\n}\n\n/**\n * Returns the element's inner height.\n *\n * @param {HTMLElement} element An element to get the height from.\n * @returns {number} Element's inner height.\n */\nexport function innerHeight(element) {\n return element.clientHeight || element.innerHeight;\n}\n\n/**\n * Returns the element's inner width.\n *\n * @param {HTMLElement} element An element to get the width from.\n * @returns {number} Element's inner width.\n */\nexport function innerWidth(element) {\n return element.clientWidth || element.innerWidth;\n}\n\n/**\n * @param {HTMLElement} element An element to which the event is added.\n * @param {string} event The event name.\n * @param {Function} callback The callback to add.\n */\nexport function addEvent(element, event, callback) {\n element.addEventListener(event, callback, false);\n}\n\n/**\n * @param {HTMLElement} element An element from which the event is removed.\n * @param {string} event The event name.\n * @param {Function} callback The function reference to remove.\n */\nexport function removeEvent(element, event, callback) {\n element.removeEventListener(event, callback, false);\n}\n\n/**\n * Returns caret position in text input.\n *\n * @author https://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea\n * @param {HTMLElement} el An element to check.\n * @returns {number}\n */\nexport function getCaretPosition(el) {\n if (el.selectionStart) {\n return el.selectionStart;\n }\n return 0;\n}\n\n/**\n * Returns end of the selection in text input.\n *\n * @param {HTMLElement} el An element to check.\n * @returns {number}\n */\nexport function getSelectionEndPosition(el) {\n if (el.selectionEnd) {\n return el.selectionEnd;\n }\n return 0;\n}\n\n/**\n * Returns text under selection.\n *\n * @param {Window} [rootWindow] The document window owner.\n * @returns {string}\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getSelectionText() {\n let rootWindow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;\n const rootDocument = rootWindow.document;\n let text = '';\n if (rootWindow.getSelection) {\n text = rootWindow.getSelection().toString();\n } else if (rootDocument.selection && rootDocument.selection.type !== 'Control') {\n text = rootDocument.selection.createRange().text;\n }\n return text;\n}\n\n/**\n * Cross-platform helper to clear text selection.\n *\n * @param {Window} [rootWindow] The document window owner.\n */\n// eslint-disable-next-line no-restricted-globals\nexport function clearTextSelection() {\n let rootWindow = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;\n // http://stackoverflow.com/questions/3169786/clear-text-selection-with-javascript\n if (rootWindow.getSelection) {\n if (rootWindow.getSelection().empty) {\n // Chrome\n rootWindow.getSelection().empty();\n } else if (rootWindow.getSelection().removeAllRanges) {\n // Firefox\n rootWindow.getSelection().removeAllRanges();\n }\n }\n}\n\n/**\n * Sets caret position in text input.\n *\n * @author http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/\n * @param {Element} element An element to process.\n * @param {number} pos The selection start position.\n * @param {number} endPos The selection end position.\n */\nexport function setCaretPosition(element, pos, endPos) {\n if (endPos === undefined) {\n endPos = pos;\n }\n if (element.setSelectionRange) {\n element.focus();\n try {\n element.setSelectionRange(pos, endPos);\n } catch (err) {\n const elementParent = element.parentNode;\n const parentDisplayValue = elementParent.style.display;\n elementParent.style.display = 'block';\n element.setSelectionRange(pos, endPos);\n elementParent.style.display = parentDisplayValue;\n }\n }\n}\nlet cachedScrollbarWidth;\n\n/**\n * Helper to calculate scrollbar width.\n * Source: https://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes.\n *\n * @private\n * @param {Document} rootDocument The onwer of the document.\n * @returns {number}\n */\n// eslint-disable-next-line no-restricted-globals\nfunction walkontableCalculateScrollbarWidth() {\n let rootDocument = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n const inner = rootDocument.createElement('div');\n inner.style.height = '200px';\n inner.style.width = '100%';\n const outer = rootDocument.createElement('div');\n outer.style.boxSizing = 'content-box';\n outer.style.height = '150px';\n outer.style.left = '0px';\n outer.style.overflow = 'hidden';\n outer.style.position = 'absolute';\n outer.style.top = '0px';\n outer.style.width = '200px';\n outer.style.visibility = 'hidden';\n outer.appendChild(inner);\n (rootDocument.body || rootDocument.documentElement).appendChild(outer);\n const w1 = inner.offsetWidth;\n outer.style.overflow = 'scroll';\n let w2 = inner.offsetWidth;\n if (w1 === w2) {\n w2 = outer.clientWidth;\n }\n (rootDocument.body || rootDocument.documentElement).removeChild(outer);\n return w1 - w2;\n}\n\n/**\n * Returns the computed width of the native browser scroll bar.\n *\n * @param {Document} [rootDocument] The owner of the document.\n * @returns {number} Width.\n */\n// eslint-disable-next-line no-restricted-globals\nexport function getScrollbarWidth() {\n let rootDocument = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n if (cachedScrollbarWidth === undefined) {\n cachedScrollbarWidth = walkontableCalculateScrollbarWidth(rootDocument);\n }\n return cachedScrollbarWidth;\n}\n\n/**\n * Checks if the provided element has a vertical scrollbar.\n *\n * @param {HTMLElement} element An element to check.\n * @returns {boolean}\n */\nexport function hasVerticalScrollbar(element) {\n return element.offsetWidth !== element.clientWidth;\n}\n\n/**\n * Checks if the provided element has a vertical scrollbar.\n *\n * @param {HTMLElement} element An element to check.\n * @returns {boolean}\n */\nexport function hasHorizontalScrollbar(element) {\n return element.offsetHeight !== element.clientHeight;\n}\n\n/**\n * Sets overlay position depending on it's type and used browser.\n *\n * @param {HTMLElement} overlayElem An element to process.\n * @param {number|string} left The left position of the overlay.\n * @param {number|string} top The top position of the overlay.\n */\nexport function setOverlayPosition(overlayElem, left, top) {\n overlayElem.style.transform = `translate3d(${left},${top},0)`;\n}\n\n/**\n * @param {HTMLElement} element An element to process.\n * @returns {number|Array}\n */\nexport function getCssTransform(element) {\n let transform;\n if (element.style.transform && (transform = element.style.transform) !== '') {\n return ['transform', transform];\n }\n return -1;\n}\n\n/**\n * @param {HTMLElement} element An element to process.\n */\nexport function resetCssTransform(element) {\n if (element.style.transform && element.style.transform !== '') {\n element.style.transform = '';\n }\n}\n\n/**\n * Determines if the given DOM element is an input field.\n * Notice: By 'input' we mean input, textarea and select nodes.\n *\n * @param {HTMLElement} element - DOM element.\n * @returns {boolean}\n */\nexport function isInput(element) {\n const inputs = ['INPUT', 'SELECT', 'TEXTAREA'];\n return element && (inputs.indexOf(element.nodeName) > -1 || element.contentEditable === 'true');\n}\n\n/**\n * Determines if the given DOM element is an input field placed OUTSIDE of HOT.\n * Notice: By 'input' we mean input, textarea and select nodes which have defined 'data-hot-input' attribute.\n *\n * @param {HTMLElement} element - DOM element.\n * @returns {boolean}\n */\nexport function isOutsideInput(element) {\n return isInput(element) && element.hasAttribute('data-hot-input') === false;\n}\n\n/**\n * Check if the given DOM element can be focused (by using \"select\" method).\n *\n * @param {HTMLElement} element - DOM element.\n */\nexport function selectElementIfAllowed(element) {\n const activeElement = element.ownerDocument.activeElement;\n if (!isOutsideInput(activeElement)) {\n element.select();\n }\n}\n\n/**\n * Check if the provided element is detached from DOM.\n *\n * @param {HTMLElement} element HTML element to be checked.\n * @returns {boolean} `true` if the element is detached, `false` otherwise.\n */\nexport function isDetached(element) {\n return !element.parentNode;\n}\n\n/**\n * Set up an observer to recognize when the provided element first becomes visible and trigger a callback when it\n * happens.\n *\n * @param {HTMLElement} elementToBeObserved Element to be observed.\n * @param {Function} callback The callback function.\n */\nexport function observeVisibilityChangeOnce(elementToBeObserved, callback) {\n const visibilityObserver = new IntersectionObserver((entries, observer) => {\n entries.forEach(entry => {\n if (entry.isIntersecting && elementToBeObserved.offsetParent !== null) {\n callback();\n observer.unobserve(elementToBeObserved);\n }\n });\n }, {\n root: elementToBeObserved.ownerDocument.body\n });\n visibilityObserver.observe(elementToBeObserved);\n}\n\n/**\n * Add a `contenteditable` attribute, select the contents and optionally add the `invisibleSelection`\n * class to the provided element.\n *\n * @param {HTMLElement} element Element to be processed.\n * @param {boolean} [invisibleSelection=true] `true` if the class should be added to the element.\n * @param {boolean} [ariaHidden=true] `true` if the `aria-hidden` attribute should be added to the processed element.\n */\nexport function makeElementContentEditableAndSelectItsContent(element) {\n let invisibleSelection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n let ariaHidden = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n const ownerDocument = element.ownerDocument;\n const range = ownerDocument.createRange();\n const sel = ownerDocument.defaultView.getSelection();\n setAttribute(element, 'contenteditable', true);\n if (ariaHidden) {\n setAttribute(element, ...A11Y_HIDDEN());\n }\n if (invisibleSelection) {\n addClass(element, 'invisibleSelection');\n }\n range.selectNodeContents(element);\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n/**\n * Remove the `contenteditable` attribute, deselect the contents and optionally remove the `invisibleSelection`\n * class from the provided element.\n *\n * @param {HTMLElement} selectedElement The element to be deselected.\n * @param {boolean} [removeInvisibleSelectionClass=true] `true` if the class should be removed from the element.\n */\nexport function removeContentEditableFromElementAndDeselect(selectedElement) {\n let removeInvisibleSelectionClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n const sel = selectedElement.ownerDocument.defaultView.getSelection();\n if (selectedElement.hasAttribute('aria-hidden')) {\n selectedElement.removeAttribute('aria-hidden');\n }\n sel.removeAllRanges();\n if (removeInvisibleSelectionClass) {\n removeClass(selectedElement, 'invisibleSelection');\n }\n selectedElement.removeAttribute('contenteditable');\n}\n\n/**\n * Run the provided callback while the provided element is selected and modified to have the `contenteditable`\n * attribute added. Optionally, the selection can be configured to be invisible.\n *\n * @param {HTMLElement} element Element to be selected.\n * @param {Function} callback Callback to be called.\n * @param {boolean} [invisibleSelection=true] `true` if the selection should be invisible.\n */\nexport function runWithSelectedContendEditableElement(element, callback) {\n let invisibleSelection = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n makeElementContentEditableAndSelectItsContent(element, invisibleSelection);\n callback();\n removeContentEditableFromElementAndDeselect(element, invisibleSelection);\n}","import \"core-js/modules/es.array.push.js\";\nimport DOMPurify from 'dompurify';\nimport { stringify } from \"./mixed.mjs\";\n/**\n * Convert string to upper case first letter.\n *\n * @param {string} string String to convert.\n * @returns {string}\n */\nexport function toUpperCaseFirst(string) {\n return string[0].toUpperCase() + string.substr(1);\n}\n\n/**\n * Compare strings case insensitively.\n *\n * @param {...string} strings Strings to compare.\n * @returns {boolean}\n */\nexport function equalsIgnoreCase() {\n const unique = [];\n for (var _len = arguments.length, strings = new Array(_len), _key = 0; _key < _len; _key++) {\n strings[_key] = arguments[_key];\n }\n let length = strings.length;\n while (length) {\n length -= 1;\n const string = stringify(strings[length]).toLowerCase();\n if (unique.indexOf(string) === -1) {\n unique.push(string);\n }\n }\n return unique.length === 1;\n}\n\n/**\n * Generates a random hex string. Used as namespace for Handsontable instance events.\n *\n * @returns {string} Returns 16-long character random string (eq. `'92b1bfc74ec4'`).\n */\nexport function randomString() {\n /**\n * @returns {string}\n */\n function s4() {\n return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\n }\n return s4() + s4() + s4() + s4();\n}\n\n/**\n * Checks if value is valid percent.\n *\n * @param {string} value The value to check.\n * @returns {boolean}\n */\nexport function isPercentValue(value) {\n return /^([0-9][0-9]?%$)|(^100%$)/.test(value);\n}\n\n/**\n * Substitute strings placed beetwen square brackets into value defined in `variables` object. String names defined in\n * square brackets must be the same as property name of `variables` object.\n *\n * @param {string} template Template string.\n * @param {object} variables Object which contains all available values which can be injected into template.\n * @returns {string}\n */\nexport function substitute(template) {\n let variables = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n return `${template}`.replace(/(?:\\\\)?\\[([^[\\]]+)]/g, (match, name) => {\n if (match.charAt(0) === '\\\\') {\n return match.substr(1, match.length - 1);\n }\n return variables[name] === undefined ? '' : variables[name];\n });\n}\n\n/**\n * Strip any HTML tag from the string.\n *\n * @param {string} string String to cut HTML from.\n * @returns {string}\n */\nexport function stripTags(string) {\n return sanitize(`${string}`, {\n ALLOWED_TAGS: []\n });\n}\n\n/**\n * Sanitizes string from potential security vulnerabilities.\n *\n * @param {string} string String to sanitize.\n * @param {object} [options] DOMPurify's configuration object.\n * @returns {string}\n */\nexport function sanitize(string, options) {\n return DOMPurify.sanitize(string, options);\n}","import moment from 'moment';\nimport { toSingleLine } from \"./templateLiteralTag.mjs\";\n/**\n * Converts any value to string.\n *\n * @param {*} value The value to stringify.\n * @returns {string}\n */\nexport function stringify(value) {\n let result;\n switch (typeof value) {\n case 'string':\n case 'number':\n result = `${value}`;\n break;\n case 'object':\n result = value === null ? '' : value.toString();\n break;\n case 'undefined':\n result = '';\n break;\n default:\n result = value.toString();\n break;\n }\n return result;\n}\n\n/**\n * Checks if given variable is defined.\n *\n * @param {*} variable Variable to check.\n * @returns {boolean}\n */\nexport function isDefined(variable) {\n return typeof variable !== 'undefined';\n}\n\n/**\n * Checks if given variable is undefined.\n *\n * @param {*} variable Variable to check.\n * @returns {boolean}\n */\nexport function isUndefined(variable) {\n return typeof variable === 'undefined';\n}\n\n/**\n * Check if given variable is null, empty string or undefined.\n *\n * @param {*} variable Variable to check.\n * @returns {boolean}\n */\nexport function isEmpty(variable) {\n return variable === null || variable === '' || isUndefined(variable);\n}\n\n/**\n * Check if given variable is a regular expression.\n *\n * @param {*} variable Variable to check.\n * @returns {boolean}\n */\nexport function isRegExp(variable) {\n return Object.prototype.toString.call(variable) === '[object RegExp]';\n}\n\n/* eslint-disable */\nconst _m = '\\x6C\\x65\\x6E\\x67\\x74\\x68';\nconst _hd = v => parseInt(v, 16);\nconst _pi = v => parseInt(v, 10);\nconst _ss = (v, s, l) => v['\\x73\\x75\\x62\\x73\\x74\\x72'](s, l);\nconst _cp = v => v['\\x63\\x6F\\x64\\x65\\x50\\x6F\\x69\\x6E\\x74\\x41\\x74'](0) - 65;\nconst _norm = v => `${v}`.replace(/\\-/g, '');\nconst _extractTime = v => _hd(_ss(_norm(v), _hd('12'), _cp('\\x46'))) / (_hd(_ss(_norm(v), _cp('\\x42'), ~~![][_m])) || 9);\nconst _ignored = () => typeof location !== 'undefined' && /^([a-z0-9\\-]+\\.)?\\x68\\x61\\x6E\\x64\\x73\\x6F\\x6E\\x74\\x61\\x62\\x6C\\x65\\x2E\\x63\\x6F\\x6D$/i.test(location.host);\nlet _notified = false;\nconst consoleMessages = {\n invalid: () => toSingleLine`\n The license key for Handsontable is invalid.\\x20\n If you need any help, contact us at support@handsontable.com.`,\n expired: _ref => {\n let {\n keyValidityDate,\n hotVersion\n } = _ref;\n return toSingleLine`\n The license key for Handsontable expired on ${keyValidityDate}, and is not valid for the installed\\x20\n version ${hotVersion}. Renew your license key at handsontable.com or downgrade to a version released prior\\x20\n to ${keyValidityDate}. If you need any help, contact us at sales@handsontable.com.`;\n },\n missing: () => toSingleLine`\n The license key for Handsontable is missing. Use your purchased key to activate the product.\\x20\n Alternatively, you can activate Handsontable to use for non-commercial purposes by\\x20\n passing the key: 'non-commercial-and-evaluation'. If you need any help, contact\\x20\n us at support@handsontable.com.`,\n non_commercial: () => ''\n};\nconst domMessages = {\n invalid: () => toSingleLine`\n The license key for Handsontable is invalid.\\x20\n Read more on how to\\x20\n install it properly or contact us at support@handsontable.com.`,\n expired: _ref2 => {\n let {\n keyValidityDate,\n hotVersion\n } = _ref2;\n return toSingleLine`\n The license key for Handsontable expired on ${keyValidityDate}, and is not valid for the installed\\x20\n version ${hotVersion}. Renew your\\x20\n license key or downgrade to a version released prior to ${keyValidityDate}. If you need any\\x20\n help, contact us at sales@handsontable.com.`;\n },\n missing: () => toSingleLine`\n The license key for Handsontable is missing. Use your purchased key to activate the product.\\x20\n Alternatively, you can activate Handsontable to use for non-commercial purposes by\\x20\n passing the key: 'non-commercial-and-evaluation'.\\x20\n Read more about it in\\x20\n the documentation or contact us at support@handsontable.com.`,\n non_commercial: () => ''\n};\nexport function _injectProductInfo(key, element) {\n const hasValidType = !isEmpty(key);\n const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';\n const hotVersion = \"14.5.0\";\n let keyValidityDate;\n let consoleMessageState = 'invalid';\n let domMessageState = 'invalid';\n key = _norm(key || '');\n const schemaValidity = _checkKeySchema(key);\n if (hasValidType || isNonCommercial || schemaValidity) {\n if (schemaValidity) {\n const releaseDate = moment(\"30/07/2024\", 'DD/MM/YYYY');\n const releaseDays = Math.floor(releaseDate.toDate().getTime() / 8.64e7);\n const keyValidityDays = _extractTime(key);\n keyValidityDate = moment((keyValidityDays + 1) * 8.64e7, 'x').format('MMMM DD, YYYY');\n if (releaseDays > keyValidityDays) {\n consoleMessageState = 'expired';\n domMessageState = 'expired';\n } else {\n consoleMessageState = 'valid';\n domMessageState = 'valid';\n }\n } else if (isNonCommercial) {\n consoleMessageState = 'non_commercial';\n domMessageState = 'valid';\n } else {\n consoleMessageState = 'invalid';\n domMessageState = 'invalid';\n }\n } else {\n consoleMessageState = 'missing';\n domMessageState = 'missing';\n }\n if (_ignored()) {\n consoleMessageState = 'valid';\n domMessageState = 'valid';\n }\n if (!_notified && consoleMessageState !== 'valid') {\n const message = consoleMessages[consoleMessageState]({\n keyValidityDate,\n hotVersion\n });\n if (message) {\n console[consoleMessageState === 'non_commercial' ? 'info' : 'warn'](consoleMessages[consoleMessageState]({\n keyValidityDate,\n hotVersion\n }));\n }\n _notified = true;\n }\n if (domMessageState !== 'valid' && element.parentNode) {\n const message = domMessages[domMessageState]({\n keyValidityDate,\n hotVersion\n });\n if (message) {\n const messageNode = document.createElement('div');\n messageNode.className = 'hot-display-license-info';\n messageNode.innerHTML = domMessages[domMessageState]({\n keyValidityDate,\n hotVersion\n });\n element.parentNode.insertBefore(messageNode, element.nextSibling);\n }\n }\n}\nfunction _checkKeySchema(v) {\n let z = [][_m];\n let p = z;\n if (v[_m] !== _cp('\\x5A')) {\n return false;\n }\n for (let c = '', i = '\\x42\\x3C\\x48\\x34\\x50\\x2B'.split(''), j = _cp(i.shift()); j; j = _cp(i.shift() || 'A')) {\n --j < ''[_m] ? p = p | (_pi(`${_pi(_hd(c) + (_hd(_ss(v, Math.abs(j), 2)) + []).padStart(2, '0'))}`) % 97 || 2) >> 1 : c = _ss(v, j, !j ? 6 : i[_m] === 1 ? 9 : 8);\n }\n return p === z;\n}\n/* eslint-enable */","import \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\n/**\n * @param {Array} arr An array to process.\n */\nexport function to2dArray(arr) {\n const ilen = arr.length;\n let i = 0;\n while (i < ilen) {\n arr[i] = [arr[i]];\n i += 1;\n }\n}\n\n/**\n * @param {Array} arr An array to extend.\n * @param {Array} extension The data to extend from.\n */\nexport function extendArray(arr, extension) {\n const ilen = extension.length;\n let i = 0;\n while (i < ilen) {\n arr.push(extension[i]);\n i += 1;\n }\n}\n\n/**\n * @param {Array} arr An array to pivot.\n * @returns {Array}\n */\nexport function pivot(arr) {\n const pivotedArr = [];\n if (!arr || arr.length === 0 || !arr[0] || arr[0].length === 0) {\n return pivotedArr;\n }\n const rowCount = arr.length;\n const colCount = arr[0].length;\n for (let i = 0; i < rowCount; i++) {\n for (let j = 0; j < colCount; j++) {\n if (!pivotedArr[j]) {\n pivotedArr[j] = [];\n }\n pivotedArr[j][i] = arr[i][j];\n }\n }\n return pivotedArr;\n}\n\n/**\n * A specialized version of `.reduce` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * {@link https://github.com/lodash/lodash/blob/master/lodash.js}.\n *\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initFromArray] Specify using the first element of `array` as the initial value.\n * @returns {*} Returns the accumulated value.\n */\nexport function arrayReduce(array, iteratee, accumulator, initFromArray) {\n let index = -1;\n let iterable = array;\n let result = accumulator;\n if (!Array.isArray(array)) {\n iterable = Array.from(array);\n }\n const length = iterable.length;\n if (initFromArray && length) {\n index += 1;\n result = iterable[index];\n }\n index += 1;\n while (index < length) {\n result = iteratee(result, iterable[index], index, iterable);\n index += 1;\n }\n return result;\n}\n\n/**\n * A specialized version of `.filter` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * {@link https://github.com/lodash/lodash/blob/master/lodash.js}.\n *\n * @param {Array} array The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nexport function arrayFilter(array, predicate) {\n let index = 0;\n let iterable = array;\n if (!Array.isArray(array)) {\n iterable = Array.from(array);\n }\n const length = iterable.length;\n const result = [];\n let resIndex = -1;\n while (index < length) {\n const value = iterable[index];\n if (predicate(value, index, iterable)) {\n resIndex += 1;\n result[resIndex] = value;\n }\n index += 1;\n }\n return result;\n}\n\n/**\n * A specialized version of `.map` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nexport function arrayMap(array, iteratee) {\n let index = 0;\n let iterable = array;\n if (!Array.isArray(array)) {\n iterable = Array.from(array);\n }\n const length = iterable.length;\n const result = [];\n let resIndex = -1;\n while (index < length) {\n const value = iterable[index];\n resIndex += 1;\n result[resIndex] = iteratee(value, index, iterable);\n index += 1;\n }\n return result;\n}\n\n/**\n * A specialized version of `.forEach` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * {@link https://github.com/lodash/lodash/blob/master/lodash.js}.\n *\n * @param {Array|*} array The array to iterate over or an any element with implemented iterator protocol.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nexport function arrayEach(array, iteratee) {\n let index = 0;\n let iterable = array;\n if (!Array.isArray(array)) {\n iterable = Array.from(array);\n }\n const length = iterable.length;\n while (index < length) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n index += 1;\n }\n return array;\n}\n\n/**\n * Calculate sum value for each item of the array.\n *\n * @param {Array} array The array to process.\n * @returns {number} Returns calculated sum value.\n */\nexport function arraySum(array) {\n return arrayReduce(array, (a, b) => a + b, 0);\n}\n\n/**\n * Returns the highest value from an array. Can be array of numbers or array of strings.\n * NOTICE: Mixed values is not supported.\n *\n * @param {Array} array The array to process.\n * @returns {number} Returns the highest value from an array.\n */\nexport function arrayMax(array) {\n return arrayReduce(array, (a, b) => a > b ? a : b, Array.isArray(array) ? array[0] : undefined);\n}\n\n/**\n * Returns the lowest value from an array. Can be array of numbers or array of strings.\n * NOTICE: Mixed values is not supported.\n *\n * @param {Array} array The array to process.\n * @returns {number} Returns the lowest value from an array.\n */\nexport function arrayMin(array) {\n return arrayReduce(array, (a, b) => a < b ? a : b, Array.isArray(array) ? array[0] : undefined);\n}\n\n/**\n * Calculate average value for each item of the array.\n *\n * @param {Array} array The array to process.\n * @returns {number} Returns calculated average value.\n */\nexport function arrayAvg(array) {\n if (!array.length) {\n return 0;\n }\n return arraySum(array) / array.length;\n}\n\n/**\n * Flatten multidimensional array.\n *\n * @param {Array} array Array of Arrays.\n * @returns {Array}\n */\nexport function arrayFlatten(array) {\n return arrayReduce(array, (initial, value) => initial.concat(Array.isArray(value) ? arrayFlatten(value) : value), []);\n}\n\n/**\n * Unique values in the array.\n *\n * @param {Array} array The array to process.\n * @returns {Array}\n */\nexport function arrayUnique(array) {\n const unique = [];\n arrayEach(array, value => {\n if (unique.indexOf(value) === -1) {\n unique.push(value);\n }\n });\n return unique;\n}\n\n/**\n * Differences from two or more arrays.\n *\n * @param {...Array} arrays Array of strings or array of numbers.\n * @returns {Array} Returns the difference between arrays.\n */\nexport function getDifferenceOfArrays() {\n for (var _len = arguments.length, arrays = new Array(_len), _key = 0; _key < _len; _key++) {\n arrays[_key] = arguments[_key];\n }\n const [first, ...rest] = [...arrays];\n let filteredFirstArray = first;\n arrayEach(rest, array => {\n filteredFirstArray = filteredFirstArray.filter(value => !array.includes(value));\n });\n return filteredFirstArray;\n}\n\n/**\n * Intersection of two or more arrays.\n *\n * @param {...Array} arrays Array of strings or array of numbers.\n * @returns {Array} Returns elements that exists in every array.\n */\nexport function getIntersectionOfArrays() {\n for (var _len2 = arguments.length, arrays = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n arrays[_key2] = arguments[_key2];\n }\n const [first, ...rest] = [...arrays];\n let filteredFirstArray = first;\n arrayEach(rest, array => {\n filteredFirstArray = filteredFirstArray.filter(value => array.includes(value));\n });\n return filteredFirstArray;\n}\n\n/**\n * Union of two or more arrays.\n *\n * @param {...Array} arrays Array of strings or array of numbers.\n * @returns {Array} Returns the elements that exist in any of the arrays, without duplicates.\n */\nexport function getUnionOfArrays() {\n for (var _len3 = arguments.length, arrays = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n arrays[_key3] = arguments[_key3];\n }\n const [first, ...rest] = [...arrays];\n const set = new Set(first);\n arrayEach(rest, array => {\n arrayEach(array, value => {\n if (!set.has(value)) {\n set.add(value);\n }\n });\n });\n return Array.from(set);\n}\n\n/**\n * Convert a separated strings to an array of strings.\n *\n * @param {string} value A string of class name(s).\n * @param {string|RegExp} delimiter The pattern describing where each split should occur.\n * @returns {string[]} Returns array of string or empty array.\n */\nexport function stringToArray(value) {\n let delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' ';\n return value.split(delimiter);\n}","import { arrayReduce } from \"../helpers/array.mjs\";\n/**\n * Tags a multiline string and return new one without line break characters and following spaces.\n *\n * @param {Array} strings Parts of the entire string without expressions.\n * @param {...string} expressions Expressions converted to strings, which are added to the entire string.\n * @returns {string}\n */\nexport function toSingleLine(strings) {\n for (var _len = arguments.length, expressions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n expressions[_key - 1] = arguments[_key];\n }\n const result = arrayReduce(strings, (previousValue, currentValue, index) => {\n const valueWithoutWhiteSpaces = currentValue.replace(/\\r?\\n\\s*/g, '');\n const expressionForIndex = expressions[index] ? expressions[index] : '';\n return previousValue + valueWithoutWhiteSpaces + expressionForIndex;\n }, '');\n return result.trim();\n}","export const A11Y_TABINDEX = val => ['tabindex', val];\nexport const A11Y_TREEGRID = () => ['role', 'treegrid'];\nexport const A11Y_PRESENTATION = () => ['role', 'presentation'];\nexport const A11Y_GRIDCELL = () => ['role', 'gridcell'];\nexport const A11Y_ROWHEADER = () => ['role', 'rowheader'];\nexport const A11Y_ROWGROUP = () => ['role', 'rowgroup'];\nexport const A11Y_COLUMNHEADER = () => ['role', 'columnheader'];\nexport const A11Y_ROW = () => ['role', 'row'];\nexport const A11Y_MENU = () => ['role', 'menu'];\nexport const A11Y_MENU_ITEM = () => ['role', 'menuitem'];\nexport const A11Y_COMBOBOX = () => ['role', 'combobox'];\nexport const A11Y_LISTBOX = () => ['role', 'listbox'];\nexport const A11Y_OPTION = () => ['role', 'option'];\nexport const A11Y_CHECKBOX = () => ['role', 'checkbox'];\nexport const A11Y_SCOPE_COL = () => ['scope', 'col'];\nexport const A11Y_SCOPE_ROW = () => ['scope', 'row'];\nexport const A11Y_TEXT = () => ['type', 'text'];\nexport const A11Y_LABEL = val => ['aria-label', val];\nexport const A11Y_HIDDEN = () => ['aria-hidden', 'true'];\nexport const A11Y_DISABLED = () => ['aria-disabled', 'true'];\nexport const A11Y_MULTISELECTABLE = () => ['aria-multiselectable', 'true'];\nexport const A11Y_HASPOPUP = val => ['aria-haspopup', val];\nexport const A11Y_ROWCOUNT = val => ['aria-rowcount', val];\nexport const A11Y_COLCOUNT = val => ['aria-colcount', val];\nexport const A11Y_ROWINDEX = val => ['aria-rowindex', val];\nexport const A11Y_COLINDEX = val => ['aria-colindex', val];\nexport const A11Y_EXPANDED = val => ['aria-expanded', val];\nexport const A11Y_SORT = val => ['aria-sort', val];\nexport const A11Y_READONLY = () => ['aria-readonly', 'true'];\nexport const A11Y_INVALID = () => ['aria-invalid', 'true'];\nexport const A11Y_CHECKED = val => ['aria-checked', val];\nexport const A11Y_SELECTED = () => ['aria-selected', 'true'];\nexport const A11Y_AUTOCOMPLETE = () => ['aria-autocomplete', 'list'];\nexport const A11Y_CONTROLS = val => ['aria-controls', val];\nexport const A11Y_ACTIVEDESCENDANT = val => ['aria-activedescendant', val];\nexport const A11Y_LIVE = val => ['aria-live', val];\nexport const A11Y_RELEVANT = val => ['aria-relevant', val];\nexport const A11Y_SETSIZE = val => ['aria-setsize', val];\nexport const A11Y_POSINSET = val => ['aria-posinset', val];","import { arrayReduce } from \"./array.mjs\";\nimport { isDefined } from \"./mixed.mjs\";\n/**\n * Checks if given variable is function.\n *\n * @param {*} func Variable to check.\n * @returns {boolean}\n */\nexport function isFunction(func) {\n return typeof func === 'function';\n}\n\n/**\n * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over time (`wait`).\n *\n * @param {Function} func Function to invoke.\n * @param {number} wait Delay in miliseconds.\n * @returns {Function}\n */\nexport function throttle(func) {\n let wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n let lastCalled = 0;\n const result = {\n lastCallThrottled: true\n };\n let lastTimer = null;\n\n /**\n * @param {...*} args The list of arguments passed during the function invocation.\n * @returns {object}\n */\n function _throttle() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n const stamp = Date.now();\n let needCall = false;\n result.lastCallThrottled = true;\n if (!lastCalled) {\n lastCalled = stamp;\n needCall = true;\n }\n const remaining = wait - (stamp - lastCalled);\n if (needCall) {\n result.lastCallThrottled = false;\n func.apply(this, args);\n } else {\n if (lastTimer) {\n clearTimeout(lastTimer);\n }\n lastTimer = setTimeout(() => {\n result.lastCallThrottled = false;\n func.apply(this, args);\n lastCalled = 0;\n lastTimer = undefined;\n }, remaining);\n }\n return result;\n }\n return _throttle;\n}\n\n/**\n * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over\n * time (`wait`) after specified hits.\n *\n * @param {Function} func Function to invoke.\n * @param {number} wait Delay in miliseconds.\n * @param {number} hits Number of hits after throttling will be applied.\n * @returns {Function}\n */\nexport function throttleAfterHits(func) {\n let wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n let hits = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;\n const funcThrottle = throttle(func, wait);\n let remainHits = hits;\n\n /**\n *\n */\n function _clearHits() {\n remainHits = hits;\n }\n /**\n * @param {*} args The list of arguments passed during the function invocation.\n * @returns {*}\n */\n function _throttleAfterHits() {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n if (remainHits) {\n remainHits -= 1;\n return func.apply(this, args);\n }\n return funcThrottle.apply(this, args);\n }\n _throttleAfterHits.clearHits = _clearHits;\n return _throttleAfterHits;\n}\n\n/**\n * Creates debounce function that enforces a function (`func`) not be called again until a certain amount of time (`wait`)\n * has passed without it being called.\n *\n * @param {Function} func Function to invoke.\n * @param {number} wait Delay in milliseconds.\n * @returns {Function}\n */\nexport function debounce(func) {\n let wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n let lastTimer = null;\n let result;\n\n /**\n * @param {*} args The list of arguments passed during the function invocation.\n * @returns {*}\n */\n function _debounce() {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n if (lastTimer) {\n clearTimeout(lastTimer);\n }\n lastTimer = setTimeout(() => {\n result = func.apply(this, args);\n }, wait);\n return result;\n }\n return _debounce;\n}\n\n/**\n * Creates the function that returns the result of calling the given functions. Result of the first function is passed to\n * the second as an argument and so on. Only first function in the chain can handle multiple arguments.\n *\n * @param {Function} functions Functions to compose.\n * @returns {Function}\n */\nexport function pipe() {\n for (var _len4 = arguments.length, functions = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n functions[_key4] = arguments[_key4];\n }\n const [firstFunc, ...restFunc] = functions;\n return function _pipe() {\n for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {\n args[_key5] = arguments[_key5];\n }\n return arrayReduce(restFunc, (acc, fn) => fn(acc), firstFunc.apply(this, args));\n };\n}\n\n/**\n * Creates the function that returns the function with cached arguments.\n *\n * @param {Function} func Function to partialization.\n * @param {Array} params Function arguments to cache.\n * @returns {Function}\n */\nexport function partial(func) {\n for (var _len6 = arguments.length, params = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {\n params[_key6 - 1] = arguments[_key6];\n }\n return function _partial() {\n for (var _len7 = arguments.length, restParams = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {\n restParams[_key7] = arguments[_key7];\n }\n return func.apply(this, params.concat(restParams));\n };\n}\n\n/**\n * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched\n * to the arguments defined in `func` then function will be invoked.\n * Arguments are added to the stack in direction from the left to the right.\n *\n * @example\n * ```\n * var replace = curry(function(find, replace, string) {\n * return string.replace(find, replace);\n * });\n *\n * // returns function with bounded first argument\n * var replace = replace('foo')\n *\n * // returns replaced string - all arguments was passed so function was invoked\n * replace('bar', 'Some test with foo...');\n *\n * ```\n *\n * @param {Function} func Function to currying.\n * @returns {Function}\n */\nexport function curry(func) {\n const argsLength = func.length;\n\n /**\n * @param {*} argsSoFar The list of arguments passed during the function invocation.\n * @returns {Function}\n */\n function given(argsSoFar) {\n return function _curry() {\n for (var _len8 = arguments.length, params = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {\n params[_key8] = arguments[_key8];\n }\n const passedArgsSoFar = argsSoFar.concat(params);\n let result;\n if (passedArgsSoFar.length >= argsLength) {\n result = func.apply(this, passedArgsSoFar);\n } else {\n result = given(passedArgsSoFar);\n }\n return result;\n };\n }\n return given([]);\n}\n\n/**\n * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched\n * to the arguments defined in `func` then function will be invoked.\n * Arguments are added to the stack in direction from the right to the left.\n *\n * @example\n * ```\n * var replace = curry(function(find, replace, string) {\n * return string.replace(find, replace);\n * });\n *\n * // returns function with bounded first argument\n * var replace = replace('Some test with foo...')\n *\n * // returns replaced string - all arguments was passed so function was invoked\n * replace('bar', 'foo');\n *\n * ```\n *\n * @param {Function} func Function to currying.\n * @returns {Function}\n */\nexport function curryRight(func) {\n const argsLength = func.length;\n\n /**\n * @param {*} argsSoFar The list of arguments passed during the function invocation.\n * @returns {Function}\n */\n function given(argsSoFar) {\n return function _curry() {\n for (var _len9 = arguments.length, params = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {\n params[_key9] = arguments[_key9];\n }\n const passedArgsSoFar = argsSoFar.concat(params.reverse());\n let result;\n if (passedArgsSoFar.length >= argsLength) {\n result = func.apply(this, passedArgsSoFar);\n } else {\n result = given(passedArgsSoFar);\n }\n return result;\n };\n }\n return given([]);\n}\n\n/**\n * Calls a function in the quickest way available.\n *\n * In contrast to the `apply()` method that passes arguments as an array,\n * the `call()` method passes arguments directly, to avoid garbage collection costs.\n *\n * @param {Function} func The function to call.\n * @param {*} context The value to use as `this` when calling the `func` function.\n * @param {*} [arg1] An argument passed to the `func` function.\n * @param {*} [arg2] An argument passed to `func` function.\n * @param {*} [arg3] An argument passed to `func` function.\n * @param {*} [arg4] An argument passed to `func` function.\n * @param {*} [arg5] An argument passed to `func` function.\n * @param {*} [arg6] An argument passed to `func` function.\n * @returns {*}\n */\nexport function fastCall(func, context, arg1, arg2, arg3, arg4, arg5, arg6) {\n if (isDefined(arg6)) {\n return func.call(context, arg1, arg2, arg3, arg4, arg5, arg6);\n } else if (isDefined(arg5)) {\n return func.call(context, arg1, arg2, arg3, arg4, arg5);\n } else if (isDefined(arg4)) {\n return func.call(context, arg1, arg2, arg3, arg4);\n } else if (isDefined(arg3)) {\n return func.call(context, arg1, arg2, arg3);\n } else if (isDefined(arg2)) {\n return func.call(context, arg1, arg2);\n } else if (isDefined(arg1)) {\n return func.call(context, arg1);\n }\n return func.call(context);\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/es.json.stringify.js\";\nimport { arrayEach } from \"./array.mjs\";\n/**\n * Generate schema for passed object.\n *\n * @param {Array|object} object An object to analyze.\n * @returns {Array|object}\n */\nexport function duckSchema(object) {\n let schema;\n if (Array.isArray(object)) {\n schema = object.length ? new Array(object.length).fill(null) : [];\n } else {\n schema = {};\n objectEach(object, (value, key) => {\n if (key === '__children') {\n return;\n }\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n schema[key] = duckSchema(value);\n } else if (Array.isArray(value)) {\n if (value.length && typeof value[0] === 'object' && !Array.isArray(value[0])) {\n schema[key] = [duckSchema(value[0])];\n } else {\n schema[key] = [];\n }\n } else {\n schema[key] = null;\n }\n });\n }\n return schema;\n}\n\n/**\n * Inherit without without calling parent constructor, and setting `Child.prototype.constructor` to `Child` instead of `Parent`.\n * Creates temporary dummy function to call it as constructor.\n * Described in ticket: https://github.com/handsontable/handsontable/pull/516.\n *\n * @param {object} Child The child class.\n * @param {object} Parent The parent class.\n * @returns {object}\n */\nexport function inherit(Child, Parent) {\n Parent.prototype.constructor = Parent;\n Child.prototype = new Parent();\n Child.prototype.constructor = Child;\n return Child;\n}\n\n/**\n * Perform shallow extend of a target object with extension's own properties.\n *\n * @param {object} target An object that will receive the new properties.\n * @param {object} extension An object containing additional properties to merge into the target.\n * @param {string[]} [writableKeys] An array of keys that are writable to target object.\n * @returns {object}\n */\nexport function extend(target, extension, writableKeys) {\n const hasWritableKeys = Array.isArray(writableKeys);\n objectEach(extension, (value, key) => {\n if (hasWritableKeys === false || writableKeys.includes(key)) {\n target[key] = value;\n }\n });\n return target;\n}\n\n/**\n * Perform deep extend of a target object with extension's own properties.\n *\n * @param {object} target An object that will receive the new properties.\n * @param {object} extension An object containing additional properties to merge into the target.\n */\nexport function deepExtend(target, extension) {\n objectEach(extension, (value, key) => {\n if (extension[key] && typeof extension[key] === 'object') {\n if (!target[key]) {\n if (Array.isArray(extension[key])) {\n target[key] = [];\n } else if (Object.prototype.toString.call(extension[key]) === '[object Date]') {\n target[key] = extension[key];\n } else {\n target[key] = {};\n }\n }\n deepExtend(target[key], extension[key]);\n } else {\n target[key] = extension[key];\n }\n });\n}\n\n/**\n * Perform deep clone of an object.\n * WARNING! Only clones JSON properties. Will cause error when `obj` contains a function, Date, etc.\n *\n * @param {object} obj An object that will be cloned.\n * @returns {object}\n */\nexport function deepClone(obj) {\n if (typeof obj === 'object') {\n return JSON.parse(JSON.stringify(obj));\n }\n return obj;\n}\n\n/**\n * Shallow clone object.\n *\n * @param {object} object An object to clone.\n * @returns {object}\n */\nexport function clone(object) {\n const result = {};\n objectEach(object, (value, key) => {\n result[key] = value;\n });\n return result;\n}\n\n/**\n * Extend the Base object (usually prototype) of the functionality the `mixins` objects.\n *\n * @param {object} Base Base object which will be extended.\n * @param {object} mixins The object of the functionality will be \"copied\".\n * @returns {object}\n */\nexport function mixin(Base) {\n if (!Base.MIXINS) {\n Base.MIXINS = [];\n }\n for (var _len = arguments.length, mixins = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n mixins[_key - 1] = arguments[_key];\n }\n arrayEach(mixins, mixinItem => {\n Base.MIXINS.push(mixinItem.MIXIN_NAME);\n objectEach(mixinItem, (value, key) => {\n if (Base.prototype[key] !== undefined) {\n throw new Error(`Mixin conflict. Property '${key}' already exist and cannot be overwritten.`);\n }\n if (typeof value === 'function') {\n Base.prototype[key] = value;\n } else {\n const getter = function _getter(property, initialValue) {\n const propertyName = `_${property}`;\n const initValue = newValue => {\n let result = newValue;\n if (Array.isArray(result) || isObject(result)) {\n result = deepClone(result);\n }\n return result;\n };\n return function () {\n if (this[propertyName] === undefined) {\n this[propertyName] = initValue(initialValue);\n }\n return this[propertyName];\n };\n };\n const setter = function _setter(property) {\n const propertyName = `_${property}`;\n return function (newValue) {\n this[propertyName] = newValue;\n };\n };\n Object.defineProperty(Base.prototype, key, {\n get: getter(key, value),\n set: setter(key),\n configurable: true\n });\n }\n });\n });\n return Base;\n}\n\n/**\n * Checks if two objects or arrays are (deep) equal.\n *\n * @param {object|Array} object1 The first object to compare.\n * @param {object|Array} object2 The second object to compare.\n * @returns {boolean}\n */\nexport function isObjectEqual(object1, object2) {\n return JSON.stringify(object1) === JSON.stringify(object2);\n}\n\n/**\n * Determines whether given object is a plain Object.\n * Note: String and Array are not plain Objects.\n *\n * @param {*} object An object to check.\n * @returns {boolean}\n */\nexport function isObject(object) {\n return Object.prototype.toString.call(object) === '[object Object]';\n}\n\n/**\n * @param {object} object The object on which to define the property.\n * @param {string} property The name of the property to be defined or modified.\n * @param {*} value The value associated with the property.\n * @param {object} options The descriptor for the property being defined or modified.\n */\nexport function defineGetter(object, property, value, options) {\n options.value = value;\n options.writable = options.writable !== false;\n options.enumerable = options.enumerable !== false;\n options.configurable = options.configurable !== false;\n Object.defineProperty(object, property, options);\n}\n\n/**\n * A specialized version of `.forEach` for objects.\n *\n * @param {object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {object} Returns `object`.\n */\nexport function objectEach(object, iteratee) {\n // eslint-disable-next-line no-restricted-syntax\n for (const key in object) {\n if (!object.hasOwnProperty || object.hasOwnProperty && Object.prototype.hasOwnProperty.call(object, key)) {\n if (iteratee(object[key], key, object) === false) {\n break;\n }\n }\n }\n return object;\n}\n\n/**\n * Get object property by its name. Access to sub properties can be achieved by dot notation (e.q. `'foo.bar.baz'`).\n *\n * @param {object} object Object which value will be exported.\n * @param {string} name Object property name.\n * @returns {*}\n */\nexport function getProperty(object, name) {\n const names = name.split('.');\n let result = object;\n objectEach(names, nameItem => {\n result = result[nameItem];\n if (result === undefined) {\n result = undefined;\n return false;\n }\n });\n return result;\n}\n\n/**\n * Set a property value on the provided object. Works on nested object prop names as well (e.g. `first.name`).\n *\n * @param {object} object Object to work on.\n * @param {string} name Prop name.\n * @param {*} value Value to be assigned at the provided property.\n */\nexport function setProperty(object, name, value) {\n const names = name.split('.');\n let workingObject = object;\n names.forEach((propName, index) => {\n if (index !== names.length - 1) {\n if (!hasOwnProperty(workingObject, propName)) {\n workingObject[propName] = {};\n }\n workingObject = workingObject[propName];\n } else {\n workingObject[propName] = value;\n }\n });\n}\n\n/**\n * Return object length (recursively).\n *\n * @param {*} object Object for which we want get length.\n * @returns {number}\n */\nexport function deepObjectSize(object) {\n if (!isObject(object)) {\n return 0;\n }\n const recursObjLen = function (obj) {\n let result = 0;\n if (isObject(obj)) {\n objectEach(obj, (value, key) => {\n if (key === '__children') {\n return;\n }\n result += recursObjLen(value);\n });\n } else {\n result += 1;\n }\n return result;\n };\n return recursObjLen(object);\n}\n\n/**\n * Create object with property where its value change will be observed.\n *\n * @param {*} [defaultValue=undefined] Default value.\n * @param {string} [propertyToListen='value'] Property to listen.\n * @returns {object}\n */\nexport function createObjectPropListener(defaultValue) {\n let propertyToListen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'value';\n const privateProperty = `_${propertyToListen}`;\n const holder = {\n _touched: false,\n [privateProperty]: defaultValue,\n isTouched() {\n return this._touched;\n }\n };\n Object.defineProperty(holder, propertyToListen, {\n get() {\n return this[privateProperty];\n },\n set(value) {\n this._touched = true;\n this[privateProperty] = value;\n },\n enumerable: true,\n configurable: true\n });\n return holder;\n}\n\n/**\n * Check if at specified `key` there is any value for `object`.\n *\n * @param {object} object Object to search value at specific key.\n * @param {string} key String key to check.\n * @returns {boolean}\n */\nexport function hasOwnProperty(object, key) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}","/* eslint-disable no-restricted-globals */\n/**\n * Polyfill for requestAnimationFrame.\n *\n * @param {Function} callback The function to call when it's time.\n * @returns {number}\n */\nexport function requestAnimationFrame(callback) {\n return window.requestAnimationFrame(callback);\n}\n\n/**\n * Polyfill for cancelAnimationFrame.\n *\n * @param {number} id The request Id, generated by `requestAnimationFrame`.\n */\nexport function cancelAnimationFrame(id) {\n window.cancelAnimationFrame(id);\n}\n\n/**\n * @returns {boolean}\n */\nexport function isTouchSupported() {\n return 'ontouchstart' in window;\n}\n\n/**\n * Checks if the environment that the code runs in is a browser.\n *\n * @returns {boolean}\n */\nexport function isCSR() {\n return typeof window !== 'undefined';\n}\nlet comparisonFunction;\n\n/**\n * Get string comparison function for sorting purposes. It supports multilingual string comparison base on Internationalization API.\n *\n * @param {string} [language] The language code used for phrases sorting.\n * @param {object} [options] Additional options for sort comparator.\n * @returns {*}\n */\nexport function getComparisonFunction(language) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (comparisonFunction) {\n return comparisonFunction;\n }\n if (typeof Intl === 'object') {\n comparisonFunction = new Intl.Collator(language, options).compare;\n } else if (typeof String.prototype.localeCompare === 'function') {\n comparisonFunction = (a, b) => `${a}`.localeCompare(b);\n } else {\n comparisonFunction = (a, b) => {\n if (a === b) {\n return 0;\n }\n return a > b ? -1 : 1;\n };\n }\n return comparisonFunction;\n}","import { objectEach } from \"./object.mjs\";\nimport { isCSR } from \"./feature.mjs\";\nconst tester = testerFunc => {\n const result = {\n value: false\n };\n result.test = (ua, vendor) => {\n result.value = testerFunc(ua, vendor);\n };\n return result;\n};\nconst browsers = {\n chrome: tester((ua, vendor) => /Chrome/.test(ua) && /Google/.test(vendor)),\n chromeWebKit: tester(ua => /CriOS/.test(ua)),\n edge: tester(ua => /Edge/.test(ua)),\n edgeWebKit: tester(ua => /EdgiOS/.test(ua)),\n firefox: tester(ua => /Firefox/.test(ua)),\n firefoxWebKit: tester(ua => /FxiOS/.test(ua)),\n mobile: tester(ua => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua)),\n safari: tester((ua, vendor) => /Safari/.test(ua) && /Apple Computer/.test(vendor))\n};\nconst platforms = {\n mac: tester(platform => /^Mac/.test(platform)),\n win: tester(platform => /^Win/.test(platform)),\n linux: tester(platform => /^Linux/.test(platform)),\n ios: tester(ua => /iPhone|iPad|iPod/i.test(ua))\n};\n\n/**\n * @param {object} [metaObject] The browser identity collection.\n * @param {object} [metaObject.userAgent] The user agent reported by browser.\n * @param {object} [metaObject.vendor] The vendor name reported by browser.\n */\nexport function setBrowserMeta() {\n let {\n userAgent = navigator.userAgent,\n vendor = navigator.vendor\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n objectEach(browsers, _ref => {\n let {\n test\n } = _ref;\n return void test(userAgent, vendor);\n });\n}\n\n/**\n * @param {object} [metaObject] The platform identity collection.\n * @param {object} [metaObject.platform] The platform ID.\n */\nexport function setPlatformMeta() {\n let {\n platform = navigator.platform\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n objectEach(platforms, _ref2 => {\n let {\n test\n } = _ref2;\n return void test(platform);\n });\n}\nif (isCSR()) {\n setBrowserMeta();\n setPlatformMeta();\n}\n\n/**\n * @returns {boolean}\n */\nexport function isChrome() {\n return browsers.chrome.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isChromeWebKit() {\n return browsers.chromeWebKit.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isFirefox() {\n return browsers.firefox.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isFirefoxWebKit() {\n return browsers.firefoxWebKit.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isSafari() {\n return browsers.safari.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isEdge() {\n return browsers.edge.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isEdgeWebKit() {\n return browsers.edgeWebKit.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isMobileBrowser() {\n return browsers.mobile.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isIOS() {\n return platforms.ios.value;\n}\n\n/**\n * A hacky way to recognize the iPad. Since iOS 13, the iPad on Safari mimics macOS behavior and user agent.\n *\n * @see {@https://stackoverflow.com/a/57838385}\n * @param {object} [metaObject] The browser identity collection.\n * @param {number} [metaObject.maxTouchPoints] The maximum number of simultanous touch points.\n * @returns {boolean}\n */\nexport function isIpadOS() {\n let {\n maxTouchPoints\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : navigator;\n return maxTouchPoints > 2 && platforms.mac.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isWindowsOS() {\n return platforms.win.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isMacOS() {\n return platforms.mac.value;\n}\n\n/**\n * @returns {boolean}\n */\nexport function isLinuxOS() {\n return platforms.linux.value;\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { isFunctionKey, isCtrlMetaKey } from \"./helpers/unicode.mjs\";\nimport { isImmediatePropagationStopped } from \"./helpers/dom/event.mjs\";\nimport { getEditorInstance } from \"./editors/registry.mjs\";\nimport EventManager from \"./eventManager.mjs\";\nvar _EditorManager_brand = /*#__PURE__*/new WeakSet();\nclass EditorManager {\n /**\n * @param {Core} hotInstance The Handsontable instance.\n * @param {TableMeta} tableMeta The table meta instance.\n * @param {Selection} selection The selection instance.\n */\n constructor(hotInstance, tableMeta, _selection) {\n /**\n * OnAfterDocumentKeyDown callback.\n *\n * @param {KeyboardEvent} event The keyboard event object.\n */\n _classPrivateMethodInitSpec(this, _EditorManager_brand);\n /**\n * Instance of {@link Handsontable}.\n *\n * @private\n * @type {Handsontable}\n */\n _defineProperty(this, \"hot\", void 0);\n /**\n * Reference to an instance's private GridSettings object.\n *\n * @private\n * @type {GridSettings}\n */\n _defineProperty(this, \"tableMeta\", void 0);\n /**\n * Instance of {@link Selection}.\n *\n * @private\n * @type {Selection}\n */\n _defineProperty(this, \"selection\", void 0);\n /**\n * Instance of {@link EventManager}.\n *\n * @private\n * @type {EventManager}\n */\n _defineProperty(this, \"eventManager\", void 0);\n /**\n * Determines if EditorManager is destroyed.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"destroyed\", false);\n /**\n * A reference to an instance of the activeEditor.\n *\n * @private\n * @type {BaseEditor}\n */\n _defineProperty(this, \"activeEditor\", void 0);\n /**\n * Keeps a reference to the cell's properties object.\n *\n * @type {object}\n */\n _defineProperty(this, \"cellProperties\", void 0);\n this.hot = hotInstance;\n this.tableMeta = tableMeta;\n this.selection = _selection;\n this.eventManager = new EventManager(hotInstance);\n this.hot.addHook('afterDocumentKeyDown', event => _assertClassBrand(_EditorManager_brand, this, _onAfterDocumentKeyDown).call(this, event));\n\n // Open editor when text composition is started (IME editor)\n this.eventManager.addEventListener(this.hot.rootDocument.documentElement, 'compositionstart', event => {\n if (!this.destroyed && this.hot.isListening()) {\n this.openEditor('', event);\n }\n });\n this.hot.view._wt.update('onCellDblClick', (event, coords, elem) => _assertClassBrand(_EditorManager_brand, this, _onCellDblClick).call(this, event, coords, elem));\n }\n\n /**\n * Get active editor.\n *\n * @returns {BaseEditor}\n */\n getActiveEditor() {\n return this.activeEditor;\n }\n\n /**\n * Prepare text input to be displayed at given grid cell.\n */\n prepareEditor() {\n var _this$hot$getSelected;\n if (this.activeEditor && this.activeEditor.isWaiting()) {\n this.closeEditor(false, false, dataSaved => {\n if (dataSaved) {\n this.prepareEditor();\n }\n });\n return;\n }\n const highlight = (_this$hot$getSelected = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected === void 0 ? void 0 : _this$hot$getSelected.highlight;\n if (!highlight || highlight.isHeader()) {\n return;\n }\n const {\n row,\n col\n } = highlight;\n const modifiedCellCoords = this.hot.runHooks('modifyGetCellCoords', row, col);\n let visualRowToCheck = row;\n let visualColumnToCheck = col;\n if (Array.isArray(modifiedCellCoords)) {\n [visualRowToCheck, visualColumnToCheck] = modifiedCellCoords;\n }\n\n // Getting values using the modified coordinates.\n this.cellProperties = this.hot.getCellMeta(visualRowToCheck, visualColumnToCheck);\n if (!this.isCellEditable()) {\n this.clearActiveEditor();\n return;\n }\n const td = this.hot.getCell(row, col, true);\n\n // Skip the preparation when the cell is not rendered in the DOM. The cell is scrolled out of\n // the table's viewport.\n if (td) {\n const editorClass = this.hot.getCellEditor(this.cellProperties);\n const prop = this.hot.colToProp(visualColumnToCheck);\n const originalValue = this.hot.getSourceDataAtCell(this.hot.toPhysicalRow(visualRowToCheck), visualColumnToCheck);\n this.activeEditor = getEditorInstance(editorClass, this.hot);\n // Using not modified coordinates, as we need to get the table element using selection coordinates.\n // There is an extra translation in the editor for saving value.\n this.activeEditor.prepare(row, col, prop, td, originalValue, this.cellProperties);\n }\n }\n\n /**\n * Check is editor is opened/showed.\n *\n * @returns {boolean}\n */\n isEditorOpened() {\n return this.activeEditor && this.activeEditor.isOpened();\n }\n\n /**\n * Open editor with initial value.\n *\n * @param {null|string} newInitialValue New value from which editor will start if handled property it's not the `null`.\n * @param {Event} event The event object.\n * @param {boolean} [enableFullEditMode=false] When true, an editor works in full editing mode. Mode disallows closing an editor\n * when arrow keys are pressed.\n */\n openEditor(newInitialValue, event) {\n let enableFullEditMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n if (!this.isCellEditable()) {\n this.clearActiveEditor();\n return;\n }\n const selection = this.hot.getSelectedRangeLast();\n let allowOpening = this.hot.runHooks('beforeBeginEditing', selection.highlight.row, selection.highlight.col, newInitialValue, event, enableFullEditMode);\n\n // If the above hook does not return boolean apply default behavior which disallows opening\n // an editor after double mouse click for non-contiguous selection (while pressing Ctrl/Cmd) and\n // for multiple selected cells (while pressing SHIFT).\n if (event instanceof MouseEvent && typeof allowOpening !== 'boolean') {\n allowOpening = this.hot.selection.getLayerLevel() === 0 && selection.isSingle();\n }\n if (allowOpening === false) {\n this.clearActiveEditor();\n return;\n }\n if (!this.activeEditor) {\n this.hot.scrollToFocusedCell();\n this.prepareEditor();\n }\n if (this.activeEditor) {\n if (enableFullEditMode) {\n this.activeEditor.enableFullEditMode();\n }\n this.activeEditor.beginEditing(newInitialValue, event);\n }\n }\n\n /**\n * Close editor, finish editing cell.\n *\n * @param {boolean} restoreOriginalValue If `true`, then closes editor without saving value from the editor into a cell.\n * @param {boolean} isCtrlPressed If `true`, then editor will save value to each cell in the last selected range.\n * @param {Function} callback The callback function, fired after editor closing.\n */\n closeEditor(restoreOriginalValue, isCtrlPressed, callback) {\n if (this.activeEditor) {\n this.activeEditor.finishEditing(restoreOriginalValue, isCtrlPressed, callback);\n } else if (callback) {\n callback(false);\n }\n }\n\n /**\n * Close editor and save changes.\n *\n * @param {boolean} isCtrlPressed If `true`, then editor will save value to each cell in the last selected range.\n */\n closeEditorAndSaveChanges(isCtrlPressed) {\n this.closeEditor(false, isCtrlPressed);\n }\n\n /**\n * Close editor and restore original value.\n *\n * @param {boolean} isCtrlPressed Indication of whether the CTRL button is pressed.\n */\n closeEditorAndRestoreOriginalValue(isCtrlPressed) {\n this.closeEditor(true, isCtrlPressed);\n }\n\n /**\n * Clears reference to an instance of the active editor.\n *\n * @private\n */\n clearActiveEditor() {\n this.activeEditor = undefined;\n }\n\n /**\n * Checks if the currently selected cell (pointed by selection highlight coords) is editable.\n * Editable cell is when:\n * - the cell has defined an editor type;\n * - the cell is not marked as read-only;\n * - the cell is not hidden.\n *\n * @private\n * @returns {boolean}\n */\n isCellEditable() {\n const selection = this.hot.getSelectedRangeLast();\n if (!selection) {\n return false;\n }\n const editorClass = this.hot.getCellEditor(this.cellProperties);\n const {\n row,\n col\n } = selection.highlight;\n const {\n rowIndexMapper,\n columnIndexMapper\n } = this.hot;\n const isCellHidden = rowIndexMapper.isHidden(this.hot.toPhysicalRow(row)) || columnIndexMapper.isHidden(this.hot.toPhysicalColumn(col));\n if (this.cellProperties.readOnly || !editorClass || isCellHidden) {\n return false;\n }\n return true;\n }\n\n /**\n * Controls selection's behavior after clicking `Enter`.\n *\n * @private\n * @param {KeyboardEvent} event The keyboard event object.\n */\n moveSelectionAfterEnter(event) {\n const enterMoves = {\n ...(typeof this.tableMeta.enterMoves === 'function' ? this.tableMeta.enterMoves(event) : this.tableMeta.enterMoves)\n };\n if (event.shiftKey) {\n enterMoves.row = -enterMoves.row;\n enterMoves.col = -enterMoves.col;\n }\n if (this.hot.selection.isMultiple()) {\n this.selection.transformFocus(enterMoves.row, enterMoves.col);\n } else {\n this.selection.transformStart(enterMoves.row, enterMoves.col, true);\n }\n }\n /**\n * Destroy the instance.\n */\n destroy() {\n this.destroyed = true;\n this.eventManager.destroy();\n }\n}\nfunction _onAfterDocumentKeyDown(event) {\n const selection = this.hot.getSelectedRangeLast();\n if (!this.hot.isListening() || !selection || selection.highlight.isHeader() || isImmediatePropagationStopped(event)) {\n return;\n }\n const {\n keyCode\n } = event;\n\n // catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)\n const isCtrlPressed = (event.ctrlKey || event.metaKey) && !event.altKey;\n if (!this.activeEditor || this.activeEditor && !this.activeEditor.isWaiting()) {\n if (!isFunctionKey(keyCode) && !isCtrlMetaKey(keyCode) && !isCtrlPressed && !this.isEditorOpened()) {\n this.openEditor('', event);\n }\n }\n}\n/**\n * OnCellDblClick callback.\n *\n * @param {MouseEvent} event The mouse event object.\n * @param {object} coords The cell coordinates.\n */\nfunction _onCellDblClick(event, coords) {\n if (coords.isCell()) {\n this.openEditor(null, event, true);\n }\n}\nconst instances = new WeakMap();\n\n/**\n * @param {Core} hotInstance The Handsontable instance.\n * @param {TableMeta} tableMeta The table meta class instance.\n * @param {Selection} selection The selection instance.\n * @returns {EditorManager}\n */\nEditorManager.getInstance = function (hotInstance, tableMeta, selection) {\n let editorManager = instances.get(hotInstance);\n if (!editorManager) {\n editorManager = new EditorManager(hotInstance, tableMeta, selection);\n instances.set(hotInstance, editorManager);\n }\n return editorManager;\n};\nexport default EditorManager;","import \"core-js/modules/es.array.push.js\";\nimport { arrayEach } from \"./array.mjs\";\nimport { isMacOS, isFirefox } from \"./browser.mjs\";\nexport const KEY_CODES = {\n ALT: 18,\n ARROW_DOWN: 40,\n ARROW_LEFT: 37,\n ARROW_RIGHT: 39,\n ARROW_UP: 38,\n AUDIO_DOWN: isFirefox() ? 182 : 174,\n AUDIO_MUTE: isFirefox() ? 181 : 173,\n AUDIO_UP: isFirefox() ? 183 : 175,\n BACKSPACE: 8,\n CAPS_LOCK: 20,\n COMMA: 188,\n COMMAND_LEFT: 91,\n COMMAND_RIGHT: 93,\n COMMAND_FIREFOX: 224,\n CONTROL: 17,\n DELETE: 46,\n END: 35,\n ENTER: 13,\n ESCAPE: 27,\n F1: 112,\n F2: 113,\n F3: 114,\n F4: 115,\n F5: 116,\n F6: 117,\n F7: 118,\n F8: 119,\n F9: 120,\n F10: 121,\n F11: 122,\n F12: 123,\n F13: 124,\n F14: 125,\n F15: 126,\n F16: 127,\n F17: 128,\n F18: 129,\n F19: 130,\n HOME: 36,\n INSERT: 45,\n MEDIA_NEXT: 176,\n MEDIA_PLAY_PAUSE: 179,\n MEDIA_PREV: 177,\n MEDIA_STOP: 178,\n NULL: 0,\n NUM_LOCK: 144,\n PAGE_DOWN: 34,\n PAGE_UP: 33,\n PAUSE: 19,\n PERIOD: 190,\n SCROLL_LOCK: 145,\n SHIFT: 16,\n SPACE: 32,\n TAB: 9,\n A: 65,\n C: 67,\n D: 68,\n F: 70,\n L: 76,\n O: 79,\n P: 80,\n S: 83,\n V: 86,\n X: 88,\n Y: 89,\n Z: 90\n};\nconst FUNCTION_KEYS = [KEY_CODES.ALT, KEY_CODES.ARROW_DOWN, KEY_CODES.ARROW_LEFT, KEY_CODES.ARROW_RIGHT, KEY_CODES.ARROW_UP, KEY_CODES.AUDIO_DOWN, KEY_CODES.AUDIO_MUTE, KEY_CODES.AUDIO_UP, KEY_CODES.BACKSPACE, KEY_CODES.CAPS_LOCK, KEY_CODES.DELETE, KEY_CODES.END, KEY_CODES.ENTER, KEY_CODES.ESCAPE, KEY_CODES.F1, KEY_CODES.F2, KEY_CODES.F3, KEY_CODES.F4, KEY_CODES.F5, KEY_CODES.F6, KEY_CODES.F7, KEY_CODES.F8, KEY_CODES.F9, KEY_CODES.F10, KEY_CODES.F11, KEY_CODES.F12, KEY_CODES.F13, KEY_CODES.F14, KEY_CODES.F15, KEY_CODES.F16, KEY_CODES.F17, KEY_CODES.F18, KEY_CODES.F19, KEY_CODES.HOME, KEY_CODES.INSERT, KEY_CODES.MEDIA_NEXT, KEY_CODES.MEDIA_PLAY_PAUSE, KEY_CODES.MEDIA_PREV, KEY_CODES.MEDIA_STOP, KEY_CODES.NULL, KEY_CODES.NUM_LOCK, KEY_CODES.PAGE_DOWN, KEY_CODES.PAGE_UP, KEY_CODES.PAUSE, KEY_CODES.SCROLL_LOCK, KEY_CODES.SHIFT, KEY_CODES.TAB];\n\n/**\n * Returns true if keyCode represents a printable character.\n *\n * @param {number} keyCode The keyboard key code.\n * @returns {boolean}\n */\nexport function isPrintableChar(keyCode) {\n return keyCode === 32 ||\n // space\n keyCode >= 48 && keyCode <= 57 ||\n // 0-9\n keyCode >= 96 && keyCode <= 111 ||\n // numpad\n keyCode >= 186 && keyCode <= 192 ||\n // ;=,-./`\n keyCode >= 219 && keyCode <= 222 ||\n // []{}\\|\"'\n keyCode >= 226 ||\n // special chars (229 for Asian chars)\n keyCode >= 65 && keyCode <= 90; // a-z\n}\n\n/**\n * @param {number} keyCode The keyboard key code.\n * @returns {boolean}\n */\nexport function isFunctionKey(keyCode) {\n return FUNCTION_KEYS.includes(keyCode);\n}\n\n/**\n * Checks if passed key code is ctrl or cmd key. Depends on what OS the code runs it check key code based on\n * different meta key codes.\n *\n * @param {number} keyCode The keyboard key code.\n * @returns {boolean}\n */\nexport function isCtrlKey(keyCode) {\n const keys = [];\n if (isMacOS()) {\n keys.push(KEY_CODES.COMMAND_LEFT, KEY_CODES.COMMAND_RIGHT, KEY_CODES.COMMAND_FIREFOX);\n } else {\n keys.push(KEY_CODES.CONTROL);\n }\n return keys.includes(keyCode);\n}\n\n/**\n * Checks if passed key code is ctrl or cmd key. This helper checks if the key code matches to meta keys\n * regardless of the OS on which it is running.\n *\n * @param {number} keyCode The keyboard key code.\n * @returns {boolean}\n */\nexport function isCtrlMetaKey(keyCode) {\n return [KEY_CODES.CONTROL, KEY_CODES.COMMAND_LEFT, KEY_CODES.COMMAND_RIGHT, KEY_CODES.COMMAND_FIREFOX].includes(keyCode);\n}\n\n/**\n * @param {number} keyCode The keyboard key code.\n * @param {string} baseCode The list of the key codes to compare with.\n * @returns {boolean}\n */\nexport function isKey(keyCode, baseCode) {\n const keys = baseCode.split('|');\n let result = false;\n arrayEach(keys, key => {\n if (keyCode === KEY_CODES[key]) {\n result = true;\n return false;\n }\n });\n return result;\n}","/**\n * Prevent other listeners of the same event from being called.\n *\n * @param {Event} event The mouse event object.\n */\nexport function stopImmediatePropagation(event) {\n event.isImmediatePropagationEnabled = false;\n event.cancelBubble = true;\n}\n\n/**\n * Check if event was stopped by `stopImmediatePropagation`.\n *\n * @param {Event} event The mouse event object.\n * @returns {boolean}\n */\nexport function isImmediatePropagationStopped(event) {\n return event.isImmediatePropagationEnabled === false;\n}\n\n/**\n * Check if provided event was triggered by clicking the right mouse button.\n *\n * @param {Event} event The mouse event object.\n * @returns {boolean}\n */\nexport function isRightClick(event) {\n return event.button === 2;\n}\n\n/**\n * Check if provided event was triggered by clicking the left mouse button.\n *\n * @param {Event} event The mouse event object.\n * @returns {boolean}\n */\nexport function isLeftClick(event) {\n return event.button === 0;\n}\n\n/**\n * Check if the provided event is a touch event.\n *\n * @param {Event} event The event object.\n * @returns {boolean}\n */\nexport function isTouchEvent(event) {\n return event instanceof TouchEvent;\n}\n\n/**\n * Calculates the event offset until reaching the element defined by `relativeElement` argument.\n *\n * @param {Event} event The mouse event object.\n * @param {HTMLElement|undefined} [untilElement] The element to which the offset will be calculated.\n * @returns {{ x: number, y: number }}\n */\nexport function offsetRelativeTo(event, untilElement) {\n const offset = {\n x: event.offsetX,\n y: event.offsetY\n };\n let element = event.target;\n if (!(untilElement instanceof HTMLElement) || element !== untilElement && element.contains(untilElement)) {\n return offset;\n }\n while (element !== untilElement) {\n offset.x += element.offsetLeft;\n offset.y += element.offsetTop;\n element = element.offsetParent;\n }\n return offset;\n}","import \"core-js/modules/es.error.cause.js\";\n/**\n * Utility to register editors and common namespace for keeping reference to all editor classes.\n */\nimport Hooks from \"../pluginHooks.mjs\";\nimport staticRegister from \"../utils/staticRegister.mjs\";\nconst registeredEditorClasses = new WeakMap();\nconst {\n register,\n getItem,\n hasItem,\n getNames,\n getValues\n} = staticRegister('editors');\n\n/**\n * @param {BaseEditor} editorClass The editor constructor.\n */\nexport function RegisteredEditor(editorClass) {\n const instances = {};\n const Clazz = editorClass;\n this.getConstructor = function () {\n return editorClass;\n };\n this.getInstance = function (hotInstance) {\n if (!(hotInstance.guid in instances)) {\n instances[hotInstance.guid] = new Clazz(hotInstance);\n }\n return instances[hotInstance.guid];\n };\n Hooks.getSingleton().add('afterDestroy', function () {\n instances[this.guid] = null;\n });\n}\n\n/**\n * Returns instance (singleton) of editor class.\n *\n * @param {string} name Name of an editor under which it has been stored.\n * @param {object} hotInstance Instance of Handsontable.\n * @returns {Function} Returns instance of editor.\n */\nexport function _getEditorInstance(name, hotInstance) {\n let editor;\n if (typeof name === 'function') {\n if (!registeredEditorClasses.get(name)) {\n _register(null, name);\n }\n editor = registeredEditorClasses.get(name);\n } else if (typeof name === 'string') {\n editor = getItem(name);\n } else {\n throw Error('Only strings and functions can be passed as \"editor\" parameter');\n }\n if (!editor) {\n throw Error(`No editor registered under name \"${name}\"`);\n }\n return editor.getInstance(hotInstance);\n}\n\n/**\n * Retrieve editor class.\n *\n * @param {string} name Editor identification.\n * @returns {Function} Returns editor class.\n */\nfunction _getItem(name) {\n if (typeof name === 'function') {\n return name;\n }\n if (!hasItem(name)) {\n throw Error(`No registered editor found under \"${name}\" name`);\n }\n return getItem(name).getConstructor();\n}\n\n/**\n * Register editor class under specified name.\n *\n * @param {string} name Editor identification.\n * @param {Function} editorClass Editor class.\n */\nfunction _register(name, editorClass) {\n if (name && typeof name !== 'string') {\n editorClass = name;\n name = editorClass.EDITOR_TYPE;\n }\n const editorWrapper = new RegisteredEditor(editorClass);\n if (typeof name === 'string') {\n register(name, editorWrapper);\n }\n registeredEditorClasses.set(editorClass, editorWrapper);\n}\nexport { _register as registerEditor, _getItem as getEditor, _getEditorInstance as getEditorInstance, hasItem as hasEditor, getNames as getRegisteredEditorNames, getValues as getRegisteredEditors };","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/es.array.unscopables.flat-map.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { arrayEach } from \"./helpers/array.mjs\";\nimport { objectEach } from \"./helpers/object.mjs\";\nimport { substitute } from \"./helpers/string.mjs\";\nimport { warn } from \"./helpers/console.mjs\";\nimport { toSingleLine } from \"./helpers/templateLiteralTag.mjs\";\nimport { fastCall } from \"./helpers/function.mjs\";\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * @description\n *\n * ::: only-for javascript\n * Handsontable events are the common interface that function in 2 ways: as __callbacks__ and as __hooks__.\n * :::\n *\n * ::: only-for react\n * This page lists all the **Handsontable hooks** – callbacks that let you react before or after an action occurs.\n *\n * Read more on the [Events and hooks](@/guides/getting-started/events-and-hooks/events-and-hooks.md) page.\n * :::\n *\n * @example\n *\n * ::: only-for javascript\n * ```js\n * // using events as callbacks\n * ...\n * const hot1 = new Handsontable(document.getElementById('example1'), {\n * afterChange: function(changes, source) {\n * $.ajax({\n * url: \"save.php',\n * data: change\n * });\n * }\n * });\n * ...\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * fetch('save.php', {\n * method: 'POST',\n * headers: {\n * 'Accept': 'application/json',\n * 'Content-Type': 'application/json'\n * },\n * body: JSON.stringify(changes)\n * });\n * }}\n * />\n * :::\n *\n * ::: only-for javascript\n * ```js\n * // using events as plugin hooks\n * ...\n * const hot1 = new Handsontable(document.getElementById('example1'), {\n * myPlugin: true\n * });\n *\n * const hot2 = new Handsontable(document.getElementById('example2'), {\n * myPlugin: false\n * });\n *\n * // global hook\n * Handsontable.hooks.add('afterChange', function() {\n * // Fired twice - for hot1 and hot2\n * if (this.getSettings().myPlugin) {\n * // function body - will only run for hot1\n * }\n * });\n *\n * // local hook (has same effect as a callback)\n * hot2.addHook('afterChange', function() {\n * // function body - will only run in #example2\n * });\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * const hotRef1 = useRef(null);\n * const hotRef2 = useRef(null);\n *\n * // Using events as plugin hooks:\n * ...\n *\n * {\n * changes?.forEach(([row, prop, oldValue, newValue]) => {\n * // Some logic...\n * });\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * changes?.forEach(([row, prop, oldValue, newValue]) => {\n * // Some logic...\n * });\n * }}\n * />\n * ```\n * :::\n */\n'afterChange',\n/**\n * Fired each time user opens {@link ContextMenu} and after setting up the Context Menu's default options. These options are a collection\n * which user can select by setting an array of keys or an array of objects in {@link Options#contextMenu} option.\n *\n * @event Hooks#afterContextMenuDefaultOptions\n * @param {Array} predefinedItems An array of objects containing information about the pre-defined Context Menu items.\n */\n'afterContextMenuDefaultOptions',\n/**\n * Fired each time user opens {@link ContextMenu} plugin before setting up the Context Menu's items but after filtering these options by\n * user ([`contextMenu`](@/api/options.md#contextmenu) option). This hook can by helpful to determine if user use specified menu item or to set up\n * one of the menu item to by always visible.\n *\n * @event Hooks#beforeContextMenuSetItems\n * @param {object[]} menuItems An array of objects containing information about to generated Context Menu items.\n */\n'beforeContextMenuSetItems',\n/**\n * Fired by {@link DropdownMenu} plugin after setting up the Dropdown Menu's default options. These options are a\n * collection which user can select by setting an array of keys or an array of objects in {@link Options#dropdownMenu}\n * option.\n *\n * @event Hooks#afterDropdownMenuDefaultOptions\n * @param {object[]} predefinedItems An array of objects containing information about the pre-defined Context Menu items.\n */\n'afterDropdownMenuDefaultOptions',\n/**\n * Fired by {@link DropdownMenu} plugin before setting up the Dropdown Menu's items but after filtering these options\n * by user ([`dropdownMenu`](@/api/options.md#dropdownmenu) option). This hook can by helpful to determine if user use specified menu item or to set\n * up one of the menu item to by always visible.\n *\n * @event Hooks#beforeDropdownMenuSetItems\n * @param {object[]} menuItems An array of objects containing information about to generated Dropdown Menu items.\n */\n'beforeDropdownMenuSetItems',\n/**\n * Fired by {@link ContextMenu} plugin after hiding the Context Menu. This hook is fired when {@link Options#contextMenu}\n * option is enabled.\n *\n * @event Hooks#afterContextMenuHide\n * @param {object} context The Context Menu plugin instance.\n */\n'afterContextMenuHide',\n/**\n * Fired by {@link ContextMenu} plugin before opening the Context Menu. This hook is fired when {@link Options#contextMenu}\n * option is enabled.\n *\n * @event Hooks#beforeContextMenuShow\n * @param {object} context The Context Menu instance.\n */\n'beforeContextMenuShow',\n/**\n * Fired by {@link ContextMenu} plugin after opening the Context Menu. This hook is fired when {@link Options#contextMenu}\n * option is enabled.\n *\n * @event Hooks#afterContextMenuShow\n * @param {object} context The Context Menu plugin instance.\n */\n'afterContextMenuShow',\n/**\n * Fired by {@link CopyPaste} plugin after reaching the copy limit while copying data. This hook is fired when\n * {@link Options#copyPaste} option is enabled.\n *\n * @event Hooks#afterCopyLimit\n * @param {number} selectedRows Count of selected copyable rows.\n * @param {number} selectedColumns Count of selected copyable columns.\n * @param {number} copyRowsLimit Current copy rows limit.\n * @param {number} copyColumnsLimit Current copy columns limit.\n */\n'afterCopyLimit',\n/**\n * Fired before created a new column.\n *\n * @event Hooks#beforeCreateCol\n * @param {number} index Represents the visual index of first newly created column in the data source array.\n * @param {number} amount Number of newly created columns in the data source array.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {*} If `false` then creating columns is cancelled.\n * @example\n * ::: only-for javascript\n * ```js\n * // Return `false` to cancel column inserting.\n * new Handsontable(element, {\n * beforeCreateCol: function(data, coords) {\n * return false;\n * }\n * });\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * // Return `false` to cancel column inserting.\n * {\n * return false;\n * }}\n * />\n * ```\n * :::\n */\n'beforeCreateCol',\n/**\n * Fired after the order of columns has changed.\n * This hook is fired by changing column indexes of any type supported by the {@link IndexMapper}.\n *\n * @event Hooks#afterColumnSequenceChange\n * @param {'init'|'remove'|'insert'|'move'|'update'} [source] A string that indicates what caused the change to the order of columns.\n */\n'afterColumnSequenceChange',\n/**\n * Fired after created a new column.\n *\n * @event Hooks#afterCreateCol\n * @param {number} index Represents the visual index of first newly created column in the data source.\n * @param {number} amount Number of newly created columns in the data source.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterCreateCol',\n/**\n * Fired before created a new row.\n *\n * @event Hooks#beforeCreateRow\n * @param {number} index Represents the visual index of first newly created row in the data source array.\n * @param {number} amount Number of newly created rows in the data source array.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeCreateRow',\n/**\n * Fired after created a new row.\n *\n * @event Hooks#afterCreateRow\n * @param {number} index Represents the visual index of first newly created row in the data source array.\n * @param {number} amount Number of newly created rows in the data source array.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterCreateRow',\n/**\n * Fired after all selected cells are deselected.\n *\n * @event Hooks#afterDeselect\n */\n'afterDeselect',\n/**\n * Fired after destroying the Handsontable instance.\n *\n * @event Hooks#afterDestroy\n */\n'afterDestroy',\n/**\n * Hook fired after `keydown` event is handled.\n *\n * @event Hooks#afterDocumentKeyDown\n * @param {Event} event A native `keydown` event object.\n */\n'afterDocumentKeyDown',\n/**\n * Fired inside the Walkontable's selection `draw` method. Can be used to add additional class names to cells, depending on the current selection.\n *\n * @event Hooks#afterDrawSelection\n * @param {number} currentRow Row index of the currently processed cell.\n * @param {number} currentColumn Column index of the currently cell.\n * @param {number[]} cornersOfSelection Array of the current selection in a form of `[startRow, startColumn, endRow, endColumn]`.\n * @param {number|undefined} layerLevel Number indicating which layer of selection is currently processed.\n * @since 0.38.1\n * @returns {string|undefined} Can return a `String`, which will act as an additional `className` to be added to the currently processed cell.\n */\n'afterDrawSelection',\n/**\n * Fired inside the Walkontable's `refreshSelections` method. Can be used to remove additional class names from all cells in the table.\n *\n * @event Hooks#beforeRemoveCellClassNames\n * @since 0.38.1\n * @returns {string[]|undefined} Can return an `Array` of `String`s. Each of these strings will act like class names to be removed from all the cells in the table.\n */\n'beforeRemoveCellClassNames',\n/**\n * Fired after getting the cell settings.\n *\n * @event Hooks#afterGetCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {object} cellProperties Object containing the cell properties.\n */\n'afterGetCellMeta',\n/**\n * Fired after retrieving information about a column header and appending it to the table header.\n *\n * @event Hooks#afterGetColHeader\n * @param {number} column Visual column index.\n * @param {HTMLTableCellElement} TH Header's TH element.\n * @param {number} [headerLevel=0] (Since 12.2.0) Header level index. Accepts positive (0 to n)\n * and negative (-1 to -n) values. For positive values, 0 points to the\n * topmost header. For negative values, -1 points to the bottom-most\n * header (the header closest to the cells).\n */\n'afterGetColHeader',\n/**\n * Fired after retrieving information about a row header and appending it to the table header.\n *\n * @event Hooks#afterGetRowHeader\n * @param {number} row Visual row index.\n * @param {HTMLTableCellElement} TH Header's TH element.\n */\n'afterGetRowHeader',\n/**\n * Fired after the Handsontable instance is initiated.\n *\n * @event Hooks#afterInit\n */\n'afterInit',\n/**\n * Fired after Handsontable's [`data`](@/api/options.md#data)\n * gets modified by the [`loadData()`](@/api/core.md#loaddata) method\n * or the [`updateSettings()`](@/api/core.md#updatesettings) method.\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @event Hooks#afterLoadData\n * @param {Array} sourceData An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {boolean} initialLoad A flag that indicates whether the data was loaded at Handsontable's initialization (`true`) or later (`false`)\n * @param {string} source The source of the call\n */\n'afterLoadData',\n/**\n * Fired after the [`updateData()`](@/api/core.md#updatedata) method\n * modifies Handsontable's [`data`](@/api/options.md#data).\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @event Hooks#afterUpdateData\n * @since 11.1.0\n * @param {Array} sourceData An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {boolean} initialLoad A flag that indicates whether the data was loaded at Handsontable's initialization (`true`) or later (`false`)\n * @param {string} source The source of the call\n */\n'afterUpdateData',\n/**\n * Fired after a scroll event, which is identified as a momentum scroll (e.g. on an iPad).\n *\n * @event Hooks#afterMomentumScroll\n */\n'afterMomentumScroll',\n/**\n * Fired after a `mousedown` event is triggered on the cell corner (the drag handle).\n *\n * @event Hooks#afterOnCellCornerMouseDown\n * @param {Event} event `mousedown` event object.\n */\n'afterOnCellCornerMouseDown',\n/**\n * Fired after a `dblclick` event is triggered on the cell corner (the drag handle).\n *\n * @event Hooks#afterOnCellCornerDblClick\n * @param {Event} event `dblclick` event object.\n */\n'afterOnCellCornerDblClick',\n/**\n * Fired after clicking on a cell or row/column header. In case the row/column header was clicked, the coordinate\n * indexes are negative.\n *\n * For example clicking on the row header of cell (0, 0) results with `afterOnCellMouseDown` called\n * with coordinates `{row: 0, col: -1}`.\n *\n * @event Hooks#afterOnCellMouseDown\n * @param {Event} event `mousedown` event object.\n * @param {CellCoords} coords Coordinates object containing the visual row and visual column indexes of the clicked cell.\n * @param {HTMLTableCellElement} TD Cell's TD (or TH) element.\n */\n'afterOnCellMouseDown',\n/**\n * Fired after clicking on a cell or row/column header. In case the row/column header was clicked, the coordinate\n * indexes are negative.\n *\n * For example clicking on the row header of cell (0, 0) results with `afterOnCellMouseUp` called\n * with coordinates `{row: 0, col: -1}`.\n *\n * @event Hooks#afterOnCellMouseUp\n * @param {Event} event `mouseup` event object.\n * @param {CellCoords} coords Coordinates object containing the visual row and visual column indexes of the clicked cell.\n * @param {HTMLTableCellElement} TD Cell's TD (or TH) element.\n */\n'afterOnCellMouseUp',\n/**\n * Fired after clicking right mouse button on a cell or row/column header.\n *\n * For example clicking on the row header of cell (0, 0) results with `afterOnCellContextMenu` called\n * with coordinates `{row: 0, col: -1}`.\n *\n * @event Hooks#afterOnCellContextMenu\n * @since 4.1.0\n * @param {Event} event `contextmenu` event object.\n * @param {CellCoords} coords Coordinates object containing the visual row and visual column indexes of the clicked cell.\n * @param {HTMLTableCellElement} TD Cell's TD (or TH) element.\n */\n'afterOnCellContextMenu',\n/**\n * Fired after hovering a cell or row/column header with the mouse cursor. In case the row/column header was\n * hovered, the index is negative.\n *\n * For example, hovering over the row header of cell (0, 0) results with `afterOnCellMouseOver` called\n * with coords `{row: 0, col: -1}`.\n *\n * @event Hooks#afterOnCellMouseOver\n * @param {Event} event `mouseover` event object.\n * @param {CellCoords} coords Hovered cell's visual coordinate object.\n * @param {HTMLTableCellElement} TD Cell's TD (or TH) element.\n */\n'afterOnCellMouseOver',\n/**\n * Fired after leaving a cell or row/column header with the mouse cursor.\n *\n * @event Hooks#afterOnCellMouseOut\n * @param {Event} event `mouseout` event object.\n * @param {CellCoords} coords Leaved cell's visual coordinate object.\n * @param {HTMLTableCellElement} TD Cell's TD (or TH) element.\n */\n'afterOnCellMouseOut',\n/**\n * Fired after one or more columns are removed.\n *\n * @event Hooks#afterRemoveCol\n * @param {number} index Visual index of starter column.\n * @param {number} amount An amount of removed columns.\n * @param {number[]} physicalColumns An array of physical columns removed from the data source.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterRemoveCol',\n/**\n * Fired after one or more rows are removed.\n *\n * @event Hooks#afterRemoveRow\n * @param {number} index Visual index of starter row.\n * @param {number} amount An amount of removed rows.\n * @param {number[]} physicalRows An array of physical rows removed from the data source.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterRemoveRow',\n/**\n * Fired before starting rendering the cell.\n *\n * @event Hooks#beforeRenderer\n * @param {HTMLTableCellElement} TD Currently rendered cell's TD element.\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string|number} prop Column property name or a column index, if datasource is an array of arrays.\n * @param {*} value Value of the rendered cell.\n * @param {object} cellProperties Object containing the cell's properties.\n */\n'beforeRenderer',\n/**\n * Fired after finishing rendering the cell (after the renderer finishes).\n *\n * @event Hooks#afterRenderer\n * @param {HTMLTableCellElement} TD Currently rendered cell's TD element.\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string|number} prop Column property name or a column index, if datasource is an array of arrays.\n * @param {*} value Value of the rendered cell.\n * @param {object} cellProperties Object containing the cell's properties.\n */\n'afterRenderer',\n/**\n * Fired after the order of rows has changed.\n * This hook is fired by changing row indexes of any type supported by the {@link IndexMapper}.\n *\n * @event Hooks#afterRowSequenceChange\n * @param {'init'|'remove'|'insert'|'move'|'update'} [source] A string that indicates what caused the change to the order of rows.\n */\n'afterRowSequenceChange',\n/**\n * Fired before the vertical viewport scroll. Triggered by the [`scrollViewportTo()`](@/api/core.md#scrollviewportto)\n * method or table internals.\n *\n * @since 14.0.0\n * @event Hooks#beforeViewportScrollVertically\n * @param {number} visualRow Visual row index.\n * @returns {number | boolean} Returns modified row index (or the same as passed in the method argument) to which\n * the viewport will be scrolled. If the returned value is `false`, the scrolling will be canceled.\n */\n'beforeViewportScrollVertically',\n/**\n * Fired before the horizontal viewport scroll. Triggered by the [`scrollViewportTo()`](@/api/core.md#scrollviewportto)\n * method or table internals.\n *\n * @since 14.0.0\n * @event Hooks#beforeViewportScrollHorizontally\n * @param {number} visualColumn Visual column index.\n * @returns {number | boolean} Returns modified column index (or the same as passed in the method argument) to which\n * the viewport will be scrolled. If the returned value is `false`, the scrolling will be canceled.\n */\n'beforeViewportScrollHorizontally',\n/**\n * Fired before the vertical or horizontal viewport scroll. Triggered by the [`scrollViewportTo()`](@/api/core.md#scrollviewportto)\n * method or table internals.\n *\n * @since 14.0.0\n * @event Hooks#beforeViewportScroll\n */\n'beforeViewportScroll',\n/**\n * Fired after the horizontal scroll event.\n *\n * @event Hooks#afterScrollHorizontally\n */\n'afterScrollHorizontally',\n/**\n * Fired after the vertical scroll event.\n *\n * @event Hooks#afterScrollVertically\n */\n'afterScrollVertically',\n/**\n * Fired after the vertical or horizontal scroll event.\n *\n * @since 14.0.0\n * @event Hooks#afterScroll\n */\n'afterScroll',\n/**\n * Fired after one or more cells are selected (e.g. during mouse move).\n *\n * @event Hooks#afterSelection\n * @param {number} row Selection start visual row index.\n * @param {number} column Selection start visual column index.\n * @param {number} row2 Selection end visual row index.\n * @param {number} column2 Selection end visual column index.\n * @param {object} preventScrolling A reference to the observable object with the `value` property.\n * Property `preventScrolling.value` expects a boolean value that\n * Handsontable uses to control scroll behavior after selection.\n * @param {number} selectionLayerLevel The number which indicates what selection layer is currently modified.\n * @example\n * ::: only-for javascript\n * ```js\n * new Handsontable(element, {\n * afterSelection: (row, column, row2, column2, preventScrolling, selectionLayerLevel) => {\n * // If set to `false` (default): when cell selection is outside the viewport,\n * // Handsontable scrolls the viewport to cell selection's end corner.\n * // If set to `true`: when cell selection is outside the viewport,\n * // Handsontable doesn't scroll to cell selection's end corner.\n * preventScrolling.value = true;\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * // If set to `false` (default): when cell selection is outside the viewport,\n * // Handsontable scrolls the viewport to cell selection's end corner.\n * // If set to `true`: when cell selection is outside the viewport,\n * // Handsontable doesn't scroll to cell selection's end corner.\n * preventScrolling.value = true;\n * }}\n * />\n * ```\n * :::\n */\n'afterSelection',\n/**\n * Fired after one or more cells are selected.\n *\n * The `prop` and `prop2` arguments represent the source object property name instead of the column number.\n *\n * @event Hooks#afterSelectionByProp\n * @param {number} row Selection start visual row index.\n * @param {string} prop Selection start data source object property name.\n * @param {number} row2 Selection end visual row index.\n * @param {string} prop2 Selection end data source object property name.\n * @param {object} preventScrolling A reference to the observable object with the `value` property.\n * Property `preventScrolling.value` expects a boolean value that\n * Handsontable uses to control scroll behavior after selection.\n * @param {number} selectionLayerLevel The number which indicates what selection layer is currently modified.\n * @example\n * ```js\n * ::: only-for javascript\n * new Handsontable(element, {\n * afterSelectionByProp: (row, column, row2, column2, preventScrolling, selectionLayerLevel) => {\n * // setting if prevent scrolling after selection\n * preventScrolling.value = true;\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * // setting if prevent scrolling after selection\n * preventScrolling.value = true;\n * }}\n * />\n * ```\n * :::\n */\n'afterSelectionByProp',\n/**\n * Fired after one or more cells are selected (e.g. on mouse up).\n *\n * @event Hooks#afterSelectionEnd\n * @param {number} row Selection start visual row index.\n * @param {number} column Selection start visual column index.\n * @param {number} row2 Selection end visual row index.\n * @param {number} column2 Selection end visual column index.\n * @param {number} selectionLayerLevel The number which indicates what selection layer is currently modified.\n */\n'afterSelectionEnd',\n/**\n * Fired after one or more cells are selected (e.g. on mouse up).\n *\n * The `prop` and `prop2` arguments represent the source object property name instead of the column number.\n *\n * @event Hooks#afterSelectionEndByProp\n * @param {number} row Selection start visual row index.\n * @param {string} prop Selection start data source object property index.\n * @param {number} row2 Selection end visual row index.\n * @param {string} prop2 Selection end data source object property index.\n * @param {number} selectionLayerLevel The number which indicates what selection layer is currently modified.\n */\n'afterSelectionEndByProp',\n/**\n * Fired after the focus position within a selected range is changed.\n *\n * @since 14.3.0\n * @event Hooks#afterSelectionFocusSet\n * @param {number} row The focus visual row index position.\n * @param {number} column The focus visual column index position.\n * @param {object} preventScrolling A reference to the observable object with the `value` property.\n * Property `preventScrolling.value` expects a boolean value that\n * Handsontable uses to control scroll behavior after selection.\n * @example\n * ```js\n * ::: only-for javascript\n * new Handsontable(element, {\n * afterSelectionFocusSet: (row, column, preventScrolling) => {\n * // If set to `false` (default): when focused cell selection is outside the viewport,\n * // Handsontable scrolls the viewport to that cell.\n * // If set to `true`: when focused cell selection is outside the viewport,\n * // Handsontable doesn't scroll the viewport.\n * preventScrolling.value = true;\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * // If set to `false` (default): when focused cell selection is outside the viewport,\n * // Handsontable scrolls the viewport to that cell.\n * // If set to `true`: when focused cell selection is outside the viewport,\n * // Handsontable doesn't scroll the viewport.\n * preventScrolling.value = true;\n * }}\n * />\n * ```\n * :::\n */\n'afterSelectionFocusSet',\n/**\n * Fired before one or more columns are selected (e.g. During mouse header click or {@link Core#selectColumns} API call).\n *\n * @since 14.0.0\n * @event Hooks#beforeSelectColumns\n * @param {CellCoords} from Selection start coords object.\n * @param {CellCoords} to Selection end coords object.\n * @param {CellCoords} highlight Selection cell focus coords object.\n * @example\n * ::: only-for javascript\n * ```js\n * new Handsontable(element, {\n * beforeSelectColumns: (from, to, highlight) => {\n * // Extend the column selection by one column left and one column right.\n * from.col = Math.max(from.col - 1, 0);\n * to.col = Math.min(to.col + 1, this.countCols() - 1);\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * // Extend the column selection by one column left and one column right.\n * from.col = Math.max(from.col - 1, 0);\n * to.col = Math.min(to.col + 1, this.countCols() - 1);\n * }}\n * />\n * ```\n * :::\n */\n'beforeSelectColumns',\n/**\n * Fired after one or more columns are selected (e.g. during mouse header click or {@link Core#selectColumns} API call).\n *\n * @since 14.0.0\n * @event Hooks#afterSelectColumns\n * @param {CellCoords} from Selection start coords object.\n * @param {CellCoords} to Selection end coords object.\n * @param {CellCoords} highlight Selection cell focus coords object.\n */\n'afterSelectColumns',\n/**\n * Fired before one or more rows are selected (e.g. during mouse header click or {@link Core#selectRows} API call).\n *\n * @since 14.0.0\n * @event Hooks#beforeSelectRows\n * @param {CellCoords} from Selection start coords object.\n * @param {CellCoords} to Selection end coords object.\n * @param {CellCoords} highlight Selection cell focus coords object.\n * @example\n * ::: only-for javascript\n * ```js\n * new Handsontable(element, {\n * beforeSelectRows: (from, to, highlight) => {\n * // Extend the row selection by one row up and one row bottom more.\n * from.row = Math.max(from.row - 1, 0);\n * to.row = Math.min(to.row + 1, this.countRows() - 1);\n * }\n * })\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * {\n * // Extend the row selection by one row up and one row bottom more.\n * from.row = Math.max(from.row - 1, 0);\n * to.row = Math.min(to.row + 1, this.countRows() - 1);\n * }}\n * />\n * ```\n * :::\n */\n'beforeSelectRows',\n/**\n * Fired after one or more rows are selected (e.g. during mouse header click or {@link Core#selectRows} API call).\n *\n * @since 14.0.0\n * @event Hooks#afterSelectRows\n * @param {CellCoords} from Selection start coords object.\n * @param {CellCoords} to Selection end coords object.\n * @param {CellCoords} highlight Selection cell focus coords object.\n */\n'afterSelectRows',\n/**\n * Fired after cell meta is changed.\n *\n * @event Hooks#afterSetCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key The updated meta key.\n * @param {*} value The updated meta value.\n */\n'afterSetCellMeta',\n/**\n * Fired after cell meta is removed.\n *\n * @event Hooks#afterRemoveCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key The removed meta key.\n * @param {*} value Value which was under removed key of cell meta.\n */\n'afterRemoveCellMeta',\n/**\n * Fired after cell data was changed.\n *\n * @event Hooks#afterSetDataAtCell\n * @param {Array} changes An array of changes in format `[[row, column, oldValue, value], ...]`.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterSetDataAtCell',\n/**\n * Fired after cell data was changed.\n * Called only when [`setDataAtRowProp`](@/api/core.md#setdataatrowprop) was executed.\n *\n * @event Hooks#afterSetDataAtRowProp\n * @param {Array} changes An array of changes in format `[[row, prop, oldValue, value], ...]`.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'afterSetDataAtRowProp',\n/**\n * Fired after cell source data was changed.\n *\n * @event Hooks#afterSetSourceDataAtCell\n * @since 8.0.0\n * @param {Array} changes An array of changes in format `[[row, column, oldValue, value], ...]`.\n * @param {string} [source] String that identifies source of hook call.\n */\n'afterSetSourceDataAtCell',\n/**\n * Fired after calling the [`updateSettings`](@/api/core.md#updatesettings) method.\n *\n * @event Hooks#afterUpdateSettings\n * @param {object} newSettings New settings object.\n */\n'afterUpdateSettings',\n/**\n * @description\n * A plugin hook executed after validator function, only if validator function is defined.\n * Validation result is the first parameter. This can be used to determinate if validation passed successfully or not.\n *\n * __Returning false from the callback will mark the cell as invalid__.\n *\n * @event Hooks#afterValidate\n * @param {boolean} isValid `true` if valid, `false` if not.\n * @param {*} value The value in question.\n * @param {number} row Visual row index.\n * @param {string|number} prop Property name / visual column index.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {undefined | boolean} If `false` the cell will be marked as invalid, `true` otherwise.\n */\n'afterValidate',\n/**\n * Fired before successful change of language (when proper language code was set).\n *\n * @event Hooks#beforeLanguageChange\n * @since 0.35.0\n * @param {string} languageCode New language code.\n */\n'beforeLanguageChange',\n/**\n * Fired after successful change of language (when proper language code was set).\n *\n * @event Hooks#afterLanguageChange\n * @since 0.35.0\n * @param {string} languageCode New language code.\n */\n'afterLanguageChange',\n/**\n * Fired by {@link Autofill} plugin before populating the data in the autofill feature. This hook is fired when\n * {@link Options#fillHandle} option is enabled.\n *\n * @event Hooks#beforeAutofill\n * @param {Array[]} selectionData Data the autofill operation will start from.\n * @param {CellRange} sourceRange The range values will be filled from.\n * @param {CellRange} targetRange The range new values will be filled into.\n * @param {string} direction Declares the direction of the autofill. Possible values: `up`, `down`, `left`, `right`.\n *\n * @returns {boolean|Array[]} If false, the operation is cancelled. If array of arrays, the returned data\n * will be passed into [`populateFromArray`](@/api/core.md#populatefromarray) instead of the default autofill\n * algorithm's result.\n */\n'beforeAutofill',\n/**\n * Fired by {@link Autofill} plugin after populating the data in the autofill feature. This hook is fired when\n * {@link Options#fillHandle} option is enabled.\n *\n * @event Hooks#afterAutofill\n * @since 8.0.0\n * @param {Array[]} fillData The data that was used to fill the `targetRange`. If `beforeAutofill` was used\n * and returned `[[]]`, this will be the same object that was returned from `beforeAutofill`.\n * @param {CellRange} sourceRange The range values will be filled from.\n * @param {CellRange} targetRange The range new values will be filled into.\n * @param {string} direction Declares the direction of the autofill. Possible values: `up`, `down`, `left`, `right`.\n */\n'afterAutofill',\n/**\n * Fired before aligning the cell contents.\n *\n * @event Hooks#beforeCellAlignment\n * @param {object} stateBefore An object with class names defining the cell alignment.\n * @param {CellRange[]} range An array of `CellRange` coordinates where the alignment will be applied.\n * @param {string} type Type of the alignment - either `horizontal` or `vertical`.\n * @param {string} alignmentClass String defining the alignment class added to the cell.\n * Possible values: `htLeft` , `htCenter`, `htRight`, `htJustify`, `htTop`, `htMiddle`, `htBottom`.\n */\n'beforeCellAlignment',\n/**\n * Fired before one or more cells are changed.\n *\n * Use this hook to silently alter the user's changes before Handsontable re-renders.\n *\n * To ignore the user's changes, use a nullified array or return `false`.\n *\n * @event Hooks#beforeChange\n * @param {Array[]} changes 2D array containing information about each of the edited cells `[[row, prop, oldVal, newVal], ...]`. `row` is a visual row index.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {undefined | boolean} If `false` all changes were cancelled, `true` otherwise.\n * @example\n * ::: only-for javascript\n * ```js\n * // to alter a single change, overwrite the value with `changes[i][3]`\n * new Handsontable(element, {\n * beforeChange: (changes, source) => {\n * // [[row, prop, oldVal, newVal], ...]\n * changes[0][3] = 10;\n * }\n * });\n *\n * // to ignore a single change, set `changes[i]` to `null`\n * // or remove `changes[i]` from the array, by using `changes.splice(i, 1)`\n * new Handsontable(element, {\n * beforeChange: (changes, source) => {\n * // [[row, prop, oldVal, newVal], ...]\n * changes[0] = null;\n * }\n * });\n *\n * // to ignore all changes, return `false`\n * // or set the array's length to 0, by using `changes.length = 0`\n * new Handsontable(element, {\n * beforeChange: (changes, source) => {\n * // [[row, prop, oldVal, newVal], ...]\n * return false;\n * }\n * });\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * // to alter a single change, overwrite the desired value with `changes[i][3]`\n * {\n * // [[row, prop, oldVal, newVal], ...]\n * changes[0][3] = 10;\n * }}\n * />\n *\n * // to ignore a single change, set `changes[i]` to `null`\n * // or remove `changes[i]` from the array, by using changes.splice(i, 1).\n * {\n * // [[row, prop, oldVal, newVal], ...]\n * changes[0] = null;\n * }}\n * />\n *\n * // to ignore all changes, return `false`\n * // or set the array's length to 0 (`changes.length = 0`)\n * {\n * // [[row, prop, oldVal, newVal], ...]\n * return false;\n * }}\n * />\n * ```\n * :::\n */\n'beforeChange',\n/**\n * Fired right before rendering the changes.\n *\n * @event Hooks#beforeChangeRender\n * @param {Array[]} changes Array in form of `[row, prop, oldValue, newValue]`.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'beforeChangeRender',\n/**\n * Fired before drawing the borders.\n *\n * @event Hooks#beforeDrawBorders\n * @param {Array} corners Array specifying the current selection borders.\n * @param {string} borderClassName Specifies the border class name.\n */\n'beforeDrawBorders',\n/**\n * Fired before getting cell settings.\n *\n * @event Hooks#beforeGetCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {object} cellProperties Object containing the cell's properties.\n */\n'beforeGetCellMeta',\n/**\n * Fired before cell meta is removed.\n *\n * @event Hooks#beforeRemoveCellMeta\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key The removed meta key.\n * @param {*} value Value which is under removed key of cell meta.\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeRemoveCellMeta',\n/**\n * Fired before the Handsontable instance is initiated.\n *\n * @event Hooks#beforeInit\n */\n'beforeInit',\n/**\n * Fired before the Walkontable instance is initiated.\n *\n * @event Hooks#beforeInitWalkontable\n * @param {object} walkontableConfig Walkontable configuration object.\n */\n'beforeInitWalkontable',\n/**\n * Fired before Handsontable's [`data`](@/api/options.md#data)\n * gets modified by the [`loadData()`](@/api/core.md#loaddata) method\n * or the [`updateSettings()`](@/api/core.md#updatesettings) method.\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @event Hooks#beforeLoadData\n * @since 8.0.0\n * @param {Array} sourceData An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {boolean} initialLoad A flag that indicates whether the data was loaded at Handsontable's initialization (`true`) or later (`false`)\n * @param {string} source The source of the call\n * @returns {Array} The returned array will be used as Handsontable's new dataset.\n */\n'beforeLoadData',\n/**\n * Fired before the [`updateData()`](@/api/core.md#updatedata) method\n * modifies Handsontable's [`data`](@/api/options.md#data).\n *\n * Read more:\n * - [Binding to data](@/guides/getting-started/binding-to-data/binding-to-data.md)\n * - [Saving data](@/guides/getting-started/saving-data/saving-data.md)\n *\n * @event Hooks#beforeUpdateData\n * @since 11.1.0\n * @param {Array} sourceData An [array of arrays](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-arrays), or an [array of objects](@/guides/getting-started/binding-to-data/binding-to-data.md#array-of-objects), that contains Handsontable's data\n * @param {boolean} initialLoad A flag that indicates whether the data was loaded at Handsontable's initialization (`true`) or later (`false`)\n * @param {string} source The source of the call\n * @returns {Array} The returned array will be used as Handsontable's new dataset.\n */\n'beforeUpdateData',\n/**\n * Hook fired before `keydown` event is handled. It can be used to stop default key bindings.\n *\n * __Note__: To prevent default behavior you need to call `false` in your `beforeKeyDown` handler.\n *\n * @event Hooks#beforeKeyDown\n * @param {Event} event Original DOM event.\n */\n'beforeKeyDown',\n/**\n * Fired after the user clicked a cell, but before all the calculations related with it.\n *\n * @event Hooks#beforeOnCellMouseDown\n * @param {Event} event The `mousedown` event object.\n * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.\n * @param {HTMLTableCellElement} TD TD element.\n * @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains\n * a boolean value that allows or disallows changing the selection for that particular area.\n */\n'beforeOnCellMouseDown',\n/**\n * Fired after the user clicked a cell.\n *\n * @event Hooks#beforeOnCellMouseUp\n * @param {Event} event The `mouseup` event object.\n * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.\n * @param {HTMLTableCellElement} TD TD element.\n */\n'beforeOnCellMouseUp',\n/**\n * Fired after the user clicked a cell, but before all the calculations related with it.\n *\n * @event Hooks#beforeOnCellContextMenu\n * @since 4.1.0\n * @param {Event} event The `contextmenu` event object.\n * @param {CellCoords} coords Cell coords object containing the visual coordinates of the clicked cell.\n * @param {HTMLTableCellElement} TD TD element.\n */\n'beforeOnCellContextMenu',\n/**\n * Fired after the user moved cursor over a cell, but before all the calculations related with it.\n *\n * @event Hooks#beforeOnCellMouseOver\n * @param {Event} event The `mouseover` event object.\n * @param {CellCoords} coords CellCoords object containing the visual coordinates of the clicked cell.\n * @param {HTMLTableCellElement} TD TD element.\n * @param {object} controller An object with properties `row`, `column` and `cell`. Each property contains\n * a boolean value that allows or disallows changing the selection for that particular area.\n */\n'beforeOnCellMouseOver',\n/**\n * Fired after the user moved cursor out from a cell, but before all the calculations related with it.\n *\n * @event Hooks#beforeOnCellMouseOut\n * @param {Event} event The `mouseout` event object.\n * @param {CellCoords} coords CellCoords object containing the visual coordinates of the leaved cell.\n * @param {HTMLTableCellElement} TD TD element.\n */\n'beforeOnCellMouseOut',\n/**\n * Fired before one or more columns are about to be removed.\n *\n * @event Hooks#beforeRemoveCol\n * @param {number} index Visual index of starter column.\n * @param {number} amount Amount of columns to be removed.\n * @param {number[]} physicalColumns An array of physical columns removed from the data source.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeRemoveCol',\n/**\n * Fired when one or more rows are about to be removed.\n *\n * @event Hooks#beforeRemoveRow\n * @param {number} index Visual index of starter row.\n * @param {number} amount Amount of rows to be removed.\n * @param {number[]} physicalRows An array of physical rows removed from the data source.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeRemoveRow',\n/**\n * Fired before Handsontable's view-rendering engine is rendered.\n *\n * __Note:__ In Handsontable 9.x and earlier, the `beforeViewRender` hook was named `beforeRender`.\n *\n * @event Hooks#beforeViewRender\n * @since 10.0.0\n * @param {boolean} isForced If set to `true`, the rendering gets triggered by a change of settings, a change of\n * data, or a logic that needs a full Handsontable render cycle.\n * If set to `false`, the rendering gets triggered by scrolling or moving the selection.\n * @param {object} skipRender Object with `skipRender` property, if it is set to `true ` the next rendering cycle will be skipped.\n */\n'beforeViewRender',\n/**\n * Fired after Handsontable's view-rendering engine is rendered,\n * but before redrawing the selection borders and before scroll syncing.\n *\n * __Note:__ In Handsontable 9.x and earlier, the `afterViewRender` hook was named `afterRender`.\n *\n * @event Hooks#afterViewRender\n * @since 10.0.0\n * @param {boolean} isForced If set to `true`, the rendering gets triggered by a change of settings, a change of\n * data, or a logic that needs a full Handsontable render cycle.\n * If set to `false`, the rendering gets triggered by scrolling or moving the selection.\n */\n'afterViewRender',\n/**\n * Fired before Handsontable's view-rendering engine updates the view.\n *\n * The `beforeRender` event is fired right after the Handsontable\n * business logic is executed and right before the rendering engine starts calling\n * the Core logic, renderers, cell meta objects etc. to update the view.\n *\n * @event Hooks#beforeRender\n * @param {boolean} isForced If set to `true`, the rendering gets triggered by a change of settings, a change of\n * data, or a logic that needs a full Handsontable render cycle.\n * If set to `false`, the rendering gets triggered by scrolling or moving the selection.\n */\n'beforeRender',\n/**\n * Fired after Handsontable's view-rendering engine updates the view.\n *\n * @event Hooks#afterRender\n * @param {boolean} isForced If set to `true`, the rendering gets triggered by a change of settings, a change of\n * data, or a logic that needs a full Handsontable render cycle.\n * If set to `false`, the rendering gets triggered by scrolling or moving the selection.\n */\n'afterRender',\n/**\n * When the focus position is moved to the next or previous row caused by the {@link Options#autoWrapRow} option\n * the hook is triggered.\n *\n * @since 14.0.0\n * @event Hooks#beforeRowWrap\n * @param {boolean} isWrapEnabled Tells whether the row wrapping is going to happen.\n * There may be situations where the option does not work even though it is enabled.\n * This is due to the priority of other options that may block the feature.\n * For example, when the {@link Options#minSpareCols} is defined, the {@link Options#autoWrapRow} option is not checked.\n * Thus, row wrapping is off.\n * @param {CellCoords} newCoords The new focus position. It is an object with keys `row` and `col`, where a value of `-1` indicates a header.\n * @param {boolean} isFlipped `true` if the row index was flipped, `false` otherwise.\n * Flipped index means that the user reached the last row and the focus is moved to the first row or vice versa.\n */\n'beforeRowWrap',\n/**\n * When the focus position is moved to the next or previous column caused by the {@link Options#autoWrapCol} option\n * the hook is triggered.\n *\n * @since 14.0.0\n * @event Hooks#beforeColumnWrap\n * @param {boolean} isWrapEnabled Tells whether the column wrapping is going to happen.\n * There may be situations where the option does not work even though it is enabled.\n * This is due to the priority of other options that may block the feature.\n * For example, when the {@link Options#minSpareRows} is defined, the {@link Options#autoWrapCol} option is not checked.\n * Thus, column wrapping is off.\n * @param {CellCoords} newCoords The new focus position. It is an object with keys `row` and `col`, where a value of `-1` indicates a header.\n * @param {boolean} isFlipped `true` if the column index was flipped, `false` otherwise.\n * Flipped index means that the user reached the last column and the focus is moved to the first column or vice versa.\n */\n'beforeColumnWrap',\n/**\n * Fired before cell meta is changed.\n *\n * @event Hooks#beforeSetCellMeta\n * @since 8.0.0\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {string} key The updated meta key.\n * @param {*} value The updated meta value.\n * @returns {boolean|undefined} If false is returned the action is canceled.\n */\n'beforeSetCellMeta',\n/**\n * Fired before setting focus selection.\n *\n * @since 14.3.0\n * @event Hooks#beforeSelectionFocusSet\n * @param {CellCoords} coords CellCoords instance.\n */\n'beforeSelectionFocusSet',\n/**\n * Fired before setting range is started but not finished yet.\n *\n * @event Hooks#beforeSetRangeStartOnly\n * @param {CellCoords} coords `CellCoords` instance.\n */\n'beforeSetRangeStartOnly',\n/**\n * Fired before setting range is started.\n *\n * @event Hooks#beforeSetRangeStart\n * @param {CellCoords} coords `CellCoords` instance.\n */\n'beforeSetRangeStart',\n/**\n * Fired before setting range is ended.\n *\n * @event Hooks#beforeSetRangeEnd\n * @param {CellCoords} coords `CellCoords` instance.\n */\n'beforeSetRangeEnd',\n/**\n * Fired before applying selection coordinates to the renderable coordinates for Walkontable (rendering engine).\n * It occurs even when cell coordinates remain unchanged and activates during cell selection and drag selection.\n * The behavior of Shift+Tab differs from Arrow Left when there's no further movement possible.\n *\n * @since 14.0.0\n * @event Hooks#beforeSelectionHighlightSet\n */\n'beforeSelectionHighlightSet',\n/**\n * Fired before the logic of handling a touch scroll, when user started scrolling on a touch-enabled device.\n *\n * @event Hooks#beforeTouchScroll\n */\n'beforeTouchScroll',\n/**\n * Fired before cell validation, only if validator function is defined. This can be used to manipulate the value\n * of changed cell before it is applied to the validator function.\n *\n * __Note:__ this will not affect values of changes. This will change value *ONLY* for validation.\n *\n * @event Hooks#beforeValidate\n * @param {*} value Value of the cell.\n * @param {number} row Visual row index.\n * @param {string|number} prop Property name / column index.\n * @param {string} [source] String that identifies source of hook call\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n */\n'beforeValidate',\n/**\n * Fired before cell value is rendered into the DOM (through renderer function). This can be used to manipulate the\n * value which is passed to the renderer without modifying the renderer itself.\n *\n * @event Hooks#beforeValueRender\n * @param {*} value Cell value to render.\n * @param {object} cellProperties An object containing the cell properties.\n */\n'beforeValueRender',\n/**\n * Fired after Handsontable instance is constructed (using `new` operator).\n *\n * @event Hooks#construct\n */\n'construct',\n/**\n * Fired after Handsontable instance is initiated but before table is rendered.\n *\n * @event Hooks#init\n */\n'init',\n/**\n * Fired when a column header index is about to be modified by a callback function.\n *\n * @event Hooks#modifyColHeader\n * @param {number} column Visual column header index.\n */\n'modifyColHeader',\n/**\n * Fired when a column width is about to be modified by a callback function.\n *\n * @event Hooks#modifyColWidth\n * @param {number} width Current column width.\n * @param {number} column Visual column index.\n */\n'modifyColWidth',\n/**\n * Fired when rendering the list of values in the multiple-selection component of the Filters dropdown.\n * The hook allows modifying the displayed values in that component.\n *\n * @since 14.2.0\n * @event Hooks#modifyFiltersMultiSelectValue\n * @param {object} item The item in the list of values.\n * @param {object} meta The cell properties object.\n */\n'modifyFiltersMultiSelectValue',\n/**\n * Fired when focusing a cell or a header element. Allows replacing the element to be focused by returning a\n * different HTML element.\n *\n * @since 14.0.0\n * @event Hooks#modifyFocusedElement\n * @param {number} row Row index.\n * @param {number} column Column index.\n * @param {HTMLElement|undefined} focusedElement The element to be focused. `null` for focusedElement is intended when focused cell is hidden.\n */\n'modifyFocusedElement',\n/**\n * Fired when a row header index is about to be modified by a callback function.\n *\n * @event Hooks#modifyRowHeader\n * @param {number} row Visual row header index.\n */\n'modifyRowHeader',\n/**\n * Fired when a row height is about to be modified by a callback function.\n *\n * @event Hooks#modifyRowHeight\n * @param {number} height Row height.\n * @param {number} row Visual row index.\n */\n'modifyRowHeight',\n/**\n * Fired when a row height is about to be modified by a callback function. The hook allows to change the row height\n * for the specified overlay type.\n *\n * @since 14.5.0\n * @event Hooks#modifyRowHeightByOverlayName\n * @param {number} height Row height.\n * @param {number} row Visual row index.\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'|'master'} overlayName Overlay name.\n */\n'modifyRowHeightByOverlayName',\n/**\n * Fired when a data was retrieved or modified.\n *\n * @event Hooks#modifyData\n * @param {number} row Physical row index.\n * @param {number} column Visual column index.\n * @param {object} valueHolder Object which contains original value which can be modified by overwriting `.value` property.\n * @param {string} ioMode String which indicates for what operation hook is fired (`get` or `set`).\n */\n'modifyData',\n/**\n * Fired when a data was retrieved or modified from the source data set.\n *\n * @event Hooks#modifySourceData\n * @since 8.0.0\n * @param {number} row Physical row index.\n * @param {number} column Physical column index or property name.\n * @param {object} valueHolder Object which contains original value which can be modified by overwriting `.value` property.\n * @param {string} ioMode String which indicates for what operation hook is fired (`get` or `set`).\n */\n'modifySourceData',\n/**\n * Fired when a data was retrieved or modified.\n *\n * @event Hooks#modifyRowData\n * @param {number} row Physical row index.\n */\n'modifyRowData',\n/**\n * Used to modify the cell coordinates when using the [`getCell`](@/api/core.md#getcell) method, opening editor, getting value from the editor\n * and saving values from the closed editor.\n *\n * @event Hooks#modifyGetCellCoords\n * @since 0.36.0\n * @param {number} row Visual row index.\n * @param {number} column Visual column index.\n * @param {boolean} topmost If set to `true`, it returns the TD element from the topmost overlay. For example,\n * if the wanted cell is in the range of fixed rows, it will return a TD element\n * from the `top` overlay.\n * @returns {undefined|number[]}\n */\n'modifyGetCellCoords',\n/**\n * Used to modify the cell coordinates when the table is activated (going into the listen mode).\n *\n * @event Hooks#modifyFocusOnTabNavigation\n * @since 14.0.0\n * @param {'from_above' | 'from_below'} tabActivationDir The browsers Tab navigation direction. Depending on\n * whether the user activated the table from the element above or below, another cell can be selected.\n * @param {CellCoords} visualCoords The coords that will be used to select a cell.\n */\n'modifyFocusOnTabNavigation',\n/**\n * Allows modify the visual row index that is used to retrieve the row header element (TH) before it's\n * highlighted (proper CSS class names are added). Modifying the visual row index allows building a custom\n * implementation of the nested headers feature or other features that require highlighting other DOM\n * elements than that the rendering engine, by default, would have highlighted.\n *\n * @event Hooks#beforeHighlightingRowHeader\n * @since 8.4.0\n * @param {number} row Visual row index.\n * @param {number} headerLevel Column header level (0 = most distant to the table).\n * @param {object} highlightMeta An object that contains additional information about processed selection.\n * @returns {number|undefined}\n */\n'beforeHighlightingRowHeader',\n/**\n * Allows modify the visual column index that is used to retrieve the column header element (TH) before it's\n * highlighted (proper CSS class names are added). Modifying the visual column index allows building a custom\n * implementation of the nested headers feature or other features that require highlighting other DOM\n * elements than that the rendering engine, by default, would have highlighted.\n *\n * @event Hooks#beforeHighlightingColumnHeader\n * @since 8.4.0\n * @param {number} column Visual column index.\n * @param {number} headerLevel Row header level (0 = most distant to the table).\n * @param {object} highlightMeta An object that contains additional information about processed selection.\n * @returns {number|undefined}\n */\n'beforeHighlightingColumnHeader',\n/**\n * Fired by {@link PersistentState} plugin, after loading value, saved under given key, from browser local storage.\n *\n * The `persistentStateLoad` hook is fired even when the {@link Options#persistentState} option is disabled.\n *\n * @event Hooks#persistentStateLoad\n * @param {string} key Key.\n * @param {object} valuePlaceholder Object containing the loaded value under `valuePlaceholder.value` (if no value have been saved, `value` key will be undefined).\n */\n'persistentStateLoad',\n/**\n * Fired by {@link PersistentState} plugin after resetting data from local storage. If no key is given, all values associated with table will be cleared.\n * This hook is fired when {@link Options#persistentState} option is enabled.\n *\n * @event Hooks#persistentStateReset\n * @param {string} [key] Key.\n */\n'persistentStateReset',\n/**\n * Fired by {@link PersistentState} plugin, after saving value under given key in browser local storage.\n *\n * The `persistentStateSave` hook is fired even when the {@link Options#persistentState} option is disabled.\n *\n * @event Hooks#persistentStateSave\n * @param {string} key Key.\n * @param {Mixed} value Value to save.\n */\n'persistentStateSave',\n/**\n * Fired by {@link ColumnSorting} and {@link MultiColumnSorting} plugins before sorting the column. If you return `false` value inside callback for hook, then sorting\n * will be not applied by the Handsontable (useful for server-side sorting).\n *\n * This hook is fired when {@link Options#columnSorting} or {@link Options#multiColumnSorting} option is enabled.\n *\n * @event Hooks#beforeColumnSort\n * @param {Array} currentSortConfig Current sort configuration (for all sorted columns).\n * @param {Array} destinationSortConfigs Destination sort configuration (for all sorted columns).\n * @returns {boolean | undefined} If `false` the column will not be sorted, `true` otherwise.\n */\n'beforeColumnSort',\n/**\n * Fired by {@link ColumnSorting} and {@link MultiColumnSorting} plugins after sorting the column. This hook is fired when {@link Options#columnSorting}\n * or {@link Options#multiColumnSorting} option is enabled.\n *\n * @event Hooks#afterColumnSort\n * @param {Array} currentSortConfig Current sort configuration (for all sorted columns).\n * @param {Array} destinationSortConfigs Destination sort configuration (for all sorted columns).\n */\n'afterColumnSort',\n/**\n * Fired by {@link Autofill} plugin after setting range of autofill. This hook is fired when {@link Options#fillHandle}\n * option is enabled.\n *\n * @event Hooks#modifyAutofillRange\n * @param {Array} startArea Array of visual coordinates of the starting point for the drag-down operation (`[startRow, startColumn, endRow, endColumn]`).\n * @param {Array} entireArea Array of visual coordinates of the entire area of the drag-down operation (`[startRow, startColumn, endRow, endColumn]`).\n */\n'modifyAutofillRange',\n/**\n * Fired to allow modifying the copyable range with a callback function.\n *\n * @event Hooks#modifyCopyableRange\n * @param {Array[]} copyableRanges Array of objects defining copyable cells.\n */\n'modifyCopyableRange',\n/**\n * Fired by {@link CopyPaste} plugin before copying the values to the clipboard and before clearing values of\n * the selected cells. This hook is fired when {@link Options#copyPaste} option is enabled.\n *\n * @event Hooks#beforeCut\n * @param {Array[]} data An array of arrays which contains data to cut.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * which will be cut out.\n * @returns {*} If returns `false` then operation of the cutting out is canceled.\n * @example\n * ::: only-for javascript\n * ```js\n * // To disregard a single row, remove it from the array using data.splice(i, 1).\n * new Handsontable(element, {\n * beforeCut: function(data, coords) {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }\n * });\n * // To cancel a cutting action, just return `false`.\n * new Handsontable(element, {\n * beforeCut: function(data, coords) {\n * return false;\n * }\n * });\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * // To disregard a single row, remove it from the array using data.splice(i, 1).\n * {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }}\n * />\n * // To cancel a cutting action, just return `false`.\n * {\n * return false;\n * }}\n * />\n * ```\n * :::\n */\n'beforeCut',\n/**\n * Fired by {@link CopyPaste} plugin after data was cut out from the table. This hook is fired when\n * {@link Options#copyPaste} option is enabled.\n *\n * @event Hooks#afterCut\n * @param {Array[]} data An array of arrays with the cut data.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * which was cut out.\n */\n'afterCut',\n/**\n * Fired before values are copied to the clipboard.\n *\n * @event Hooks#beforeCopy\n * @param {Array[]} data An array of arrays which contains data to copied.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * which will copied.\n * @param {{ columnHeadersCount: number }} copiedHeadersCount (Since 12.3.0) The number of copied column headers.\n * @returns {*} If returns `false` then copying is canceled.\n *\n * @example\n * ::: only-for javascript\n * ```js\n * // To disregard a single row, remove it from array using data.splice(i, 1).\n * ...\n * new Handsontable(document.getElementById('example'), {\n * beforeCopy: (data, coords) => {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }\n * });\n * ...\n *\n * // To cancel copying, return false from the callback.\n * ...\n * new Handsontable(document.getElementById('example'), {\n * beforeCopy: (data, coords) => {\n * return false;\n * }\n * });\n * ...\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * // To disregard a single row, remove it from array using data.splice(i, 1).\n * ...\n * {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }}\n * />\n * ...\n *\n * // To cancel copying, return false from the callback.\n * ...\n * {\n * return false;\n * }}\n * />\n * ...\n * ```\n * :::\n */\n'beforeCopy',\n/**\n * Fired by {@link CopyPaste} plugin after data are pasted into table. This hook is fired when {@link Options#copyPaste}\n * option is enabled.\n *\n * @event Hooks#afterCopy\n * @param {Array[]} data An array of arrays which contains the copied data.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * which was copied.\n * @param {{ columnHeadersCount: number }} copiedHeadersCount (Since 12.3.0) The number of copied column headers.\n */\n'afterCopy',\n/**\n * Fired by {@link CopyPaste} plugin before values are pasted into table. This hook is fired when\n * {@link Options#copyPaste} option is enabled.\n *\n * @event Hooks#beforePaste\n * @param {Array[]} data An array of arrays which contains data to paste.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * that correspond to the previously selected area.\n * @returns {*} If returns `false` then pasting is canceled.\n * @example\n * ```js\n * ::: only-for javascript\n * // To disregard a single row, remove it from array using data.splice(i, 1).\n * new Handsontable(example, {\n * beforePaste: (data, coords) => {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }\n * });\n * // To cancel pasting, return false from the callback.\n * new Handsontable(example, {\n * beforePaste: (data, coords) => {\n * return false;\n * }\n * });\n * ```\n * :::\n *\n * ::: only-for react\n * ```jsx\n * // To disregard a single row, remove it from array using data.splice(i, 1).\n * {\n * // data -> [[1, 2, 3], [4, 5, 6]]\n * data.splice(0, 1);\n * // data -> [[4, 5, 6]]\n * // coords -> [{startRow: 0, startCol: 0, endRow: 1, endCol: 2}]\n * }}\n * />\n * // To cancel pasting, return false from the callback.\n * {\n * return false;\n * }}\n * />\n * ```\n * :::\n */\n'beforePaste',\n/**\n * Fired by {@link CopyPaste} plugin after values are pasted into table. This hook is fired when\n * {@link Options#copyPaste} option is enabled.\n *\n * @event Hooks#afterPaste\n * @param {Array[]} data An array of arrays with the pasted data.\n * @param {object[]} coords An array of objects with ranges of the visual indexes (`startRow`, `startCol`, `endRow`, `endCol`)\n * that correspond to the previously selected area.\n */\n'afterPaste',\n/**\n * Fired by the {@link ManualColumnFreeze} plugin, before freezing a column.\n *\n * @event Hooks#beforeColumnFreeze\n * @since 12.1.0\n * @param {number} column The visual index of the column that is going to freeze.\n * @param {boolean} freezePerformed If `true`: the column is going to freeze. If `false`: the column is not going to freeze (which might happen if the column is already frozen).\n * @returns {boolean|undefined} If `false`: the column is not going to freeze, and the `afterColumnFreeze` hook won't fire.\n */\n'beforeColumnFreeze',\n/**\n * Fired by the {@link ManualColumnFreeze} plugin, right after freezing a column.\n *\n * @event Hooks#afterColumnFreeze\n * @since 12.1.0\n * @param {number} column The visual index of the frozen column.\n * @param {boolean} freezePerformed If `true`: the column got successfully frozen. If `false`: the column didn't get frozen.\n */\n'afterColumnFreeze',\n/**\n * Fired by {@link ManualColumnMove} plugin before change order of the visual indexes. This hook is fired when\n * {@link Options#manualColumnMove} option is enabled.\n *\n * @event Hooks#beforeColumnMove\n * @param {Array} movedColumns Array of visual column indexes to be moved.\n * @param {number} finalIndex Visual column index, being a start index for the moved columns.\n * Points to where the elements will be placed after the moving action.\n * To check visualization of final index please take a look at\n * [documentation](@/guides/columns/column-moving/column-moving.md).\n * @param {number|undefined} dropIndex Visual column index, being a drop index for the moved columns.\n * Points to where we are going to drop the moved elements. To check\n * visualization of drop index please take a look at\n * [documentation](@/guides/columns/column-moving/column-moving.md).\n * It's `undefined` when `dragColumns` function wasn't called.\n * @param {boolean} movePossible Indicates if it's possible to move rows to the desired position.\n * @returns {undefined | boolean} If `false` the column will not be moved, `true` otherwise.\n */\n'beforeColumnMove',\n/**\n * Fired by {@link ManualColumnMove} plugin after changing order of the visual indexes.\n * This hook is fired when {@link Options#manualColumnMove} option is enabled.\n *\n * @event Hooks#afterColumnMove\n * @param {Array} movedColumns Array of visual column indexes to be moved.\n * @param {number} finalIndex Visual column index, being a start index for the moved columns.\n * Points to where the elements will be placed after the moving action.\n * To check visualization of final index please take a look at\n * [documentation](@/guides/columns/column-moving/column-moving.md).\n * @param {number|undefined} dropIndex Visual column index, being a drop index for the moved columns.\n * Points to where we are going to drop the moved elements.\n * To check visualization of drop index please take a look at\n * [documentation](@/guides/columns/column-moving/column-moving.md).\n * It's `undefined` when `dragColumns` function wasn't called.\n * @param {boolean} movePossible Indicates if it was possible to move columns to the desired position.\n * @param {boolean} orderChanged Indicates if order of columns was changed by move.\n */\n'afterColumnMove',\n/**\n * Fired by the {@link ManualColumnFreeze} plugin, before unfreezing a column.\n *\n * @event Hooks#beforeColumnUnfreeze\n * @since 12.1.0\n * @param {number} column The visual index of the column that is going to unfreeze.\n * @param {boolean} unfreezePerformed If `true`: the column is going to unfreeze. If `false`: the column is not going to unfreeze (which might happen if the column is already unfrozen).\n * @returns {boolean|undefined} If `false`: the column is not going to unfreeze, and the `afterColumnUnfreeze` hook won't fire.\n */\n'beforeColumnUnfreeze',\n/**\n * Fired by the {@link ManualColumnFreeze} plugin, right after unfreezing a column.\n *\n * @event Hooks#afterColumnUnfreeze\n * @since 12.1.0\n * @param {number} column The visual index of the unfrozen column.\n * @param {boolean} unfreezePerformed If `true`: the column got successfully unfrozen. If `false`: the column didn't get unfrozen.\n */\n'afterColumnUnfreeze',\n/**\n * Fired by {@link ManualRowMove} plugin before changing the order of the visual indexes. This hook is fired when\n * {@link Options#manualRowMove} option is enabled.\n *\n * @event Hooks#beforeRowMove\n * @param {Array} movedRows Array of visual row indexes to be moved.\n * @param {number} finalIndex Visual row index, being a start index for the moved rows.\n * Points to where the elements will be placed after the moving action.\n * To check visualization of final index please take a look at\n * [documentation](@/guides/rows/row-moving/row-moving.md).\n * @param {number|undefined} dropIndex Visual row index, being a drop index for the moved rows.\n * Points to where we are going to drop the moved elements.\n * To check visualization of drop index please take a look at\n * [documentation](@/guides/rows/row-moving/row-moving.md).\n * It's `undefined` when `dragRows` function wasn't called.\n * @param {boolean} movePossible Indicates if it's possible to move rows to the desired position.\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeRowMove',\n/**\n * Fired by {@link ManualRowMove} plugin after changing the order of the visual indexes.\n * This hook is fired when {@link Options#manualRowMove} option is enabled.\n *\n * @event Hooks#afterRowMove\n * @param {Array} movedRows Array of visual row indexes to be moved.\n * @param {number} finalIndex Visual row index, being a start index for the moved rows.\n * Points to where the elements will be placed after the moving action.\n * To check visualization of final index please take a look at\n * [documentation](@/guides/rows/row-moving/row-moving.md).\n * @param {number|undefined} dropIndex Visual row index, being a drop index for the moved rows.\n * Points to where we are going to drop the moved elements.\n * To check visualization of drop index please take a look at\n * [documentation](@/guides/rows/row-moving/row-moving.md).\n * It's `undefined` when `dragRows` function wasn't called.\n * @param {boolean} movePossible Indicates if it was possible to move rows to the desired position.\n * @param {boolean} orderChanged Indicates if order of rows was changed by move.\n */\n'afterRowMove',\n/**\n * Fired by {@link ManualColumnResize} plugin before rendering the table with modified column sizes. This hook is\n * fired when {@link Options#manualColumnResize} option is enabled.\n *\n * @event Hooks#beforeColumnResize\n * @param {number} newSize Calculated new column width.\n * @param {number} column Visual index of the resized column.\n * @param {boolean} isDoubleClick Flag that determines whether there was a double-click.\n * @returns {number} Returns a new column size or `undefined`, if column size should be calculated automatically.\n */\n'beforeColumnResize',\n/**\n * Fired by {@link ManualColumnResize} plugin after rendering the table with modified column sizes. This hook is\n * fired when {@link Options#manualColumnResize} option is enabled.\n *\n * @event Hooks#afterColumnResize\n * @param {number} newSize Calculated new column width.\n * @param {number} column Visual index of the resized column.\n * @param {boolean} isDoubleClick Flag that determines whether there was a double-click.\n */\n'afterColumnResize',\n/**\n * Fired by {@link ManualRowResize} plugin before rendering the table with modified row sizes. This hook is\n * fired when {@link Options#manualRowResize} option is enabled.\n *\n * @event Hooks#beforeRowResize\n * @param {number} newSize Calculated new row height.\n * @param {number} row Visual index of the resized row.\n * @param {boolean} isDoubleClick Flag that determines whether there was a double-click.\n * @returns {number|undefined} Returns the new row size or `undefined` if row size should be calculated automatically.\n */\n'beforeRowResize',\n/**\n * Fired by {@link ManualRowResize} plugin after rendering the table with modified row sizes. This hook is\n * fired when {@link Options#manualRowResize} option is enabled.\n *\n * @event Hooks#afterRowResize\n * @param {number} newSize Calculated new row height.\n * @param {number} row Visual index of the resized row.\n * @param {boolean} isDoubleClick Flag that determines whether there was a double-click.\n */\n'afterRowResize',\n/**\n * Fired after getting the column header renderers.\n *\n * @event Hooks#afterGetColumnHeaderRenderers\n * @param {Function[]} renderers An array of the column header renderers.\n */\n'afterGetColumnHeaderRenderers',\n/**\n * Fired after getting the row header renderers.\n *\n * @event Hooks#afterGetRowHeaderRenderers\n * @param {Function[]} renderers An array of the row header renderers.\n */\n'afterGetRowHeaderRenderers',\n/**\n * Fired before applying stretched column width to column.\n *\n * @event Hooks#beforeStretchingColumnWidth\n * @param {number} stretchedWidth Calculated width.\n * @param {number} column Visual column index.\n * @returns {number|undefined} Returns new width which will be applied to the column element.\n */\n'beforeStretchingColumnWidth',\n/**\n * Fired by the [`Filters`](@/api/filters.md) plugin,\n * before a [column filter](@/guides/columns/column-filter/column-filter.md) gets applied.\n *\n * [`beforeFilter`](#beforefilter) takes one argument (`conditionsStack`), which is an array of objects.\n * Each object represents one of your [column filters](@/api/filters.md#addcondition),\n * and consists of the following properties:\n *\n * | Property | Possible values | Description |\n * | ------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n * | `column` | Number | A visual index of the column to which the filter will be applied. |\n * | `conditions` | Array of objects | Each object represents one condition. For details, see [`addCondition()`](@/api/filters.md#addcondition). |\n * | `operation` | `'conjunction'` \\| `'disjunction'` \\| `'disjunctionWithExtraCondition'` | An operation to perform on your set of `conditions`. For details, see [`addCondition()`](@/api/filters.md#addcondition). |\n *\n * An example of the format of the `conditionsStack` argument:\n *\n * ```js\n * [\n * {\n * column: 2,\n * conditions: [\n * {name: 'begins_with', args: [['S']]}\n * ],\n * operation: 'conjunction'\n * },\n * {\n * column: 4,\n * conditions: [\n * {name: 'not_empty', args: []}\n * ],\n * operation: 'conjunction'\n * },\n * ]\n * ```\n *\n * To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI),\n * set [`beforeFilter`](#beforefilter) to return `false`:\n *\n * ```js\n * new Handsontable(document.getElementById('example'), {\n * beforeFilter: (conditionsStack) => {\n * return false;\n * }\n * });\n *```\n *\n * Read more:\n * - [Guides: Column filter](@/guides/columns/column-filter/column-filter.md)\n * - [Hooks: `afterFilter`](#afterfilter)\n * - [Options: `filters`](@/api/options.md#filters)\n * - [Plugins: `Filters`](@/api/filters.md)\n * – [Plugin methods: `addCondition()`](@/api/filters.md#addcondition)\n *\n * @event Hooks#beforeFilter\n * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).\n * @returns {boolean} To perform server-side filtering (i.e., to not apply filtering to Handsontable's UI), return `false`.\n */\n'beforeFilter',\n/**\n * Fired by the [`Filters`](@/api/filters.md) plugin,\n * after a [column filter](@/guides/columns/column-filter/column-filter.md) gets applied.\n *\n * [`afterFilter`](#afterfilter) takes one argument (`conditionsStack`), which is an array of objects.\n * Each object represents one of your [column filters](@/api/filters.md#addcondition),\n * and consists of the following properties:\n *\n * | Property | Possible values | Description |\n * | ------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n * | `column` | Number | A visual index of the column to which the filter was applied. |\n * | `conditions` | Array of objects | Each object represents one condition. For details, see [`addCondition()`](@/api/filters.md#addcondition). |\n * | `operation` | `'conjunction'` \\| `'disjunction'` \\| `'disjunctionWithExtraCondition'` | An operation to perform on your set of `conditions`. For details, see [`addCondition()`](@/api/filters.md#addcondition). |\n *\n * An example of the format of the `conditionsStack` argument:\n *\n * ```js\n * [\n * {\n * column: 2,\n * conditions: [\n * {name: 'begins_with', args: [['S']]}\n * ],\n * operation: 'conjunction'\n * },\n * {\n * column: 4,\n * conditions: [\n * {name: 'not_empty', args: []}\n * ],\n * operation: 'conjunction'\n * },\n * ]\n * ```\n *\n * Read more:\n * - [Guides: Column filter](@/guides/columns/column-filter/column-filter.md)\n * - [Hooks: `beforeFilter`](#beforefilter)\n * - [Options: `filters`](@/api/options.md#filters)\n * - [Plugins: `Filters`](@/api/filters.md)\n * – [Plugin methods: `addCondition()`](@/api/filters.md#addcondition)\n *\n * @event Hooks#afterFilter\n * @param {object[]} conditionsStack An array of objects with your [column filters](@/api/filters.md#addcondition).\n */\n'afterFilter',\n/**\n * Fired by the {@link Formulas} plugin, when any cell value changes.\n *\n * Returns an array of objects that contains:\n * - The addresses (`sheet`, `row`, `col`) and new values (`newValue`) of the changed cells.\n * - The addresses and new values of any cells that had to be recalculated (because their formulas depend on the cells that changed).\n *\n * This hook gets also fired on Handsontable's initialization, returning the addresses and values of all cells.\n *\n * Read more:\n * - [Guides: Formula calculation](@/guides/formulas/formula-calculation/formula-calculation.md)\n * - [HyperFormula documentation: `valuesUpdated`](https://hyperformula.handsontable.com/api/interfaces/listeners.html#valuesupdated)\n *\n * @since 9.0.0\n * @event Hooks#afterFormulasValuesUpdate\n * @param {Array} changes The addresses and new values of all the changed and recalculated cells.\n */\n'afterFormulasValuesUpdate',\n/**\n * Fired when a named expression is added to the Formulas' engine instance.\n *\n * @since 9.0.0\n * @event Hooks#afterNamedExpressionAdded\n * @param {string} namedExpressionName The name of the added expression.\n * @param {Array} changes The values and location of applied changes.\n */\n'afterNamedExpressionAdded',\n/**\n * Fired when a named expression is removed from the Formulas' engine instance.\n *\n * @since 9.0.0\n * @event Hooks#afterNamedExpressionRemoved\n * @param {string} namedExpressionName The name of the removed expression.\n * @param {Array} changes The values and location of applied changes.\n */\n'afterNamedExpressionRemoved',\n/**\n * Fired when a new sheet is added to the Formulas' engine instance.\n *\n * @since 9.0.0\n * @event Hooks#afterSheetAdded\n * @param {string} addedSheetDisplayName The name of the added sheet.\n */\n'afterSheetAdded',\n/**\n * Fired when a sheet in the Formulas' engine instance is renamed.\n *\n * @since 9.0.0\n * @event Hooks#afterSheetRenamed\n * @param {string} oldDisplayName The old name of the sheet.\n * @param {string} newDisplayName The new name of the sheet.\n */\n'afterSheetRenamed',\n/**\n * Fired when a sheet is removed from the Formulas' engine instance.\n *\n * @since 9.0.0\n * @event Hooks#afterSheetRemoved\n * @param {string} removedSheetDisplayName The removed sheet name.\n * @param {Array} changes The values and location of applied changes.\n */\n'afterSheetRemoved',\n/**\n * Fired while retrieving the column header height.\n *\n * @event Hooks#modifyColumnHeaderHeight\n */\n'modifyColumnHeaderHeight',\n/**\n * Fired while retrieving a column header's value.\n *\n * @since 12.3.0\n * @event Hooks#modifyColumnHeaderValue\n * @param {string} value A column header value.\n * @param {number} visualColumnIndex A visual column index.\n * @param {number} [headerLevel=0] Header level index. Accepts positive (`0` to `n`)\n * and negative (`-1` to `-n`) values. For positive values, `0` points to the\n * topmost header. For negative values, `-1` points to the bottom-most\n * header (the header closest to the cells).\n * @returns {string} The column header value to be updated.\n */\n'modifyColumnHeaderValue',\n/**\n * Fired by {@link UndoRedo} plugin before the undo action. Contains information about the action that is being undone.\n * This hook is fired when {@link Options#undo} option is enabled.\n *\n * @event Hooks#beforeUndo\n * @param {object} action The action object. Contains information about the action being undone. The `actionType`\n * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeUndo',\n/**\n * Fired by {@link UndoRedo} plugin before changing undo stack.\n *\n * @event Hooks#beforeUndoStackChange\n * @since 8.4.0\n * @param {Array} doneActions Stack of actions which may be undone.\n * @param {string} [source] String that identifies source of action\n * ([list of all available sources](@/guides/getting-started/events-and-hooks/events-and-hooks.md#definition-for-source-argument)).\n * @returns {*|boolean} If false is returned the action of changing undo stack is canceled.\n */\n'beforeUndoStackChange',\n/**\n * Fired by {@link UndoRedo} plugin after the undo action. Contains information about the action that is being undone.\n * This hook is fired when {@link Options#undo} option is enabled.\n *\n * @event Hooks#afterUndo\n * @param {object} action The action object. Contains information about the action being undone. The `actionType`\n * property of the object specifies the type of the action in a String format. (e.g. `'remove_row'`).\n */\n'afterUndo',\n/**\n * Fired by {@link UndoRedo} plugin after changing undo stack.\n *\n * @event Hooks#afterUndoStackChange\n * @since 8.4.0\n * @param {Array} doneActionsBefore Stack of actions which could be undone before performing new action.\n * @param {Array} doneActionsAfter Stack of actions which can be undone after performing new action.\n */\n'afterUndoStackChange',\n/**\n * Fired by {@link UndoRedo} plugin before the redo action. Contains information about the action that is being redone.\n * This hook is fired when {@link Options#undo} option is enabled.\n *\n * @event Hooks#beforeRedo\n * @param {object} action The action object. Contains information about the action being redone. The `actionType`\n * property of the object specifies the type of the action in a String format (e.g. `'remove_row'`).\n * @returns {*|boolean} If false is returned the action is canceled.\n */\n'beforeRedo',\n/**\n * Fired by {@link UndoRedo} plugin before changing redo stack.\n *\n * @event Hooks#beforeRedoStackChange\n * @since 8.4.0\n * @param {Array} undoneActions Stack of actions which may be redone.\n */\n'beforeRedoStackChange',\n/**\n * Fired by {@link UndoRedo} plugin after the redo action. Contains information about the action that is being redone.\n * This hook is fired when {@link Options#undo} option is enabled.\n *\n * @event Hooks#afterRedo\n * @param {object} action The action object. Contains information about the action being redone. The `actionType`\n * property of the object specifies the type of the action in a String format (e.g. `'remove_row'`).\n */\n'afterRedo',\n/**\n * Fired by {@link UndoRedo} plugin after changing redo stack.\n *\n * @event Hooks#afterRedoStackChange\n * @since 8.4.0\n * @param {Array} undoneActionsBefore Stack of actions which could be redone before performing new action.\n * @param {Array} undoneActionsAfter Stack of actions which can be redone after performing new action.\n */\n'afterRedoStackChange',\n/**\n * Fired while retrieving the row header width.\n *\n * @event Hooks#modifyRowHeaderWidth\n * @param {number} rowHeaderWidth Row header width.\n */\n'modifyRowHeaderWidth',\n/**\n * Fired when the focus of the selection is being modified (e.g. Moving the focus with the enter/tab keys).\n *\n * @since 14.3.0\n * @event Hooks#modifyTransformFocus\n * @param {CellCoords} delta Cell coords object declaring the delta of the new selection relative to the previous one.\n */\n'modifyTransformFocus',\n/**\n * Fired when the start of the selection is being modified (e.g. Moving the selection with the arrow keys).\n *\n * @event Hooks#modifyTransformStart\n * @param {CellCoords} delta Cell coords object declaring the delta of the new selection relative to the previous one.\n */\n'modifyTransformStart',\n/**\n * Fired when the end of the selection is being modified (e.g. Moving the selection with the arrow keys).\n *\n * @event Hooks#modifyTransformEnd\n * @param {CellCoords} delta Cell coords object declaring the delta of the new selection relative to the previous one.\n */\n'modifyTransformEnd',\n/**\n * Fired after the focus of the selection is being modified (e.g. Moving the focus with the enter/tab keys).\n *\n * @since 14.3.0\n * @event Hooks#afterModifyTransformFocus\n * @param {CellCoords} coords Coords of the freshly focused cell.\n * @param {number} rowTransformDir `-1` if trying to focus a cell with a negative row index. `0` otherwise.\n * @param {number} colTransformDir `-1` if trying to focus a cell with a negative column index. `0` otherwise.\n */\n'afterModifyTransformFocus',\n/**\n * Fired after the start of the selection is being modified (e.g. Moving the selection with the arrow keys).\n *\n * @event Hooks#afterModifyTransformStart\n * @param {CellCoords} coords Coords of the freshly selected cell.\n * @param {number} rowTransformDir `-1` if trying to select a cell with a negative row index. `0` otherwise.\n * @param {number} colTransformDir `-1` if trying to select a cell with a negative column index. `0` otherwise.\n */\n'afterModifyTransformStart',\n/**\n * Fired after the end of the selection is being modified (e.g. Moving the selection with the arrow keys).\n *\n * @event Hooks#afterModifyTransformEnd\n * @param {CellCoords} coords Visual coords of the freshly selected cell.\n * @param {number} rowTransformDir `-1` if trying to select a cell with a negative row index. `0` otherwise.\n * @param {number} colTransformDir `-1` if trying to select a cell with a negative column index. `0` otherwise.\n */\n'afterModifyTransformEnd',\n/**\n * Fired inside the `viewportRowCalculatorOverride` method. Allows modifying the row calculator parameters.\n *\n * @event Hooks#afterViewportRowCalculatorOverride\n * @param {object} calc The row calculator.\n */\n'afterViewportRowCalculatorOverride',\n/**\n * Fired inside the `viewportColumnCalculatorOverride` method. Allows modifying the row calculator parameters.\n *\n * @event Hooks#afterViewportColumnCalculatorOverride\n * @param {object} calc The row calculator.\n */\n'afterViewportColumnCalculatorOverride',\n/**\n * Fired after initializing all the plugins.\n * This hook should be added before Handsontable is initialized.\n *\n * @event Hooks#afterPluginsInitialized\n *\n * @example\n * ```js\n * Handsontable.hooks.add('afterPluginsInitialized', myCallback);\n * ```\n */\n'afterPluginsInitialized',\n/**\n * Fired by {@link HiddenRows} plugin before marking the rows as hidden. Fired only if the {@link Options#hiddenRows} option is enabled.\n * Returning `false` in the callback will prevent the hiding action from completing.\n *\n * @event Hooks#beforeHideRows\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical row indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical row indexes.\n * @param {boolean} actionPossible `true`, if provided row indexes are valid, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the hiding action will not be completed.\n */\n'beforeHideRows',\n/**\n * Fired by {@link HiddenRows} plugin after marking the rows as hidden. Fired only if the {@link Options#hiddenRows} option is enabled.\n *\n * @event Hooks#afterHideRows\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical row indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical row indexes.\n * @param {boolean} actionPossible `true`, if provided row indexes are valid, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any non-hidden rows, `false` otherwise.\n */\n'afterHideRows',\n/**\n * Fired by {@link HiddenRows} plugin before marking the rows as not hidden. Fired only if the {@link Options#hiddenRows} option is enabled.\n * Returning `false` in the callback will prevent the row revealing action from completing.\n *\n * @event Hooks#beforeUnhideRows\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical row indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical row indexes.\n * @param {boolean} actionPossible `true`, if provided row indexes are valid, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the revealing action will not be completed.\n */\n'beforeUnhideRows',\n/**\n * Fired by {@link HiddenRows} plugin after marking the rows as not hidden. Fired only if the {@link Options#hiddenRows} option is enabled.\n *\n * @event Hooks#afterUnhideRows\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical row indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical row indexes.\n * @param {boolean} actionPossible `true`, if provided row indexes are valid, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any hidden rows, `false` otherwise.\n */\n'afterUnhideRows',\n/**\n * Fired by {@link HiddenColumns} plugin before marking the columns as hidden. Fired only if the {@link Options#hiddenColumns} option is enabled.\n * Returning `false` in the callback will prevent the hiding action from completing.\n *\n * @event Hooks#beforeHideColumns\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical column indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical column indexes.\n * @param {boolean} actionPossible `true`, if the provided column indexes are valid, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the hiding action will not be completed.\n */\n'beforeHideColumns',\n/**\n * Fired by {@link HiddenColumns} plugin after marking the columns as hidden. Fired only if the {@link Options#hiddenColumns} option is enabled.\n *\n * @event Hooks#afterHideColumns\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical column indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical column indexes.\n * @param {boolean} actionPossible `true`, if the provided column indexes are valid, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any non-hidden columns, `false` otherwise.\n */\n'afterHideColumns',\n/**\n * Fired by {@link HiddenColumns} plugin before marking the columns as not hidden. Fired only if the {@link Options#hiddenColumns} option is enabled.\n * Returning `false` in the callback will prevent the column revealing action from completing.\n *\n * @event Hooks#beforeUnhideColumns\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical column indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical column indexes.\n * @param {boolean} actionPossible `true`, if the provided column indexes are valid, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the hiding action will not be completed.\n */\n'beforeUnhideColumns',\n/**\n * Fired by {@link HiddenColumns} plugin after marking the columns as not hidden. Fired only if the {@link Options#hiddenColumns} option is enabled.\n *\n * @event Hooks#afterUnhideColumns\n * @param {Array} currentHideConfig Current hide configuration - a list of hidden physical column indexes.\n * @param {Array} destinationHideConfig Destination hide configuration - a list of hidden physical column indexes.\n * @param {boolean} actionPossible `true`, if the provided column indexes are valid, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any hidden columns, `false` otherwise.\n */\n'afterUnhideColumns',\n/**\n * Fired by {@link TrimRows} plugin before trimming rows. This hook is fired when {@link Options#trimRows} option is enabled.\n *\n * @event Hooks#beforeTrimRow\n * @param {Array} currentTrimConfig Current trim configuration - a list of trimmed physical row indexes.\n * @param {Array} destinationTrimConfig Destination trim configuration - a list of trimmed physical row indexes.\n * @param {boolean} actionPossible `true`, if all of the row indexes are withing the bounds of the table, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the trimming action will not be completed.\n */\n'beforeTrimRow',\n/**\n * Fired by {@link TrimRows} plugin after trimming rows. This hook is fired when {@link Options#trimRows} option is enabled.\n *\n * @event Hooks#afterTrimRow\n * @param {Array} currentTrimConfig Current trim configuration - a list of trimmed physical row indexes.\n * @param {Array} destinationTrimConfig Destination trim configuration - a list of trimmed physical row indexes.\n * @param {boolean} actionPossible `true`, if all of the row indexes are withing the bounds of the table, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any non-trimmed rows, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the trimming action will not be completed.\n */\n'afterTrimRow',\n/**\n * Fired by {@link TrimRows} plugin before untrimming rows. This hook is fired when {@link Options#trimRows} option is enabled.\n *\n * @event Hooks#beforeUntrimRow\n * @param {Array} currentTrimConfig Current trim configuration - a list of trimmed physical row indexes.\n * @param {Array} destinationTrimConfig Destination trim configuration - a list of trimmed physical row indexes.\n * @param {boolean} actionPossible `true`, if all of the row indexes are withing the bounds of the table, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the untrimming action will not be completed.\n */\n'beforeUntrimRow',\n/**\n * Fired by {@link TrimRows} plugin after untrimming rows. This hook is fired when {@link Options#trimRows} option is enabled.\n *\n * @event Hooks#afterUntrimRow\n * @param {Array} currentTrimConfig Current trim configuration - a list of trimmed physical row indexes.\n * @param {Array} destinationTrimConfig Destination trim configuration - a list of trimmed physical row indexes.\n * @param {boolean} actionPossible `true`, if all of the row indexes are withing the bounds of the table, `false` otherwise.\n * @param {boolean} stateChanged `true`, if the action affected any trimmed rows, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the untrimming action will not be completed.\n */\n'afterUntrimRow',\n/**\n * Fired by {@link DropdownMenu} plugin before opening the dropdown menu. This hook is fired when {@link Options#dropdownMenu}\n * option is enabled.\n *\n * @event Hooks#beforeDropdownMenuShow\n * @param {DropdownMenu} dropdownMenu The `DropdownMenu` instance.\n */\n'beforeDropdownMenuShow',\n/**\n * Fired by {@link DropdownMenu} plugin after opening the Dropdown Menu. This hook is fired when {@link Options#dropdownMenu}\n * option is enabled.\n *\n * @event Hooks#afterDropdownMenuShow\n * @param {DropdownMenu} dropdownMenu The `DropdownMenu` instance.\n */\n'afterDropdownMenuShow',\n/**\n * Fired by {@link DropdownMenu} plugin after hiding the Dropdown Menu. This hook is fired when {@link Options#dropdownMenu}\n * option is enabled.\n *\n * @event Hooks#afterDropdownMenuHide\n * @param {DropdownMenu} instance The `DropdownMenu` instance.\n */\n'afterDropdownMenuHide',\n/**\n * Fired by {@link NestedRows} plugin before adding a children to the `NestedRows` structure. This hook is fired when\n * {@link Options#nestedRows} option is enabled.\n *\n * @event Hooks#beforeAddChild\n * @param {object} parent The parent object.\n * @param {object|undefined} element The element added as a child. If `undefined`, a blank child was added.\n * @param {number|undefined} index The index within the parent where the new child was added. If `undefined`, the element was added as the last child.\n */\n'beforeAddChild',\n/**\n * Fired by {@link NestedRows} plugin after adding a children to the `NestedRows` structure. This hook is fired when\n * {@link Options#nestedRows} option is enabled.\n *\n * @event Hooks#afterAddChild\n * @param {object} parent The parent object.\n * @param {object|undefined} element The element added as a child. If `undefined`, a blank child was added.\n * @param {number|undefined} index The index within the parent where the new child was added. If `undefined`, the element was added as the last child.\n */\n'afterAddChild',\n/**\n * Fired by {@link NestedRows} plugin before detaching a child from its parent. This hook is fired when\n * {@link Options#nestedRows} option is enabled.\n *\n * @event Hooks#beforeDetachChild\n * @param {object} parent An object representing the parent from which the element is to be detached.\n * @param {object} element The detached element.\n */\n'beforeDetachChild',\n/**\n * Fired by {@link NestedRows} plugin after detaching a child from its parent. This hook is fired when\n * {@link Options#nestedRows} option is enabled.\n *\n * @event Hooks#afterDetachChild\n * @param {object} parent An object representing the parent from which the element was detached.\n * @param {object} element The detached element.\n * @param {number} finalElementPosition The final row index of the detached element.\n */\n'afterDetachChild',\n/**\n * Fired before the editor is opened and rendered.\n *\n * @since 14.2.0\n * @event Hooks#beforeBeginEditing\n * @param {number} row Visual row index of the edited cell.\n * @param {number} column Visual column index of the edited cell.\n * @param {*} initialValue The initial editor value.\n * @param {MouseEvent | KeyboardEvent} event The event which was responsible for opening the editor.\n * @param {boolean} fullEditMode `true` if the editor is opened in full edit mode, `false` otherwise.\n * Editor opened in full edit mode does not close after pressing Arrow keys.\n * @returns {boolean | undefined} If the callback returns `false,` the editor won't be opened after\n * the mouse double click or after pressing the Enter key. Returning `undefined` (or other value\n * than boolean) will result in default behavior, which disallows opening an editor for non-contiguous\n * selection (while pressing Ctrl/Cmd) and for multiple selected cells (while pressing SHIFT).\n * Returning `true` removes those restrictions.\n */\n'beforeBeginEditing',\n/**\n * Fired after the editor is opened and rendered.\n *\n * @event Hooks#afterBeginEditing\n * @param {number} row Visual row index of the edited cell.\n * @param {number} column Visual column index of the edited cell.\n */\n'afterBeginEditing',\n/**\n * Fired by {@link MergeCells} plugin before cell merging. This hook is fired when {@link Options#mergeCells}\n * option is enabled.\n *\n * @event Hooks#beforeMergeCells\n * @param {CellRange} cellRange Selection cell range.\n * @param {boolean} [auto=false] `true` if called automatically by the plugin.\n */\n'beforeMergeCells',\n/**\n * Fired by {@link MergeCells} plugin after cell merging. This hook is fired when {@link Options#mergeCells}\n * option is enabled.\n *\n * @event Hooks#afterMergeCells\n * @param {CellRange} cellRange Selection cell range.\n * @param {object} mergeParent The parent collection of the provided cell range.\n * @param {boolean} [auto=false] `true` if called automatically by the plugin.\n */\n'afterMergeCells',\n/**\n * Fired by {@link MergeCells} plugin before unmerging the cells. This hook is fired when {@link Options#mergeCells}\n * option is enabled.\n *\n * @event Hooks#beforeUnmergeCells\n * @param {CellRange} cellRange Selection cell range.\n * @param {boolean} [auto=false] `true` if called automatically by the plugin.\n */\n'beforeUnmergeCells',\n/**\n * Fired by {@link MergeCells} plugin after unmerging the cells. This hook is fired when {@link Options#mergeCells}\n * option is enabled.\n *\n * @event Hooks#afterUnmergeCells\n * @param {CellRange} cellRange Selection cell range.\n * @param {boolean} [auto=false] `true` if called automatically by the plugin.\n */\n'afterUnmergeCells',\n/**\n * Fired after the table was switched into listening mode. This allows Handsontable to capture keyboard events and\n * respond in the right way.\n *\n * @event Hooks#afterListen\n */\n'afterListen',\n/**\n * Fired after the table was switched off from the listening mode. This makes the Handsontable inert for any\n * keyboard events.\n *\n * @event Hooks#afterUnlisten\n */\n'afterUnlisten',\n/**\n * Fired after the window was resized or the size of the Handsontable root element was changed.\n *\n * @event Hooks#afterRefreshDimensions\n * @param {{ width: number, height: number }} previousDimensions Previous dimensions of the container.\n * @param {{ width: number, height: number }} currentDimensions Current dimensions of the container.\n * @param {boolean} stateChanged `true`, if the container was re-render, `false` otherwise.\n */\n'afterRefreshDimensions',\n/**\n * Cancellable hook, called after resizing a window or after detecting size change of the\n * Handsontable root element, but before redrawing a table.\n *\n * @event Hooks#beforeRefreshDimensions\n * @param {{ width: number, height: number }} previousDimensions Previous dimensions of the container.\n * @param {{ width: number, height: number }} currentDimensions Current dimensions of the container.\n * @param {boolean} actionPossible `true`, if current and previous dimensions are different, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the refresh action will not be completed.\n */\n'beforeRefreshDimensions',\n/**\n * Fired by {@link CollapsibleColumns} plugin before columns collapse. This hook is fired when {@link Options#collapsibleColumns} option is enabled.\n *\n * @event Hooks#beforeColumnCollapse\n * @since 8.0.0\n * @param {Array} currentCollapsedColumns Current collapsible configuration - a list of collapsible physical column indexes.\n * @param {Array} destinationCollapsedColumns Destination collapsible configuration - a list of collapsible physical column indexes.\n * @param {boolean} collapsePossible `true`, if all of the column indexes are withing the bounds of the collapsed sections, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the collapsing action will not be completed.\n */\n'beforeColumnCollapse',\n/**\n * Fired by {@link CollapsibleColumns} plugin before columns collapse. This hook is fired when {@link Options#collapsibleColumns} option is enabled.\n *\n * @event Hooks#afterColumnCollapse\n * @since 8.0.0\n * @param {Array} currentCollapsedColumns Current collapsible configuration - a list of collapsible physical column indexes.\n * @param {Array} destinationCollapsedColumns Destination collapsible configuration - a list of collapsible physical column indexes.\n * @param {boolean} collapsePossible `true`, if all of the column indexes are withing the bounds of the collapsed sections, `false` otherwise.\n * @param {boolean} successfullyCollapsed `true`, if the action affected any non-collapsible column, `false` otherwise.\n */\n'afterColumnCollapse',\n/**\n * Fired by {@link CollapsibleColumns} plugin before columns expand. This hook is fired when {@link Options#collapsibleColumns} option is enabled.\n *\n * @event Hooks#beforeColumnExpand\n * @since 8.0.0\n * @param {Array} currentCollapsedColumns Current collapsible configuration - a list of collapsible physical column indexes.\n * @param {Array} destinationCollapsedColumns Destination collapsible configuration - a list of collapsible physical column indexes.\n * @param {boolean} expandPossible `true`, if all of the column indexes are withing the bounds of the collapsed sections, `false` otherwise.\n * @returns {undefined|boolean} If the callback returns `false`, the expanding action will not be completed.\n */\n'beforeColumnExpand',\n/**\n * Fired by {@link CollapsibleColumns} plugin before columns expand. This hook is fired when {@link Options#collapsibleColumns} option is enabled.\n *\n * @event Hooks#afterColumnExpand\n * @since 8.0.0\n * @param {Array} currentCollapsedColumns Current collapsible configuration - a list of collapsible physical column indexes.\n * @param {Array} destinationCollapsedColumns Destination collapsible configuration - a list of collapsible physical column indexes.\n * @param {boolean} expandPossible `true`, if all of the column indexes are withing the bounds of the collapsed sections, `false` otherwise.\n * @param {boolean} successfullyExpanded `true`, if the action affected any non-collapsible column, `false` otherwise.\n */\n'afterColumnExpand',\n/**\n * Fired by {@link AutoColumnSize} plugin within SampleGenerator utility.\n *\n * @event Hooks#modifyAutoColumnSizeSeed\n * @since 8.4.0\n * @param {string|undefined} seed Seed ID, unique name to categorize samples.\n * @param {object} cellProperties Object containing the cell properties.\n * @param {*} cellValue Value of the cell.\n */\n'modifyAutoColumnSizeSeed'];\n\n/**\n * Template warning message for removed hooks.\n *\n * @type {string}\n */\nconst REMOVED_MESSAGE = toSingleLine`The plugin hook \"[hookName]\" was removed in Handsontable [removedInVersion].\\x20\n Please consult release notes https://github.com/handsontable/handsontable/releases/tag/[removedInVersion] to\\x20\n learn about the migration path.`;\n\n/**\n * The list of the hooks which are removed from the API. The warning message is printed out in\n * the developer console when the hook is used.\n *\n * The Map key is represented by hook name and its value points to the Handsontable version\n * in which it was removed.\n *\n * @type {Map}\n */\nconst REMOVED_HOOKS = new Map([['modifyRow', '8.0.0'], ['modifyCol', '8.0.0'], ['unmodifyRow', '8.0.0'], ['unmodifyCol', '8.0.0'], ['skipLengthCache', '8.0.0'], ['hiddenColumn', '8.0.0'], ['hiddenRow', '8.0.0']]);\n\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * The list of the hooks which are deprecated. The warning message is printed out in\n * the developer console when the hook is used.\n *\n * The Map key is represented by hook name and its value keeps message which whould be\n * printed out when the hook is used.\n *\n * Usage:\n * ```js\n * ...\n * New Map([\n * ['beforeColumnExpand', 'The plugin hook \"beforeColumnExpand\" is deprecated. Use \"beforeColumnExpand2\" instead.'],\n * ])\n * ...\n * ```\n *\n *\n * @type {Map}\n */\n/* eslint-enable jsdoc/require-description-complete-sentence */\nconst DEPRECATED_HOOKS = new Map([[]]);\nconst callbackOrder = new WeakMap();\nclass Hooks {\n static getSingleton() {\n return getGlobalSingleton();\n }\n\n /**\n * @type {object}\n */\n\n /**\n *\n */\n constructor() {\n _defineProperty(this, \"globalBucket\", void 0);\n this.globalBucket = this.createEmptyBucket();\n }\n\n /**\n * Returns a new object with empty handlers related to every registered hook name.\n *\n * @returns {object} The empty bucket object.\n *\n * @example\n * ```js\n * Handsontable.hooks.createEmptyBucket();\n * // Results:\n * {\n * ...\n * afterCreateCol: [],\n * afterCreateRow: [],\n * beforeInit: [],\n * ...\n * }\n * ```\n */\n createEmptyBucket() {\n const bucket = Object.create(null);\n\n // eslint-disable-next-line no-return-assign\n arrayEach(REGISTERED_HOOKS, hook => {\n bucket[hook] = [];\n this.initOrderMap(bucket, hook);\n });\n return bucket;\n }\n\n /**\n * Get hook bucket based on the context of the object or if argument is `undefined`, get the global hook bucket.\n *\n * @param {object} [context=null] A Handsontable instance.\n * @returns {object} Returns a global or Handsontable instance bucket.\n */\n getBucket() {\n let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n if (context) {\n if (!context.pluginHookBucket) {\n context.pluginHookBucket = this.createEmptyBucket();\n }\n return context.pluginHookBucket;\n }\n return this.globalBucket;\n }\n\n /**\n * Adds a listener (globally or locally) to a specified hook name.\n * If the `context` parameter is provided, the hook will be added only to the instance it references.\n * Otherwise, the callback will be used everytime the hook fires on any Handsontable instance.\n * You can provide an array of callback functions as the `callback` argument, this way they will all be fired\n * once the hook is triggered.\n *\n * @see Core#addHook\n * @param {string} key Hook name.\n * @param {Function|Array} callback Callback function or an array of functions.\n * @param {object} [context=null] The context for the hook callback to be added - a Handsontable instance or leave empty.\n * @param {number} [orderIndex] Order index of the callback.\n * If > 0, the callback will be added after the others, for example, with an index of 1, the callback will be added before the ones with an index of 2, 3, etc., but after the ones with an index of 0 and lower.\n * If < 0, the callback will be added before the others, for example, with an index of -1, the callback will be added after the ones with an index of -2, -3, etc., but before the ones with an index of 0 and higher.\n * If 0 or no order index is provided, the callback will be added between the \"negative\" and \"positive\" indexes.\n * @returns {Hooks} Instance of Hooks.\n *\n * @example\n * ```js\n * // single callback, added locally\n * Handsontable.hooks.add('beforeInit', myCallback, hotInstance);\n *\n * // single callback, added globally\n * Handsontable.hooks.add('beforeInit', myCallback);\n *\n * // multiple callbacks, added locally\n * Handsontable.hooks.add('beforeInit', [myCallback, anotherCallback], hotInstance);\n *\n * // multiple callbacks, added globally\n * Handsontable.hooks.add('beforeInit', [myCallback, anotherCallback]);\n * ```\n */\n add(key, callback) {\n let context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n let orderIndex = arguments.length > 3 ? arguments[3] : undefined;\n if (Array.isArray(callback)) {\n arrayEach(callback, c => this.add(key, c, context));\n } else {\n if (REMOVED_HOOKS.has(key)) {\n warn(substitute(REMOVED_MESSAGE, {\n hookName: key,\n removedInVersion: REMOVED_HOOKS.get(key)\n }));\n }\n if (DEPRECATED_HOOKS.has(key)) {\n warn(DEPRECATED_HOOKS.get(key));\n }\n const bucket = this.getBucket(context);\n if (typeof bucket[key] === 'undefined') {\n this.register(key);\n bucket[key] = [];\n this.initOrderMap(bucket, key);\n }\n callback.skip = false;\n if (bucket[key].indexOf(callback) === -1) {\n // only add a hook if it has not already been added (adding the same hook twice is now silently ignored)\n let foundInitialHook = false;\n if (callback.initialHook) {\n arrayEach(bucket[key], (cb, i) => {\n if (cb.initialHook) {\n bucket[key][i] = callback;\n foundInitialHook = true;\n return false;\n }\n });\n }\n if (!foundInitialHook) {\n bucket[key].push(callback);\n }\n }\n this.setCallbackOrderIndex(bucket, key, callback, orderIndex);\n this.orderBucketByOrderIndex(bucket, key);\n }\n return this;\n }\n\n /**\n * Adds a listener to a specified hook. After the hook runs this listener will be automatically removed from the bucket.\n *\n * @see Core#addHookOnce\n * @param {string} key Hook/Event name.\n * @param {Function|Array} callback Callback function.\n * @param {object} [context=null] A Handsontable instance.\n * @param {number} [orderIndex] Order index of the callback.\n * If > 0, the callback will be added after the others, for example, with an index of 1, the callback will be added before the ones with an index of 2, 3, etc., but after the ones with an index of 0 and lower.\n * If < 0, the callback will be added before the others, for example, with an index of -1, the callback will be added after the ones with an index of -2, -3, etc., but before the ones with an index of 0 and higher.\n * If 0 or no order index is provided, the callback will be added between the \"negative\" and \"positive\" indexes.\n *\n * @example\n * ```js\n * Handsontable.hooks.once('beforeInit', myCallback, hotInstance);\n * ```\n */\n once(key, callback) {\n let context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n let orderIndex = arguments.length > 3 ? arguments[3] : undefined;\n if (Array.isArray(callback)) {\n arrayEach(callback, c => this.once(key, c, context));\n } else {\n callback.runOnce = true;\n this.add(key, callback, context, orderIndex);\n }\n }\n\n /**\n * Removes a listener from a hook with a given name. If the `context` argument is provided, it removes a listener from a local hook assigned to the given Handsontable instance.\n *\n * @see Core#removeHook\n * @param {string} key Hook/Event name.\n * @param {Function} callback Callback function (needs the be the function that was previously added to the hook).\n * @param {object} [context=null] Handsontable instance.\n * @returns {boolean} Returns `true` if hook was removed, `false` otherwise.\n *\n * @example\n * ```js\n * Handsontable.hooks.remove('beforeInit', myCallback);\n * ```\n */\n remove(key, callback) {\n let context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n const bucket = this.getBucket(context);\n if (typeof bucket[key] !== 'undefined') {\n if (bucket[key].indexOf(callback) >= 0) {\n callback.skip = true;\n return true;\n }\n }\n return false;\n }\n\n /**\n * Checks whether there are any registered listeners for the provided hook name.\n * If the `context` parameter is provided, it only checks for listeners assigned to the given Handsontable instance.\n *\n * @param {string} key Hook name.\n * @param {object} [context=null] A Handsontable instance.\n * @returns {boolean} `true` for success, `false` otherwise.\n */\n has(key) {\n let context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n const bucket = this.getBucket(context);\n return !!(bucket[key] !== undefined && bucket[key].length);\n }\n\n /**\n * Runs all local and global callbacks assigned to the hook identified by the `key` parameter.\n * It returns either a return value from the last called callback or the first parameter (`p1`) passed to the `run` function.\n *\n * @see Core#runHooks\n * @param {object} context Handsontable instance.\n * @param {string} key Hook/Event name.\n * @param {*} [p1] Parameter to be passed as an argument to the callback function.\n * @param {*} [p2] Parameter to be passed as an argument to the callback function.\n * @param {*} [p3] Parameter to be passed as an argument to the callback function.\n * @param {*} [p4] Parameter to be passed as an argument to the callback function.\n * @param {*} [p5] Parameter to be passed as an argument to the callback function.\n * @param {*} [p6] Parameter to be passed as an argument to the callback function.\n * @returns {*} Either a return value from the last called callback or `p1`.\n *\n * @example\n * ```js\n * Handsontable.hooks.run(hot, 'beforeInit');\n * ```\n */\n run(context, key, p1, p2, p3, p4, p5, p6) {\n {\n const globalHandlers = this.globalBucket[key];\n const length = globalHandlers ? globalHandlers.length : 0;\n let index = 0;\n if (length) {\n // Do not optimise this loop with arrayEach or arrow function! If you do You'll decrease perf because of GC.\n while (index < length) {\n if (!globalHandlers[index] || globalHandlers[index].skip) {\n index += 1;\n /* eslint-disable no-continue */\n continue;\n }\n const res = fastCall(globalHandlers[index], context, p1, p2, p3, p4, p5, p6);\n if (res !== undefined) {\n // eslint-disable-next-line no-param-reassign\n p1 = res;\n }\n if (globalHandlers[index] && globalHandlers[index].runOnce) {\n this.remove(key, globalHandlers[index]);\n }\n index += 1;\n }\n }\n }\n {\n const localHandlers = this.getBucket(context)[key];\n const length = localHandlers ? localHandlers.length : 0;\n let index = 0;\n if (length) {\n // Do not optimise this loop with arrayEach or arrow function! If you do You'll decrease perf because of GC.\n while (index < length) {\n if (!localHandlers[index] || localHandlers[index].skip) {\n index += 1;\n /* eslint-disable no-continue */\n continue;\n }\n const res = fastCall(localHandlers[index], context, p1, p2, p3, p4, p5, p6);\n if (res !== undefined) {\n // eslint-disable-next-line no-param-reassign\n p1 = res;\n }\n if (localHandlers[index] && localHandlers[index].runOnce) {\n this.remove(key, localHandlers[index], context);\n }\n index += 1;\n }\n }\n }\n return p1;\n }\n\n /**\n * Destroy all listeners connected to the context. If no context is provided, the global listeners will be destroyed.\n *\n * @param {object} [context=null] A Handsontable instance.\n * @example\n * ```js\n * // destroy the global listeners\n * Handsontable.hooks.destroy();\n *\n * // destroy the local listeners\n * Handsontable.hooks.destroy(hotInstance);\n * ```\n */\n destroy() {\n let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n // eslint-disable-next-line no-return-assign\n objectEach(this.getBucket(context), (value, key, bucket) => bucket[key].length = 0);\n }\n\n /**\n * Registers a hook name (adds it to the list of the known hook names). Used by plugins.\n * It is not necessary to call register, but if you use it, your plugin hook will be used returned by\n * the `getRegistered` method. (which itself is used in the [demo](@/guides/getting-started/events-and-hooks/events-and-hooks.md)).\n *\n * @param {string} key The hook name.\n *\n * @example\n * ```js\n * Handsontable.hooks.register('myHook');\n * ```\n */\n register(key) {\n if (!this.isRegistered(key)) {\n REGISTERED_HOOKS.push(key);\n }\n }\n\n /**\n * Deregisters a hook name (removes it from the list of known hook names).\n *\n * @param {string} key The hook name.\n *\n * @example\n * ```js\n * Handsontable.hooks.deregister('myHook');\n * ```\n */\n deregister(key) {\n if (this.isRegistered(key)) {\n REGISTERED_HOOKS.splice(REGISTERED_HOOKS.indexOf(key), 1);\n }\n }\n\n /**\n * Returns a boolean value depending on if a hook by such name has been removed or deprecated.\n *\n * @param {string} hookName The hook name to check.\n * @returns {boolean} Returns `true` if the provided hook name was marked as deprecated or\n * removed from API, `false` otherwise.\n * @example\n * ```js\n * Handsontable.hooks.isDeprecated('skipLengthCache');\n *\n * // Results:\n * true\n * ```\n */\n isDeprecated(hookName) {\n return DEPRECATED_HOOKS.has(hookName) || REMOVED_HOOKS.has(hookName);\n }\n\n /**\n * Returns a boolean depending on if a hook by such name has been registered.\n *\n * @param {string} hookName The hook name to check.\n * @returns {boolean} `true` for success, `false` otherwise.\n * @example\n * ```js\n * Handsontable.hooks.isRegistered('beforeInit');\n *\n * // Results:\n * true\n * ```\n */\n isRegistered(hookName) {\n return REGISTERED_HOOKS.indexOf(hookName) >= 0;\n }\n\n /**\n * Returns an array of registered hooks.\n *\n * @returns {Array} An array of registered hooks.\n *\n * @example\n * ```js\n * Handsontable.hooks.getRegistered();\n *\n * // Results:\n * [\n * ...\n * 'beforeInit',\n * 'beforeRender',\n * 'beforeSetRangeEnd',\n * 'beforeDrawBorders',\n * 'beforeChange',\n * ...\n * ]\n * ```\n */\n getRegistered() {\n return REGISTERED_HOOKS;\n }\n\n /**\n * Sets the order index of the callback in the bucket object.\n *\n * @private\n * @param {object} bucket The bucket object.\n * @param {string} key Hook name.\n * @param {Function} callback Callback function.\n * @param {number|undefined} orderIndex Order index of the callback.\n */\n setCallbackOrderIndex(bucket, key, callback, orderIndex) {\n const normalizedOrderIndex = Number.isInteger(orderIndex) ? orderIndex : 0;\n const orderMap = this.getCallbackOrderMap(bucket, key);\n orderMap.set(normalizedOrderIndex, [...(orderMap.get(normalizedOrderIndex) || []), callback]);\n }\n\n /**\n * Reorders the callbacks in the bucket object by their order index.\n *\n * @private\n * @param {objcet} bucket The bucket object.\n * @param {string} key Hook name.\n */\n orderBucketByOrderIndex(bucket, key) {\n const orderMap = this.getCallbackOrderMap(bucket, key);\n if (orderMap === undefined || orderMap.size === 0 || orderMap.size === 1 && orderMap.has(0)) {\n return;\n }\n bucket[key] = [...orderMap].sort((a, b) => a[0] - b[0]).flatMap(_ref => {\n let [, callbacks] = _ref;\n return callbacks;\n });\n }\n\n /**\n * Extends the bucket object with the order property.\n *\n * @private\n * @param {object} bucket The bucket object.\n * @param {string} hook The hook name.\n */\n initOrderMap(bucket, hook) {\n if (!callbackOrder.has(bucket)) {\n callbackOrder.set(bucket, []);\n }\n callbackOrder.get(bucket)[hook] = new Map();\n }\n\n /**\n * Returns the order map for the provided hook.\n *\n * @private\n * @param {object} bucket The bucket object.\n * @param {string} hook The hook name.\n * @returns {Map>} Returns the order map for the provided hook.\n */\n getCallbackOrderMap(bucket, hook) {\n return callbackOrder.get(bucket)[hook];\n }\n}\nconst globalSingleton = new Hooks();\n\n/**\n * @returns {Hooks}\n */\nfunction getGlobalSingleton() {\n return globalSingleton;\n}\nexport default Hooks;","/* eslint-disable no-console */\n/* eslint-disable no-restricted-globals */\n/**\n * \"In Internet Explorer 9 (and 8), the console object is only exposed when the developer tools are opened\n * for a particular tab.\".\n *\n * Source: https://stackoverflow.com/a/5473193.\n */\nimport { isDefined } from \"./mixed.mjs\";\n/**\n * Logs message to the console if the `console` object is exposed.\n *\n * @param {...*} args Values which will be logged.\n */\nexport function log() {\n if (isDefined(console)) {\n console.log(...arguments);\n }\n}\n\n/**\n * Logs warn to the console if the `console` object is exposed.\n *\n * @param {...*} args Values which will be logged.\n */\nexport function warn() {\n if (isDefined(console)) {\n console.warn(...arguments);\n }\n}\n\n/**\n * Logs info to the console if the `console` object is exposed.\n *\n * @param {...*} args Values which will be logged.\n */\nexport function info() {\n if (isDefined(console)) {\n console.info(...arguments);\n }\n}\n\n/**\n * Logs error to the console if the `console` object is exposed.\n *\n * @param {...*} args Values which will be logged.\n */\nexport function error() {\n if (isDefined(console)) {\n console.error(...arguments);\n }\n}","export const collection = new Map();\n\n/**\n * @param {string} namespace The namespace for the storage.\n * @returns {object}\n */\nexport default function staticRegister() {\n let namespace = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'common';\n if (!collection.has(namespace)) {\n collection.set(namespace, new Map());\n }\n const subCollection = collection.get(namespace);\n\n /**\n * Register an item to the collection. If the item under the same was exist earlier then this item will be replaced with new one.\n *\n * @param {string} name Identification of the item.\n * @param {*} item Item to save in the collection.\n */\n function register(name, item) {\n subCollection.set(name, item);\n }\n\n /**\n * Retrieve the item from the collection.\n *\n * @param {string} name Identification of the item.\n * @returns {*} Returns item which was saved in the collection.\n */\n function getItem(name) {\n return subCollection.get(name);\n }\n\n /**\n * Check if item under specified name is exists.\n *\n * @param {string} name Identification of the item.\n * @returns {boolean} Returns `true` or `false` depends on if element exists in the collection.\n */\n function hasItem(name) {\n return subCollection.has(name);\n }\n\n /**\n * Retrieve list of names registered from the collection.\n *\n * @returns {Array} Returns an array of strings with all names under which objects are stored.\n */\n function getNames() {\n return [...subCollection.keys()];\n }\n\n /**\n * Retrieve all registered values from the collection.\n *\n * @returns {Array} Returns an array with all values stored in the collection.\n */\n function getValues() {\n return [...subCollection.values()];\n }\n return {\n register,\n getItem,\n hasItem,\n getNames,\n getValues\n };\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { stopImmediatePropagation as _stopImmediatePropagation } from \"./helpers/dom/event.mjs\";\n/**\n * Counter which tracks unregistered listeners (useful for detecting memory leaks).\n *\n * @type {number}\n */\nlet listenersCounter = 0;\n\n/**\n * Event DOM manager for internal use in Handsontable.\n *\n * @class EventManager\n */\nclass EventManager {\n /**\n * @param {object} [context=null] An object to which event listeners will be stored.\n * @private\n */\n constructor() {\n let context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n /**\n * @type {object}\n */\n _defineProperty(this, \"context\", void 0);\n this.context = context || this;\n\n // TODO it modify external object. Rethink that.\n if (!this.context.eventListeners) {\n this.context.eventListeners = []; // TODO perf It would be more performant if every instance of EventManager tracked its own listeners only\n }\n }\n\n /**\n * Register specified listener (`eventName`) to the element.\n *\n * @param {Element} element Target element.\n * @param {string} eventName Event name.\n * @param {Function} callback Function which will be called after event occur.\n * @param {AddEventListenerOptions|boolean} [options] Listener options if object or useCapture if boolean.\n * @returns {Function} Returns function which you can easily call to remove that event.\n */\n addEventListener(element, eventName, callback) {\n let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n /**\n * @private\n * @param {Event} event The event object.\n */\n function callbackProxy(event) {\n callback.call(this, extendEvent(event));\n }\n this.context.eventListeners.push({\n element,\n event: eventName,\n callback,\n callbackProxy,\n options,\n eventManager: this\n });\n element.addEventListener(eventName, callbackProxy, options);\n listenersCounter += 1;\n return () => {\n this.removeEventListener(element, eventName, callback);\n };\n }\n\n /**\n * Remove the event listener previously registered.\n *\n * @param {Element} element Target element.\n * @param {string} eventName Event name.\n * @param {Function} callback Function to remove from the event target. It must be the same as during registration listener.\n * @param {boolean} [onlyOwnEvents] Whether whould remove only events registered using this instance of EventManager.\n */\n removeEventListener(element, eventName, callback) {\n let onlyOwnEvents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n let len = this.context.eventListeners.length;\n let tmpEvent;\n while (len) {\n len -= 1;\n tmpEvent = this.context.eventListeners[len];\n if (tmpEvent.event === eventName && tmpEvent.element === element) {\n if (callback && callback !== tmpEvent.callback) {\n /* eslint-disable no-continue */\n continue;\n }\n // TODO rethink that, main bulk is that it needs multi instances to handle same context, but with a different scopes.\n // TODO I suppose much more efficient way will be comparing string with scope id, or any similar approach.\n if (onlyOwnEvents && tmpEvent.eventManager !== this) {\n continue;\n }\n this.context.eventListeners.splice(len, 1);\n tmpEvent.element.removeEventListener(tmpEvent.event, tmpEvent.callbackProxy, tmpEvent.options);\n listenersCounter -= 1;\n }\n }\n }\n\n /**\n * Clear all previously registered events.\n *\n * @private\n * @since 0.15.0-beta3\n * @param {boolean} [onlyOwnEvents] Whether whould remove only events registered using this instance of EventManager.\n */\n clearEvents() {\n let onlyOwnEvents = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n if (!this.context) {\n return;\n }\n let len = this.context.eventListeners.length;\n while (len) {\n len -= 1;\n const event = this.context.eventListeners[len];\n if (onlyOwnEvents && event.eventManager !== this) {\n continue;\n }\n this.context.eventListeners.splice(len, 1);\n event.element.removeEventListener(event.event, event.callbackProxy, event.options);\n listenersCounter -= 1;\n }\n }\n\n /**\n * Clear all previously registered events.\n */\n clear() {\n this.clearEvents();\n }\n\n /**\n * Destroy instance of EventManager, clearing all events of the context.\n */\n destroy() {\n this.clearEvents();\n this.context = null;\n }\n\n /**\n * Destroy instance of EventManager, clearing only the own events.\n */\n destroyWithOwnEventsOnly() {\n this.clearEvents(true);\n this.context = null;\n }\n\n /**\n * Trigger event at the specified target element.\n *\n * @param {Element} element Target element.\n * @param {string} eventName Event name.\n */\n fireEvent(element, eventName) {\n let rootDocument = element.document;\n let rootWindow = element;\n if (!rootDocument) {\n rootDocument = element.ownerDocument ? element.ownerDocument : element;\n rootWindow = rootDocument.defaultView;\n }\n const options = {\n bubbles: true,\n cancelable: eventName !== 'mousemove',\n view: rootWindow,\n detail: 0,\n screenX: 0,\n screenY: 0,\n clientX: 1,\n clientY: 1,\n ctrlKey: false,\n altKey: false,\n shiftKey: false,\n metaKey: false,\n button: 0,\n relatedTarget: undefined\n };\n let event;\n if (rootDocument.createEvent) {\n event = rootDocument.createEvent('MouseEvents');\n event.initMouseEvent(eventName, options.bubbles, options.cancelable, options.view, options.detail, options.screenX, options.screenY, options.clientX, options.clientY, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, options.relatedTarget || rootDocument.body.parentNode);\n } else {\n event = rootDocument.createEventObject();\n }\n if (element.dispatchEvent) {\n element.dispatchEvent(event);\n } else {\n element.fireEvent(`on${eventName}`, event);\n }\n }\n}\n\n/**\n * @private\n * @param {Event} event The event object.\n * @returns {Event}\n */\nfunction extendEvent(event) {\n const nativeStopImmediatePropagation = event.stopImmediatePropagation;\n event.stopImmediatePropagation = function () {\n nativeStopImmediatePropagation.apply(this);\n _stopImmediatePropagation(this);\n };\n return event;\n}\nexport default EventManager;\n\n/**\n * @private\n * @returns {number}\n */\nexport function getListenersCounter() {\n return listenersCounter;\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { warn } from \"./helpers/console.mjs\";\nimport { isOutsideInput } from \"./helpers/dom/element.mjs\";\nimport { debounce } from \"./helpers/function.mjs\";\n/**\n * Possible focus modes.\n * - CELL - The browser's focus stays on the lastly selected cell element.\n * - MIXED - The browser's focus switches from the lastly selected cell element to the currently active editor's\n * `TEXTAREA` element after a delay defined in the manager.\n *\n * @type {{CELL: string, MIXED: string}}\n */\nconst FOCUS_MODES = Object.freeze({\n CELL: 'cell',\n MIXED: 'mixed'\n});\n\n/**\n * Manages the browser's focus in the table.\n */\nvar _hot = /*#__PURE__*/new WeakMap();\nvar _focusMode = /*#__PURE__*/new WeakMap();\nvar _refocusDelay = /*#__PURE__*/new WeakMap();\nvar _refocusElementGetter = /*#__PURE__*/new WeakMap();\nvar _debouncedSelect = /*#__PURE__*/new WeakMap();\nvar _FocusManager_brand = /*#__PURE__*/new WeakSet();\nexport class FocusManager {\n constructor(hotInstance) {\n var _this = this;\n /**\n * Get and return the currently selected and highlighted cell/header element.\n *\n * @param {Function} callback Callback function to be called after the cell element is retrieved.\n */\n _classPrivateMethodInitSpec(this, _FocusManager_brand);\n /**\n * The Handsontable instance.\n */\n _classPrivateFieldInitSpec(this, _hot, void 0);\n /**\n * The currently enabled focus mode.\n * Can be either:\n *\n * - 'cell' - The browser's focus stays on the lastly selected cell element.\n * - 'mixed' - The browser's focus switches from the lastly selected cell element to the currently active editor's\n * `TEXTAREA` element after a delay defined in the manager.\n *\n * @type {'cell' | 'mixed'}\n */\n _classPrivateFieldInitSpec(this, _focusMode, void 0);\n /**\n * The delay after which the focus switches from the lastly selected cell to the active editor's `TEXTAREA`\n * element if the focus mode is set to 'mixed'.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _refocusDelay, 1);\n /**\n * Getter function for the element to be used when refocusing the browser after a delay. If `null`, the active\n * editor's `TEXTAREA` element will be used.\n *\n * @type {null|Function}\n */\n _classPrivateFieldInitSpec(this, _refocusElementGetter, null);\n /**\n * Map of the debounced `select` functions.\n *\n * @type {Map}\n */\n _classPrivateFieldInitSpec(this, _debouncedSelect, new Map());\n const hotSettings = hotInstance.getSettings();\n _classPrivateFieldSet(_hot, this, hotInstance);\n _classPrivateFieldSet(_focusMode, this, hotSettings.imeFastEdit ? FOCUS_MODES.MIXED : FOCUS_MODES.CELL);\n _classPrivateFieldGet(_hot, this).addHook('afterUpdateSettings', function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return _assertClassBrand(_FocusManager_brand, _this, _onUpdateSettings).call(_this, ...args);\n });\n _classPrivateFieldGet(_hot, this).addHook('afterSelection', function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return _assertClassBrand(_FocusManager_brand, _this, _focusCell).call(_this, ...args);\n });\n _classPrivateFieldGet(_hot, this).addHook('afterSelectionFocusSet', function () {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n return _assertClassBrand(_FocusManager_brand, _this, _focusCell).call(_this, ...args);\n });\n _classPrivateFieldGet(_hot, this).addHook('afterSelectionEnd', function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return _assertClassBrand(_FocusManager_brand, _this, _focusEditorElement).call(_this, ...args);\n });\n }\n\n /**\n * Get the current focus mode.\n *\n * @returns {'cell' | 'mixed'}\n */\n getFocusMode() {\n return _classPrivateFieldGet(_focusMode, this);\n }\n\n /**\n * Set the focus mode.\n *\n * @param {'cell' | 'mixed'} focusMode The new focus mode.\n */\n setFocusMode(focusMode) {\n if (Object.values(FOCUS_MODES).includes(focusMode)) {\n _classPrivateFieldSet(_focusMode, this, focusMode);\n } else {\n warn(`\"${focusMode}\" is not a valid focus mode.`);\n }\n }\n\n /**\n * Get the delay after which the focus will change from the cell elements to the active editor's `TEXTAREA`\n * element if the focus mode is set to 'mixed'.\n *\n * @returns {number} Delay in milliseconds.\n */\n getRefocusDelay() {\n return _classPrivateFieldGet(_refocusDelay, this);\n }\n\n /**\n * Set the delay after which the focus will change from the cell elements to the active editor's `TEXTAREA`\n * element if the focus mode is set to 'mixed'.\n *\n * @param {number} delay Delay in milliseconds.\n */\n setRefocusDelay(delay) {\n _classPrivateFieldSet(_refocusDelay, this, delay);\n }\n\n /**\n * Set the function to be used as the \"refocus element\" getter. It should return a focusable HTML element.\n *\n * @param {Function} getRefocusElementFunction The refocus element getter.\n */\n setRefocusElementGetter(getRefocusElementFunction) {\n _classPrivateFieldSet(_refocusElementGetter, this, getRefocusElementFunction);\n }\n\n /**\n * Get the element to be used when refocusing the browser after a delay in case of the focus mode being 'mixed'.\n *\n * @returns {HTMLTextAreaElement|HTMLElement|undefined}\n */\n getRefocusElement() {\n if (typeof _classPrivateFieldGet(_refocusElementGetter, this) === 'function') {\n return _classPrivateFieldGet(_refocusElementGetter, this).call(this);\n } else {\n var _classPrivateFieldGet2;\n return (_classPrivateFieldGet2 = _classPrivateFieldGet(_hot, this).getActiveEditor()) === null || _classPrivateFieldGet2 === void 0 ? void 0 : _classPrivateFieldGet2.TEXTAREA;\n }\n }\n\n /**\n * Set the browser's focus to the highlighted cell of the last selection.\n *\n * @param {HTMLTableCellElement} [selectedCell] The highlighted cell/header element.\n */\n focusOnHighlightedCell(selectedCell) {\n const focusElement = element => {\n var _classPrivateFieldGet3, _classPrivateFieldGet4;\n const currentHighlightCoords = (_classPrivateFieldGet3 = _classPrivateFieldGet(_hot, this).getSelectedRangeLast()) === null || _classPrivateFieldGet3 === void 0 ? void 0 : _classPrivateFieldGet3.highlight;\n if (!currentHighlightCoords) {\n return;\n }\n let elementToBeFocused = _classPrivateFieldGet(_hot, this).runHooks('modifyFocusedElement', currentHighlightCoords.row, currentHighlightCoords.col, element);\n if (!(elementToBeFocused instanceof HTMLElement)) {\n elementToBeFocused = element;\n }\n if (elementToBeFocused && !((_classPrivateFieldGet4 = _classPrivateFieldGet(_hot, this).getActiveEditor()) !== null && _classPrivateFieldGet4 !== void 0 && _classPrivateFieldGet4.isOpened())) {\n elementToBeFocused.focus({\n preventScroll: true\n });\n }\n };\n if (selectedCell) {\n focusElement(selectedCell);\n } else {\n _assertClassBrand(_FocusManager_brand, this, _getSelectedCell).call(this, element => focusElement(element));\n }\n }\n\n /**\n * Set the focus to the active editor's `TEXTAREA` element after the provided delay. If no delay is provided, it\n * will be taken from the manager's configuration.\n *\n * @param {number} [delay] Delay in milliseconds.\n */\n refocusToEditorTextarea() {\n var _classPrivateFieldGet5;\n let delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _classPrivateFieldGet(_refocusDelay, this);\n const refocusElement = this.getRefocusElement();\n\n // Re-focus on the editor's `TEXTAREA` element (or a predefined element) if the `imeFastEdit` option is enabled.\n if (_classPrivateFieldGet(_hot, this).getSettings().imeFastEdit && !((_classPrivateFieldGet5 = _classPrivateFieldGet(_hot, this).getActiveEditor()) !== null && _classPrivateFieldGet5 !== void 0 && _classPrivateFieldGet5.isOpened()) && !!refocusElement) {\n if (!_classPrivateFieldGet(_debouncedSelect, this).has(delay)) {\n _classPrivateFieldGet(_debouncedSelect, this).set(delay, debounce(() => {\n refocusElement.select();\n }, delay));\n }\n _classPrivateFieldGet(_debouncedSelect, this).get(delay)();\n }\n }\n}\nfunction _getSelectedCell(callback) {\n var _classPrivateFieldGet6;\n const highlight = (_classPrivateFieldGet6 = _classPrivateFieldGet(_hot, this).getSelectedRangeLast()) === null || _classPrivateFieldGet6 === void 0 ? void 0 : _classPrivateFieldGet6.highlight;\n if (!highlight || !_classPrivateFieldGet(_hot, this).selection.isCellVisible(highlight)) {\n callback(null);\n return;\n }\n const cell = _classPrivateFieldGet(_hot, this).getCell(highlight.row, highlight.col, true);\n if (cell === null) {\n _classPrivateFieldGet(_hot, this).addHookOnce('afterScroll', () => {\n callback(_classPrivateFieldGet(_hot, this).getCell(highlight.row, highlight.col, true));\n });\n } else {\n callback(cell);\n }\n}\n/**\n * Manage the browser's focus after each cell selection change.\n */\nfunction _focusCell() {\n _assertClassBrand(_FocusManager_brand, this, _getSelectedCell).call(this, selectedCell => {\n const {\n activeElement\n } = _classPrivateFieldGet(_hot, this).rootDocument;\n\n // Blurring the `activeElement` removes the unwanted border around the focusable element (#6877)\n // and resets the `document.activeElement` property. The blurring should happen only when the\n // previously selected input element has not belonged to the Handsontable editor. If blurring is\n // triggered for all elements, there is a problem with the disappearing IME editor (#9672).\n if (activeElement && isOutsideInput(activeElement)) {\n activeElement.blur();\n }\n this.focusOnHighlightedCell(selectedCell);\n });\n}\n/**\n * Manage the browser's focus after cell selection end.\n */\nfunction _focusEditorElement() {\n _assertClassBrand(_FocusManager_brand, this, _getSelectedCell).call(this, selectedCell => {\n if (this.getFocusMode() === FOCUS_MODES.MIXED && selectedCell.nodeName === 'TD') {\n this.refocusToEditorTextarea();\n }\n });\n}\n/**\n * Update the manager configuration after calling `updateSettings`.\n *\n * @param {object} newSettings The new settings passed to the `updateSettings` method.\n */\nfunction _onUpdateSettings(newSettings) {\n if (typeof newSettings.imeFastEdit === 'boolean') {\n this.setFocusMode(newSettings.imeFastEdit ? FOCUS_MODES.MIXED : FOCUS_MODES.CELL);\n }\n}","import \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/es.string.replace-all.js\";\nimport { isEmpty } from \"./../helpers/mixed.mjs\";\nconst ESCAPED_HTML_CHARS = {\n ' ': '\\x20',\n '&': '&',\n '<': '<',\n '>': '>'\n};\nconst regEscapedChars = new RegExp(Object.keys(ESCAPED_HTML_CHARS).map(key => `(${key})`).join('|'), 'gi');\n\n/**\n * Verifies if node is an HTMLTable element.\n *\n * @param {Node} element Node to verify if it's an HTMLTable.\n * @returns {boolean}\n */\nfunction isHTMLTable(element) {\n return (element && element.nodeName || '') === 'TABLE';\n}\n\n/**\n * Converts Handsontable into HTMLTableElement.\n *\n * @param {Core} instance The Handsontable instance.\n * @returns {string} OuterHTML of the HTMLTableElement.\n */\nexport function instanceToHTML(instance) {\n const hasColumnHeaders = instance.hasColHeaders();\n const hasRowHeaders = instance.hasRowHeaders();\n const coords = [hasColumnHeaders ? -1 : 0, hasRowHeaders ? -1 : 0, instance.countRows() - 1, instance.countCols() - 1];\n const data = instance.getData(...coords);\n const countRows = data.length;\n const countCols = countRows > 0 ? data[0].length : 0;\n const TABLE = ['
');\n return result.join('');\n}\n\n/**\n * Converts HTMLTable or string into Handsontable configuration object.\n *\n * @param {Element|string} element Node element which should contain `
...
`.\n * @param {Document} [rootDocument] The document window owner.\n * @returns {object} Return configuration object. Contains keys as DefaultSettings.\n */\n// eslint-disable-next-line no-restricted-globals\nexport function htmlToGridSettings(element) {\n let rootDocument = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n const settingsObj = {};\n const fragment = rootDocument.createDocumentFragment();\n const tempElem = rootDocument.createElement('div');\n fragment.appendChild(tempElem);\n let checkElement = element;\n if (typeof checkElement === 'string') {\n const escapedAdjacentHTML = checkElement.replace(/
]*?>/g)[0];\n const paragraphRegexp = //g;\n const cellValue = cellFragment.substring(openingTag.length, cellFragment.lastIndexOf('<')).trim() // Removing whitespaces from the start and the end of HTML fragment\n .replaceAll(/\\n\\s+/g, ' ') // HTML tags may be split using multiple new lines and whitespaces\n .replaceAll(paragraphRegexp, '\\n') // Only paragraphs should split text using new line characters\n .replace('\\n', '') // First paragraph shouldn't start with new line characters\n .replaceAll(/<\\/(.*)>\\s+$/mg, '$1>') // HTML tags may end with whitespace.\n .replace(/(<(?!br)([^>]+)>)/gi, '') // Removing HTML tags\n .replaceAll(/^ $/mg, ''); // Removing single characters separating new lines\n const closingTag = '
';\n return `${openingTag}${cellValue}${closingTag}`;\n });\n tempElem.insertAdjacentHTML('afterbegin', `${escapedAdjacentHTML}`);\n checkElement = tempElem.querySelector('table');\n }\n if (!checkElement || !isHTMLTable(checkElement)) {\n return;\n }\n const generator = tempElem.querySelector('meta[name$=\"enerator\"]');\n const hasRowHeaders = checkElement.querySelector('tbody th') !== null;\n const trElement = checkElement.querySelector('tr');\n const countCols = !trElement ? 0 : Array.from(trElement.cells).reduce((cols, cell) => cols + cell.colSpan, 0) - (hasRowHeaders ? 1 : 0);\n const fixedRowsBottom = checkElement.tFoot && Array.from(checkElement.tFoot.rows) || [];\n const fixedRowsTop = [];\n let hasColHeaders = false;\n let thRowsLen = 0;\n let countRows = 0;\n if (checkElement.tHead) {\n const thRows = Array.from(checkElement.tHead.rows).filter(tr => {\n const isDataRow = tr.querySelector('td') !== null;\n if (isDataRow) {\n fixedRowsTop.push(tr);\n }\n return !isDataRow;\n });\n thRowsLen = thRows.length;\n hasColHeaders = thRowsLen > 0;\n if (thRowsLen > 1) {\n settingsObj.nestedHeaders = Array.from(thRows).reduce((rows, row) => {\n const headersRow = Array.from(row.cells).reduce((headers, header, currentIndex) => {\n if (hasRowHeaders && currentIndex === 0) {\n return headers;\n }\n const {\n colSpan: colspan,\n innerHTML\n } = header;\n const nextHeader = colspan > 1 ? {\n label: innerHTML,\n colspan\n } : innerHTML;\n headers.push(nextHeader);\n return headers;\n }, []);\n rows.push(headersRow);\n return rows;\n }, []);\n } else if (hasColHeaders) {\n settingsObj.colHeaders = Array.from(thRows[0].children).reduce((headers, header, index) => {\n if (hasRowHeaders && index === 0) {\n return headers;\n }\n headers.push(header.innerHTML);\n return headers;\n }, []);\n }\n }\n if (fixedRowsTop.length) {\n settingsObj.fixedRowsTop = fixedRowsTop.length;\n }\n if (fixedRowsBottom.length) {\n settingsObj.fixedRowsBottom = fixedRowsBottom.length;\n }\n const dataRows = [...fixedRowsTop, ...Array.from(checkElement.tBodies).reduce((sections, section) => {\n sections.push(...Array.from(section.rows));\n return sections;\n }, []), ...fixedRowsBottom];\n countRows = dataRows.length;\n const dataArr = new Array(countRows);\n for (let r = 0; r < countRows; r++) {\n dataArr[r] = new Array(countCols);\n }\n const mergeCells = [];\n const rowHeaders = [];\n for (let row = 0; row < countRows; row++) {\n const tr = dataRows[row];\n const cells = Array.from(tr.cells);\n const cellsLen = cells.length;\n for (let cellId = 0; cellId < cellsLen; cellId++) {\n const cell = cells[cellId];\n const {\n nodeName,\n innerHTML,\n rowSpan: rowspan,\n colSpan: colspan\n } = cell;\n const col = dataArr[row].findIndex(value => value === undefined);\n if (nodeName === 'TD') {\n if (rowspan > 1 || colspan > 1) {\n for (let rstart = row; rstart < row + rowspan; rstart++) {\n if (rstart < countRows) {\n for (let cstart = col; cstart < col + colspan; cstart++) {\n dataArr[rstart][cstart] = null;\n }\n }\n }\n const styleAttr = cell.getAttribute('style');\n const ignoreMerge = styleAttr && styleAttr.includes('mso-ignore:colspan');\n if (!ignoreMerge) {\n mergeCells.push({\n col,\n row,\n rowspan,\n colspan\n });\n }\n }\n let cellValue = '';\n if (generator && /excel/gi.test(generator.content)) {\n cellValue = innerHTML.replace(/[\\r\\n][\\x20]{0,2}/g, '\\x20').replace(/ [\\r\\n]?[\\x20]{0,3}/gim, '\\r\\n');\n } else {\n cellValue = innerHTML.replace(/ [\\r\\n]?/gim, '\\r\\n');\n }\n dataArr[row][col] = cellValue.replace(regEscapedChars, match => ESCAPED_HTML_CHARS[match]);\n } else {\n rowHeaders.push(innerHTML);\n }\n }\n }\n if (mergeCells.length) {\n settingsObj.mergeCells = mergeCells;\n }\n if (rowHeaders.length) {\n settingsObj.rowHeaders = rowHeaders;\n }\n if (dataArr.length) {\n settingsObj.data = dataArr;\n }\n return settingsObj;\n}","import \"core-js/modules/es.error.cause.js\";\n/**\n * Utility to register plugins and common namespace for keeping the reference to all plugins classes.\n */\nimport { toUpperCaseFirst } from \"../helpers/string.mjs\";\nimport { createPriorityMap } from \"../utils/dataStructures/priorityMap.mjs\";\nimport { createUniqueMap } from \"../utils/dataStructures/uniqueMap.mjs\";\nimport { createUniqueSet } from \"../utils/dataStructures/uniqueSet.mjs\";\nconst ERROR_PLUGIN_REGISTERED = pluginName => `There is already registered \"${pluginName}\" plugin.`;\nconst ERROR_PRIORITY_REGISTERED = priority => `There is already registered plugin on priority \"${priority}\".`;\nconst ERROR_PRIORITY_NAN = priority => `The priority \"${priority}\" is not a number.`;\n\n/**\n * Stores plugins' names' queue with their priorities.\n */\nconst priorityPluginsQueue = createPriorityMap({\n errorPriorityExists: ERROR_PRIORITY_REGISTERED,\n errorPriorityNaN: ERROR_PRIORITY_NAN\n});\n/**\n * Stores plugins names' queue by registration order.\n */\nconst uniquePluginsQueue = createUniqueSet({\n errorItemExists: ERROR_PLUGIN_REGISTERED\n});\n/**\n * Stores plugins references between their name and class.\n */\nconst uniquePluginsList = createUniqueMap({\n errorIdExists: ERROR_PLUGIN_REGISTERED\n});\n\n/**\n * Gets registered plugins' names in the following order:\n * 1) Plugins registered with a defined priority attribute, in the ascending order of priority.\n * 2) Plugins registered without a defined priority attribute, in the registration order.\n *\n * @returns {string[]}\n */\nexport function getPluginsNames() {\n return [...priorityPluginsQueue.getItems(), ...uniquePluginsQueue.getItems()];\n}\n\n/**\n * Gets registered plugin's class based on the given name.\n *\n * @param {string} pluginName Plugin's name.\n * @returns {BasePlugin}\n */\nexport function getPlugin(pluginName) {\n const unifiedPluginName = toUpperCaseFirst(pluginName);\n return uniquePluginsList.getItem(unifiedPluginName);\n}\n\n/**\n * Checks if the plugin under the name is already registered.\n *\n * @param {string} pluginName Plugin's name.\n * @returns {boolean}\n */\nexport function hasPlugin(pluginName) {\n /* eslint-disable no-unneeded-ternary */\n return getPlugin(pluginName) ? true : false;\n}\n\n/**\n * Registers plugin under the given name only once.\n *\n * @param {string|Function} pluginName The plugin name or plugin class.\n * @param {Function} [pluginClass] The plugin class.\n * @param {number} [priority] The plugin priority.\n */\nexport function registerPlugin(pluginName, pluginClass, priority) {\n [pluginName, pluginClass, priority] = unifyPluginArguments(pluginName, pluginClass, priority);\n if (getPlugin(pluginName) === undefined) {\n _registerPlugin(pluginName, pluginClass, priority);\n }\n}\n\n/**\n * Registers plugin under the given name.\n *\n * @param {string|Function} pluginName The plugin name or plugin class.\n * @param {Function} [pluginClass] The plugin class.\n * @param {number} [priority] The plugin priority.\n */\nfunction _registerPlugin(pluginName, pluginClass, priority) {\n const unifiedPluginName = toUpperCaseFirst(pluginName);\n if (uniquePluginsList.hasItem(unifiedPluginName)) {\n throw new Error(ERROR_PLUGIN_REGISTERED(unifiedPluginName));\n }\n if (priority === undefined) {\n uniquePluginsQueue.addItem(unifiedPluginName);\n } else {\n priorityPluginsQueue.addItem(priority, unifiedPluginName);\n }\n uniquePluginsList.addItem(unifiedPluginName, pluginClass);\n}\n\n/**\n * Unifies arguments to register the plugin.\n *\n * @param {string|Function} pluginName The plugin name or plugin class.\n * @param {Function} [pluginClass] The plugin class.\n * @param {number} [priority] The plugin priority.\n * @returns {Array}\n */\nfunction unifyPluginArguments(pluginName, pluginClass, priority) {\n if (typeof pluginName === 'function') {\n pluginClass = pluginName;\n pluginName = pluginClass.PLUGIN_KEY;\n priority = pluginClass.PLUGIN_PRIORITY;\n }\n return [pluginName, pluginClass, priority];\n}","import \"core-js/modules/es.error.cause.js\";\nimport { isNumeric } from \"../../helpers/number.mjs\";\nimport { isFunction } from \"../../helpers/function.mjs\";\nexport const ASC = 'asc';\nexport const DESC = 'desc';\nconst ORDER_MAP = new Map([[ASC, [-1, 1]], [DESC, [1, -1]]]);\nconst DEFAULT_ERROR_PRIORITY_EXISTS = priority => `The priority '${priority}' is already declared in a map.`;\nconst DEFAULT_ERROR_PRIORITY_NAN = priority => `The priority '${priority}' is not a number.`;\n\n/**\n * @typedef {object} PriorityMap\n * @property {Function} addItem Adds items to the priority map.\n * @property {Function} getItems Gets items from the passed map in a ASC or DESC order of priorities.\n */\n/**\n * Creates a new priority map.\n *\n * @param {object} config The config for priority map.\n * @param {Function} config.errorPriorityExists The function to generate a custom error message if priority is already taken.\n * @param {Function} config.errorPriorityNaN The function to generate a custom error message if priority is not a number.\n * @returns {PriorityMap}\n */\nexport function createPriorityMap() {\n let {\n errorPriorityExists,\n errorPriorityNaN\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n const priorityMap = new Map();\n errorPriorityExists = isFunction(errorPriorityExists) ? errorPriorityExists : DEFAULT_ERROR_PRIORITY_EXISTS;\n errorPriorityNaN = isFunction(errorPriorityNaN) ? errorPriorityNaN : DEFAULT_ERROR_PRIORITY_NAN;\n\n /**\n * Adds items to priority map. Throws an error if `priority` is not a number or if is already added.\n *\n * @param {number} priority The priority for adding item.\n * @param {*} item The adding item.\n */\n function addItem(priority, item) {\n if (!isNumeric(priority)) {\n throw new Error(errorPriorityNaN(priority));\n }\n if (priorityMap.has(priority)) {\n throw new Error(errorPriorityExists(priority));\n }\n priorityMap.set(priority, item);\n }\n\n /**\n * Gets items from the passed map in a ASC or DESC order of priorities.\n *\n * @param {string} [order] The order for getting items. ASC is an default.\n * @returns {*}\n */\n function getItems() {\n let order = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ASC;\n const [left, right] = ORDER_MAP.get(order) || ORDER_MAP.get(ASC);\n return [...priorityMap]\n // we want to be sure we sort over a priority key\n // if we are sure we can remove custom compare function\n // then we should replace next line with a default `.sort()`\n .sort((a, b) => a[0] < b[0] ? left : right).map(item => item[1]);\n }\n return {\n addItem,\n getItems\n };\n}","import \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * Checks if the passed value is numeric one. For example these values (passed as string or number)\n * are considered as numeric values:\n * - 0.001\n * - .001\n * - 10000\n * - 1e+26\n * - 22e-26\n * - .45e+26\n * - 0xabcdef (hex)\n * - 0x1 (hex)\n *\n * these values are not considered as numeric:\n * - - 1000\n * - 100 000\n *\n * @param {*} value The value to check.\n * @param {string[]} additionalDelimiters An additional delimiters to be used while checking the numeric value.\n * @returns {boolean}\n */\nexport function isNumeric(value) {\n let additionalDelimiters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n const type = typeof value;\n if (type === 'number') {\n return !isNaN(value) && isFinite(value);\n } else if (type === 'string') {\n if (value.length === 0) {\n return false;\n } else if (value.length === 1) {\n return /\\d/.test(value);\n }\n const delimiter = Array.from(new Set(['.', ...additionalDelimiters])).map(d => `\\\\${d}`).join('|');\n return new RegExp(`^[+-]?(((${delimiter})?\\\\d+((${delimiter})\\\\d+)?(e[+-]?\\\\d+)?)|(0x[a-f\\\\d]+))$`, 'i').test(value.trim());\n } else if (type === 'object') {\n return !!value && typeof value.valueOf() === 'number' && !(value instanceof Date);\n }\n return false;\n}\n/* eslint-enable jsdoc/require-description-complete-sentence */\n\n/**\n * Checks if the passed value is numeric-like value. The helper returns `true` for the same\n * values as for the `isNumeric` function plus `true` for numbers delimited by comma.\n *\n * @param {*} value The value to check.\n * @returns {boolean}\n */\nexport function isNumericLike(value) {\n return isNumeric(value, [',']);\n}\n\n/**\n * A specialized version of `.forEach` defined by ranges.\n *\n * @param {number} rangeFrom The number from start iterate.\n * @param {number|Function} rangeTo The number where finish iterate or function as a iteratee.\n * @param {Function} [iteratee] The function invoked per iteration.\n */\nexport function rangeEach(rangeFrom, rangeTo, iteratee) {\n let index = -1;\n if (typeof rangeTo === 'function') {\n iteratee = rangeTo;\n rangeTo = rangeFrom;\n } else {\n index = rangeFrom - 1;\n }\n\n /* eslint-disable-next-line no-plusplus */\n while (++index <= rangeTo) {\n if (iteratee(index) === false) {\n break;\n }\n }\n}\n\n/**\n * A specialized version of `.forEach` defined by ranges iterable in reverse order.\n *\n * @param {number} rangeFrom The number from start iterate.\n * @param {number|Function} rangeTo The number where finish iterate or function as a iteratee.\n * @param {Function} [iteratee] The function invoked per iteration.\n */\nexport function rangeEachReverse(rangeFrom, rangeTo, iteratee) {\n let index = rangeFrom + 1;\n if (typeof rangeTo === 'function') {\n iteratee = rangeTo;\n rangeTo = 0;\n }\n /* eslint-disable-next-line no-plusplus */\n while (--index >= rangeTo) {\n if (iteratee(index) === false) {\n break;\n }\n }\n}\n\n/**\n * Calculate value from percent.\n *\n * @param {number} value Base value from percent will be calculated.\n * @param {string|number} percent Can be number or string (eq. `'33%'`).\n * @returns {number}\n */\nexport function valueAccordingPercent(value, percent) {\n percent = parseInt(percent.toString().replace('%', ''), 10);\n percent = isNaN(percent) ? 0 : percent;\n return parseInt(value * percent / 100, 10);\n}\n\n/**\n * Clamps the value between min and max.\n *\n * @param {number} value The base number value.\n * @param {number} minValue The max number value.\n * @param {number} maxValue The min number value.\n * @returns {number}\n */\nexport function clamp(value, minValue, maxValue) {\n if (Math.min(value, minValue) === value) {\n return minValue;\n } else if (Math.max(value, maxValue) === value) {\n return maxValue;\n }\n return value;\n}","import \"core-js/modules/es.error.cause.js\";\nimport { isFunction } from \"../../helpers/function.mjs\";\nconst DEFAULT_ERROR_ID_EXISTS = id => `The id '${id}' is already declared in a map.`;\n\n/**\n * @typedef {object} UniqueMap\n * @property {Function} addItem Adds a new item to the unique map.\n * @property {Function} clear Clears the map.\n * @property {Function} getId Returns ID for the passed item.\n * @property {Function} getItem Gets item from the passed ID.\n * @property {Function} getItems Gets all items from the map.\n * @property {Function} hasItem Verifies if the passed ID exists in a map.\n * @property {Function} removeItem Removes item from the passed id if exists.\n */\n/**\n * Creates a new unique map.\n *\n * @param {object} config The config for priority queue.\n * @param {Function} config.errorIdExists The function to generate custom message if ID is already taken.\n * @returns {UniqueMap}\n */\nexport function createUniqueMap() {\n let {\n errorIdExists\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n const uniqueMap = new Map();\n errorIdExists = isFunction(errorIdExists) ? errorIdExists : DEFAULT_ERROR_ID_EXISTS;\n\n /**\n * Adds a new item to the unique map. Throws error if `id` is already added.\n *\n * @param {*} id The ID of the adding item.\n * @param {*} item The adding item.\n */\n function addItem(id, item) {\n if (hasItem(id)) {\n throw new Error(errorIdExists(id));\n }\n uniqueMap.set(id, item);\n }\n\n /**\n * Removes item from the passed id if exists.\n *\n * @param {*} id The ID to remove.\n * @returns {boolean}\n */\n function removeItem(id) {\n return uniqueMap.delete(id);\n }\n\n /**\n * Clears the map.\n */\n function clear() {\n uniqueMap.clear();\n }\n\n /**\n * Returns ID for the passed item.\n *\n * @param {*} item The item of the getting ID.\n * @returns {*}\n */\n function getId(item) {\n const [itemId] = getItems().find(_ref => {\n let [id, element] = _ref;\n if (item === element) {\n return id;\n }\n return false;\n }) || [null];\n return itemId;\n }\n\n /**\n * Returns item from the passed ID.\n *\n * @param {*} id The ID of the getting item.\n * @returns {*}\n */\n function getItem(id) {\n return uniqueMap.get(id);\n }\n\n /**\n * Gets all items from the map.\n *\n * @returns {Array}\n */\n function getItems() {\n return [...uniqueMap];\n }\n\n /**\n * Verifies if the passed ID exists in a map.\n *\n * @param {*} id The ID to check if registered.\n * @returns {boolean}\n */\n function hasItem(id) {\n return uniqueMap.has(id);\n }\n return {\n addItem,\n clear,\n getId,\n getItem,\n getItems,\n hasItem,\n removeItem\n };\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nimport { isFunction } from \"../../helpers/function.mjs\";\nconst DEFAULT_ERROR_ITEM_EXISTS = item => `'${item}' value is already declared in a unique set.`;\n\n/**\n * @typedef {object} UniqueSet\n * @property {Function} addItem Adds items to the priority set.\n * @property {Function} getItems Gets items from the set in order of addition.\n */\n/**\n * Creates a new unique set.\n *\n * @param {object} config The config for priority set.\n * @param {Function} config.errorItemExists The function to generate custom error message if item is already in the set.\n * @returns {UniqueSet}\n */\nexport function createUniqueSet() {\n let {\n errorItemExists\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n const uniqueSet = new Set();\n errorItemExists = isFunction(errorItemExists) ? errorItemExists : DEFAULT_ERROR_ITEM_EXISTS;\n\n /**\n * Adds items to the unique set. Throws an error if `item` is already added.\n *\n * @param {*} item The adding item.\n */\n function addItem(item) {\n if (uniqueSet.has(item)) {\n throw new Error(errorItemExists(item));\n }\n uniqueSet.add(item);\n }\n\n /**\n * Gets items from the set in order of addition.\n *\n * @returns {*}\n */\n function getItems() {\n return [...uniqueSet];\n }\n\n /**\n * Clears the unique set.\n */\n function clear() {\n uniqueSet.clear();\n }\n return {\n addItem,\n clear,\n getItems\n };\n}","import \"core-js/modules/es.error.cause.js\";\nimport staticRegister from \"../utils/staticRegister.mjs\";\nconst {\n register,\n getItem,\n hasItem,\n getNames,\n getValues\n} = staticRegister('renderers');\n\n/**\n * Retrieve renderer function.\n *\n * @param {string} name Renderer identification.\n * @returns {Function} Returns renderer function.\n */\nfunction _getItem(name) {\n if (typeof name === 'function') {\n return name;\n }\n if (!hasItem(name)) {\n throw Error(`No registered renderer found under \"${name}\" name`);\n }\n return getItem(name);\n}\n\n/**\n * Register renderer under its alias.\n *\n * @param {string|Function} name Renderer's alias or renderer function with its descriptor.\n * @param {Function} [renderer] Renderer function.\n */\nfunction _register(name, renderer) {\n if (typeof name !== 'string') {\n renderer = name;\n name = renderer.RENDERER_TYPE;\n }\n register(name, renderer);\n}\nexport { _register as registerRenderer, _getItem as getRenderer, hasItem as hasRenderer, getNames as getRegisteredRendererNames, getValues as getRegisteredRenderers };","import \"core-js/modules/es.error.cause.js\";\nimport staticRegister from \"../utils/staticRegister.mjs\";\nconst {\n register,\n getItem,\n hasItem,\n getNames,\n getValues\n} = staticRegister('validators');\n\n/**\n * Retrieve validator function.\n *\n * @param {string} name Validator identification.\n * @returns {Function} Returns validator function.\n */\nfunction _getItem(name) {\n if (typeof name === 'function') {\n return name;\n }\n if (!hasItem(name)) {\n throw Error(`No registered validator found under \"${name}\" name`);\n }\n return getItem(name);\n}\n\n/**\n * Register validator under its alias.\n *\n * @param {string|Function} name Validator's alias or validator function with its descriptor.\n * @param {Function} [validator] Validator function.\n */\nfunction _register(name, validator) {\n if (typeof name !== 'string') {\n validator = name;\n name = validator.VALIDATOR_TYPE;\n }\n register(name, validator);\n}\nexport { _register as registerValidator, _getItem as getValidator, hasItem as hasValidator, getNames as getRegisteredValidatorNames, getValues as getRegisteredValidators };","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { addClass, clearTextSelection, empty, fastInnerHTML, fastInnerText, getScrollbarWidth, hasClass, isChildOf, isInput, isOutsideInput, isVisible, setAttribute, getParentWindow } from \"./helpers/dom/element.mjs\";\nimport EventManager from \"./eventManager.mjs\";\nimport { isImmediatePropagationStopped, isRightClick, isLeftClick } from \"./helpers/dom/event.mjs\";\nimport Walkontable from \"./3rdparty/walkontable/src/index.mjs\";\nimport { handleMouseEvent } from \"./selection/mouseEventHandler.mjs\";\nimport { isRootInstance } from \"./utils/rootInstance.mjs\";\nimport { A11Y_COLCOUNT, A11Y_MULTISELECTABLE, A11Y_PRESENTATION, A11Y_ROWCOUNT, A11Y_TREEGRID } from \"./helpers/a11y.mjs\";\n/**\n * @class TableView\n * @private\n */\nvar _columnHeadersCount = /*#__PURE__*/new WeakMap();\nvar _rowHeadersCount = /*#__PURE__*/new WeakMap();\nvar _selectionMouseDown = /*#__PURE__*/new WeakMap();\nvar _mouseDown = /*#__PURE__*/new WeakMap();\nvar _table = /*#__PURE__*/new WeakMap();\nvar _lastWidth = /*#__PURE__*/new WeakMap();\nvar _lastHeight = /*#__PURE__*/new WeakMap();\nvar _TableView_brand = /*#__PURE__*/new WeakSet();\nclass TableView {\n /**\n * @param {Hanstontable} hotInstance Instance of {@link Handsontable}.\n */\n constructor(hotInstance) {\n /**\n * Return the value of the `aria-colcount` attribute.\n *\n * @returns {number} The value of the `aria-colcount` attribute.\n */\n _classPrivateMethodInitSpec(this, _TableView_brand);\n /**\n * Instance of {@link Handsontable}.\n *\n * @private\n * @type {Handsontable}\n */\n _defineProperty(this, \"hot\", void 0);\n /**\n * Instance of {@link EventManager}.\n *\n * @private\n * @type {EventManager}\n */\n _defineProperty(this, \"eventManager\", void 0);\n /**\n * Current Handsontable's GridSettings object.\n *\n * @private\n * @type {GridSettings}\n */\n _defineProperty(this, \"settings\", void 0);\n /**\n * Main element.\n *\n * @private\n * @type {HTMLTableSectionElement}\n */\n _defineProperty(this, \"THEAD\", void 0);\n /**\n * Main element.\n *\n * @private\n * @type {HTMLTableSectionElement}\n */\n _defineProperty(this, \"TBODY\", void 0);\n /**\n * Main Walkontable instance.\n *\n * @private\n * @type {Walkontable}\n */\n _defineProperty(this, \"_wt\", void 0);\n /**\n * Main Walkontable instance.\n *\n * @type {Walkontable}\n */\n _defineProperty(this, \"activeWt\", void 0);\n /**\n * The total number of the column header renderers applied to the table through the\n * `afterGetColumnHeaderRenderers` hook.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _columnHeadersCount, 0);\n /**\n * The total number of the row header renderers applied to the table through the\n * `afterGetRowHeaderRenderers` hook.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _rowHeadersCount, 0);\n /**\n * The flag determines if the `adjustElementsSize` method call was made during\n * the render suspending. If true, the method has to be triggered once after render\n * resuming.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"postponedAdjustElementsSize\", false);\n /**\n * Defines if the text should be selected during mousemove.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _selectionMouseDown, false);\n /**\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _mouseDown, void 0);\n /**\n * Main
element.\n *\n * @type {HTMLTableElement}\n */\n _classPrivateFieldInitSpec(this, _table, void 0);\n /**\n * Cached width of the rootElement.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _lastWidth, 0);\n /**\n * Cached height of the rootElement.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _lastHeight, 0);\n this.hot = hotInstance;\n this.eventManager = new EventManager(this.hot);\n this.settings = this.hot.getSettings();\n this.createElements();\n this.registerEvents();\n this.initializeWalkontable();\n }\n\n /**\n * Renders WalkontableUI.\n */\n render() {\n if (!this.hot.isRenderSuspended()) {\n this.hot.runHooks('beforeRender', this.hot.forceFullRender);\n if (this.postponedAdjustElementsSize) {\n this.postponedAdjustElementsSize = false;\n this.adjustElementsSize(true);\n }\n this._wt.draw(!this.hot.forceFullRender);\n this.hot.runHooks('afterRender', this.hot.forceFullRender);\n this.hot.forceFullRender = false;\n this.hot.renderCall = false;\n }\n }\n\n /**\n * Adjust overlays elements size and master table size.\n */\n adjustElementsSize() {\n if (this.hot.isRenderSuspended()) {\n this.postponedAdjustElementsSize = true;\n } else {\n this._wt.wtOverlays.adjustElementsSize();\n }\n }\n\n /**\n * Returns td object given coordinates.\n *\n * @param {CellCoords} coords Renderable cell coordinates.\n * @param {boolean} topmost Indicates whether the cell should be calculated from the topmost.\n * @returns {HTMLTableCellElement|null}\n */\n getCellAtCoords(coords, topmost) {\n const td = this._wt.getCell(coords, topmost);\n if (td < 0) {\n // there was an exit code (cell is out of bounds)\n return null;\n }\n return td;\n }\n\n /**\n * Scroll viewport to a cell.\n *\n * @param {CellCoords} coords Renderable cell coordinates.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right side of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom side of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left side of the table.\n * @returns {boolean}\n */\n scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft) {\n return this._wt.scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft);\n }\n\n /**\n * Scroll viewport to a column.\n *\n * @param {number} column Renderable column index.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right side of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left side of the table.\n * @returns {boolean}\n */\n scrollViewportHorizontally(column, snapToRight, snapToLeft) {\n return this._wt.scrollViewportHorizontally(column, snapToRight, snapToLeft);\n }\n\n /**\n * Scroll viewport to a row.\n *\n * @param {number} row Renderable row index.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom side of the table.\n * @returns {boolean}\n */\n scrollViewportVertically(row, snapToTop, snapToBottom) {\n return this._wt.scrollViewportVertically(row, snapToTop, snapToBottom);\n }\n\n /**\n * Prepares DOMElements and adds correct className to the root element.\n *\n * @private\n */\n createElements() {\n const {\n rootElement,\n rootDocument\n } = this.hot;\n const originalStyle = rootElement.getAttribute('style');\n if (originalStyle) {\n rootElement.setAttribute('data-originalstyle', originalStyle); // needed to retrieve original style in jsFiddle link generator in HT examples. may be removed in future versions\n }\n addClass(rootElement, 'handsontable');\n _classPrivateFieldSet(_table, this, rootDocument.createElement('TABLE'));\n addClass(_classPrivateFieldGet(_table, this), 'htCore');\n if (this.hot.getSettings().tableClassName) {\n addClass(_classPrivateFieldGet(_table, this), this.hot.getSettings().tableClassName);\n }\n if (this.settings.ariaTags) {\n setAttribute(_classPrivateFieldGet(_table, this), [A11Y_PRESENTATION()]);\n setAttribute(rootElement, [A11Y_TREEGRID(), A11Y_ROWCOUNT(-1), A11Y_COLCOUNT(this.hot.countCols()), A11Y_MULTISELECTABLE()]);\n }\n this.THEAD = rootDocument.createElement('THEAD');\n _classPrivateFieldGet(_table, this).appendChild(this.THEAD);\n this.TBODY = rootDocument.createElement('TBODY');\n _classPrivateFieldGet(_table, this).appendChild(this.TBODY);\n this.hot.table = _classPrivateFieldGet(_table, this);\n this.hot.container.insertBefore(_classPrivateFieldGet(_table, this), this.hot.container.firstChild);\n }\n\n /**\n * Attaches necessary listeners.\n *\n * @private\n */\n registerEvents() {\n const {\n rootElement,\n rootDocument,\n selection,\n rootWindow\n } = this.hot;\n const documentElement = rootDocument.documentElement;\n this.eventManager.addEventListener(rootElement, 'mousedown', event => {\n _classPrivateFieldSet(_selectionMouseDown, this, true);\n if (!this.isTextSelectionAllowed(event.target)) {\n clearTextSelection(rootWindow);\n event.preventDefault();\n rootWindow.focus(); // make sure that window that contains HOT is active. Important when HOT is in iframe.\n }\n });\n this.eventManager.addEventListener(rootElement, 'mouseup', () => {\n _classPrivateFieldSet(_selectionMouseDown, this, false);\n });\n this.eventManager.addEventListener(rootElement, 'mousemove', event => {\n if (_classPrivateFieldGet(_selectionMouseDown, this) && !this.isTextSelectionAllowed(event.target)) {\n // Clear selection only when fragmentSelection is enabled, otherwise clearing selection breaks the IME editor.\n if (this.settings.fragmentSelection) {\n clearTextSelection(rootWindow);\n }\n event.preventDefault();\n }\n });\n this.eventManager.addEventListener(documentElement, 'keyup', event => {\n // TODO: is it the best place and way to finish cell selection?\n if (selection.isInProgress() && !event.shiftKey) {\n selection.finish();\n }\n });\n this.eventManager.addEventListener(documentElement, 'mouseup', event => {\n if (selection.isInProgress() && isLeftClick(event)) {\n selection.finish();\n }\n _classPrivateFieldSet(_mouseDown, this, false);\n const isOutsideInputElement = isOutsideInput(rootDocument.activeElement);\n if (isInput(rootDocument.activeElement) && !isOutsideInputElement) {\n return;\n }\n if (isOutsideInputElement || !selection.isSelected() && !selection.isSelectedByAnyHeader() && !rootElement.contains(event.target) && !isRightClick(event)) {\n this.hot.unlisten();\n }\n });\n this.eventManager.addEventListener(documentElement, 'contextmenu', event => {\n if (selection.isInProgress() && isRightClick(event)) {\n selection.finish();\n _classPrivateFieldSet(_mouseDown, this, false);\n }\n });\n this.eventManager.addEventListener(documentElement, 'touchend', () => {\n if (selection.isInProgress()) {\n selection.finish();\n }\n _classPrivateFieldSet(_mouseDown, this, false);\n });\n this.eventManager.addEventListener(documentElement, 'mousedown', event => {\n const originalTarget = event.target;\n const eventX = event.x || event.clientX;\n const eventY = event.y || event.clientY;\n let next = event.target;\n if (_classPrivateFieldGet(_mouseDown, this) || !rootElement || !this.hot.view) {\n return; // it must have been started in a cell\n }\n\n // immediate click on \"holder\" means click on the right side of vertical scrollbar\n const {\n holder\n } = this._wt.wtTable;\n if (next === holder) {\n const scrollbarWidth = getScrollbarWidth(rootDocument);\n if (rootDocument.elementFromPoint(eventX + scrollbarWidth, eventY) !== holder || rootDocument.elementFromPoint(eventX, eventY + scrollbarWidth) !== holder) {\n return;\n }\n } else {\n while (next !== documentElement) {\n if (next === null) {\n if (event.isTargetWebComponent) {\n break;\n }\n\n // click on something that was a row but now is detached (possibly because your click triggered a rerender)\n return;\n }\n if (next === rootElement) {\n // click inside container\n return;\n }\n next = next.parentNode;\n }\n }\n\n // function did not return until here, we have an outside click!\n const outsideClickDeselects = typeof this.settings.outsideClickDeselects === 'function' ? this.settings.outsideClickDeselects(originalTarget) : this.settings.outsideClickDeselects;\n if (outsideClickDeselects) {\n this.hot.deselectCell();\n } else {\n this.hot.destroyEditor(false, false);\n }\n });\n let parentWindow = getParentWindow(rootWindow);\n while (parentWindow !== null) {\n this.eventManager.addEventListener(parentWindow.document.documentElement, 'click', () => {\n this.hot.unlisten();\n });\n parentWindow = getParentWindow(parentWindow);\n }\n this.eventManager.addEventListener(_classPrivateFieldGet(_table, this), 'selectstart', event => {\n if (this.settings.fragmentSelection || isInput(event.target)) {\n return;\n }\n // https://github.com/handsontable/handsontable/issues/160\n // Prevent text from being selected when performing drag down.\n event.preventDefault();\n });\n }\n\n /**\n * Translate renderable cell coordinates to visual coordinates.\n *\n * @param {CellCoords} coords The cell coordinates.\n * @returns {CellCoords}\n */\n translateFromRenderableToVisualCoords(_ref) {\n let {\n row,\n col\n } = _ref;\n // TODO: To consider an idea to reusing the CellCoords instance instead creating new one.\n return this.hot._createCellCoords(...this.translateFromRenderableToVisualIndex(row, col));\n }\n\n /**\n * Translate renderable row and column indexes to visual row and column indexes.\n *\n * @param {number} renderableRow Renderable row index.\n * @param {number} renderableColumn Renderable columnIndex.\n * @returns {number[]}\n */\n translateFromRenderableToVisualIndex(renderableRow, renderableColumn) {\n // TODO: Some helper may be needed.\n // We perform translation for indexes (without headers).\n let visualRow = renderableRow >= 0 ? this.hot.rowIndexMapper.getVisualFromRenderableIndex(renderableRow) : renderableRow;\n let visualColumn = renderableColumn >= 0 ? this.hot.columnIndexMapper.getVisualFromRenderableIndex(renderableColumn) : renderableColumn;\n if (visualRow === null) {\n visualRow = renderableRow;\n }\n if (visualColumn === null) {\n visualColumn = renderableColumn;\n }\n return [visualRow, visualColumn];\n }\n\n /**\n * Returns the number of renderable indexes.\n *\n * @private\n * @param {IndexMapper} indexMapper The IndexMapper instance for specific axis.\n * @param {number} maxElements Maximum number of elements (rows or columns).\n *\n * @returns {number|*}\n */\n countRenderableIndexes(indexMapper, maxElements) {\n const consideredElements = Math.min(indexMapper.getNotTrimmedIndexesLength(), maxElements);\n // Don't take hidden indexes into account. We are looking just for renderable indexes.\n const firstNotHiddenIndex = indexMapper.getNearestNotHiddenIndex(consideredElements - 1, -1);\n\n // There are no renderable indexes.\n if (firstNotHiddenIndex === null) {\n return 0;\n }\n return indexMapper.getRenderableFromVisualIndex(firstNotHiddenIndex) + 1;\n }\n\n /**\n * Returns the number of renderable columns.\n *\n * @returns {number}\n */\n countRenderableColumns() {\n return this.countRenderableIndexes(this.hot.columnIndexMapper, this.settings.maxCols);\n }\n\n /**\n * Returns the number of renderable rows.\n *\n * @returns {number}\n */\n countRenderableRows() {\n return this.countRenderableIndexes(this.hot.rowIndexMapper, this.settings.maxRows);\n }\n\n /**\n * Returns number of not hidden row indexes counting from the passed starting index.\n * The counting direction can be controlled by `incrementBy` argument.\n *\n * @param {number} visualIndex The visual index from which the counting begins.\n * @param {number} incrementBy If `-1` then counting is backwards or forward when `1`.\n * @returns {number}\n */\n countNotHiddenRowIndexes(visualIndex, incrementBy) {\n return this.countNotHiddenIndexes(visualIndex, incrementBy, this.hot.rowIndexMapper, this.countRenderableRows());\n }\n\n /**\n * Returns number of not hidden column indexes counting from the passed starting index.\n * The counting direction can be controlled by `incrementBy` argument.\n *\n * @param {number} visualIndex The visual index from which the counting begins.\n * @param {number} incrementBy If `-1` then counting is backwards or forward when `1`.\n * @returns {number}\n */\n countNotHiddenColumnIndexes(visualIndex, incrementBy) {\n return this.countNotHiddenIndexes(visualIndex, incrementBy, this.hot.columnIndexMapper, this.countRenderableColumns());\n }\n\n /**\n * Returns number of not hidden indexes counting from the passed starting index.\n * The counting direction can be controlled by `incrementBy` argument.\n *\n * @param {number} visualIndex The visual index from which the counting begins.\n * @param {number} incrementBy If `-1` then counting is backwards or forward when `1`.\n * @param {IndexMapper} indexMapper The IndexMapper instance for specific axis.\n * @param {number} renderableIndexesCount Total count of renderable indexes for specific axis.\n * @returns {number}\n */\n countNotHiddenIndexes(visualIndex, incrementBy, indexMapper, renderableIndexesCount) {\n if (isNaN(visualIndex) || visualIndex < 0) {\n return 0;\n }\n const firstVisibleIndex = indexMapper.getNearestNotHiddenIndex(visualIndex, incrementBy);\n const renderableIndex = indexMapper.getRenderableFromVisualIndex(firstVisibleIndex);\n if (!Number.isInteger(renderableIndex)) {\n return 0;\n }\n let notHiddenIndexes = 0;\n if (incrementBy < 0) {\n // Zero-based numbering for renderable indexes corresponds to a number of not hidden indexes.\n notHiddenIndexes = renderableIndex + 1;\n } else if (incrementBy > 0) {\n notHiddenIndexes = renderableIndexesCount - renderableIndex;\n }\n return notHiddenIndexes;\n }\n\n /**\n * The function returns the number of not hidden column indexes that fit between the first and\n * last fixed column in the left (or right in RTL mode) overlay.\n *\n * @returns {number}\n */\n countNotHiddenFixedColumnsStart() {\n const countCols = this.hot.countCols();\n const visualFixedColumnsStart = Math.min(parseInt(this.settings.fixedColumnsStart, 10), countCols) - 1;\n return this.countNotHiddenColumnIndexes(visualFixedColumnsStart, -1);\n }\n\n /**\n * The function returns the number of not hidden row indexes that fit between the first and\n * last fixed row in the top overlay.\n *\n * @returns {number}\n */\n countNotHiddenFixedRowsTop() {\n const countRows = this.hot.countRows();\n const visualFixedRowsTop = Math.min(parseInt(this.settings.fixedRowsTop, 10), countRows) - 1;\n return this.countNotHiddenRowIndexes(visualFixedRowsTop, -1);\n }\n\n /**\n * The function returns the number of not hidden row indexes that fit between the first and\n * last fixed row in the bottom overlay.\n *\n * @returns {number}\n */\n countNotHiddenFixedRowsBottom() {\n const countRows = this.hot.countRows();\n const visualFixedRowsBottom = Math.max(countRows - parseInt(this.settings.fixedRowsBottom, 10), 0);\n return this.countNotHiddenRowIndexes(visualFixedRowsBottom, 1);\n }\n\n /**\n * The function returns the number of renderable column indexes within the passed range of the visual indexes.\n *\n * @param {number} columnStart The column visual start index.\n * @param {number} columnEnd The column visual end index.\n * @returns {number}\n */\n countRenderableColumnsInRange(columnStart, columnEnd) {\n let count = 0;\n for (let column = columnStart; column <= columnEnd; column++) {\n if (this.hot.columnIndexMapper.getRenderableFromVisualIndex(column) !== null) {\n count += 1;\n }\n }\n return count;\n }\n\n /**\n * The function returns the number of renderable row indexes within the passed range of the visual indexes.\n *\n * @param {number} rowStart The row visual start index.\n * @param {number} rowEnd The row visual end index.\n * @returns {number}\n */\n countRenderableRowsInRange(rowStart, rowEnd) {\n let count = 0;\n for (let row = rowStart; row <= rowEnd; row++) {\n if (this.hot.rowIndexMapper.getRenderableFromVisualIndex(row) !== null) {\n count += 1;\n }\n }\n return count;\n }\n\n /**\n * Checks if at least one cell than belongs to the main table is not covered by the top, left or\n * bottom overlay.\n *\n * @returns {boolean}\n */\n isMainTableNotFullyCoveredByOverlays() {\n const fixedAllRows = this.countNotHiddenFixedRowsTop() + this.countNotHiddenFixedRowsBottom();\n const fixedAllColumns = this.countNotHiddenFixedColumnsStart();\n return this.hot.countRenderedRows() > fixedAllRows && this.hot.countRenderedCols() > fixedAllColumns;\n }\n\n /**\n * Defines default configuration and initializes WalkOnTable instance.\n *\n * @private\n */\n initializeWalkontable() {\n const walkontableConfig = {\n ariaTags: this.settings.ariaTags,\n rtlMode: this.hot.isRtl(),\n externalRowCalculator: this.hot.getPlugin('autoRowSize') && this.hot.getPlugin('autoRowSize').isEnabled(),\n table: _classPrivateFieldGet(_table, this),\n isDataViewInstance: () => isRootInstance(this.hot),\n preventOverflow: () => this.settings.preventOverflow,\n preventWheel: () => this.settings.preventWheel,\n stretchH: () => this.settings.stretchH,\n data: (renderableRow, renderableColumn) => {\n return this.hot.getDataAtCell(...this.translateFromRenderableToVisualIndex(renderableRow, renderableColumn));\n },\n totalRows: () => this.countRenderableRows(),\n totalColumns: () => this.countRenderableColumns(),\n // Number of renderable columns for the left overlay.\n fixedColumnsStart: () => this.countNotHiddenFixedColumnsStart(),\n // Number of renderable rows for the top overlay.\n fixedRowsTop: () => this.countNotHiddenFixedRowsTop(),\n // Number of renderable rows for the bottom overlay.\n fixedRowsBottom: () => this.countNotHiddenFixedRowsBottom(),\n // Enable the inline start overlay when conditions are met.\n shouldRenderInlineStartOverlay: () => {\n return this.settings.fixedColumnsStart > 0 || walkontableConfig.rowHeaders().length > 0;\n },\n // Enable the top overlay when conditions are met.\n shouldRenderTopOverlay: () => {\n return this.settings.fixedRowsTop > 0 || walkontableConfig.columnHeaders().length > 0;\n },\n // Enable the bottom overlay when conditions are met.\n shouldRenderBottomOverlay: () => {\n return this.settings.fixedRowsBottom > 0;\n },\n minSpareRows: () => this.settings.minSpareRows,\n renderAllRows: this.settings.renderAllRows,\n renderAllColumns: this.settings.renderAllColumns,\n rowHeaders: () => {\n const headerRenderers = [];\n if (this.hot.hasRowHeaders()) {\n headerRenderers.push((renderableRowIndex, TH) => {\n // TODO: Some helper may be needed.\n // We perform translation for row indexes (without row headers).\n const visualRowIndex = renderableRowIndex >= 0 ? this.hot.rowIndexMapper.getVisualFromRenderableIndex(renderableRowIndex) : renderableRowIndex;\n this.appendRowHeader(visualRowIndex, TH);\n });\n }\n this.hot.runHooks('afterGetRowHeaderRenderers', headerRenderers);\n _classPrivateFieldSet(_rowHeadersCount, this, headerRenderers.length);\n if (this.hot.getSettings().ariaTags) {\n // Update the aria-colcount attribute.\n // Only needs to be done once after initialization/data update.\n if (_assertClassBrand(_TableView_brand, this, _getAriaColcount).call(this) === this.hot.countCols()) {\n _assertClassBrand(_TableView_brand, this, _updateAriaColcount).call(this, _classPrivateFieldGet(_rowHeadersCount, this));\n }\n }\n return headerRenderers;\n },\n columnHeaders: () => {\n const headerRenderers = [];\n if (this.hot.hasColHeaders()) {\n headerRenderers.push((renderedColumnIndex, TH) => {\n // TODO: Some helper may be needed.\n // We perform translation for columns indexes (without column headers).\n const visualColumnsIndex = renderedColumnIndex >= 0 ? this.hot.columnIndexMapper.getVisualFromRenderableIndex(renderedColumnIndex) : renderedColumnIndex;\n this.appendColHeader(visualColumnsIndex, TH);\n });\n }\n this.hot.runHooks('afterGetColumnHeaderRenderers', headerRenderers);\n _classPrivateFieldSet(_columnHeadersCount, this, headerRenderers.length);\n return headerRenderers;\n },\n columnWidth: renderedColumnIndex => {\n const visualIndex = this.hot.columnIndexMapper.getVisualFromRenderableIndex(renderedColumnIndex);\n\n // It's not a bug that we can't find visual index for some handled by method indexes. The function is called also\n // for indexes that are not displayed (indexes that are beyond the grid's boundaries), i.e. when `fixedColumnsStart` > `startCols` (wrong config?) or\n // scrolling and dataset is empty (scroll should handle that?).\n return this.hot.getColWidth(visualIndex === null ? renderedColumnIndex : visualIndex);\n },\n rowHeight: renderedRowIndex => {\n const visualIndex = this.hot.rowIndexMapper.getVisualFromRenderableIndex(renderedRowIndex);\n return this.hot.getRowHeight(visualIndex === null ? renderedRowIndex : visualIndex);\n },\n rowHeightByOverlayName: (renderedRowIndex, overlayType) => {\n const visualIndex = this.hot.rowIndexMapper.getVisualFromRenderableIndex(renderedRowIndex);\n const visualRowIndex = visualIndex === null ? renderedRowIndex : visualIndex;\n return this.hot.runHooks('modifyRowHeightByOverlayName', this.hot.getRowHeight(visualRowIndex), visualRowIndex, overlayType);\n },\n cellRenderer: (renderedRowIndex, renderedColumnIndex, TD) => {\n const [visualRowIndex, visualColumnIndex] = this.translateFromRenderableToVisualIndex(renderedRowIndex, renderedColumnIndex);\n\n // Coords may be modified. For example, by the `MergeCells` plugin. It should affect cell value and cell meta.\n const modifiedCellCoords = this.hot.runHooks('modifyGetCellCoords', visualRowIndex, visualColumnIndex);\n let visualRowToCheck = visualRowIndex;\n let visualColumnToCheck = visualColumnIndex;\n if (Array.isArray(modifiedCellCoords)) {\n [visualRowToCheck, visualColumnToCheck] = modifiedCellCoords;\n }\n const cellProperties = this.hot.getCellMeta(visualRowToCheck, visualColumnToCheck);\n const prop = this.hot.colToProp(visualColumnToCheck);\n let value = this.hot.getDataAtRowProp(visualRowToCheck, prop);\n if (this.hot.hasHook('beforeValueRender')) {\n value = this.hot.runHooks('beforeValueRender', value, cellProperties);\n }\n this.hot.runHooks('beforeRenderer', TD, visualRowIndex, visualColumnIndex, prop, value, cellProperties);\n this.hot.getCellRenderer(cellProperties)(this.hot, TD, visualRowIndex, visualColumnIndex, prop, value, cellProperties);\n this.hot.runHooks('afterRenderer', TD, visualRowIndex, visualColumnIndex, prop, value, cellProperties);\n },\n selections: this.hot.selection.highlight,\n hideBorderOnMouseDownOver: () => this.settings.fragmentSelection,\n onWindowResize: () => {\n if (this.hot && !this.hot.isDestroyed) {\n this.hot.refreshDimensions();\n }\n },\n onContainerElementResize: () => {\n if (this.hot && !this.hot.isDestroyed && isVisible(this.hot.rootElement)) {\n this.hot.refreshDimensions();\n }\n },\n onCellMouseDown: (event, coords, TD, wt) => {\n const visualCoords = this.translateFromRenderableToVisualCoords(coords);\n const controller = {\n row: false,\n column: false,\n cell: false\n };\n this.hot.listen();\n this.activeWt = wt;\n _classPrivateFieldSet(_mouseDown, this, true);\n this.hot.runHooks('beforeOnCellMouseDown', event, visualCoords, TD, controller);\n if (isImmediatePropagationStopped(event)) {\n return;\n }\n handleMouseEvent(event, {\n coords: visualCoords,\n selection: this.hot.selection,\n controller,\n cellCoordsFactory: (row, column) => this.hot._createCellCoords(row, column)\n });\n this.hot.runHooks('afterOnCellMouseDown', event, visualCoords, TD);\n this.activeWt = this._wt;\n },\n onCellContextMenu: (event, coords, TD, wt) => {\n const visualCoords = this.translateFromRenderableToVisualCoords(coords);\n this.activeWt = wt;\n _classPrivateFieldSet(_mouseDown, this, false);\n if (this.hot.selection.isInProgress()) {\n this.hot.selection.finish();\n }\n this.hot.runHooks('beforeOnCellContextMenu', event, visualCoords, TD);\n if (isImmediatePropagationStopped(event)) {\n return;\n }\n this.hot.runHooks('afterOnCellContextMenu', event, visualCoords, TD);\n this.activeWt = this._wt;\n },\n onCellMouseOut: (event, coords, TD, wt) => {\n const visualCoords = this.translateFromRenderableToVisualCoords(coords);\n this.activeWt = wt;\n this.hot.runHooks('beforeOnCellMouseOut', event, visualCoords, TD);\n if (isImmediatePropagationStopped(event)) {\n return;\n }\n this.hot.runHooks('afterOnCellMouseOut', event, visualCoords, TD);\n this.activeWt = this._wt;\n },\n onCellMouseOver: (event, coords, TD, wt) => {\n const visualCoords = this.translateFromRenderableToVisualCoords(coords);\n const controller = {\n row: false,\n column: false,\n cell: false\n };\n this.activeWt = wt;\n this.hot.runHooks('beforeOnCellMouseOver', event, visualCoords, TD, controller);\n if (isImmediatePropagationStopped(event)) {\n return;\n }\n if (_classPrivateFieldGet(_mouseDown, this)) {\n handleMouseEvent(event, {\n coords: visualCoords,\n selection: this.hot.selection,\n controller,\n cellCoordsFactory: (row, column) => this.hot._createCellCoords(row, column)\n });\n }\n this.hot.runHooks('afterOnCellMouseOver', event, visualCoords, TD);\n this.activeWt = this._wt;\n },\n onCellMouseUp: (event, coords, TD, wt) => {\n const visualCoords = this.translateFromRenderableToVisualCoords(coords);\n this.activeWt = wt;\n this.hot.runHooks('beforeOnCellMouseUp', event, visualCoords, TD);\n\n // TODO: The second condition check is a workaround. Callback corresponding the method `updateSettings`\n // disable plugin and enable it again. Disabling plugin closes the menu. Thus, calling the\n // `updateSettings` in a body of any callback executed right after some context-menu action\n // breaks the table (#7231).\n if (isImmediatePropagationStopped(event) || this.hot.isDestroyed) {\n return;\n }\n this.hot.runHooks('afterOnCellMouseUp', event, visualCoords, TD);\n this.activeWt = this._wt;\n },\n onCellCornerMouseDown: event => {\n event.preventDefault();\n this.hot.runHooks('afterOnCellCornerMouseDown', event);\n },\n onCellCornerDblClick: event => {\n event.preventDefault();\n this.hot.runHooks('afterOnCellCornerDblClick', event);\n },\n beforeDraw: (force, skipRender) => this.beforeRender(force, skipRender),\n onDraw: force => this.afterRender(force),\n onBeforeViewportScrollVertically: renderableRow => {\n const rowMapper = this.hot.rowIndexMapper;\n const areColumnHeadersSelected = renderableRow < 0;\n let visualRow = renderableRow;\n if (!areColumnHeadersSelected) {\n visualRow = rowMapper.getVisualFromRenderableIndex(renderableRow);\n\n // for an empty data return index as is\n if (visualRow === null) {\n return renderableRow;\n }\n }\n visualRow = this.hot.runHooks('beforeViewportScrollVertically', visualRow);\n this.hot.runHooks('beforeViewportScroll');\n if (!areColumnHeadersSelected) {\n return rowMapper.getRenderableFromVisualIndex(visualRow);\n }\n return visualRow;\n },\n onBeforeViewportScrollHorizontally: renderableColumn => {\n const columnMapper = this.hot.columnIndexMapper;\n const areRowHeadersSelected = renderableColumn < 0;\n let visualColumn = renderableColumn;\n if (!areRowHeadersSelected) {\n visualColumn = columnMapper.getVisualFromRenderableIndex(renderableColumn);\n\n // for an empty data return index as is\n if (visualColumn === null) {\n return renderableColumn;\n }\n }\n visualColumn = this.hot.runHooks('beforeViewportScrollHorizontally', visualColumn);\n this.hot.runHooks('beforeViewportScroll');\n if (!areRowHeadersSelected) {\n return columnMapper.getRenderableFromVisualIndex(visualColumn);\n }\n return visualColumn;\n },\n onScrollVertically: () => {\n this.hot.runHooks('afterScrollVertically');\n this.hot.runHooks('afterScroll');\n },\n onScrollHorizontally: () => {\n this.hot.runHooks('afterScrollHorizontally');\n this.hot.runHooks('afterScroll');\n },\n onBeforeRemoveCellClassNames: () => this.hot.runHooks('beforeRemoveCellClassNames'),\n onBeforeHighlightingRowHeader: (renderableRow, headerLevel, highlightMeta) => {\n const rowMapper = this.hot.rowIndexMapper;\n const areColumnHeadersSelected = renderableRow < 0;\n let visualRow = renderableRow;\n if (!areColumnHeadersSelected) {\n visualRow = rowMapper.getVisualFromRenderableIndex(renderableRow);\n }\n const newVisualRow = this.hot.runHooks('beforeHighlightingRowHeader', visualRow, headerLevel, highlightMeta);\n if (!areColumnHeadersSelected) {\n return rowMapper.getRenderableFromVisualIndex(rowMapper.getNearestNotHiddenIndex(newVisualRow, 1));\n }\n return newVisualRow;\n },\n onBeforeHighlightingColumnHeader: (renderableColumn, headerLevel, highlightMeta) => {\n const columnMapper = this.hot.columnIndexMapper;\n const areRowHeadersSelected = renderableColumn < 0;\n let visualColumn = renderableColumn;\n if (!areRowHeadersSelected) {\n visualColumn = columnMapper.getVisualFromRenderableIndex(renderableColumn);\n }\n const newVisualColumn = this.hot.runHooks('beforeHighlightingColumnHeader', visualColumn, headerLevel, highlightMeta);\n if (!areRowHeadersSelected) {\n return columnMapper.getRenderableFromVisualIndex(columnMapper.getNearestNotHiddenIndex(newVisualColumn, 1));\n }\n return newVisualColumn;\n },\n onAfterDrawSelection: (currentRow, currentColumn, layerLevel) => {\n let cornersOfSelection;\n const [visualRowIndex, visualColumnIndex] = this.translateFromRenderableToVisualIndex(currentRow, currentColumn);\n const selectedRange = this.hot.selection.getSelectedRange();\n const selectionRangeSize = selectedRange.size();\n if (selectionRangeSize > 0) {\n const selectionForLayer = selectedRange.peekByIndex(layerLevel !== null && layerLevel !== void 0 ? layerLevel : 0);\n cornersOfSelection = [selectionForLayer.from.row, selectionForLayer.from.col, selectionForLayer.to.row, selectionForLayer.to.col];\n }\n return this.hot.runHooks('afterDrawSelection', visualRowIndex, visualColumnIndex, cornersOfSelection, layerLevel);\n },\n onBeforeDrawBorders: (corners, borderClassName) => {\n const [startRenderableRow, startRenderableColumn, endRenderableRow, endRenderableColumn] = corners;\n const visualCorners = [this.hot.rowIndexMapper.getVisualFromRenderableIndex(startRenderableRow), this.hot.columnIndexMapper.getVisualFromRenderableIndex(startRenderableColumn), this.hot.rowIndexMapper.getVisualFromRenderableIndex(endRenderableRow), this.hot.columnIndexMapper.getVisualFromRenderableIndex(endRenderableColumn)];\n return this.hot.runHooks('beforeDrawBorders', visualCorners, borderClassName);\n },\n onBeforeTouchScroll: () => this.hot.runHooks('beforeTouchScroll'),\n onAfterMomentumScroll: () => this.hot.runHooks('afterMomentumScroll'),\n onBeforeStretchingColumnWidth: (stretchedWidth, renderedColumnIndex) => {\n const visualColumnIndex = this.hot.columnIndexMapper.getVisualFromRenderableIndex(renderedColumnIndex);\n return this.hot.runHooks('beforeStretchingColumnWidth', stretchedWidth, visualColumnIndex);\n },\n onModifyRowHeaderWidth: rowHeaderWidth => this.hot.runHooks('modifyRowHeaderWidth', rowHeaderWidth),\n onModifyGetCellCoords: (renderableRowIndex, renderableColumnIndex, topmost) => {\n const rowMapper = this.hot.rowIndexMapper;\n const columnMapper = this.hot.columnIndexMapper;\n\n // Callback handle also headers. We shouldn't translate them.\n const visualColumnIndex = renderableColumnIndex >= 0 ? columnMapper.getVisualFromRenderableIndex(renderableColumnIndex) : renderableColumnIndex;\n const visualRowIndex = renderableRowIndex >= 0 ? rowMapper.getVisualFromRenderableIndex(renderableRowIndex) : renderableRowIndex;\n const visualIndexes = this.hot.runHooks('modifyGetCellCoords', visualRowIndex, visualColumnIndex, topmost);\n if (Array.isArray(visualIndexes)) {\n const [visualRowFrom, visualColumnFrom, visualRowTo, visualColumnTo] = visualIndexes;\n\n // Result of the hook is handled by the Walkontable (renderable indexes).\n return [visualRowFrom >= 0 ? rowMapper.getRenderableFromVisualIndex(rowMapper.getNearestNotHiddenIndex(visualRowFrom, 1)) : visualRowFrom, visualColumnFrom >= 0 ? columnMapper.getRenderableFromVisualIndex(columnMapper.getNearestNotHiddenIndex(visualColumnFrom, 1)) : visualColumnFrom, visualRowTo >= 0 ? rowMapper.getRenderableFromVisualIndex(rowMapper.getNearestNotHiddenIndex(visualRowTo, -1)) : visualRowTo, visualColumnTo >= 0 ? columnMapper.getRenderableFromVisualIndex(columnMapper.getNearestNotHiddenIndex(visualColumnTo, -1)) : visualColumnTo];\n }\n },\n viewportRowCalculatorOverride: calc => {\n let viewportOffset = this.settings.viewportRowRenderingOffset;\n if (viewportOffset === 'auto' && this.settings.fixedRowsTop) {\n viewportOffset = 10;\n }\n if (viewportOffset > 0 || viewportOffset === 'auto') {\n const renderableRows = this.countRenderableRows();\n const firstRenderedRow = calc.startRow;\n const lastRenderedRow = calc.endRow;\n if (typeof viewportOffset === 'number') {\n calc.startRow = Math.max(firstRenderedRow - viewportOffset, 0);\n calc.endRow = Math.min(lastRenderedRow + viewportOffset, renderableRows - 1);\n } else if (viewportOffset === 'auto') {\n const offset = Math.ceil(lastRenderedRow / renderableRows * 12);\n calc.startRow = Math.max(firstRenderedRow - offset, 0);\n calc.endRow = Math.min(lastRenderedRow + offset, renderableRows - 1);\n }\n }\n this.hot.runHooks('afterViewportRowCalculatorOverride', calc);\n },\n viewportColumnCalculatorOverride: calc => {\n let viewportOffset = this.settings.viewportColumnRenderingOffset;\n if (viewportOffset === 'auto' && this.settings.fixedColumnsStart) {\n viewportOffset = 10;\n }\n if (viewportOffset > 0 || viewportOffset === 'auto') {\n const renderableColumns = this.countRenderableColumns();\n const firstRenderedColumn = calc.startColumn;\n const lastRenderedColumn = calc.endColumn;\n if (typeof viewportOffset === 'number') {\n calc.startColumn = Math.max(firstRenderedColumn - viewportOffset, 0);\n calc.endColumn = Math.min(lastRenderedColumn + viewportOffset, renderableColumns - 1);\n }\n if (viewportOffset === 'auto') {\n const offset = Math.ceil(lastRenderedColumn / renderableColumns * 6);\n calc.startColumn = Math.max(firstRenderedColumn - offset, 0);\n calc.endColumn = Math.min(lastRenderedColumn + offset, renderableColumns - 1);\n }\n }\n this.hot.runHooks('afterViewportColumnCalculatorOverride', calc);\n },\n rowHeaderWidth: () => this.settings.rowHeaderWidth,\n columnHeaderHeight: () => {\n const columnHeaderHeight = this.hot.runHooks('modifyColumnHeaderHeight');\n return this.settings.columnHeaderHeight || columnHeaderHeight;\n }\n };\n this.hot.runHooks('beforeInitWalkontable', walkontableConfig);\n this._wt = new Walkontable(walkontableConfig);\n this.activeWt = this._wt;\n const spreader = this._wt.wtTable.spreader;\n // We have to cache width and height after Walkontable initialization.\n const {\n width,\n height\n } = this.hot.rootElement.getBoundingClientRect();\n this.setLastSize(width, height);\n this.eventManager.addEventListener(spreader, 'mousedown', event => {\n // right mouse button exactly on spreader means right click on the right hand side of vertical scrollbar\n if (event.target === spreader && event.which === 3) {\n event.stopPropagation();\n }\n });\n this.eventManager.addEventListener(spreader, 'contextmenu', event => {\n // right mouse button exactly on spreader means right click on the right hand side of vertical scrollbar\n if (event.target === spreader && event.which === 3) {\n event.stopPropagation();\n }\n });\n this.eventManager.addEventListener(this.hot.rootDocument.documentElement, 'click', () => {\n if (this.settings.observeDOMVisibility) {\n if (this._wt.drawInterrupted) {\n this.hot.forceFullRender = true;\n this.render();\n }\n }\n });\n }\n\n /**\n * Checks if it's possible to create text selection in element.\n *\n * @private\n * @param {HTMLElement} el The element to check.\n * @returns {boolean}\n */\n isTextSelectionAllowed(el) {\n if (isInput(el)) {\n return true;\n }\n const isChildOfTableBody = isChildOf(el, this._wt.wtTable.spreader);\n if (this.settings.fragmentSelection === true && isChildOfTableBody) {\n return true;\n }\n if (this.settings.fragmentSelection === 'cell' && this.isSelectedOnlyCell() && isChildOfTableBody) {\n return true;\n }\n if (!this.settings.fragmentSelection && this.isCellEdited() && this.isSelectedOnlyCell()) {\n return true;\n }\n return false;\n }\n\n /**\n * Checks if user's been called mousedown.\n *\n * @private\n * @returns {boolean}\n */\n isMouseDown() {\n return _classPrivateFieldGet(_mouseDown, this);\n }\n\n /**\n * Check if selected only one cell.\n *\n * @private\n * @returns {boolean}\n */\n isSelectedOnlyCell() {\n var _this$hot$getSelected, _this$hot$getSelected2;\n return (_this$hot$getSelected = (_this$hot$getSelected2 = this.hot.getSelectedRangeLast()) === null || _this$hot$getSelected2 === void 0 ? void 0 : _this$hot$getSelected2.isSingleCell()) !== null && _this$hot$getSelected !== void 0 ? _this$hot$getSelected : false;\n }\n\n /**\n * Checks if active cell is editing.\n *\n * @private\n * @returns {boolean}\n */\n isCellEdited() {\n const activeEditor = this.hot.getActiveEditor();\n return activeEditor && activeEditor.isOpened();\n }\n\n /**\n * `beforeDraw` callback.\n *\n * @private\n * @param {boolean} force If `true` rendering was triggered by a change of settings or data or `false` if\n * rendering was triggered by scrolling or moving selection.\n * @param {object} skipRender Object with `skipRender` property, if it is set to `true ` the next rendering\n * cycle will be skipped.\n */\n beforeRender(force, skipRender) {\n if (force) {\n // this.hot.forceFullRender = did Handsontable request full render?\n this.hot.runHooks('beforeViewRender', this.hot.forceFullRender, skipRender);\n }\n }\n\n /**\n * `afterRender` callback.\n *\n * @private\n * @param {boolean} force If `true` rendering was triggered by a change of settings or data or `false` if\n * rendering was triggered by scrolling or moving selection.\n */\n afterRender(force) {\n if (force) {\n // this.hot.forceFullRender = did Handsontable request full render?\n this.hot.runHooks('afterViewRender', this.hot.forceFullRender);\n }\n }\n\n /**\n * Append row header to a TH element.\n *\n * @private\n * @param {number} visualRowIndex The visual row index.\n * @param {HTMLTableHeaderCellElement} TH The table header element.\n */\n appendRowHeader(visualRowIndex, TH) {\n if (TH.firstChild) {\n const container = TH.firstChild;\n if (!hasClass(container, 'relative')) {\n empty(TH);\n this.appendRowHeader(visualRowIndex, TH);\n return;\n }\n this.updateCellHeader(container.querySelector('.rowHeader'), visualRowIndex, this.hot.getRowHeader);\n } else {\n const {\n rootDocument,\n getRowHeader\n } = this.hot;\n const div = rootDocument.createElement('div');\n const span = rootDocument.createElement('span');\n div.className = 'relative';\n span.className = 'rowHeader';\n this.updateCellHeader(span, visualRowIndex, getRowHeader);\n div.appendChild(span);\n TH.appendChild(div);\n }\n this.hot.runHooks('afterGetRowHeader', visualRowIndex, TH);\n }\n\n /**\n * Append column header to a TH element.\n *\n * @private\n * @param {number} visualColumnIndex Visual column index.\n * @param {HTMLTableCellElement} TH The table header element.\n * @param {Function} [label] The function that returns the header label.\n * @param {number} [headerLevel=0] The index of header level counting from the top (positive\n * values counting from 0 to N).\n */\n appendColHeader(visualColumnIndex, TH) {\n let label = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.hot.getColHeader;\n let headerLevel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;\n const getColumnHeaderClassNames = () => {\n const metaHeaderClassNames = visualColumnIndex >= 0 ? this.hot.getColumnMeta(visualColumnIndex).headerClassName : null;\n return metaHeaderClassNames ? metaHeaderClassNames.split(' ') : [];\n };\n if (TH.firstChild) {\n const container = TH.firstChild;\n if (hasClass(container, 'relative')) {\n this.updateCellHeader(container.querySelector('.colHeader'), visualColumnIndex, label, headerLevel);\n container.className = '';\n addClass(container, ['relative', ...getColumnHeaderClassNames()]);\n } else {\n empty(TH);\n this.appendColHeader(visualColumnIndex, TH, label, headerLevel);\n }\n } else {\n const {\n rootDocument\n } = this.hot;\n const div = rootDocument.createElement('div');\n const span = rootDocument.createElement('span');\n const classNames = getColumnHeaderClassNames();\n div.classList.add('relative', ...classNames);\n span.className = 'colHeader';\n if (this.settings.ariaTags) {\n setAttribute(div, ...A11Y_PRESENTATION());\n setAttribute(span, ...A11Y_PRESENTATION());\n }\n this.updateCellHeader(span, visualColumnIndex, label, headerLevel);\n div.appendChild(span);\n TH.appendChild(div);\n }\n this.hot.runHooks('afterGetColHeader', visualColumnIndex, TH, headerLevel);\n }\n\n /**\n * Updates header cell content.\n *\n * @private\n * @param {HTMLElement} element Element to update.\n * @param {number} index Row index or column index.\n * @param {Function} content Function which should be returns content for this cell.\n * @param {number} [headerLevel=0] The index of header level counting from the top (positive\n * values counting from 0 to N).\n */\n updateCellHeader(element, index, content) {\n let headerLevel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;\n let renderedIndex = index;\n const parentOverlay = this._wt.wtOverlays.getParentOverlay(element) || this._wt;\n\n // prevent wrong calculations from SampleGenerator\n if (element.parentNode) {\n if (hasClass(element, 'colHeader')) {\n renderedIndex = parentOverlay.wtTable.columnFilter.sourceToRendered(index);\n } else if (hasClass(element, 'rowHeader')) {\n renderedIndex = parentOverlay.wtTable.rowFilter.sourceToRendered(index);\n }\n }\n if (renderedIndex > -1) {\n fastInnerHTML(element, content(index, headerLevel));\n } else {\n // workaround for https://github.com/handsontable/handsontable/issues/1946\n fastInnerText(element, String.fromCharCode(160));\n addClass(element, 'cornerHeader');\n }\n }\n\n /**\n * Given a element's left (or right in RTL mode) position relative to the viewport, returns maximum\n * element width until the right (or left) edge of the viewport (before scrollbar).\n *\n * @private\n * @param {number} inlineOffset The left (or right in RTL mode) offset.\n * @returns {number}\n */\n maximumVisibleElementWidth(inlineOffset) {\n const workspaceWidth = this._wt.wtViewport.getWorkspaceWidth();\n const maxWidth = workspaceWidth - inlineOffset;\n return maxWidth > 0 ? maxWidth : 0;\n }\n\n /**\n * Given a element's top position relative to the viewport, returns maximum element height until the bottom\n * edge of the viewport (before scrollbar).\n *\n * @private\n * @param {number} topOffset The top offset.\n * @returns {number}\n */\n maximumVisibleElementHeight(topOffset) {\n const workspaceHeight = this._wt.wtViewport.getWorkspaceHeight();\n const maxHeight = workspaceHeight - topOffset;\n return maxHeight > 0 ? maxHeight : 0;\n }\n\n /**\n * Sets new dimensions of the container.\n *\n * @param {number} width The table width.\n * @param {number} height The table height.\n */\n setLastSize(width, height) {\n _classPrivateFieldSet(_lastWidth, this, width);\n _classPrivateFieldSet(_lastHeight, this, height);\n }\n\n /**\n * Returns cached dimensions.\n *\n * @returns {object}\n */\n getLastSize() {\n return {\n width: _classPrivateFieldGet(_lastWidth, this),\n height: _classPrivateFieldGet(_lastHeight, this)\n };\n }\n\n /**\n * Returns the first rendered row in the DOM (usually is not visible in the table's viewport).\n *\n * @returns {number | null}\n */\n getFirstRenderedVisibleRow() {\n if (!this._wt.wtViewport.rowsRenderCalculator) {\n return null;\n }\n return this.hot.rowIndexMapper.getNearestNotHiddenIndex(this._wt.wtTable.getFirstRenderedRow(), 1);\n }\n\n /**\n * Returns the last rendered row in the DOM (usually is not visible in the table's viewport).\n *\n * @returns {number | null}\n */\n getLastRenderedVisibleRow() {\n if (!this._wt.wtViewport.rowsRenderCalculator) {\n return null;\n }\n return this.hot.rowIndexMapper.getNearestNotHiddenIndex(this._wt.wtTable.getLastRenderedRow(), -1);\n }\n\n /**\n * Returns the first rendered column in the DOM (usually is not visible in the table's viewport).\n *\n * @returns {number | null}\n */\n getFirstRenderedVisibleColumn() {\n if (!this._wt.wtViewport.columnsRenderCalculator) {\n return null;\n }\n return this.hot.columnIndexMapper.getNearestNotHiddenIndex(this._wt.wtTable.getFirstRenderedColumn(), 1);\n }\n\n /**\n * Returns the last rendered column in the DOM (usually is not visible in the table's viewport).\n *\n * @returns {number | null}\n */\n getLastRenderedVisibleColumn() {\n if (!this._wt.wtViewport.columnsRenderCalculator) {\n return null;\n }\n return this.hot.columnIndexMapper.getNearestNotHiddenIndex(this._wt.wtTable.getLastRenderedColumn(), -1);\n }\n\n /**\n * Returns the first fully visible row in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getFirstFullyVisibleRow() {\n return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getFirstVisibleRow());\n }\n\n /**\n * Returns the last fully visible row in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getLastFullyVisibleRow() {\n return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getLastVisibleRow());\n }\n\n /**\n * Returns the first fully visible column in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getFirstFullyVisibleColumn() {\n return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getFirstVisibleColumn());\n }\n\n /**\n * Returns the last fully visible column in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getLastFullyVisibleColumn() {\n return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getLastVisibleColumn());\n }\n\n /**\n * Returns the first partially visible row in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getFirstPartiallyVisibleRow() {\n return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getFirstPartiallyVisibleRow());\n }\n\n /**\n * Returns the last partially visible row in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getLastPartiallyVisibleRow() {\n return this.hot.rowIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getLastPartiallyVisibleRow());\n }\n\n /**\n * Returns the first partially visible column in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getFirstPartiallyVisibleColumn() {\n return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getFirstPartiallyVisibleColumn());\n }\n\n /**\n * Returns the last partially visible column in the table viewport. When the table has overlays the method returns\n * the first row of the master table that is not overlapped by overlay.\n *\n * @returns {number}\n */\n getLastPartiallyVisibleColumn() {\n return this.hot.columnIndexMapper.getVisualFromRenderableIndex(this._wt.wtScroll.getLastPartiallyVisibleColumn());\n }\n\n /**\n * Returns the total count of the rendered column headers.\n *\n * @returns {number}\n */\n getColumnHeadersCount() {\n return _classPrivateFieldGet(_columnHeadersCount, this);\n }\n\n /**\n * Returns the total count of the rendered row headers.\n *\n * @returns {number}\n */\n getRowHeadersCount() {\n return _classPrivateFieldGet(_rowHeadersCount, this);\n }\n\n /**\n * Returns the table's viewport width. When the table has defined the size of the container,\n * and the columns do not fill the entire viewport, the viewport width is equal to the sum of\n * the columns' widths.\n *\n * @returns {number}\n */\n getViewportWidth() {\n return this._wt.wtViewport.getViewportWidth();\n }\n\n /**\n * Returns the table's total width including the scrollbar width.\n *\n * @returns {number}\n */\n getWorkspaceWidth() {\n return this._wt.wtViewport.getWorkspaceWidth();\n }\n\n /**\n * Returns the table's viewport height. When the table has defined the size of the container,\n * and the rows do not fill the entire viewport, the viewport height is equal to the sum of\n * the rows' heights.\n *\n * @returns {number}\n */\n getViewportHeight() {\n return this._wt.wtViewport.getViewportHeight();\n }\n\n /**\n * Returns the table's total height including the scrollbar height.\n *\n * @returns {number}\n */\n getWorkspaceHeight() {\n return this._wt.wtViewport.getWorkspaceHeight();\n }\n\n /**\n * Checks to what overlay the provided element belongs.\n *\n * @param {HTMLElement} element The DOM element to check.\n * @returns {'master'|'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'}\n */\n getElementOverlayName(element) {\n var _this$_wt$wtOverlays$;\n return ((_this$_wt$wtOverlays$ = this._wt.wtOverlays.getParentOverlay(element)) !== null && _this$_wt$wtOverlays$ !== void 0 ? _this$_wt$wtOverlays$ : this._wt).wtTable.name;\n }\n\n /**\n * Gets the overlay instance by its name.\n *\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'} overlayName The overlay name.\n * @returns {Overlay | null}\n */\n getOverlayByName(overlayName) {\n return this._wt.getOverlayByName(overlayName);\n }\n\n /**\n * Checks if the table is visible or not.\n *\n * @returns {boolean}\n */\n isVisible() {\n return this._wt.wtTable.isVisible();\n }\n /**\n * Destroys internal WalkOnTable's instance. Detaches all of the bonded listeners.\n *\n * @private\n */\n destroy() {\n this._wt.destroy();\n this.eventManager.destroy();\n }\n}\nfunction _getAriaColcount() {\n return parseInt(this.hot.rootElement.getAttribute(A11Y_COLCOUNT()[0]), 10);\n}\n/**\n * Update the `aria-colcount` attribute by the provided value.\n *\n * @param {number} delta The number of columns to add or remove to the aria tag.\n */\nfunction _updateAriaColcount(delta) {\n const colCount = _assertClassBrand(_TableView_brand, this, _getAriaColcount).call(this) + delta;\n setAttribute(this.hot.rootElement, ...A11Y_COLCOUNT(colCount));\n}\nexport default TableView;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.at.js\";\nimport \"core-js/modules/es.string.at-alternative.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class FullyVisibleColumnsCalculationType\n */\nexport class FullyVisibleColumnsCalculationType {\n constructor() {\n /**\n * Total number of fully visible columns in the viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * The column index of the first fully visible column in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startColumn\", null);\n /**\n * The column index of the last fully visible column in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"endColumn\", null);\n /**\n * Position of the first fully visible column (in px).\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startPosition\", null);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", false);\n }\n /**\n * Initializes the calculation.\n */\n initialize() {}\n\n /**\n * Processes the column.\n *\n * @param {number} column The column index.\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n process(column, viewportCalculator) {\n const {\n totalCalculatedWidth,\n zeroBasedScrollOffset,\n viewportWidth,\n columnWidth\n } = viewportCalculator;\n const compensatedViewportWidth = zeroBasedScrollOffset > 0 ? viewportWidth + 1 : viewportWidth;\n if (totalCalculatedWidth >= zeroBasedScrollOffset && totalCalculatedWidth + columnWidth <= zeroBasedScrollOffset + compensatedViewportWidth) {\n if (this.startColumn === null || this.startColumn === undefined) {\n this.startColumn = column;\n }\n this.endColumn = column;\n }\n }\n\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n const {\n scrollOffset,\n viewportWidth,\n inlineStartOffset,\n zeroBasedScrollOffset,\n totalColumns,\n needReverse,\n startPositions,\n columnWidth\n } = viewportCalculator;\n\n // If the estimation has reached the last column and there is still some space available in the viewport,\n // we need to render in reverse in order to fill the whole viewport with columns\n if (this.endColumn === totalColumns - 1 && needReverse) {\n this.startColumn = this.endColumn;\n while (this.startColumn > 0) {\n const calculatedViewportHeight = startPositions[this.endColumn] + columnWidth - startPositions[this.startColumn - 1];\n if (calculatedViewportHeight <= viewportWidth) {\n this.startColumn -= 1;\n }\n if (calculatedViewportHeight >= viewportWidth) {\n break;\n }\n }\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startColumn]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n const compensatedViewportWidth = zeroBasedScrollOffset > 0 ? viewportWidth + 1 : viewportWidth;\n const mostRightScrollOffset = scrollOffset + viewportWidth - compensatedViewportWidth;\n const inlineStartColumnOffset = this.startColumn === null ? 0 : viewportCalculator.getColumnWidth(this.startColumn);\n if (\n // the table is to the left of the viewport\n mostRightScrollOffset < -1 * inlineStartOffset || scrollOffset > startPositions.at(-1) ||\n // the table is to the right of the viewport\n -1 * scrollOffset - viewportWidth > -1 * inlineStartColumnOffset) {\n this.isVisibleInTrimmingContainer = false;\n } else {\n this.isVisibleInTrimmingContainer = true;\n }\n if (totalColumns < this.endColumn) {\n this.endColumn = totalColumns - 1;\n }\n if (this.startColumn !== null) {\n this.count = this.endColumn - this.startColumn + 1;\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.at.js\";\nimport \"core-js/modules/es.string.at-alternative.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class FullyVisibleRowsCalculationType\n */\nexport class FullyVisibleRowsCalculationType {\n constructor() {\n /**\n * Total number of fully visible rows in the viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * The row index of the first fully visible row in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startRow\", null);\n /**\n * The row index of the last fully visible row in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"endRow\", null);\n /**\n * Position of the first fully visible row (in px).\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startPosition\", null);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", false);\n }\n /**\n * Initializes the calculation.\n */\n initialize() {}\n\n /**\n * Processes the row.\n *\n * @param {number} row The row index.\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n process(row, viewportCalculator) {\n const {\n totalCalculatedHeight,\n zeroBasedScrollOffset,\n innerViewportHeight,\n rowHeight\n } = viewportCalculator;\n if (totalCalculatedHeight >= zeroBasedScrollOffset && totalCalculatedHeight + rowHeight <= innerViewportHeight) {\n if (this.startRow === null) {\n this.startRow = row;\n }\n this.endRow = row;\n }\n }\n\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n const {\n scrollOffset,\n viewportHeight,\n horizontalScrollbarHeight,\n totalRows,\n needReverse,\n startPositions,\n rowHeight\n } = viewportCalculator;\n\n // If the estimation has reached the last row and there is still some space available in the viewport,\n // we need to render in reverse in order to fill the whole viewport with rows\n if (this.endRow === totalRows - 1 && needReverse) {\n this.startRow = this.endRow;\n while (this.startRow > 0) {\n const calculatedViewportHeight = startPositions[this.endRow] + rowHeight - startPositions[this.startRow - 1];\n if (calculatedViewportHeight <= viewportHeight - horizontalScrollbarHeight) {\n this.startRow -= 1;\n }\n if (calculatedViewportHeight >= viewportHeight - horizontalScrollbarHeight) {\n break;\n }\n }\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startRow]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n const mostBottomScrollOffset = scrollOffset + viewportHeight - horizontalScrollbarHeight;\n const topRowOffset = this.startRow === null ? 0 : viewportCalculator.getRowHeight(this.startRow);\n if (mostBottomScrollOffset < topRowOffset || scrollOffset > startPositions.at(-1)) {\n this.isVisibleInTrimmingContainer = false;\n } else {\n this.isVisibleInTrimmingContainer = true;\n }\n if (totalRows < this.endRow) {\n this.endRow = totalRows - 1;\n }\n if (this.startRow !== null) {\n this.count = this.endRow - this.startRow + 1;\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.at.js\";\nimport \"core-js/modules/es.string.at-alternative.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class PartiallyVisibleColumnsCalculationType\n */\nexport class PartiallyVisibleColumnsCalculationType {\n constructor() {\n /**\n * Total number of partially visible columns in the viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * The column index of the first partially visible column in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startColumn\", null);\n /**\n * The column index of the last partially visible column in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"endColumn\", null);\n /**\n * Position of the first partially visible column (in px).\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startPosition\", null);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", false);\n }\n /**\n * Initializes the calculation.\n */\n initialize() {}\n\n /**\n * Processes the column.\n *\n * @param {number} column The column index.\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n process(column, viewportCalculator) {\n const {\n totalCalculatedWidth,\n zeroBasedScrollOffset,\n viewportWidth\n } = viewportCalculator;\n if (totalCalculatedWidth <= zeroBasedScrollOffset) {\n this.startColumn = column;\n }\n const compensatedViewportWidth = zeroBasedScrollOffset > 0 ? viewportWidth + 1 : viewportWidth;\n if (totalCalculatedWidth >= zeroBasedScrollOffset && totalCalculatedWidth <= zeroBasedScrollOffset + compensatedViewportWidth) {\n if (this.startColumn === null || this.startColumn === undefined) {\n this.startColumn = column;\n }\n }\n this.endColumn = column;\n }\n\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n const {\n scrollOffset,\n viewportWidth,\n inlineStartOffset,\n zeroBasedScrollOffset,\n totalColumns,\n needReverse,\n startPositions,\n columnWidth\n } = viewportCalculator;\n\n // If the estimation has reached the last column and there is still some space available in the viewport,\n // we need to render in reverse in order to fill the whole viewport with columns\n if (this.endColumn === totalColumns - 1 && needReverse) {\n this.startColumn = this.endColumn;\n while (this.startColumn > 0) {\n const calculatedViewportWidth = startPositions[this.endColumn] + columnWidth - startPositions[this.startColumn - 1];\n this.startColumn -= 1;\n if (calculatedViewportWidth > viewportWidth) {\n break;\n }\n }\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startColumn]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n const compensatedViewportWidth = zeroBasedScrollOffset > 0 ? viewportWidth + 1 : viewportWidth;\n const mostRightScrollOffset = scrollOffset + viewportWidth - compensatedViewportWidth;\n if (\n // the table is to the left of the viewport\n mostRightScrollOffset < -1 * inlineStartOffset || scrollOffset > startPositions.at(-1) + columnWidth ||\n // the table is to the right of the viewport\n -1 * scrollOffset - viewportWidth > 0) {\n this.isVisibleInTrimmingContainer = false;\n } else {\n this.isVisibleInTrimmingContainer = true;\n }\n if (totalColumns < this.endColumn) {\n this.endColumn = totalColumns - 1;\n }\n if (this.startColumn !== null) {\n this.count = this.endColumn - this.startColumn + 1;\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.at.js\";\nimport \"core-js/modules/es.string.at-alternative.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class PartiallyVisibleRowsCalculationType\n */\nexport class PartiallyVisibleRowsCalculationType {\n constructor() {\n /**\n * Total number of partially visible rows in the viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * The row index of the first partially visible row in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startRow\", null);\n /**\n * The row index of the last partially visible row in the viewport.\n *\n * @type {number|null}\n */\n _defineProperty(this, \"endRow\", null);\n /**\n * Position of the first partially visible row (in px).\n *\n * @type {number|null}\n */\n _defineProperty(this, \"startPosition\", null);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", false);\n }\n /**\n * Initializes the calculation.\n */\n initialize() {}\n\n /**\n * Processes the row.\n *\n * @param {number} row The row index.\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n process(row, viewportCalculator) {\n const {\n totalCalculatedHeight,\n zeroBasedScrollOffset,\n innerViewportHeight\n } = viewportCalculator;\n if (totalCalculatedHeight <= zeroBasedScrollOffset) {\n this.startRow = row;\n }\n if (totalCalculatedHeight >= zeroBasedScrollOffset && totalCalculatedHeight <= innerViewportHeight) {\n if (this.startRow === null) {\n this.startRow = row;\n }\n }\n this.endRow = row;\n }\n\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n const {\n scrollOffset,\n viewportHeight,\n horizontalScrollbarHeight,\n totalRows,\n needReverse,\n startPositions,\n rowHeight\n } = viewportCalculator;\n\n // If the estimation has reached the last row and there is still some space available in the viewport,\n // we need to render in reverse in order to fill the whole viewport with rows\n if (this.endRow === totalRows - 1 && needReverse) {\n this.startRow = this.endRow;\n while (this.startRow > 0) {\n const calculatedViewportHeight = startPositions[this.endRow] + rowHeight - startPositions[this.startRow - 1];\n this.startRow -= 1;\n if (calculatedViewportHeight >= viewportHeight - horizontalScrollbarHeight) {\n break;\n }\n }\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startRow]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n const mostBottomScrollOffset = scrollOffset + viewportHeight - horizontalScrollbarHeight;\n if (mostBottomScrollOffset < 0 || scrollOffset > startPositions.at(-1) + rowHeight) {\n this.isVisibleInTrimmingContainer = false;\n } else {\n this.isVisibleInTrimmingContainer = true;\n }\n if (totalRows < this.endRow) {\n this.endRow = totalRows - 1;\n }\n if (this.startRow !== null) {\n this.count = this.endRow - this.startRow + 1;\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @typedef {object} RenderedAllColumnsCalculatorOptions\n * @property {number} totalColumns Total number of columns.\n */\n/**\n * Holds all calculations needed to perform the rendering of all columns.\n *\n * @class RenderedAllColumnsCalculationType\n */\nexport class RenderedAllColumnsCalculationType {\n constructor() {\n /**\n * Number of rendered/visible columns.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * Index of the first rendered/visible column.\n *\n * @type {number}\n */\n _defineProperty(this, \"startColumn\", 0);\n /**\n * Index of the last rendered/visible column.\n *\n * @type {number}\n */\n _defineProperty(this, \"endColumn\", 0);\n /**\n * Position of the first rendered/visible column (in px).\n *\n * @type {number}\n */\n _defineProperty(this, \"startPosition\", 0);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", true);\n }\n /**\n * Initializes the calculation.\n *\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n initialize(_ref) {\n let {\n totalColumns\n } = _ref;\n this.count = totalColumns;\n this.endColumn = this.count - 1;\n }\n\n /**\n * Processes the column.\n */\n process() {}\n\n /**\n * Finalizes the calculation.\n */\n finalize() {}\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @typedef {object} RenderedAllRowsCalculatorOptions\n * @property {number} totalRows Total number of rows.\n */\n/**\n * Holds all calculations needed to perform the rendering of all rows.\n *\n * @class RenderedAllRowsCalculationType\n */\nexport class RenderedAllRowsCalculationType {\n constructor() {\n /**\n * Number of rendered/visible rows.\n *\n * @type {number}\n */\n _defineProperty(this, \"count\", 0);\n /**\n * Index of the first rendered/visible row.\n *\n * @type {number}\n */\n _defineProperty(this, \"startRow\", 0);\n /**\n * Index of the last rendered/visible row.\n *\n * @type {number}\n */\n _defineProperty(this, \"endRow\", 0);\n /**\n * Position of the first rendered/visible row (in px).\n *\n * @type {number}\n */\n _defineProperty(this, \"startPosition\", 0);\n /**\n * Determines if the viewport is visible in the trimming container.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isVisibleInTrimmingContainer\", true);\n }\n /**\n * Initializes the calculation.\n *\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n initialize(_ref) {\n let {\n totalRows\n } = _ref;\n this.count = totalRows;\n this.endRow = this.count - 1;\n }\n\n /**\n * Processes the row.\n */\n process() {}\n\n /**\n * Finalizes the calculation.\n */\n finalize() {}\n}","import { PartiallyVisibleColumnsCalculationType } from \"./partiallyVisibleColumns.mjs\";\n/**\n * @class RenderedColumnsCalculationType\n */\nexport class RenderedColumnsCalculationType extends PartiallyVisibleColumnsCalculationType {\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportColumnsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n super.finalize(viewportCalculator);\n const {\n overrideFn,\n totalColumns,\n startPositions\n } = viewportCalculator;\n if (this.startColumn !== null && typeof overrideFn === 'function') {\n overrideFn(this);\n }\n if (this.startColumn < 0) {\n this.startColumn = 0;\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startColumn]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n if (totalColumns < this.endColumn) {\n this.endColumn = totalColumns - 1;\n }\n if (this.startColumn !== null) {\n this.count = this.endColumn - this.startColumn + 1;\n }\n }\n}","import { PartiallyVisibleRowsCalculationType } from \"./partiallyVisibleRows.mjs\";\n/**\n * @class RenderedRowsCalculationType\n */\nexport class RenderedRowsCalculationType extends PartiallyVisibleRowsCalculationType {\n /**\n * Finalizes the calculation.\n *\n * @param {ViewportRowsCalculator} viewportCalculator The viewport calculator object.\n */\n finalize(viewportCalculator) {\n var _startPositions$this$;\n super.finalize(viewportCalculator);\n const {\n overrideFn,\n totalRows,\n startPositions\n } = viewportCalculator;\n if (this.startRow !== null && typeof overrideFn === 'function') {\n overrideFn(this);\n }\n if (this.startRow < 0) {\n this.startRow = 0;\n }\n this.startPosition = (_startPositions$this$ = startPositions[this.startRow]) !== null && _startPositions$this$ !== void 0 ? _startPositions$this$ : null;\n if (totalRows < this.endRow) {\n this.endRow = totalRows - 1;\n }\n if (this.startRow !== null) {\n this.count = this.endRow - this.startRow + 1;\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { ViewportBaseCalculator } from \"./viewportBase.mjs\";\nexport const DEFAULT_WIDTH = 50;\n\n/**\n * @typedef {object} ViewportColumnsCalculatorOptions\n * @property {Map} calculationTypes The calculation types to be performed.\n * @property {number} viewportWidth Width of the viewport.\n * @property {number} scrollOffset Current horizontal scroll position of the viewport.\n * @property {number} totalColumns Total number of columns.\n * @property {Function} columnWidthFn Function that returns the width of the column at a given index (in px).\n * @property {Function} overrideFn Function that allows to adjust the `startRow` and `endRow` parameters.\n * @property {string} inlineStartOffset Inline-start offset of the parent container.\n */\n/**\n * Calculates indexes of columns to render OR columns that are visible OR partially visible in the viewport.\n *\n * @class ViewportColumnsCalculator\n */\nexport class ViewportColumnsCalculator extends ViewportBaseCalculator {\n /**\n * @param {ViewportColumnsCalculatorOptions} options Object with all options specified for column viewport calculation.\n */\n constructor(_ref) {\n let {\n calculationTypes,\n viewportWidth,\n scrollOffset,\n totalColumns,\n columnWidthFn,\n overrideFn,\n inlineStartOffset\n } = _ref;\n super(calculationTypes);\n _defineProperty(this, \"viewportWidth\", 0);\n _defineProperty(this, \"scrollOffset\", 0);\n _defineProperty(this, \"zeroBasedScrollOffset\", 0);\n _defineProperty(this, \"totalColumns\", 0);\n _defineProperty(this, \"columnWidthFn\", null);\n _defineProperty(this, \"columnWidth\", 0);\n _defineProperty(this, \"overrideFn\", null);\n _defineProperty(this, \"inlineStartOffset\", 0);\n _defineProperty(this, \"totalCalculatedWidth\", 0);\n _defineProperty(this, \"startPositions\", []);\n _defineProperty(this, \"needReverse\", true);\n this.viewportWidth = viewportWidth;\n this.scrollOffset = scrollOffset;\n this.zeroBasedScrollOffset = Math.max(scrollOffset, 0);\n this.totalColumns = totalColumns;\n this.columnWidthFn = columnWidthFn;\n this.overrideFn = overrideFn;\n this.inlineStartOffset = inlineStartOffset;\n this.calculate();\n }\n\n /**\n * Calculates viewport.\n */\n calculate() {\n this._initialize(this);\n for (let column = 0; column < this.totalColumns; column++) {\n this.columnWidth = this.getColumnWidth(column);\n this._process(column, this);\n this.startPositions.push(this.totalCalculatedWidth);\n this.totalCalculatedWidth += this.columnWidth;\n if (this.totalCalculatedWidth >= this.zeroBasedScrollOffset + this.viewportWidth) {\n this.needReverse = false;\n break;\n }\n }\n this._finalize(this);\n }\n\n /**\n * Gets the column width at the specified column index.\n *\n * @param {number} column Column index.\n * @returns {number}\n */\n getColumnWidth(column) {\n const width = this.columnWidthFn(column);\n if (isNaN(width)) {\n return DEFAULT_WIDTH;\n }\n return width;\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @typedef {object} ColumnsCalculationType\n * @property {number | null} startColumn The column index of the first column in the viewport.\n * @property {number | null} endColumn The column index of the last column in the viewport.\n * @property {number} count Total number of columns.\n * @property {number | null} startPosition Position of the first fully column (in px).\n * @property {boolean} isVisibleInTrimmingContainer Determines if the viewport is visible in the trimming container.\n */\n/**\n * @typedef {object} RowsCalculationType\n * @property {number | null} startRow The row index of the first row in the viewport.\n * @property {number | null} endRow The row index of the last row in the viewport.\n * @property {number} count Total number of rows.\n * @property {number | null} startPosition Position of the first fully row (in px).\n * @property {boolean} isVisibleInTrimmingContainer Determines if the viewport is visible in the trimming container.\n */\n/**\n * @class ViewportBaseCalculator\n */\nexport class ViewportBaseCalculator {\n constructor(calculationTypes) {\n /**\n * The calculation types to be performed.\n *\n * @type {Array}\n */\n _defineProperty(this, \"calculationTypes\", []);\n /**\n * The calculation results.\n *\n * @type {Map}\n */\n _defineProperty(this, \"calculationResults\", new Map());\n this.calculationTypes = calculationTypes;\n }\n\n /**\n * Initializes all calculators (triggers all calculators before calculating the rows/columns sizes).\n *\n * @param {*} context The context object (rows or columns viewport calculator).\n */\n _initialize(context) {\n this.calculationTypes.forEach(_ref => {\n let [id, calculator] = _ref;\n this.calculationResults.set(id, calculator);\n calculator.initialize(context);\n });\n }\n\n /**\n * Processes the row/column at the given index.\n *\n * @param {number} index The index of the row/column.\n * @param {*} context The context object (rows or columns viewport calculator).\n */\n _process(index, context) {\n this.calculationTypes.forEach(_ref2 => {\n let [, calculator] = _ref2;\n return calculator.process(index, context);\n });\n }\n\n /**\n * Finalizes all calculators (triggers all calculators after calculating the rows/columns sizes).\n *\n * @param {*} context The context object (rows or columns viewport calculator).\n */\n _finalize(context) {\n this.calculationTypes.forEach(_ref3 => {\n let [, calculator] = _ref3;\n return calculator.finalize(context);\n });\n }\n\n /**\n * Gets the results for the given calculator.\n *\n * @param {string} calculatorId The id of the calculator.\n * @returns {ColumnsCalculationType | RowsCalculationType}\n */\n getResultsFor(calculatorId) {\n return this.calculationResults.get(calculatorId);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { ViewportBaseCalculator } from \"./viewportBase.mjs\";\nexport const DEFAULT_HEIGHT = 23;\n\n/**\n * @typedef {object} ViewportRowsCalculatorOptions\n * @property {Map} calculationTypes The calculation types to be performed.\n * @property {number} viewportHeight Height of the viewport.\n * @property {number} scrollOffset Current vertical scroll position of the viewport.\n * @property {number} totalRows Total number of rows.\n * @property {Function} rowHeightFn Function that returns the height of the row at a given index (in px).\n * @property {Function} overrideFn Function that allows to adjust the `startRow` and `endRow` parameters.\n * @property {number} horizontalScrollbarHeight The scrollbar height.\n */\n/**\n * Calculates indexes of rows to render OR rows that are visible OR partially visible in the viewport.\n *\n * @class ViewportRowsCalculator\n */\nexport class ViewportRowsCalculator extends ViewportBaseCalculator {\n /**\n * @param {ViewportRowsCalculatorOptions} options Object with all options specified for row viewport calculation.\n */\n constructor(_ref) {\n let {\n calculationTypes,\n viewportHeight,\n scrollOffset,\n totalRows,\n rowHeightFn,\n overrideFn,\n horizontalScrollbarHeight\n } = _ref;\n super(calculationTypes);\n _defineProperty(this, \"viewportHeight\", 0);\n _defineProperty(this, \"scrollOffset\", 0);\n _defineProperty(this, \"zeroBasedScrollOffset\", 0);\n _defineProperty(this, \"totalRows\", 0);\n _defineProperty(this, \"rowHeightFn\", null);\n _defineProperty(this, \"rowHeight\", 0);\n _defineProperty(this, \"overrideFn\", null);\n _defineProperty(this, \"horizontalScrollbarHeight\", 0);\n _defineProperty(this, \"innerViewportHeight\", 0);\n _defineProperty(this, \"totalCalculatedHeight\", 0);\n _defineProperty(this, \"startPositions\", []);\n _defineProperty(this, \"needReverse\", true);\n this.viewportHeight = viewportHeight;\n this.scrollOffset = scrollOffset;\n this.zeroBasedScrollOffset = Math.max(scrollOffset, 0);\n this.totalRows = totalRows;\n this.rowHeightFn = rowHeightFn;\n this.overrideFn = overrideFn;\n this.horizontalScrollbarHeight = horizontalScrollbarHeight !== null && horizontalScrollbarHeight !== void 0 ? horizontalScrollbarHeight : 0;\n this.innerViewportHeight = this.zeroBasedScrollOffset + this.viewportHeight - this.horizontalScrollbarHeight;\n this.calculate();\n }\n\n /**\n * Calculates viewport.\n */\n calculate() {\n this._initialize(this);\n for (let row = 0; row < this.totalRows; row++) {\n this.rowHeight = this.getRowHeight(row);\n this._process(row, this);\n this.startPositions.push(this.totalCalculatedHeight);\n this.totalCalculatedHeight += this.rowHeight;\n if (this.totalCalculatedHeight >= this.innerViewportHeight) {\n this.needReverse = false;\n break;\n }\n }\n this._finalize(this);\n }\n\n /**\n * Gets the row height at the specified row index.\n *\n * @param {number} row Row index.\n * @returns {number}\n */\n getRowHeight(row) {\n const rowHeight = this.rowHeightFn(row);\n if (isNaN(rowHeight)) {\n return DEFAULT_HEIGHT;\n }\n return rowHeight;\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nvar _isRtl = /*#__PURE__*/new WeakMap();\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * @description\n *\n * The `CellCoords` class holds the coordinates (`row`, `col`) of a single cell.\n *\n * It also contains methods for validating the coordinates\n * and retrieving them as an object.\n *\n * To import the `CellCoords` class:\n *\n * ```js\n * import Handsontable, { CellCoords } from '/handsontable';\n *\n * // or, using modules\n * import Handsontable, { CellCoords } from '/handsontable/base';\n * ```\n */\nclass CellCoords {\n constructor(row, column) {\n let isRtl = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n /**\n * A visual row index.\n *\n * @type {number}\n */\n _defineProperty(this, \"row\", null);\n /**\n * A visual column index.\n *\n * @type {number}\n */\n _defineProperty(this, \"col\", null);\n /**\n * A flag which determines if the coordinates run in RTL mode.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _isRtl, false);\n _classPrivateFieldSet(_isRtl, this, isRtl);\n if (typeof row !== 'undefined' && typeof column !== 'undefined') {\n this.row = row;\n this.col = column;\n }\n }\n\n /**\n * Checks if the coordinates in your `CellCoords` instance are valid\n * in the context of given table parameters.\n *\n * The `row` index:\n * - Must be an integer.\n * - Must be higher than the number of column headers in the table.\n * - Must be lower than the total number of rows in the table.\n *\n * The `col` index:\n * - Must be an integer.\n * - Must be higher than the number of row headers in the table.\n * - Must be lower than the total number of columns in the table.\n *\n * @param {object} [tableParams] An object with a defined table size.\n * @param {number} [tableParams.countRows=0] The total number of rows.\n * @param {number} [tableParams.countCols=0] The total number of columns.\n * @param {number} [tableParams.countRowHeaders=0] A number of row headers.\n * @param {number} [tableParams.countColHeaders=0] A number of column headers.\n * @returns {boolean} `true`: The coordinates are valid.\n */\n isValid(tableParams) {\n const {\n countRows,\n countCols,\n countRowHeaders,\n countColHeaders\n } = {\n countRows: 0,\n countCols: 0,\n countRowHeaders: 0,\n countColHeaders: 0,\n ...tableParams\n };\n if (!Number.isInteger(this.row) || !Number.isInteger(this.col)) {\n return false;\n }\n if (this.row < -countColHeaders || this.col < -countRowHeaders) {\n return false;\n }\n if (this.row >= countRows || this.col >= countCols) {\n return false;\n }\n return true;\n }\n\n /**\n * Checks if another set of coordinates (`coords`)\n * is equal to the coordinates in your `CellCoords` instance.\n *\n * @param {CellCoords} coords Coordinates to check.\n * @returns {boolean}\n */\n isEqual(coords) {\n if (coords === this) {\n return true;\n }\n return this.row === coords.row && this.col === coords.col;\n }\n\n /**\n * Checks if the coordinates point to the headers range. If one of the axis (row or col) point to\n * the header (negative value) then method returns `true`.\n *\n * @returns {boolean}\n */\n isHeader() {\n return !this.isCell();\n }\n\n /**\n * Checks if the coordinates point to the cells range. If all axis (row and col) point to\n * the cell (positive value) then method returns `true`.\n *\n * @returns {boolean}\n */\n isCell() {\n return this.row >= 0 && this.col >= 0;\n }\n\n /**\n * Checks if the coordinates runs in RTL mode.\n *\n * @returns {boolean}\n */\n isRtl() {\n return _classPrivateFieldGet(_isRtl, this);\n }\n\n /**\n * Checks if another set of coordinates (`testedCoords`)\n * is south-east of the coordinates in your `CellCoords` instance.\n *\n * @param {CellCoords} testedCoords Coordinates to check.\n * @returns {boolean}\n */\n isSouthEastOf(testedCoords) {\n return this.row >= testedCoords.row && (_classPrivateFieldGet(_isRtl, this) ? this.col <= testedCoords.col : this.col >= testedCoords.col);\n }\n\n /**\n * Checks if another set of coordinates (`testedCoords`)\n * is north-west of the coordinates in your `CellCoords` instance.\n *\n * @param {CellCoords} testedCoords Coordinates to check.\n * @returns {boolean}\n */\n isNorthWestOf(testedCoords) {\n return this.row <= testedCoords.row && (_classPrivateFieldGet(_isRtl, this) ? this.col >= testedCoords.col : this.col <= testedCoords.col);\n }\n\n /**\n * Checks if another set of coordinates (`testedCoords`)\n * is south-west of the coordinates in your `CellCoords` instance.\n *\n * @param {CellCoords} testedCoords Coordinates to check.\n * @returns {boolean}\n */\n isSouthWestOf(testedCoords) {\n return this.row >= testedCoords.row && (_classPrivateFieldGet(_isRtl, this) ? this.col >= testedCoords.col : this.col <= testedCoords.col);\n }\n\n /**\n * Checks if another set of coordinates (`testedCoords`)\n * is north-east of the coordinates in your `CellCoords` instance.\n *\n * @param {CellCoords} testedCoords Coordinates to check.\n * @returns {boolean}\n */\n isNorthEastOf(testedCoords) {\n return this.row <= testedCoords.row && (_classPrivateFieldGet(_isRtl, this) ? this.col <= testedCoords.col : this.col >= testedCoords.col);\n }\n\n /**\n * Normalizes the coordinates in your `CellCoords` instance to the nearest valid position.\n *\n * Coordinates that point to headers (negative values) are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n normalize() {\n this.row = this.row === null ? this.row : Math.max(this.row, 0);\n this.col = this.col === null ? this.col : Math.max(this.col, 0);\n return this;\n }\n\n /**\n * Assigns the coordinates from another `CellCoords` instance (or compatible literal object)\n * to your `CellCoords` instance.\n *\n * @param {CellCoords | { row: number | undefined, col: number | undefined }} coords The CellCoords\n * instance or compatible literal object.\n * @returns {CellCoords}\n */\n assign(coords) {\n if (Number.isInteger(coords === null || coords === void 0 ? void 0 : coords.row)) {\n this.row = coords.row;\n }\n if (Number.isInteger(coords === null || coords === void 0 ? void 0 : coords.col)) {\n this.col = coords.col;\n }\n if (coords instanceof CellCoords) {\n _classPrivateFieldSet(_isRtl, this, coords.isRtl());\n }\n return this;\n }\n\n /**\n * Clones your `CellCoords` instance.\n *\n * @returns {CellCoords}\n */\n clone() {\n return new CellCoords(this.row, this.col, _classPrivateFieldGet(_isRtl, this));\n }\n\n /**\n * Converts your `CellCoords` instance into an object literal with `row` and `col` properties.\n *\n * @returns {{row: number, col: number}} An object literal with `row` and `col` properties.\n */\n toObject() {\n return {\n row: this.row,\n col: this.col\n };\n }\n}\nexport default CellCoords;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport CellCoords from \"./../cell/coords.mjs\";\n/* eslint-disable jsdoc/require-description-complete-sentence */\n/**\n * @description\n *\n * The `CellRange` class holds a set of cell coordinates ([`CellCoords`](@/api/cellCoords.md) instances)\n * that form a [selection range](@/guides/cell-features/selection/selection.md#select-ranges).\n *\n * A single `CellRange` instance represents a single unit of selection\n * that contains either a single cell or multiple adjacent cells.\n *\n * To import the `CellRange` class:\n *\n * ```js\n * import Handsontable, { CellRange } from '/handsontable';\n *\n * // or, using modules\n * import Handsontable, { CellRange } from '/handsontable/base';\n * ```\n */\nvar _isRtl = /*#__PURE__*/new WeakMap();\nclass CellRange {\n constructor(highlight) {\n let from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : highlight;\n let to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : highlight;\n let isRtl = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n /**\n * Used to draw bold border around a cell where selection was started and to edit the cell\n * when you press Enter. The highlight cannot point to headers (negative values) so its\n * coordinates object is normalized while assigning.\n *\n * @private\n * @type {CellCoords}\n */\n _defineProperty(this, \"highlight\", null);\n /**\n * Usually the same as highlight, but in Excel there is distinction - one can change\n * highlight within a selection.\n *\n * @private\n * @type {CellCoords}\n */\n _defineProperty(this, \"from\", null);\n /**\n * End selection.\n *\n * @private\n * @type {CellCoords}\n */\n _defineProperty(this, \"to\", null);\n /**\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _isRtl, false);\n this.highlight = highlight.clone();\n this.from = from.clone();\n this.to = to.clone();\n _classPrivateFieldSet(_isRtl, this, isRtl);\n }\n\n /**\n * Highlights cell selection at the `coords` coordinates.\n *\n * @param {CellCoords} coords Coordinates to use.\n * @returns {CellRange}\n */\n setHighlight(coords) {\n this.highlight = coords.clone();\n return this;\n }\n\n /**\n * Sets the `coords` coordinates as the start of your range.\n *\n * @param {CellCoords} coords Coordinates to use.\n * @returns {CellRange}\n */\n setFrom(coords) {\n this.from = coords.clone();\n return this;\n }\n\n /**\n * Sets the `coords` coordinates as the end of your range.\n *\n * @param {CellCoords} coords Coordinates to use.\n * @returns {CellRange}\n */\n setTo(coords) {\n this.to = coords.clone();\n return this;\n }\n\n /**\n * Checks if the coordinates in your `CellRange` instance are valid\n * in the context of given table parameters.\n *\n * See the [`isValid()`](@/api/cellCoords.md#isvalid) method of the [`CellCoords`](@/api/cellCoords.md) class.\n *\n * @param {object} tableParams An object with a defined table size.\n * @param {number} tableParams.countRows The total number of rows.\n * @param {number} tableParams.countCols The total number of columns.\n * @param {number} tableParams.countRowHeaders A number of row headers.\n * @param {number} tableParams.countColHeaders A number of column headers.\n * @returns {boolean}\n */\n isValid(tableParams) {\n return this.from.isValid(tableParams) && this.to.isValid(tableParams);\n }\n\n /**\n * Checks if your range is just a single cell or header.\n *\n * @returns {boolean}\n */\n isSingle() {\n return this.isSingleCell() || this.isSingleHeader();\n }\n\n /**\n * Checks if your range is just a single cell.\n *\n * @returns {boolean}\n */\n isSingleCell() {\n return this.from.row >= 0 && this.from.row === this.to.row && this.from.col >= 0 && this.from.col === this.to.col;\n }\n\n /**\n * Checks if your range is just a single header.\n *\n * @returns {boolean}\n */\n isSingleHeader() {\n return (this.from.row < 0 || this.from.col < 0) && this.from.row === this.to.row && this.from.col === this.to.col;\n }\n\n /**\n * Checks if your range covers only headers range (negative coordinates, without any cells).\n *\n * @returns {boolean}\n */\n isHeader() {\n if (this.from.isHeader() && this.to.isHeader()) {\n return true;\n }\n return this.from.col < 0 && this.to.col < 0 || this.from.row < 0 && this.to.row < 0;\n }\n\n /**\n * Checks if your range overlaps headers range (negative coordinates).\n *\n * @returns {boolean}\n */\n containsHeaders() {\n return this.from.isHeader() || this.to.isHeader();\n }\n\n /**\n * Returns the height of your range (as a number of rows, including row headers).\n *\n * @returns {number}\n */\n getOuterHeight() {\n return Math.max(this.from.row, this.to.row) - Math.min(this.from.row, this.to.row) + 1;\n }\n\n /**\n * Returns the width of your range (as a number of columns, including column headers).\n *\n * @returns {number}\n */\n getOuterWidth() {\n return Math.max(this.from.col, this.to.col) - Math.min(this.from.col, this.to.col) + 1;\n }\n\n /**\n * Returns the height of your range (as a number of rows, excluding row headers).\n *\n * @returns {number}\n */\n getHeight() {\n // if the selection contains only row headers, return 0\n if (this.from.row < 0 && this.to.row < 0) {\n return 0;\n }\n const fromRow = Math.max(this.from.row, 0);\n const toRow = Math.max(this.to.row, 0);\n return Math.max(fromRow, toRow) - Math.min(fromRow, toRow) + 1;\n }\n\n /**\n * Returns the width of your range (as a number of columns, excluding column headers).\n *\n * @returns {number}\n */\n getWidth() {\n // if the selection contains only column headers, return 0\n if (this.from.col < 0 && this.to.col < 0) {\n return 0;\n }\n const fromCol = Math.max(this.from.col, 0);\n const toCol = Math.max(this.to.col, 0);\n return Math.max(fromCol, toCol) - Math.min(fromCol, toCol) + 1;\n }\n\n /**\n * Returns the number of cells within your range (excluding column and row headers).\n *\n * @returns {number}\n */\n getCellsCount() {\n return this.getWidth() * this.getHeight();\n }\n\n /**\n * Checks if another set of coordinates (`cellCoords`)\n * is within the `from` and `to` coordinates of your range.\n *\n * @param {CellCoords} cellCoords Coordinates to check.\n * @returns {boolean}\n */\n includes(cellCoords) {\n const {\n row,\n col\n } = cellCoords;\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n return topStart.row <= row && bottomEnd.row >= row && topStart.col <= col && bottomEnd.col >= col;\n }\n\n /**\n * Checks if another range (`cellRange`) is within your range.\n *\n * @param {CellRange} cellRange A range to check.\n * @returns {boolean}\n */\n includesRange(cellRange) {\n return this.includes(cellRange.getOuterTopStartCorner()) && this.includes(cellRange.getOuterBottomEndCorner());\n }\n\n /**\n * Checks if another range (`cellRange`) is equal to your range.\n *\n * @param {CellRange} cellRange A range to check.\n * @returns {boolean}\n */\n isEqual(cellRange) {\n return Math.min(this.from.row, this.to.row) === Math.min(cellRange.from.row, cellRange.to.row) && Math.max(this.from.row, this.to.row) === Math.max(cellRange.from.row, cellRange.to.row) && Math.min(this.from.col, this.to.col) === Math.min(cellRange.from.col, cellRange.to.col) && Math.max(this.from.col, this.to.col) === Math.max(cellRange.from.col, cellRange.to.col);\n }\n\n /**\n * Checks if another range (`cellRange`) overlaps your range.\n *\n * Range A overlaps range B if the intersection of A and B (or B and A) is not empty.\n *\n * @param {CellRange} cellRange A range to check.\n * @returns {boolean}\n */\n overlaps(cellRange) {\n return cellRange.isSouthEastOf(this.getOuterTopLeftCorner()) && cellRange.isNorthWestOf(this.getOuterBottomRightCorner());\n }\n\n /**\n * Checks if coordinates point is south-east of your range.\n *\n * @param {CellCoords} cellCoords Coordinates to check.\n * @returns {boolean}\n */\n isSouthEastOf(cellCoords) {\n return this.getOuterTopLeftCorner().isSouthEastOf(cellCoords) || this.getOuterBottomRightCorner().isSouthEastOf(cellCoords);\n }\n\n /**\n * Checks if coordinates point is north-west of your range.\n *\n * @param {CellRange} cellCoords Coordinates to check.\n * @returns {boolean}\n */\n isNorthWestOf(cellCoords) {\n return this.getOuterTopLeftCorner().isNorthWestOf(cellCoords) || this.getOuterBottomRightCorner().isNorthWestOf(cellCoords);\n }\n\n /**\n * Checks if another range (`cellRange`) overlaps your range horizontally.\n *\n * For example: returns `true` if the last column of your range is `5`\n * and the first column of the `cellRange` range is `3`.\n *\n * @param {CellRange} cellRange A range to check.\n * @returns {boolean}\n */\n isOverlappingHorizontally(cellRange) {\n return this.getOuterTopEndCorner().col >= cellRange.getOuterTopStartCorner().col && this.getOuterTopEndCorner().col <= cellRange.getOuterTopEndCorner().col || this.getOuterTopStartCorner().col <= cellRange.getOuterTopEndCorner().col && this.getOuterTopStartCorner().col >= cellRange.getOuterTopStartCorner().col;\n }\n\n /**\n * Checks if another range (`cellRange`) overlaps your range vertically.\n *\n * For example: returns `true` if the last row of your range is `5`\n * and the first row of the `cellRange` range is `3`.\n *\n * @param {CellRange} cellRange A range to check.\n * @returns {boolean}\n */\n isOverlappingVertically(cellRange) {\n return this.getOuterBottomStartCorner().row >= cellRange.getOuterTopRightCorner().row && this.getOuterBottomStartCorner().row <= cellRange.getOuterBottomStartCorner().row || this.getOuterTopEndCorner().row <= cellRange.getOuterBottomStartCorner().row && this.getOuterTopEndCorner().row >= cellRange.getOuterTopRightCorner().row;\n }\n\n /**\n * Adds a cell to your range, at `cellCoords` coordinates.\n *\n * The `cellCoords` coordinates must exceed a corner of your range.\n *\n * @param {CellCoords} cellCoords A new cell's coordinates.\n * @returns {boolean}\n */\n expand(cellCoords) {\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n if (cellCoords.row < topStart.row || cellCoords.col < topStart.col || cellCoords.row > bottomEnd.row || cellCoords.col > bottomEnd.col) {\n this.from = this._createCellCoords(Math.min(topStart.row, cellCoords.row), Math.min(topStart.col, cellCoords.col));\n this.to = this._createCellCoords(Math.max(bottomEnd.row, cellCoords.row), Math.max(bottomEnd.col, cellCoords.col));\n return true;\n }\n return false;\n }\n\n /**\n * Expand your range with another range (`expandingRange`).\n *\n * @param {CellRange} expandingRange A new range.\n * @param {boolean} [changeDirection=true] If `true`, the direction of your range is changed to the direction\n * of the `expandingRange` range.\n * @returns {boolean}\n */\n expandByRange(expandingRange) {\n let changeDirection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n if (this.includesRange(expandingRange) || !this.overlaps(expandingRange)) {\n return false;\n }\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n const initialDirection = this.getDirection();\n const expandingTopStart = expandingRange.getOuterTopStartCorner();\n const expandingBottomEnd = expandingRange.getOuterBottomEndCorner();\n const resultTopRow = Math.min(topStart.row, expandingTopStart.row);\n const resultTopCol = Math.min(topStart.col, expandingTopStart.col);\n const resultBottomRow = Math.max(bottomEnd.row, expandingBottomEnd.row);\n const resultBottomCol = Math.max(bottomEnd.col, expandingBottomEnd.col);\n const finalFrom = this._createCellCoords(resultTopRow, resultTopCol);\n const finalTo = this._createCellCoords(resultBottomRow, resultBottomCol);\n this.from = finalFrom;\n this.to = finalTo;\n this.setDirection(initialDirection);\n if (changeDirection) {\n if (this.highlight.row === this.getOuterBottomRightCorner().row && this.getVerticalDirection() === 'N-S') {\n this.flipDirectionVertically();\n }\n if (this.highlight.col === this.getOuterTopRightCorner().col && this.getHorizontalDirection() === 'W-E') {\n this.flipDirectionHorizontally();\n }\n }\n return true;\n }\n\n /**\n * Gets the direction of the selection.\n *\n * @returns {string} Returns one of the values: `'NW-SE'`, `'NE-SW'`, `'SE-NW'`, `'SW-NE'`.\n */\n getDirection() {\n if (this.from.isNorthWestOf(this.to)) {\n // NorthWest - SouthEast\n return 'NW-SE';\n } else if (this.from.isNorthEastOf(this.to)) {\n // NorthEast - SouthWest\n return 'NE-SW';\n } else if (this.from.isSouthEastOf(this.to)) {\n // SouthEast - NorthWest\n return 'SE-NW';\n } else if (this.from.isSouthWestOf(this.to)) {\n // SouthWest - NorthEast\n return 'SW-NE';\n }\n }\n\n /**\n * Sets the direction of the selection.\n *\n * @param {string} direction One of the values: `'NW-SE'`, `'NE-SW'`, `'SE-NW'`, `'SW-NE'`.\n */\n setDirection(direction) {\n switch (direction) {\n case 'NW-SE':\n [this.from, this.to] = [this.getOuterTopLeftCorner(), this.getOuterBottomRightCorner()];\n break;\n case 'NE-SW':\n [this.from, this.to] = [this.getOuterTopRightCorner(), this.getOuterBottomLeftCorner()];\n break;\n case 'SE-NW':\n [this.from, this.to] = [this.getOuterBottomRightCorner(), this.getOuterTopLeftCorner()];\n break;\n case 'SW-NE':\n [this.from, this.to] = [this.getOuterBottomLeftCorner(), this.getOuterTopRightCorner()];\n break;\n default:\n break;\n }\n }\n\n /**\n * Gets the vertical direction of the selection.\n *\n * @returns {string} Returns one of the values: `N-S` (north->south), `S-N` (south->north).\n */\n getVerticalDirection() {\n return ['NE-SW', 'NW-SE'].indexOf(this.getDirection()) > -1 ? 'N-S' : 'S-N';\n }\n\n /**\n * Gets the horizontal direction of the selection.\n *\n * @returns {string} Returns one of the values: `W-E` (west->east), `E-W` (east->west).\n */\n getHorizontalDirection() {\n return ['NW-SE', 'SW-NE'].indexOf(this.getDirection()) > -1 ? 'W-E' : 'E-W';\n }\n\n /**\n * Flips the direction of your range vertically (e.g., `NW-SE` changes to `SW-NE`).\n */\n flipDirectionVertically() {\n const direction = this.getDirection();\n switch (direction) {\n case 'NW-SE':\n this.setDirection('SW-NE');\n break;\n case 'NE-SW':\n this.setDirection('SE-NW');\n break;\n case 'SE-NW':\n this.setDirection('NE-SW');\n break;\n case 'SW-NE':\n this.setDirection('NW-SE');\n break;\n default:\n break;\n }\n }\n\n /**\n * Flips the direction of your range horizontally (e.g., `NW-SE` changes to `NE-SW`).\n */\n flipDirectionHorizontally() {\n const direction = this.getDirection();\n switch (direction) {\n case 'NW-SE':\n this.setDirection('NE-SW');\n break;\n case 'NE-SW':\n this.setDirection('NW-SE');\n break;\n case 'SE-NW':\n this.setDirection('SW-NE');\n break;\n case 'SW-NE':\n this.setDirection('SE-NW');\n break;\n default:\n break;\n }\n }\n\n /**\n * Gets the top-left (in LTR) or top-right (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getTopStartCorner() {\n return this._createCellCoords(Math.min(this.from.row, this.to.row), Math.min(this.from.col, this.to.col)).normalize();\n }\n\n /**\n * Gets the top-left corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getTopLeftCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getTopEndCorner() : this.getTopStartCorner();\n }\n\n /**\n * Gets the bottom right (in LTR) or bottom left (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getBottomEndCorner() {\n return this._createCellCoords(Math.max(this.from.row, this.to.row), Math.max(this.from.col, this.to.col)).normalize();\n }\n\n /**\n * Gets the bottom right corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getBottomRightCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getBottomStartCorner() : this.getBottomEndCorner();\n }\n\n /**\n * Gets the top right (in LTR) or top left (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getTopEndCorner() {\n return this._createCellCoords(Math.min(this.from.row, this.to.row), Math.max(this.from.col, this.to.col)).normalize();\n }\n\n /**\n * Gets the top right corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getTopRightCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getTopStartCorner() : this.getTopEndCorner();\n }\n\n /**\n * Gets the bottom left (in LTR) or bottom right (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getBottomStartCorner() {\n return this._createCellCoords(Math.max(this.from.row, this.to.row), Math.min(this.from.col, this.to.col)).normalize();\n }\n\n /**\n * Gets the bottom left corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the corner coordinates are normalized to `0`.\n *\n * @returns {CellCoords}\n */\n getBottomLeftCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getBottomEndCorner() : this.getBottomStartCorner();\n }\n\n /**\n * Gets the top left (in LTR) or top right (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the top and start coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterTopStartCorner() {\n return this._createCellCoords(Math.min(this.from.row, this.to.row), Math.min(this.from.col, this.to.col));\n }\n\n /**\n * Gets the top left corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the top and left coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterTopLeftCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getOuterTopEndCorner() : this.getOuterTopStartCorner();\n }\n\n /**\n * Gets the bottom right (in LTR) or bottom left (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the top and start coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterBottomEndCorner() {\n return this._createCellCoords(Math.max(this.from.row, this.to.row), Math.max(this.from.col, this.to.col));\n }\n\n /**\n * Gets the bottom right corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the top and left coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterBottomRightCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getOuterBottomStartCorner() : this.getOuterBottomEndCorner();\n }\n\n /**\n * Gets the top right (in LTR) or top left (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the top and start coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterTopEndCorner() {\n return this._createCellCoords(Math.min(this.from.row, this.to.row), Math.max(this.from.col, this.to.col));\n }\n\n /**\n * Gets the top right corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the top and left coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterTopRightCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getOuterTopStartCorner() : this.getOuterTopEndCorner();\n }\n\n /**\n * Gets the bottom left (in LTR) or bottom right (in RTL) corner coordinates of your range.\n *\n * If the corner contains header coordinates (negative values),\n * the top and start coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterBottomStartCorner() {\n return this._createCellCoords(Math.max(this.from.row, this.to.row), Math.min(this.from.col, this.to.col));\n }\n\n /**\n * Gets the bottom left corner coordinates of your range,\n * both in the LTR and RTL layout direction.\n *\n * If the corner contains header coordinates (negative values),\n * the top and left coordinates are pointed to that header.\n *\n * @returns {CellCoords}\n */\n getOuterBottomLeftCorner() {\n return _classPrivateFieldGet(_isRtl, this) ? this.getOuterBottomEndCorner() : this.getOuterBottomStartCorner();\n }\n\n /**\n * Checks if a set of coordinates (`coords`) matches one of the 4 corners of your range.\n *\n * @param {CellCoords} coords Coordinates to check.\n * @returns {boolean}\n */\n isCorner(coords) {\n return coords.isEqual(this.getOuterTopLeftCorner()) || coords.isEqual(this.getOuterTopRightCorner()) || coords.isEqual(this.getOuterBottomLeftCorner()) || coords.isEqual(this.getOuterBottomRightCorner());\n }\n\n /**\n * Gets the coordinates of a range corner opposite to the provided `coords`.\n *\n * For example: if the `coords` coordinates match the bottom-right corner of your range,\n * the coordinates of the top-left corner of your range are returned.\n *\n * @param {CellCoords} coords Coordinates to check.\n * @returns {CellCoords}\n */\n getOppositeCorner(coords) {\n if (!(coords instanceof CellCoords)) {\n return false;\n }\n if (coords.isEqual(this.getOuterBottomEndCorner())) {\n return this.getOuterTopStartCorner();\n } else if (coords.isEqual(this.getOuterTopStartCorner())) {\n return this.getOuterBottomEndCorner();\n } else if (coords.isEqual(this.getOuterTopEndCorner())) {\n return this.getOuterBottomStartCorner();\n } else if (coords.isEqual(this.getOuterBottomStartCorner())) {\n return this.getOuterTopEndCorner();\n }\n }\n\n /**\n * Indicates which borders (top, right, bottom, left) are shared between\n * your `CellRange`instance and another `range` that's within your range.\n *\n * @param {CellRange} range A range to compare with.\n * @returns {Array<'top' | 'right' | 'bottom' | 'left'>}\n */\n getBordersSharedWith(range) {\n if (!this.includesRange(range)) {\n return [];\n }\n const thisBorders = {\n top: Math.min(this.from.row, this.to.row),\n bottom: Math.max(this.from.row, this.to.row),\n left: Math.min(this.from.col, this.to.col),\n right: Math.max(this.from.col, this.to.col)\n };\n const rangeBorders = {\n top: Math.min(range.from.row, range.to.row),\n bottom: Math.max(range.from.row, range.to.row),\n left: Math.min(range.from.col, range.to.col),\n right: Math.max(range.from.col, range.to.col)\n };\n const result = [];\n if (thisBorders.top === rangeBorders.top) {\n result.push('top');\n }\n if (thisBorders.right === rangeBorders.right) {\n result.push(_classPrivateFieldGet(_isRtl, this) ? 'left' : 'right');\n }\n if (thisBorders.bottom === rangeBorders.bottom) {\n result.push('bottom');\n }\n if (thisBorders.left === rangeBorders.left) {\n result.push(_classPrivateFieldGet(_isRtl, this) ? 'right' : 'left');\n }\n return result;\n }\n\n /**\n * Gets the coordinates of the inner cells of your range.\n *\n * @returns {CellCoords[]}\n */\n getInner() {\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n const out = [];\n for (let r = topStart.row; r <= bottomEnd.row; r++) {\n for (let c = topStart.col; c <= bottomEnd.col; c++) {\n if (!(this.from.row === r && this.from.col === c) && !(this.to.row === r && this.to.col === c)) {\n out.push(this._createCellCoords(r, c));\n }\n }\n }\n return out;\n }\n\n /**\n * Gets the coordinates of all cells of your range.\n *\n * @returns {CellCoords[]}\n */\n getAll() {\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n const out = [];\n for (let r = topStart.row; r <= bottomEnd.row; r++) {\n for (let c = topStart.col; c <= bottomEnd.col; c++) {\n if (topStart.row === r && topStart.col === c) {\n out.push(topStart);\n } else if (bottomEnd.row === r && bottomEnd.col === c) {\n out.push(bottomEnd);\n } else {\n out.push(this._createCellCoords(r, c));\n }\n }\n }\n return out;\n }\n\n /**\n * Runs a callback function on all cells within your range.\n *\n * You can break the iteration by returning `false` in the callback function.\n *\n * @param {function(number, number): boolean} callback A callback function.\n */\n forAll(callback) {\n const topStart = this.getOuterTopStartCorner();\n const bottomEnd = this.getOuterBottomEndCorner();\n for (let r = topStart.row; r <= bottomEnd.row; r++) {\n for (let c = topStart.col; c <= bottomEnd.col; c++) {\n const breakIteration = callback(r, c);\n if (breakIteration === false) {\n return;\n }\n }\n }\n }\n\n /**\n * Clones your `CellRange` instance.\n *\n * @returns {CellRange}\n */\n clone() {\n return new CellRange(this.highlight, this.from, this.to, _classPrivateFieldGet(_isRtl, this));\n }\n\n /**\n * Converts your `CellRange` instance into an object literal with the following properties:\n *\n * - `from`\n * - `row`\n * - `col`\n * - `to`\n * - `row`\n * - `col`\n *\n * @returns {{from: {row: number, col: number}, to: {row: number, col: number}}} An object literal with `from` and `to` properties.\n */\n toObject() {\n return {\n from: this.from.toObject(),\n to: this.to.toObject()\n };\n }\n\n /**\n * Creates and returns a new instance of the `CellCoords` class.\n *\n * The new `CellCoords` instance automatically inherits the LTR/RTL flag\n * from your `CellRange` instance.\n *\n * @private\n * @param {number} row A row index.\n * @param {number} column A column index.\n * @returns {CellCoords}\n */\n _createCellCoords(row, column) {\n return new CellCoords(row, column, _classPrivateFieldGet(_isRtl, this));\n }\n}\nexport default CellRange;","import \"core-js/modules/es.array.push.js\";\nimport Event from \"../event.mjs\";\nimport Overlays from \"../overlays.mjs\";\nimport { CLONE_TYPES } from \"../overlay/index.mjs\";\nimport Settings from \"../settings.mjs\";\nimport MasterTable from \"../table/master.mjs\";\nimport Viewport from \"../viewport.mjs\";\nimport CoreAbstract from \"./_base.mjs\";\nimport { SelectionManager } from \"../selection/manager.mjs\";\nimport { objectEach } from \"../../../../helpers/object.mjs\";\nimport { addClass, removeClass } from \"../../../../helpers/dom/element.mjs\";\n/**\n * @class Walkontable\n */\nexport default class Walkontable extends CoreAbstract {\n /**\n * @param {HTMLTableElement} table Main table.\n * @param {SettingsPure} settings The Walkontable settings.\n */\n constructor(table, settings) {\n super(table, new Settings(settings));\n const facadeGetter = this.wtSettings.getSetting('facade', this); // todo rethink. I would like to have no access to facade from the internal scope.\n\n this.wtTable = new MasterTable(this.getTableDao(), facadeGetter, this.domBindings, this.wtSettings);\n this.wtViewport = new Viewport(this.getViewportDao(), this.domBindings, this.wtSettings, this.eventManager, this.wtTable);\n this.selectionManager = new SelectionManager(this.wtSettings.getSetting('selections'));\n this.wtEvent = new Event(facadeGetter, this.domBindings, this.wtSettings, this.eventManager, this.wtTable, this.selectionManager);\n this.wtOverlays = new Overlays(\n // TODO create DAO and remove reference to the Walkontable instance.\n this, facadeGetter, this.domBindings, this.wtSettings, this.eventManager, this.wtTable);\n this.exportSettingsAsClassNames();\n this.findOriginalHeaders();\n }\n\n /**\n * Export settings as class names added to the parent element of the table.\n */\n exportSettingsAsClassNames() {\n const toExport = {\n rowHeaders: 'htRowHeaders',\n columnHeaders: 'htColumnHeaders'\n };\n const allClassNames = [];\n const newClassNames = [];\n objectEach(toExport, (className, key) => {\n if (this.wtSettings.getSetting(key).length) {\n newClassNames.push(className);\n }\n allClassNames.push(className);\n });\n removeClass(this.wtTable.wtRootElement.parentNode, allClassNames);\n addClass(this.wtTable.wtRootElement.parentNode, newClassNames);\n }\n\n /**\n * Gets the overlay instance by its name.\n *\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'} overlayName The overlay name.\n * @returns {Overlay | null}\n */\n getOverlayByName(overlayName) {\n var _this$wtOverlays;\n if (!CLONE_TYPES.includes(overlayName)) {\n return null;\n }\n const camelCaseOverlay = overlayName.replace(/_([a-z])/g, match => match[1].toUpperCase());\n return (_this$wtOverlays = this.wtOverlays[`${camelCaseOverlay}Overlay`]) !== null && _this$wtOverlays !== void 0 ? _this$wtOverlays : null;\n }\n\n /**\n * @returns {ViewportDao}\n */\n getViewportDao() {\n const wot = this;\n return {\n get wot() {\n return wot;\n },\n get topOverlayTrimmingContainer() {\n return wot.wtOverlays.topOverlay.trimmingContainer;\n },\n get inlineStartOverlayTrimmingContainer() {\n return wot.wtOverlays.inlineStartOverlay.trimmingContainer;\n },\n get topScrollPosition() {\n return wot.wtOverlays.topOverlay.getScrollPosition();\n },\n get topParentOffset() {\n return wot.wtOverlays.topOverlay.getTableParentOffset();\n },\n get inlineStartScrollPosition() {\n return wot.wtOverlays.inlineStartOverlay.getScrollPosition();\n },\n get inlineStartParentOffset() {\n return wot.wtOverlays.inlineStartOverlay.getTableParentOffset();\n },\n get topOverlay() {\n return wot.wtOverlays.topOverlay; // TODO refactoring: move outside dao, use IOC\n },\n get inlineStartOverlay() {\n return wot.wtOverlays.inlineStartOverlay; // TODO refactoring: move outside dao, use IOC\n },\n get bottomOverlay() {\n return wot.wtOverlays.bottomOverlay; // TODO refactoring: move outside dao, use IOC\n }\n };\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { closestDown, hasClass, isChildOf, getParent } from \"../../../helpers/dom/element.mjs\";\nimport { partial } from \"../../../helpers/function.mjs\";\nimport { isTouchSupported } from \"../../../helpers/feature.mjs\";\nimport { isMobileBrowser, isChromeWebKit, isFirefoxWebKit, isIOS } from \"../../../helpers/browser.mjs\";\nimport { isDefined } from \"../../../helpers/mixed.mjs\";\n/**\n * @class Event\n */\nvar _wtSettings = /*#__PURE__*/new WeakMap();\nvar _domBindings = /*#__PURE__*/new WeakMap();\nvar _wtTable = /*#__PURE__*/new WeakMap();\nvar _selectionManager = /*#__PURE__*/new WeakMap();\nvar _parent = /*#__PURE__*/new WeakMap();\nvar _eventManager = /*#__PURE__*/new WeakMap();\nvar _facadeGetter = /*#__PURE__*/new WeakMap();\nvar _selectedCellBeforeTouchEnd = /*#__PURE__*/new WeakMap();\nvar _dblClickTimeout = /*#__PURE__*/new WeakMap();\nvar _dblClickOrigin = /*#__PURE__*/new WeakMap();\nclass Event {\n /**\n * @param {FacadeGetter} facadeGetter Gets an instance facade.\n * @param {DomBindings} domBindings Bindings into dom.\n * @param {Settings} wtSettings The walkontable settings.\n * @param {EventManager} eventManager The walkontable event manager.\n * @param {Table} wtTable The table.\n * @param {SelectionManager} selectionManager Selections.\n * @param {Event} [parent=null] The main Event instance.\n */\n constructor(facadeGetter, domBindings, wtSettings, eventManager, wtTable, selectionManager) {\n let parent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;\n _classPrivateFieldInitSpec(this, _wtSettings, void 0);\n _classPrivateFieldInitSpec(this, _domBindings, void 0);\n _classPrivateFieldInitSpec(this, _wtTable, void 0);\n _classPrivateFieldInitSpec(this, _selectionManager, void 0);\n _classPrivateFieldInitSpec(this, _parent, void 0);\n /**\n * Instance of {@link EventManager}.\n *\n * @type {EventManager}\n */\n _classPrivateFieldInitSpec(this, _eventManager, void 0);\n /**\n * Should be use only for passing face called external origin methods, like registered event listeners.\n * It provides backward compatibility by getting instance facade.\n *\n * @todo Consider about removing this from Event class, because it make relationship into facade (implicit circular\n * dependency).\n * @todo Con. Maybe passing listener caller as an ioc from faced resolves this issue. To rethink later.\n *\n * @type {FacadeGetter}\n */\n _classPrivateFieldInitSpec(this, _facadeGetter, void 0);\n /**\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _selectedCellBeforeTouchEnd, void 0);\n /**\n * @type {number[]}\n */\n _classPrivateFieldInitSpec(this, _dblClickTimeout, [null, null]);\n /**\n * @type {number[]}\n */\n _classPrivateFieldInitSpec(this, _dblClickOrigin, [null, null]);\n _classPrivateFieldSet(_wtSettings, this, wtSettings);\n _classPrivateFieldSet(_domBindings, this, domBindings);\n _classPrivateFieldSet(_wtTable, this, wtTable);\n _classPrivateFieldSet(_selectionManager, this, selectionManager);\n _classPrivateFieldSet(_parent, this, parent);\n _classPrivateFieldSet(_eventManager, this, eventManager);\n _classPrivateFieldSet(_facadeGetter, this, facadeGetter);\n this.registerEvents();\n }\n\n /**\n * Adds listeners for mouse and touch events.\n *\n * @private\n */\n registerEvents() {\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'contextmenu', event => this.onContextMenu(event));\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).TABLE, 'mouseover', event => this.onMouseOver(event));\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).TABLE, 'mouseout', event => this.onMouseOut(event));\n const initTouchEvents = () => {\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'touchstart', event => this.onTouchStart(event));\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'touchend', event => this.onTouchEnd(event));\n if (!this.momentumScrolling) {\n this.momentumScrolling = {};\n }\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'scroll', () => {\n clearTimeout(this.momentumScrolling._timeout);\n if (!this.momentumScrolling.ongoing) {\n _classPrivateFieldGet(_wtSettings, this).getSetting('onBeforeTouchScroll');\n }\n this.momentumScrolling.ongoing = true;\n this.momentumScrolling._timeout = setTimeout(() => {\n if (!this.touchApplied) {\n this.momentumScrolling.ongoing = false;\n _classPrivateFieldGet(_wtSettings, this).getSetting('onAfterMomentumScroll');\n }\n }, 200);\n });\n };\n const initMouseEvents = () => {\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'mouseup', event => this.onMouseUp(event));\n _classPrivateFieldGet(_eventManager, this).addEventListener(_classPrivateFieldGet(_wtTable, this).holder, 'mousedown', event => this.onMouseDown(event));\n };\n if (isMobileBrowser()) {\n initTouchEvents();\n } else {\n // PC like devices which support both methods (touchscreen and ability to plug-in mouse).\n if (isTouchSupported()) {\n initTouchEvents();\n }\n initMouseEvents();\n }\n }\n\n /**\n * Checks if an element is already selected.\n *\n * @private\n * @param {Element} touchTarget An element to check.\n * @returns {boolean}\n */\n selectedCellWasTouched(touchTarget) {\n const cellUnderFinger = this.parentCell(touchTarget);\n const coordsOfCellUnderFinger = cellUnderFinger.coords;\n if (_classPrivateFieldGet(_selectedCellBeforeTouchEnd, this) && coordsOfCellUnderFinger) {\n const [rowTouched, rowSelected] = [coordsOfCellUnderFinger.row, _classPrivateFieldGet(_selectedCellBeforeTouchEnd, this).from.row];\n const [colTouched, colSelected] = [coordsOfCellUnderFinger.col, _classPrivateFieldGet(_selectedCellBeforeTouchEnd, this).from.col];\n return rowTouched === rowSelected && colTouched === colSelected;\n }\n return false;\n }\n\n /**\n * Gets closest TD or TH element.\n *\n * @private\n * @param {Element} elem An element from the traversing starts.\n * @returns {object} Contains coordinates and reference to TD or TH if it exists. Otherwise it's empty object.\n */\n parentCell(elem) {\n const cell = {};\n const TABLE = _classPrivateFieldGet(_wtTable, this).TABLE;\n const TD = closestDown(elem, ['TD', 'TH'], TABLE);\n if (TD) {\n cell.coords = _classPrivateFieldGet(_wtTable, this).getCoords(TD);\n cell.TD = TD;\n } else if (hasClass(elem, 'wtBorder') && hasClass(elem, 'current')) {\n cell.coords = _classPrivateFieldGet(_selectionManager, this).getFocusSelection().cellRange.highlight;\n cell.TD = _classPrivateFieldGet(_wtTable, this).getCell(cell.coords);\n } else if (hasClass(elem, 'wtBorder') && hasClass(elem, 'area')) {\n if (_classPrivateFieldGet(_selectionManager, this).getAreaSelection().cellRange) {\n cell.coords = _classPrivateFieldGet(_selectionManager, this).getAreaSelection().cellRange.to;\n cell.TD = _classPrivateFieldGet(_wtTable, this).getCell(cell.coords);\n }\n }\n return cell;\n }\n\n /**\n * OnMouseDown callback.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onMouseDown(event) {\n const activeElement = _classPrivateFieldGet(_domBindings, this).rootDocument.activeElement;\n const getParentNode = partial(getParent, event.target);\n const realTarget = event.target;\n\n // ignore non-TD focusable elements from mouse down processing\n // (https://github.com/handsontable/handsontable/issues/3555)\n if (!['TD', 'TH'].includes(activeElement.nodeName) && (realTarget === activeElement || getParentNode(0) === activeElement || getParentNode(1) === activeElement)) {\n return;\n }\n const cell = this.parentCell(realTarget);\n if (hasClass(realTarget, 'corner')) {\n _classPrivateFieldGet(_wtSettings, this).getSetting('onCellCornerMouseDown', event, realTarget);\n } else if (cell.TD && _classPrivateFieldGet(_wtSettings, this).has('onCellMouseDown')) {\n this.callListener('onCellMouseDown', event, cell.coords, cell.TD);\n }\n\n // doubleclick reacts only for left mouse button or from touch events\n if ((event.button === 0 || this.touchApplied) && cell.TD) {\n _classPrivateFieldGet(_dblClickOrigin, this)[0] = cell.TD;\n clearTimeout(_classPrivateFieldGet(_dblClickTimeout, this)[0]);\n _classPrivateFieldGet(_dblClickTimeout, this)[0] = setTimeout(() => {\n _classPrivateFieldGet(_dblClickOrigin, this)[0] = null;\n }, 1000);\n }\n }\n\n /**\n * OnContextMenu callback.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onContextMenu(event) {\n if (_classPrivateFieldGet(_wtSettings, this).has('onCellContextMenu')) {\n const cell = this.parentCell(event.target);\n if (cell.TD) {\n this.callListener('onCellContextMenu', event, cell.coords, cell.TD);\n }\n }\n }\n\n /**\n * OnMouseOver callback.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onMouseOver(event) {\n if (!_classPrivateFieldGet(_wtSettings, this).has('onCellMouseOver')) {\n return;\n }\n const table = _classPrivateFieldGet(_wtTable, this).TABLE;\n const td = closestDown(event.target, ['TD', 'TH'], table);\n const parent = _classPrivateFieldGet(_parent, this) || this;\n if (td && td !== parent.lastMouseOver && isChildOf(td, table)) {\n parent.lastMouseOver = td;\n this.callListener('onCellMouseOver', event, _classPrivateFieldGet(_wtTable, this).getCoords(td), td);\n }\n }\n\n /**\n * OnMouseOut callback.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onMouseOut(event) {\n if (!_classPrivateFieldGet(_wtSettings, this).has('onCellMouseOut')) {\n return;\n }\n const table = _classPrivateFieldGet(_wtTable, this).TABLE;\n const lastTD = closestDown(event.target, ['TD', 'TH'], table);\n const nextTD = closestDown(event.relatedTarget, ['TD', 'TH'], table);\n const parent = _classPrivateFieldGet(_parent, this) || this;\n if (lastTD && lastTD !== nextTD && isChildOf(lastTD, table)) {\n this.callListener('onCellMouseOut', event, _classPrivateFieldGet(_wtTable, this).getCoords(lastTD), lastTD);\n if (nextTD === null) {\n parent.lastMouseOver = null;\n }\n }\n }\n\n /**\n * OnMouseUp callback.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onMouseUp(event) {\n const cell = this.parentCell(event.target);\n if (cell.TD && _classPrivateFieldGet(_wtSettings, this).has('onCellMouseUp')) {\n this.callListener('onCellMouseUp', event, cell.coords, cell.TD);\n }\n\n // if not left mouse button, and the origin event is not comes from touch\n if (event.button !== 0 && !this.touchApplied) {\n return;\n }\n if (cell.TD === _classPrivateFieldGet(_dblClickOrigin, this)[0] && cell.TD === _classPrivateFieldGet(_dblClickOrigin, this)[1]) {\n if (hasClass(event.target, 'corner')) {\n this.callListener('onCellCornerDblClick', event, cell.coords, cell.TD);\n } else {\n this.callListener('onCellDblClick', event, cell.coords, cell.TD);\n }\n _classPrivateFieldGet(_dblClickOrigin, this)[0] = null;\n _classPrivateFieldGet(_dblClickOrigin, this)[1] = null;\n } else if (cell.TD === _classPrivateFieldGet(_dblClickOrigin, this)[0]) {\n _classPrivateFieldGet(_dblClickOrigin, this)[1] = cell.TD;\n clearTimeout(_classPrivateFieldGet(_dblClickTimeout, this)[1]);\n _classPrivateFieldGet(_dblClickTimeout, this)[1] = setTimeout(() => {\n _classPrivateFieldGet(_dblClickOrigin, this)[1] = null;\n }, 500);\n }\n }\n\n /**\n * OnTouchStart callback. Simulates mousedown event.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onTouchStart(event) {\n _classPrivateFieldSet(_selectedCellBeforeTouchEnd, this, _classPrivateFieldGet(_selectionManager, this).getFocusSelection().cellRange);\n this.touchApplied = true;\n this.onMouseDown(event);\n }\n\n /**\n * OnTouchEnd callback. Simulates mouseup event.\n *\n * @private\n * @param {MouseEvent} event The mouse event object.\n */\n onTouchEnd(event) {\n var _this$parentCell;\n const target = event.target;\n const parentCellCoords = (_this$parentCell = this.parentCell(target)) === null || _this$parentCell === void 0 ? void 0 : _this$parentCell.coords;\n const isCellsRange = isDefined(parentCellCoords) && parentCellCoords.row >= 0 && parentCellCoords.col >= 0;\n const isEventCancelable = event.cancelable && isCellsRange && _classPrivateFieldGet(_wtSettings, this).getSetting('isDataViewInstance');\n\n // To prevent accidental redirects or other actions that the interactive elements (e.q \"A\" link) do\n // while the cell is highlighted, all touch events that are triggered on different cells are\n // \"preventDefault\"'ed. The user can interact with the element (e.q. click on the link that opens\n // a new page) only when the same cell was previously selected (see related PR #7980).\n if (isEventCancelable) {\n const interactiveElements = ['A', 'BUTTON', 'INPUT'];\n\n // For browsers that use the WebKit as an engine (excluding Safari), there is a bug. The prevent\n // default has to be called all the time. Otherwise, the second tap won't be triggered (probably\n // caused by the native ~300ms delay - https://webkit.org/blog/5610/more-responsive-tapping-on-ios/).\n // To make the interactive elements work, the event target element has to be check. If the element\n // matches the allow-list, the event is not prevented.\n if (isIOS() && (isChromeWebKit() || isFirefoxWebKit()) && this.selectedCellWasTouched(target) && !interactiveElements.includes(target.tagName)) {\n event.preventDefault();\n } else if (!this.selectedCellWasTouched(target)) {\n // For other browsers, prevent default is fired only for the first tap and only when the previous\n // highlighted cell was different.\n event.preventDefault();\n }\n }\n this.onMouseUp(event);\n this.touchApplied = false;\n }\n\n /**\n * Call listener with backward compatibility.\n *\n * @private\n * @param {string} name Name of listener.\n * @param {MouseEvent} event The event object.\n * @param {CellCoords} coords Coordinates.\n * @param {HTMLElement} target Event target.\n */\n callListener(name, event, coords, target) {\n const listener = _classPrivateFieldGet(_wtSettings, this).getSettingPure(name);\n if (listener) {\n listener(event, coords, target, _classPrivateFieldGet(_facadeGetter, this).call(this));\n }\n }\n\n /**\n * Clears double-click timeouts and destroys the internal eventManager instance.\n */\n destroy() {\n clearTimeout(_classPrivateFieldGet(_dblClickTimeout, this)[0]);\n clearTimeout(_classPrivateFieldGet(_dblClickTimeout, this)[1]);\n _classPrivateFieldGet(_eventManager, this).destroy();\n }\n}\nexport default Event;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { getScrollableElement, getScrollbarWidth } from \"../../../helpers/dom/element.mjs\";\nimport { requestAnimationFrame } from \"../../../helpers/feature.mjs\";\nimport { arrayEach } from \"../../../helpers/array.mjs\";\nimport { isKey } from \"../../../helpers/unicode.mjs\";\nimport { isChrome } from \"../../../helpers/browser.mjs\";\nimport { warn } from \"../../../helpers/console.mjs\";\nimport { InlineStartOverlay, TopOverlay, TopInlineStartCornerOverlay, BottomOverlay, BottomInlineStartCornerOverlay } from \"./overlay/index.mjs\";\n/**\n * @class Overlays\n */\nvar _overlays = /*#__PURE__*/new WeakMap();\nvar _hasRenderingStateChanged = /*#__PURE__*/new WeakMap();\nvar _containerDomResizeCount = /*#__PURE__*/new WeakMap();\nvar _containerDomResizeCountTimeout = /*#__PURE__*/new WeakMap();\nclass Overlays {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @todo refactoring remove.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {EventManager} eventManager The walkontable event manager.\n * @param {MasterTable} wtTable The master table.\n */\n constructor(wotInstance, facadeGetter, domBindings, wtSettings, eventManager, wtTable) {\n /**\n * Walkontable instance's reference.\n *\n * @protected\n * @type {Walkontable}\n */\n _defineProperty(this, \"wot\", null);\n /**\n * An array of the all overlays.\n *\n * @type {Overlay[]}\n */\n _classPrivateFieldInitSpec(this, _overlays, []);\n /**\n * Refer to the TopOverlay instance.\n *\n * @protected\n * @type {TopOverlay}\n */\n _defineProperty(this, \"topOverlay\", null);\n /**\n * Refer to the BottomOverlay instance.\n *\n * @protected\n * @type {BottomOverlay}\n */\n _defineProperty(this, \"bottomOverlay\", null);\n /**\n * Refer to the InlineStartOverlay or instance.\n *\n * @protected\n * @type {InlineStartOverlay}\n */\n _defineProperty(this, \"inlineStartOverlay\", null);\n /**\n * Refer to the TopInlineStartCornerOverlay instance.\n *\n * @protected\n * @type {TopInlineStartCornerOverlay}\n */\n _defineProperty(this, \"topInlineStartCornerOverlay\", null);\n /**\n * Refer to the BottomInlineStartCornerOverlay instance.\n *\n * @protected\n * @type {BottomInlineStartCornerOverlay}\n */\n _defineProperty(this, \"bottomInlineStartCornerOverlay\", null);\n /**\n * Browser line height for purposes of translating mouse wheel.\n *\n * @private\n * @type {number}\n */\n _defineProperty(this, \"browserLineHeight\", undefined);\n /**\n * The walkontable settings.\n *\n * @protected\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", null);\n /**\n * Indicates whether the rendering state has changed for one of the overlays.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _hasRenderingStateChanged, false);\n /**\n * The amount of times the ResizeObserver callback was fired in direct succession.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _containerDomResizeCount, 0);\n /**\n * The timeout ID for the ResizeObserver endless-loop-blocking logic.\n *\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _containerDomResizeCountTimeout, null);\n /**\n * The instance of the ResizeObserver that observes the size of the Walkontable wrapper element.\n * In case of the size change detection the `onContainerElementResize` is fired.\n *\n * @private\n * @type {ResizeObserver}\n */\n _defineProperty(this, \"resizeObserver\", new ResizeObserver(entries => {\n requestAnimationFrame(() => {\n if (!Array.isArray(entries) || !entries.length) {\n return;\n }\n _classPrivateFieldSet(_containerDomResizeCount, this, _classPrivateFieldGet(_containerDomResizeCount, this) + 1);\n if (_classPrivateFieldGet(_containerDomResizeCount, this) === 100) {\n warn('The ResizeObserver callback was fired too many times in direct succession.' + '\\nThis may be due to an infinite loop caused by setting a dynamic height/width (for example, ' + 'with the `dvh` units) to a Handsontable container\\'s parent. ' + '\\nThe observer will be disconnected.');\n this.resizeObserver.disconnect();\n }\n\n // This logic is required to prevent an endless loop of the ResizeObserver callback.\n // https://github.com/handsontable/dev-handsontable/issues/1898#issuecomment-2154794817\n if (_classPrivateFieldGet(_containerDomResizeCountTimeout, this) !== null) {\n clearTimeout(_classPrivateFieldGet(_containerDomResizeCountTimeout, this));\n }\n _classPrivateFieldSet(_containerDomResizeCountTimeout, this, setTimeout(() => {\n _classPrivateFieldSet(_containerDomResizeCount, this, 0);\n }, 100));\n this.wtSettings.getSetting('onContainerElementResize');\n });\n }));\n this.wot = wotInstance;\n this.wtSettings = wtSettings;\n this.domBindings = domBindings;\n this.facadeGetter = facadeGetter;\n this.wtTable = wtTable;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n\n // legacy support\n this.instance = this.wot; // todo refactoring: move to facade\n this.eventManager = eventManager;\n\n // TODO refactoring: probably invalid place to this logic\n this.scrollbarSize = getScrollbarWidth(rootDocument);\n const isOverflowHidden = rootWindow.getComputedStyle(wtTable.wtRootElement.parentNode).getPropertyValue('overflow') === 'hidden';\n this.scrollableElement = isOverflowHidden ? wtTable.holder : getScrollableElement(wtTable.TABLE);\n this.initOverlays();\n this.hasScrollbarBottom = false;\n this.hasScrollbarRight = false;\n this.destroyed = false;\n this.keyPressed = false;\n this.spreaderLastSize = {\n width: null,\n height: null\n };\n this.verticalScrolling = false;\n this.horizontalScrolling = false;\n this.initBrowserLineHeight();\n this.registerListeners();\n this.lastScrollX = rootWindow.scrollX;\n this.lastScrollY = rootWindow.scrollY;\n }\n\n /**\n * Get the list of references to all overlays.\n *\n * @param {boolean} [includeMaster = false] If set to `true`, the list will contain the master table as the last\n * element.\n * @returns {(TopOverlay|TopInlineStartCornerOverlay|InlineStartOverlay|BottomOverlay|BottomInlineStartCornerOverlay)[]}\n */\n getOverlays() {\n let includeMaster = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const overlays = [..._classPrivateFieldGet(_overlays, this)];\n if (includeMaster) {\n overlays.push(this.wtTable);\n }\n return overlays;\n }\n\n /**\n * Retrieve browser line height and apply its value to `browserLineHeight`.\n *\n * @private\n */\n initBrowserLineHeight() {\n const {\n rootWindow,\n rootDocument\n } = this.domBindings;\n const computedStyle = rootWindow.getComputedStyle(rootDocument.body);\n /**\n * Sometimes `line-height` might be set to 'normal'. In that case, a default `font-size` should be multiplied by roughly 1.2.\n * Https://developer.mozilla.org/pl/docs/Web/CSS/line-height#Values.\n */\n const lineHeight = parseInt(computedStyle.lineHeight, 10);\n const lineHeightFalback = parseInt(computedStyle.fontSize, 10) * 1.2;\n this.browserLineHeight = lineHeight || lineHeightFalback;\n }\n\n /**\n * Prepare overlays based on user settings.\n *\n * @private\n */\n initOverlays() {\n const args = [this.wot, this.facadeGetter, this.wtSettings, this.domBindings];\n\n // todo refactoring: IOC, collection or factories.\n // TODO refactoring, conceive about using generic collection of overlays.\n this.topOverlay = new TopOverlay(...args);\n this.bottomOverlay = new BottomOverlay(...args);\n this.inlineStartOverlay = new InlineStartOverlay(...args);\n\n // TODO discuss, the controversial here would be removing the lazy creation mechanism for corners.\n // TODO cond. Has no any visual impact. They're initially hidden in same way like left, top, and bottom overlays.\n this.topInlineStartCornerOverlay = new TopInlineStartCornerOverlay(...args, this.topOverlay, this.inlineStartOverlay);\n this.bottomInlineStartCornerOverlay = new BottomInlineStartCornerOverlay(...args, this.bottomOverlay, this.inlineStartOverlay);\n _classPrivateFieldSet(_overlays, this, [this.topOverlay, this.bottomOverlay, this.inlineStartOverlay, this.topInlineStartCornerOverlay, this.bottomInlineStartCornerOverlay]);\n }\n\n /**\n * Runs logic for the overlays before the table is drawn.\n */\n beforeDraw() {\n _classPrivateFieldSet(_hasRenderingStateChanged, this, _classPrivateFieldGet(_overlays, this).reduce((acc, overlay) => {\n return overlay.hasRenderingStateChanged() || acc;\n }, false));\n _classPrivateFieldGet(_overlays, this).forEach(overlay => overlay.updateStateOfRendering('before'));\n }\n\n /**\n * Runs logic for the overlays after the table is drawn.\n */\n afterDraw() {\n this.syncScrollWithMaster();\n _classPrivateFieldGet(_overlays, this).forEach(overlay => {\n const hasRenderingStateChanged = overlay.hasRenderingStateChanged();\n overlay.updateStateOfRendering('after');\n if (hasRenderingStateChanged && !overlay.needFullRender) {\n overlay.reset();\n }\n });\n }\n\n /**\n * Refresh and redraw table.\n */\n refreshAll() {\n if (!this.wot.drawn) {\n return;\n }\n if (!this.wtTable.holder.parentNode) {\n // Walkontable was detached from DOM, but this handler was not removed\n this.destroy();\n return;\n }\n this.wot.draw(true);\n if (this.verticalScrolling) {\n this.inlineStartOverlay.onScroll(); // todo the inlineStartOverlay.onScroll() fires hook. Why is it needed there, not in any another place?\n }\n if (this.horizontalScrolling) {\n this.topOverlay.onScroll();\n }\n this.verticalScrolling = false;\n this.horizontalScrolling = false;\n }\n\n /**\n * Register all necessary event listeners.\n */\n registerListeners() {\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const {\n mainTableScrollableElement: topOverlayScrollableElement\n } = this.topOverlay;\n const {\n mainTableScrollableElement: inlineStartOverlayScrollableElement\n } = this.inlineStartOverlay;\n this.eventManager.addEventListener(rootDocument.documentElement, 'keydown', event => this.onKeyDown(event));\n this.eventManager.addEventListener(rootDocument.documentElement, 'keyup', () => this.onKeyUp());\n this.eventManager.addEventListener(rootDocument, 'visibilitychange', () => this.onKeyUp());\n this.eventManager.addEventListener(topOverlayScrollableElement, 'scroll', event => this.onTableScroll(event), {\n passive: true\n });\n if (topOverlayScrollableElement !== inlineStartOverlayScrollableElement) {\n this.eventManager.addEventListener(inlineStartOverlayScrollableElement, 'scroll', event => this.onTableScroll(event), {\n passive: true\n });\n }\n const isHighPixelRatio = rootWindow.devicePixelRatio && rootWindow.devicePixelRatio > 1;\n const isScrollOnWindow = this.scrollableElement === rootWindow;\n const preventWheel = this.wtSettings.getSetting('preventWheel');\n const wheelEventOptions = {\n passive: isScrollOnWindow\n };\n if (preventWheel || isHighPixelRatio || !isChrome()) {\n this.eventManager.addEventListener(this.wtTable.wtRootElement, 'wheel', event => this.onCloneWheel(event, preventWheel), wheelEventOptions);\n }\n const overlays = [this.topOverlay, this.bottomOverlay, this.inlineStartOverlay, this.topInlineStartCornerOverlay, this.bottomInlineStartCornerOverlay];\n overlays.forEach(overlay => {\n if (overlay && overlay.needFullRender) {\n const {\n holder\n } = overlay.clone.wtTable; // todo rethink, maybe: overlay.getHolder()\n\n this.eventManager.addEventListener(holder, 'wheel', event => this.onCloneWheel(event, preventWheel), wheelEventOptions);\n }\n });\n let resizeTimeout;\n this.eventManager.addEventListener(rootWindow, 'resize', () => {\n clearTimeout(resizeTimeout);\n resizeTimeout = setTimeout(() => {\n this.wtSettings.getSetting('onWindowResize');\n\n // Remove resizing the window from the ResizeObserver's endless-loop-blocking logic.\n _classPrivateFieldSet(_containerDomResizeCount, this, 0);\n }, 200);\n });\n if (!isScrollOnWindow) {\n this.resizeObserver.observe(this.wtTable.wtRootElement.parentElement);\n }\n }\n\n /**\n * Deregister all previously registered listeners.\n */\n deregisterListeners() {\n this.eventManager.clearEvents(true);\n }\n\n /**\n * Scroll listener.\n *\n * @param {Event} event The mouse event object.\n */\n onTableScroll(event) {\n // There was if statement which controlled flow of this function. It avoided the execution of the next lines\n // on mobile devices. It was changed. Broader description of this case is included within issue #4856.\n const rootWindow = this.domBindings.rootWindow;\n const masterHorizontal = this.inlineStartOverlay.mainTableScrollableElement;\n const masterVertical = this.topOverlay.mainTableScrollableElement;\n const target = event.target;\n\n // For key press, sync only master -> overlay position because while pressing Walkontable.render is triggered\n // by hot.refreshBorder\n if (this.keyPressed) {\n if (masterVertical !== rootWindow && target !== rootWindow && !event.target.contains(masterVertical) || masterHorizontal !== rootWindow && target !== rootWindow && !event.target.contains(masterHorizontal)) {\n return;\n }\n }\n this.syncScrollPositions(event);\n }\n\n /**\n * Wheel listener for cloned overlays.\n *\n * @param {Event} event The mouse event object.\n * @param {boolean} preventDefault If `true`, the `preventDefault` will be called on event object.\n */\n onCloneWheel(event, preventDefault) {\n const {\n rootWindow\n } = this.domBindings;\n\n // There was if statement which controlled flow of this function. It avoided the execution of the next lines\n // on mobile devices. It was changed. Broader description of this case is included within issue #4856.\n\n const masterHorizontal = this.inlineStartOverlay.mainTableScrollableElement;\n const masterVertical = this.topOverlay.mainTableScrollableElement;\n const target = event.target;\n\n // For key press, sync only master -> overlay position because while pressing Walkontable.render is triggered\n // by hot.refreshBorder\n const shouldNotWheelVertically = masterVertical !== rootWindow && target !== rootWindow && !target.contains(masterVertical);\n const shouldNotWheelHorizontally = masterHorizontal !== rootWindow && target !== rootWindow && !target.contains(masterHorizontal);\n if (this.keyPressed && (shouldNotWheelVertically || shouldNotWheelHorizontally) || this.scrollableElement === rootWindow) {\n return;\n }\n const isScrollPossible = this.translateMouseWheelToScroll(event);\n if (preventDefault || this.scrollableElement !== rootWindow && isScrollPossible) {\n event.preventDefault();\n }\n }\n\n /**\n * Key down listener.\n *\n * @param {Event} event The keyboard event object.\n */\n onKeyDown(event) {\n this.keyPressed = isKey(event.keyCode, 'ARROW_UP|ARROW_RIGHT|ARROW_DOWN|ARROW_LEFT');\n }\n\n /**\n * Key up listener.\n */\n onKeyUp() {\n this.keyPressed = false;\n }\n\n /**\n * Translate wheel event into scroll event and sync scroll overlays position.\n *\n * @private\n * @param {Event} event The mouse event object.\n * @returns {boolean}\n */\n translateMouseWheelToScroll(event) {\n let deltaY = isNaN(event.deltaY) ? -1 * event.wheelDeltaY : event.deltaY;\n let deltaX = isNaN(event.deltaX) ? -1 * event.wheelDeltaX : event.deltaX;\n if (event.deltaMode === 1) {\n deltaX += deltaX * this.browserLineHeight;\n deltaY += deltaY * this.browserLineHeight;\n }\n const isScrollVerticallyPossible = this.scrollVertically(deltaY);\n const isScrollHorizontallyPossible = this.scrollHorizontally(deltaX);\n return isScrollVerticallyPossible || isScrollHorizontallyPossible;\n }\n\n /**\n * Scrolls main scrollable element horizontally.\n *\n * @param {number} delta Relative value to scroll.\n * @returns {boolean}\n */\n scrollVertically(delta) {\n const previousScroll = this.scrollableElement.scrollTop;\n this.scrollableElement.scrollTop += delta;\n return previousScroll !== this.scrollableElement.scrollTop;\n }\n\n /**\n * Scrolls main scrollable element horizontally.\n *\n * @param {number} delta Relative value to scroll.\n * @returns {boolean}\n */\n scrollHorizontally(delta) {\n const previousScroll = this.scrollableElement.scrollLeft;\n this.scrollableElement.scrollLeft += delta;\n return previousScroll !== this.scrollableElement.scrollLeft;\n }\n\n /**\n * Synchronize scroll position between master table and overlay table.\n *\n * @private\n */\n syncScrollPositions() {\n if (this.destroyed) {\n return;\n }\n const {\n rootWindow\n } = this.domBindings;\n const topHolder = this.topOverlay.clone.wtTable.holder; // todo rethink\n const leftHolder = this.inlineStartOverlay.clone.wtTable.holder; // todo rethink\n\n const [scrollLeft, scrollTop] = [this.scrollableElement.scrollLeft, this.scrollableElement.scrollTop];\n this.horizontalScrolling = topHolder.scrollLeft !== scrollLeft || this.lastScrollX !== rootWindow.scrollX;\n this.verticalScrolling = leftHolder.scrollTop !== scrollTop || this.lastScrollY !== rootWindow.scrollY;\n this.lastScrollX = rootWindow.scrollX;\n this.lastScrollY = rootWindow.scrollY;\n if (this.horizontalScrolling) {\n topHolder.scrollLeft = scrollLeft;\n const bottomHolder = this.bottomOverlay.needFullRender ? this.bottomOverlay.clone.wtTable.holder : null; // todo rethink\n\n if (bottomHolder) {\n bottomHolder.scrollLeft = scrollLeft;\n }\n }\n if (this.verticalScrolling) {\n leftHolder.scrollTop = scrollTop;\n }\n this.refreshAll();\n }\n\n /**\n * Synchronize overlay scrollbars with the master scrollbar.\n */\n syncScrollWithMaster() {\n if (!_classPrivateFieldGet(_hasRenderingStateChanged, this)) {\n return;\n }\n const master = this.topOverlay.mainTableScrollableElement;\n const {\n scrollLeft,\n scrollTop\n } = master;\n if (this.topOverlay.needFullRender) {\n this.topOverlay.clone.wtTable.holder.scrollLeft = scrollLeft; // todo rethink, *overlay.setScroll*()\n }\n if (this.bottomOverlay.needFullRender) {\n this.bottomOverlay.clone.wtTable.holder.scrollLeft = scrollLeft; // todo rethink, *overlay.setScroll*()\n }\n if (this.inlineStartOverlay.needFullRender) {\n this.inlineStartOverlay.clone.wtTable.holder.scrollTop = scrollTop; // todo rethink, *overlay.setScroll*()\n }\n _classPrivateFieldSet(_hasRenderingStateChanged, this, false);\n }\n\n /**\n * Update the main scrollable elements for all the overlays.\n */\n updateMainScrollableElements() {\n this.deregisterListeners();\n this.inlineStartOverlay.updateMainScrollableElement();\n this.topOverlay.updateMainScrollableElement();\n if (this.bottomOverlay.needFullRender) {\n this.bottomOverlay.updateMainScrollableElement();\n }\n const {\n wtTable\n } = this;\n const {\n rootWindow\n } = this.domBindings;\n if (rootWindow.getComputedStyle(wtTable.wtRootElement.parentNode).getPropertyValue('overflow') === 'hidden') {\n this.scrollableElement = wtTable.holder;\n } else {\n this.scrollableElement = getScrollableElement(wtTable.TABLE);\n }\n this.registerListeners();\n }\n\n /**\n *\n */\n destroy() {\n this.resizeObserver.disconnect();\n this.eventManager.destroy();\n // todo, probably all below `destory` calls has no sense. To analyze\n this.topOverlay.destroy();\n if (this.bottomOverlay.clone) {\n this.bottomOverlay.destroy();\n }\n this.inlineStartOverlay.destroy();\n if (this.topInlineStartCornerOverlay) {\n this.topInlineStartCornerOverlay.destroy();\n }\n if (this.bottomInlineStartCornerOverlay && this.bottomInlineStartCornerOverlay.clone) {\n this.bottomInlineStartCornerOverlay.destroy();\n }\n this.destroyed = true;\n }\n\n /**\n * @param {boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering\n * the data. It will only work if Table.draw() does not force\n * rendering anyway.\n */\n refresh() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const wasSpreaderSizeUpdated = this.updateLastSpreaderSize();\n if (wasSpreaderSizeUpdated) {\n this.adjustElementsSize();\n }\n if (this.bottomOverlay.clone) {\n this.bottomOverlay.refresh(fastDraw);\n }\n this.inlineStartOverlay.refresh(fastDraw);\n this.topOverlay.refresh(fastDraw);\n if (this.topInlineStartCornerOverlay) {\n this.topInlineStartCornerOverlay.refresh(fastDraw);\n }\n if (this.bottomInlineStartCornerOverlay && this.bottomInlineStartCornerOverlay.clone) {\n this.bottomInlineStartCornerOverlay.refresh(fastDraw);\n }\n }\n\n /**\n * Update the last cached spreader size with the current size.\n *\n * @returns {boolean} `true` if the lastSpreaderSize cache was updated, `false` otherwise.\n */\n updateLastSpreaderSize() {\n const spreader = this.wtTable.spreader;\n const width = spreader.clientWidth;\n const height = spreader.clientHeight;\n const needsUpdating = width !== this.spreaderLastSize.width || height !== this.spreaderLastSize.height;\n if (needsUpdating) {\n this.spreaderLastSize.width = width;\n this.spreaderLastSize.height = height;\n }\n return needsUpdating;\n }\n\n /**\n * Adjust overlays elements size and master table size.\n */\n adjustElementsSize() {\n const {\n wtViewport\n } = this.wot;\n const {\n wtTable\n } = this;\n const {\n rootWindow\n } = this.domBindings;\n const isWindowScrolled = this.scrollableElement === rootWindow;\n const totalColumns = this.wtSettings.getSetting('totalColumns');\n const totalRows = this.wtSettings.getSetting('totalRows');\n const headerRowSize = wtViewport.getRowHeaderWidth();\n const headerColumnSize = wtViewport.getColumnHeaderHeight();\n const proposedHiderHeight = headerColumnSize + this.topOverlay.sumCellSizes(0, totalRows) + 1;\n const proposedHiderWidth = headerRowSize + this.inlineStartOverlay.sumCellSizes(0, totalColumns);\n const hiderElement = wtTable.hider;\n const hiderStyle = hiderElement.style;\n const isScrolledBeyondHiderHeight = () => {\n return isWindowScrolled ? false : this.scrollableElement.scrollTop > Math.max(0, proposedHiderHeight - wtTable.holder.clientHeight);\n };\n const isScrolledBeyondHiderWidth = () => {\n return isWindowScrolled ? false : this.scrollableElement.scrollLeft > Math.max(0, proposedHiderWidth - wtTable.holder.clientWidth);\n };\n const columnHeaderBorderCompensation = isScrolledBeyondHiderHeight() ? 1 : 0;\n const rowHeaderBorderCompensation = isScrolledBeyondHiderWidth() ? 1 : 0;\n\n // If the elements are being adjusted after scrolling the table from the very beginning to the very end,\n // we need to adjust the hider dimensions by the header border size. (https://github.com/handsontable/dev-handsontable/issues/1772)\n hiderStyle.width = `${proposedHiderWidth + rowHeaderBorderCompensation}px`;\n hiderStyle.height = `${proposedHiderHeight + columnHeaderBorderCompensation}px`;\n if (this.scrollbarSize > 0) {\n // todo refactoring, looking as a part of logic which should be moved outside the class\n const {\n scrollHeight: rootElemScrollHeight,\n scrollWidth: rootElemScrollWidth\n } = wtTable.wtRootElement;\n const {\n scrollHeight: holderScrollHeight,\n scrollWidth: holderScrollWidth\n } = wtTable.holder;\n this.hasScrollbarRight = rootElemScrollHeight < holderScrollHeight;\n this.hasScrollbarBottom = rootElemScrollWidth < holderScrollWidth;\n if (this.hasScrollbarRight && wtTable.hider.scrollWidth + this.scrollbarSize > rootElemScrollWidth) {\n this.hasScrollbarBottom = true;\n } else if (this.hasScrollbarBottom && wtTable.hider.scrollHeight + this.scrollbarSize > rootElemScrollHeight) {\n this.hasScrollbarRight = true;\n }\n }\n this.topOverlay.adjustElementsSize();\n this.inlineStartOverlay.adjustElementsSize();\n this.bottomOverlay.adjustElementsSize();\n }\n\n /**\n * Expand the hider vertically element by the provided delta value.\n *\n * @param {number} heightDelta The delta value to expand the hider element by.\n */\n expandHiderVerticallyBy(heightDelta) {\n const {\n wtTable\n } = this;\n wtTable.hider.style.height = `${parseInt(wtTable.hider.style.height, 10) + heightDelta}px`;\n }\n\n /**\n * Expand the hider horizontally element by the provided delta value.\n *\n * @param {number} widthDelta The delta value to expand the hider element by.\n */\n expandHiderHorizontallyBy(widthDelta) {\n const {\n wtTable\n } = this;\n wtTable.hider.style.width = `${parseInt(wtTable.hider.style.width, 10) + widthDelta}px`;\n }\n\n /**\n *\n */\n applyToDOM() {\n if (!this.wtTable.isVisible()) {\n return;\n }\n this.topOverlay.applyToDOM();\n if (this.bottomOverlay.clone) {\n this.bottomOverlay.applyToDOM();\n }\n this.inlineStartOverlay.applyToDOM();\n }\n\n /**\n * Get the parent overlay of the provided element.\n *\n * @param {HTMLElement} element An element to process.\n * @returns {object|null}\n */\n getParentOverlay(element) {\n if (!element) {\n return null;\n }\n const overlays = [this.topOverlay, this.inlineStartOverlay, this.bottomOverlay, this.topInlineStartCornerOverlay, this.bottomInlineStartCornerOverlay];\n let result = null;\n arrayEach(overlays, overlay => {\n if (!overlay) {\n return;\n }\n if (overlay.clone && overlay.clone.wtTable.TABLE.contains(element)) {\n // todo demeter\n result = overlay.clone;\n }\n });\n return result;\n }\n\n /**\n * Synchronize the class names between the main overlay table and the tables on the other overlays.\n *\n */\n syncOverlayTableClassNames() {\n const masterTable = this.wtTable.TABLE;\n const overlays = [this.topOverlay, this.inlineStartOverlay, this.bottomOverlay, this.topInlineStartCornerOverlay, this.bottomInlineStartCornerOverlay];\n arrayEach(overlays, elem => {\n if (!elem) {\n return;\n }\n elem.clone.wtTable.TABLE.className = masterTable.className; // todo demeter\n });\n }\n}\nexport default Overlays;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { hasClass, index, offset, removeTextNodes, overlayContainsElement, closest, outerHeight, outerWidth, innerHeight, isVisible, setAttribute } from \"../../../helpers/dom/element.mjs\";\nimport { isFunction } from \"../../../helpers/function.mjs\";\nimport ColumnFilter from \"./filter/column.mjs\";\nimport RowFilter from \"./filter/row.mjs\";\nimport { Renderer } from \"./renderer/index.mjs\";\nimport ColumnUtils from \"./utils/column.mjs\";\nimport RowUtils from \"./utils/row.mjs\";\nimport { CLONE_TOP, CLONE_BOTTOM, CLONE_INLINE_START, CLONE_TOP_INLINE_START_CORNER, CLONE_BOTTOM_INLINE_START_CORNER } from \"./overlay/index.mjs\";\nimport { A11Y_PRESENTATION } from \"../../../helpers/a11y.mjs\";\n/**\n * @todo These mixes are never added to the class Table, however their members are used here.\n * @todo Continue: Potentially it works only, because some of these mixes are added to every inherited class.\n * @todo Refactoring, move code from `if(this.isMaster)` into MasterTable, and others like that.\n * @mixes stickyColumnsStart\n * @mixes stickyRowsBottom\n * @mixes stickyRowsTop\n * @mixes calculatedRows\n * @mixes calculatedColumns\n * @abstract\n */\nclass Table {\n /**\n *\n * @abstract\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {'master'|CLONE_TYPES_ENUM} name Overlay name.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings, name) {\n /**\n * The walkontable settings.\n *\n * @protected\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", null);\n _defineProperty(this, \"domBindings\", void 0);\n _defineProperty(this, \"TBODY\", null);\n _defineProperty(this, \"THEAD\", null);\n _defineProperty(this, \"COLGROUP\", null);\n /**\n * Indicates if the table has height bigger than 0px.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"hasTableHeight\", true);\n /**\n * Indicates if the table has width bigger than 0px.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"hasTableWidth\", true);\n /**\n * Indicates if the table is visible. By visible, it means that the holder\n * element has CSS 'display' property different than 'none'.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"isTableVisible\", false);\n _defineProperty(this, \"tableOffset\", 0);\n _defineProperty(this, \"holderOffset\", 0);\n this.domBindings = domBindings;\n /**\n * Indicates if this instance is of type `MasterTable` (i.e. It is NOT an overlay).\n *\n * @type {boolean}\n */\n this.isMaster = name === 'master';\n this.name = name;\n this.dataAccessObject = dataAccessObject;\n this.facadeGetter = facadeGetter;\n this.wtSettings = wtSettings;\n\n // legacy support\n this.instance = this.dataAccessObject.wot; // TODO refactoring: it might be removed here, and provides legacy support through facade.\n this.wot = this.dataAccessObject.wot;\n this.TABLE = domBindings.rootTable;\n removeTextNodes(this.TABLE);\n\n // TODO refactoring, to recognize the legitimacy of moving them into domBidings\n this.spreader = this.createSpreader(this.TABLE);\n this.hider = this.createHider(this.spreader);\n this.holder = this.createHolder(this.hider);\n this.wtRootElement = this.holder.parentNode;\n if (this.isMaster) {\n this.alignOverlaysWithTrimmingContainer(); // todo wow, It calls method from child class (MasterTable).\n }\n this.fixTableDomTree();\n this.rowFilter = null; // TODO refactoring, eliminate all (re)creations of this object, then updates state when needed.\n this.columnFilter = null; // TODO refactoring, eliminate all (re)creations of this object, then updates state when needed.\n this.correctHeaderWidth = false;\n const origRowHeaderWidth = this.wtSettings.getSettingPure('rowHeaderWidth');\n\n // Fix for jumping row headers (https://github.com/handsontable/handsontable/issues/3850)\n this.wtSettings.update('rowHeaderWidth', () => this._modifyRowHeaderWidth(origRowHeaderWidth));\n this.rowUtils = new RowUtils(this.dataAccessObject, this.wtSettings); // TODO refactoring, It can be passed through IOC.\n this.columnUtils = new ColumnUtils(this.dataAccessObject, this.wtSettings); // TODO refactoring, It can be passed through IOC.\n\n this.tableRenderer = new Renderer({\n // TODO refactoring, It can be passed through IOC.\n TABLE: this.TABLE,\n THEAD: this.THEAD,\n COLGROUP: this.COLGROUP,\n TBODY: this.TBODY,\n rowUtils: this.rowUtils,\n columnUtils: this.columnUtils,\n cellRenderer: this.wtSettings.getSettingPure('cellRenderer')\n });\n }\n\n /**\n * Returns a boolean that is true if this Table represents a specific overlay, identified by the overlay name.\n * For MasterTable, it returns false.\n *\n * @param {string} overlayTypeName The overlay type.\n * @returns {boolean}\n */\n is(overlayTypeName) {\n // todo refactoring: eliminate all protected and private usages\n return this.name === overlayTypeName;\n }\n\n /**\n *\n */\n fixTableDomTree() {\n const rootDocument = this.domBindings.rootDocument;\n this.TBODY = this.TABLE.querySelector('tbody');\n if (!this.TBODY) {\n this.TBODY = rootDocument.createElement('tbody');\n this.TABLE.appendChild(this.TBODY);\n }\n this.THEAD = this.TABLE.querySelector('thead');\n if (!this.THEAD) {\n this.THEAD = rootDocument.createElement('thead');\n this.TABLE.insertBefore(this.THEAD, this.TBODY);\n }\n this.COLGROUP = this.TABLE.querySelector('colgroup');\n if (!this.COLGROUP) {\n this.COLGROUP = rootDocument.createElement('colgroup');\n this.TABLE.insertBefore(this.COLGROUP, this.THEAD);\n }\n }\n\n /**\n * @param {HTMLTableElement} table An element to process.\n * @returns {HTMLElement}\n */\n createSpreader(table) {\n const parent = table.parentNode;\n let spreader;\n if (!parent || parent.nodeType !== Node.ELEMENT_NODE || !hasClass(parent, 'wtHolder')) {\n spreader = this.domBindings.rootDocument.createElement('div');\n spreader.className = 'wtSpreader';\n if (parent) {\n // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n parent.insertBefore(spreader, table);\n }\n spreader.appendChild(table);\n }\n spreader.style.position = 'relative';\n if (this.wtSettings.getSetting('ariaTags')) {\n setAttribute(spreader, [A11Y_PRESENTATION()]);\n }\n return spreader;\n }\n\n /**\n * @param {HTMLElement} spreader An element to the hider element is injected.\n * @returns {HTMLElement}\n */\n createHider(spreader) {\n const parent = spreader.parentNode;\n let hider;\n if (!parent || parent.nodeType !== Node.ELEMENT_NODE || !hasClass(parent, 'wtHolder')) {\n hider = this.domBindings.rootDocument.createElement('div');\n hider.className = 'wtHider';\n if (parent) {\n // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n parent.insertBefore(hider, spreader);\n }\n hider.appendChild(spreader);\n }\n if (this.wtSettings.getSetting('ariaTags')) {\n setAttribute(hider, [A11Y_PRESENTATION()]);\n }\n return hider;\n }\n\n /**\n *\n * @param {HTMLElement} hider An element to the holder element is injected.\n * @returns {HTMLElement}\n */\n createHolder(hider) {\n const parent = hider.parentNode;\n let holder;\n if (!parent || parent.nodeType !== Node.ELEMENT_NODE || !hasClass(parent, 'wtHolder')) {\n holder = this.domBindings.rootDocument.createElement('div');\n holder.style.position = 'relative';\n holder.className = 'wtHolder';\n if (parent) {\n // if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n parent.insertBefore(holder, hider);\n }\n if (this.isMaster) {\n holder.parentNode.className += 'ht_master handsontable';\n holder.parentNode.setAttribute('dir', this.wtSettings.getSettingPure('rtlMode') ? 'rtl' : 'ltr');\n if (this.wtSettings.getSetting('ariaTags')) {\n setAttribute(holder.parentNode, [A11Y_PRESENTATION()]);\n }\n }\n holder.appendChild(hider);\n }\n if (this.wtSettings.getSetting('ariaTags')) {\n setAttribute(holder, [A11Y_PRESENTATION()]);\n }\n return holder;\n }\n\n /**\n * Redraws the table.\n *\n * @param {boolean} [fastDraw=false] If TRUE, will try to avoid full redraw and only update the border positions.\n * If FALSE or UNDEFINED, will perform a full redraw.\n * @returns {Table}\n */\n draw() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const {\n wtSettings\n } = this;\n const {\n wtOverlays,\n wtViewport\n } = this.dataAccessObject;\n const totalRows = wtSettings.getSetting('totalRows');\n const totalColumns = wtSettings.getSetting('totalColumns');\n const rowHeaders = wtSettings.getSetting('rowHeaders');\n const rowHeadersCount = rowHeaders.length;\n const columnHeaders = wtSettings.getSetting('columnHeaders');\n const columnHeadersCount = columnHeaders.length;\n let runFastDraw = fastDraw;\n if (this.isMaster) {\n wtOverlays.beforeDraw();\n this.holderOffset = offset(this.holder);\n runFastDraw = wtViewport.createCalculators(runFastDraw);\n if (rowHeadersCount && !wtSettings.getSetting('fixedColumnsStart')) {\n const leftScrollPos = wtOverlays.inlineStartOverlay.getScrollPosition();\n const previousState = this.correctHeaderWidth;\n this.correctHeaderWidth = leftScrollPos !== 0;\n if (previousState !== this.correctHeaderWidth) {\n runFastDraw = false;\n }\n }\n }\n if (runFastDraw) {\n if (this.isMaster) {\n wtOverlays.refresh(true);\n }\n } else {\n if (this.isMaster) {\n this.tableOffset = offset(this.TABLE);\n } else {\n this.tableOffset = this.dataAccessObject.parentTableOffset;\n }\n const startRow = totalRows > 0 ? this.getFirstRenderedRow() : 0;\n const startColumn = totalColumns > 0 ? this.getFirstRenderedColumn() : 0;\n this.rowFilter = new RowFilter(startRow, totalRows, columnHeadersCount);\n this.columnFilter = new ColumnFilter(startColumn, totalColumns, rowHeadersCount);\n let performRedraw = true;\n\n // Only master table rendering can be skipped\n if (this.isMaster) {\n this.alignOverlaysWithTrimmingContainer(); // todo It calls method from child class (MasterTable).\n const skipRender = {};\n this.wtSettings.getSetting('beforeDraw', true, skipRender);\n performRedraw = skipRender.skipRender !== true;\n }\n if (performRedraw) {\n this.tableRenderer.setHeaderContentRenderers(rowHeaders, columnHeaders);\n if (this.is(CLONE_BOTTOM) || this.is(CLONE_BOTTOM_INLINE_START_CORNER)) {\n // do NOT render headers on the bottom or bottom-left corner overlay\n this.tableRenderer.setHeaderContentRenderers(rowHeaders, []);\n }\n this.resetOversizedRows();\n this.tableRenderer.setActiveOverlayName(this.name).setViewportSize(this.getRenderedRowsCount(), this.getRenderedColumnsCount()).setFilters(this.rowFilter, this.columnFilter).render();\n let workspaceWidth;\n if (this.isMaster) {\n workspaceWidth = this.dataAccessObject.workspaceWidth;\n wtViewport.containerWidth = null;\n this.markOversizedColumnHeaders();\n }\n this.adjustColumnHeaderHeights();\n if (this.isMaster || this.is(CLONE_BOTTOM)) {\n this.markOversizedRows();\n }\n if (this.isMaster) {\n if (!this.wtSettings.getSetting('externalRowCalculator')) {\n wtViewport.createVisibleCalculators();\n }\n wtOverlays.refresh(false);\n wtOverlays.applyToDOM();\n const hiderWidth = outerWidth(this.hider);\n const tableWidth = outerWidth(this.TABLE);\n if (hiderWidth !== 0 && tableWidth !== hiderWidth) {\n // Recalculate the column widths, if width changes made in the overlays removed the scrollbar, thus changing the viewport width.\n this.columnUtils.calculateWidths();\n this.tableRenderer.renderer.colGroup.render();\n }\n if (workspaceWidth !== wtViewport.getWorkspaceWidth()) {\n // workspace width changed though to shown/hidden vertical scrollbar. Let's reapply stretching\n wtViewport.containerWidth = null;\n this.columnUtils.calculateWidths();\n this.tableRenderer.renderer.colGroup.render();\n }\n this.wtSettings.getSetting('onDraw', true);\n } else if (this.is(CLONE_BOTTOM)) {\n this.dataAccessObject.cloneSource.wtOverlays.adjustElementsSize();\n }\n }\n }\n let positionChanged = false;\n if (this.isMaster) {\n positionChanged = wtOverlays.topOverlay.resetFixedPosition();\n if (wtOverlays.bottomOverlay.clone) {\n positionChanged = wtOverlays.bottomOverlay.resetFixedPosition() || positionChanged;\n }\n positionChanged = wtOverlays.inlineStartOverlay.resetFixedPosition() || positionChanged;\n if (wtOverlays.topInlineStartCornerOverlay) {\n wtOverlays.topInlineStartCornerOverlay.resetFixedPosition();\n }\n if (wtOverlays.bottomInlineStartCornerOverlay && wtOverlays.bottomInlineStartCornerOverlay.clone) {\n wtOverlays.bottomInlineStartCornerOverlay.resetFixedPosition();\n }\n }\n if (positionChanged) {\n // It refreshes the cells borders caused by a 1px shift (introduced by overlays which add or\n // remove `innerBorderTop` and `innerBorderInlineStart` CSS classes to the DOM element. This happens\n // when there is a switch between rendering from 0 to N rows/columns and vice versa).\n wtOverlays.refreshAll(); // `refreshAll()` internally already calls `refreshSelections()` method\n wtOverlays.adjustElementsSize();\n } else {\n this.dataAccessObject.selectionManager.setActiveOverlay(this.facadeGetter()).render(runFastDraw);\n }\n if (this.isMaster) {\n wtOverlays.afterDraw();\n }\n this.dataAccessObject.drawn = true;\n return this;\n }\n\n /**\n * @param {number} col The visual column index.\n */\n markIfOversizedColumnHeader(col) {\n const sourceColIndex = this.columnFilter.renderedToSource(col);\n let level = this.wtSettings.getSetting('columnHeaders').length;\n const defaultRowHeight = this.wtSettings.getSetting('defaultRowHeight');\n let previousColHeaderHeight;\n let currentHeader;\n let currentHeaderHeight;\n const columnHeaderHeightSetting = this.wtSettings.getSetting('columnHeaderHeight') || [];\n while (level) {\n level -= 1;\n previousColHeaderHeight = this.getColumnHeaderHeight(level);\n currentHeader = this.getColumnHeader(sourceColIndex, level);\n if (!currentHeader) {\n /* eslint-disable no-continue */\n continue;\n }\n currentHeaderHeight = innerHeight(currentHeader);\n if (!previousColHeaderHeight && defaultRowHeight < currentHeaderHeight || previousColHeaderHeight < currentHeaderHeight) {\n this.dataAccessObject.wtViewport.oversizedColumnHeaders[level] = currentHeaderHeight;\n }\n if (Array.isArray(columnHeaderHeightSetting)) {\n if (columnHeaderHeightSetting[level] !== null && columnHeaderHeightSetting[level] !== undefined) {\n this.dataAccessObject.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level];\n }\n } else if (!isNaN(columnHeaderHeightSetting)) {\n this.dataAccessObject.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting;\n }\n if (this.dataAccessObject.wtViewport.oversizedColumnHeaders[level] < (columnHeaderHeightSetting[level] || columnHeaderHeightSetting)) {\n this.dataAccessObject.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level] || columnHeaderHeightSetting; // eslint-disable-line max-len\n }\n }\n }\n\n /**\n *\n */\n adjustColumnHeaderHeights() {\n const {\n wtSettings\n } = this;\n const children = this.THEAD.childNodes;\n const oversizedColumnHeaders = this.dataAccessObject.wtViewport.oversizedColumnHeaders;\n const columnHeaders = wtSettings.getSetting('columnHeaders');\n for (let i = 0, len = columnHeaders.length; i < len; i++) {\n if (oversizedColumnHeaders[i]) {\n if (!children[i] || children[i].childNodes.length === 0) {\n return;\n }\n children[i].childNodes[0].style.height = `${oversizedColumnHeaders[i]}px`;\n }\n }\n }\n\n /**\n * Resets cache of row heights. The cache should be cached for each render cycle in a case\n * when new cell values have content which increases/decreases cell height.\n */\n resetOversizedRows() {\n const {\n wtSettings\n } = this;\n const {\n wtViewport\n } = this.dataAccessObject;\n if (!this.isMaster && !this.is(CLONE_BOTTOM)) {\n return;\n }\n if (!wtSettings.getSetting('externalRowCalculator')) {\n const rowsToRender = this.getRenderedRowsCount();\n\n // Reset the oversized row cache for rendered rows\n for (let visibleRowIndex = 0; visibleRowIndex < rowsToRender; visibleRowIndex++) {\n const sourceRow = this.rowFilter.renderedToSource(visibleRowIndex);\n if (wtViewport.oversizedRows && wtViewport.oversizedRows[sourceRow]) {\n wtViewport.oversizedRows[sourceRow] = undefined;\n }\n }\n }\n }\n\n /**\n * Get cell element at coords.\n * Negative coords.row or coords.col are used to retrieve header cells. If there are multiple header levels, the\n * negative value corresponds to the distance from the working area. For example, when there are 3 levels of column\n * headers, coords.col=-1 corresponds to the most inner header element, while coords.col=-3 corresponds to the\n * outmost header element.\n *\n * In case an element for the coords is not rendered, the method returns an error code.\n * To produce the error code, the input parameters are validated in the order in which they\n * are given. Thus, if both the row and the column coords are out of the rendered bounds,\n * the method returns the error code for the row.\n *\n * @param {CellCoords} coords The cell coordinates.\n * @returns {HTMLElement|number} HTMLElement on success or Number one of the exit codes on error:\n * -1 row before viewport\n * -2 row after viewport\n * -3 column before viewport\n * -4 column after viewport.\n */\n getCell(coords) {\n let row = coords.row;\n let column = coords.col;\n const hookResult = this.wtSettings.getSetting('onModifyGetCellCoords', row, column);\n if (hookResult && Array.isArray(hookResult)) {\n [row, column] = hookResult;\n }\n if (this.isRowBeforeRenderedRows(row)) {\n // row before rendered rows\n return -1;\n } else if (this.isRowAfterRenderedRows(row)) {\n // row after rendered rows\n return -2;\n } else if (this.isColumnBeforeRenderedColumns(column)) {\n // column before rendered columns\n return -3;\n } else if (this.isColumnAfterRenderedColumns(column)) {\n // column after rendered columns\n return -4;\n }\n const TR = this.getRow(row);\n if (!TR && row >= 0) {\n throw new Error('TR was expected to be rendered but is not');\n }\n const TD = TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(column)];\n if (!TD && column >= 0) {\n throw new Error('TD or TH was expected to be rendered but is not');\n }\n return TD;\n }\n\n /**\n * Get the DOM element of the row with the provided index.\n *\n * @param {number} rowIndex Row index.\n * @returns {HTMLTableRowElement|boolean} Return the row's DOM element or `false` if the row with the provided\n * index doesn't exist.\n */\n getRow(rowIndex) {\n let renderedRowIndex = null;\n let parentElement = null;\n if (rowIndex < 0) {\n var _this$rowFilter;\n renderedRowIndex = (_this$rowFilter = this.rowFilter) === null || _this$rowFilter === void 0 ? void 0 : _this$rowFilter.sourceRowToVisibleColHeadedRow(rowIndex);\n parentElement = this.THEAD;\n } else {\n var _this$rowFilter2;\n renderedRowIndex = (_this$rowFilter2 = this.rowFilter) === null || _this$rowFilter2 === void 0 ? void 0 : _this$rowFilter2.sourceToRendered(rowIndex);\n parentElement = this.TBODY;\n }\n if (renderedRowIndex !== undefined && parentElement !== undefined) {\n if (parentElement.childNodes.length < renderedRowIndex + 1) {\n return false;\n } else {\n return parentElement.childNodes[renderedRowIndex];\n }\n } else {\n return false;\n }\n }\n\n /**\n * GetColumnHeader.\n *\n * @param {number} col Column index.\n * @param {number} [level=0] Header level (0 = most distant to the table).\n * @returns {object} HTMLElement on success or undefined on error.\n */\n getColumnHeader(col) {\n let level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n const TR = this.THEAD.childNodes[level];\n return TR === null || TR === void 0 ? void 0 : TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(col)];\n }\n\n /**\n * Gets all columns headers (TH elements) from the table.\n *\n * @param {number} column A source column index.\n * @returns {HTMLTableCellElement[]}\n */\n getColumnHeaders(column) {\n const THs = [];\n const visibleColumn = this.columnFilter.sourceColumnToVisibleRowHeadedColumn(column);\n this.THEAD.childNodes.forEach(TR => {\n const TH = TR.childNodes[visibleColumn];\n if (TH) {\n THs.push(TH);\n }\n });\n return THs;\n }\n\n /**\n * GetRowHeader.\n *\n * @param {number} row Row index.\n * @param {number} [level=0] Header level (0 = most distant to the table).\n * @returns {HTMLElement} HTMLElement on success or Number one of the exit codes on error: `null table doesn't have\n * row headers`.\n */\n getRowHeader(row) {\n let level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n const rowHeadersCount = this.wtSettings.getSetting('rowHeaders').length;\n if (level >= rowHeadersCount) {\n return;\n }\n const renderedRow = this.rowFilter.sourceToRendered(row);\n const visibleRow = renderedRow < 0 ? this.rowFilter.sourceRowToVisibleColHeadedRow(row) : renderedRow;\n const parentElement = renderedRow < 0 ? this.THEAD : this.TBODY;\n const TR = parentElement.childNodes[visibleRow];\n return TR === null || TR === void 0 ? void 0 : TR.childNodes[level];\n }\n\n /**\n * Gets all rows headers (TH elements) from the table.\n *\n * @param {number} row A source row index.\n * @returns {HTMLTableCellElement[]}\n */\n getRowHeaders(row) {\n const THs = [];\n const rowHeadersCount = this.wtSettings.getSetting('rowHeaders').length;\n for (let renderedRowIndex = 0; renderedRowIndex < rowHeadersCount; renderedRowIndex++) {\n const TR = this.TBODY.childNodes[this.rowFilter.sourceToRendered(row)];\n const TH = TR === null || TR === void 0 ? void 0 : TR.childNodes[renderedRowIndex];\n if (TH) {\n THs.push(TH);\n }\n }\n return THs;\n }\n\n /**\n * Returns cell coords object for a given TD (or a child element of a TD element).\n *\n * @param {HTMLTableCellElement} TD A cell DOM element (or a child of one).\n * @returns {CellCoords|null} The coordinates of the provided TD element (or the closest TD element) or null, if the\n * provided element is not applicable.\n */\n getCoords(TD) {\n let cellElement = TD;\n if (cellElement.nodeName !== 'TD' && cellElement.nodeName !== 'TH') {\n cellElement = closest(cellElement, ['TD', 'TH']);\n }\n if (cellElement === null) {\n return null;\n }\n const TR = cellElement.parentNode;\n const CONTAINER = TR.parentNode;\n let row = index(TR);\n let col = cellElement.cellIndex;\n if (overlayContainsElement(CLONE_TOP_INLINE_START_CORNER, cellElement, this.wtRootElement) || overlayContainsElement(CLONE_TOP, cellElement, this.wtRootElement)) {\n if (CONTAINER.nodeName === 'THEAD') {\n row -= CONTAINER.childNodes.length;\n }\n } else if (overlayContainsElement(CLONE_BOTTOM_INLINE_START_CORNER, cellElement, this.wtRootElement) || overlayContainsElement(CLONE_BOTTOM, cellElement, this.wtRootElement)) {\n const totalRows = this.wtSettings.getSetting('totalRows');\n row = totalRows - CONTAINER.childNodes.length + row;\n } else if (CONTAINER === this.THEAD) {\n row = this.rowFilter.visibleColHeadedRowToSourceRow(row);\n } else {\n row = this.rowFilter.renderedToSource(row);\n }\n if (overlayContainsElement(CLONE_TOP_INLINE_START_CORNER, cellElement, this.wtRootElement) || overlayContainsElement(CLONE_INLINE_START, cellElement, this.wtRootElement) || overlayContainsElement(CLONE_BOTTOM_INLINE_START_CORNER, cellElement, this.wtRootElement)) {\n col = this.columnFilter.offsettedTH(col);\n } else {\n col = this.columnFilter.visibleRowHeadedColumnToSourceColumn(col);\n }\n return this.wot.createCellCoords(row, col);\n }\n\n /**\n * Check if any of the rendered rows is higher than expected, and if so, cache them.\n */\n markOversizedRows() {\n if (this.wtSettings.getSetting('externalRowCalculator')) {\n return;\n }\n let rowCount = this.TBODY.childNodes.length;\n const expectedTableHeight = rowCount * this.wtSettings.getSetting('defaultRowHeight');\n const actualTableHeight = innerHeight(this.TBODY) - 1;\n let previousRowHeight;\n let rowInnerHeight;\n let sourceRowIndex;\n let currentTr;\n let rowHeader;\n if (expectedTableHeight === actualTableHeight && !this.wtSettings.getSetting('fixedRowsBottom')) {\n // If the actual table height equals rowCount * default single row height, no row is oversized -> no need to iterate over them\n return;\n }\n while (rowCount) {\n rowCount -= 1;\n sourceRowIndex = this.rowFilter.renderedToSource(rowCount);\n previousRowHeight = this.getRowHeight(sourceRowIndex);\n currentTr = this.getTrForRow(sourceRowIndex);\n rowHeader = currentTr.querySelector('th');\n if (rowHeader) {\n rowInnerHeight = innerHeight(rowHeader);\n } else {\n rowInnerHeight = innerHeight(currentTr) - 1;\n }\n if (!previousRowHeight && this.wtSettings.getSetting('defaultRowHeight') < rowInnerHeight || previousRowHeight < rowInnerHeight) {\n rowInnerHeight += 1;\n this.dataAccessObject.wtViewport.oversizedRows[sourceRowIndex] = rowInnerHeight;\n }\n }\n }\n\n /**\n * @param {number} row The visual row index.\n * @returns {HTMLTableElement}\n */\n getTrForRow(row) {\n return this.TBODY.childNodes[this.rowFilter.sourceToRendered(row)];\n }\n\n /**\n * Checks if the column index (negative value from -1 to N) is rendered.\n *\n * @param {number} column The column index (negative value from -1 to N).\n * @returns {boolean}\n */\n isColumnHeaderRendered(column) {\n if (column >= 0) {\n return false;\n }\n const rowHeaders = this.wtSettings.getSetting('rowHeaders');\n const rowHeadersCount = rowHeaders.length;\n return Math.abs(column) <= rowHeadersCount;\n }\n\n /**\n * Checks if the row index (negative value from -1 to N) is rendered.\n *\n * @param {number} row The row index (negative value from -1 to N).\n * @returns {boolean}\n */\n isRowHeaderRendered(row) {\n if (row >= 0) {\n return false;\n }\n const columnHeaders = this.wtSettings.getSetting('columnHeaders');\n const columnHeadersCount = columnHeaders.length;\n return Math.abs(row) <= columnHeadersCount;\n }\n\n /* eslint-disable jsdoc/require-description-complete-sentence */\n /**\n * Check if the given row index is lower than the index of the first row that\n * is currently rendered and return TRUE in that case, or FALSE otherwise.\n *\n * Negative row index is used to check the columns' headers.\n *\n * Headers\n * +--------------+ │\n * -3 │ │ │ │ │\n * +--------------+ │\n * -2 │ │ │ │ │ TRUE\n * +--------------+ │\n * -1 │ │ │ │ │\n * Cells +==================+ │\n * 0 ┇ ┇ ┇ ┇ <--- For fixedRowsTop: 1 │\n * +--------------+ the master overlay do ---+ first rendered row (index 1)\n * 1 │ A2 │ B2 │ C2 │ not render the first row. │\n * +--------------+ │ FALSE\n * 2 │ A3 │ B3 │ C3 │ │\n * +--------------+ ---+ last rendered row\n * │\n * │ FALSE\n *\n * @param {number} row The visual row index.\n * @memberof Table#\n * @function isRowBeforeRenderedRows\n * @returns {boolean}\n */\n /* eslint-enable jsdoc/require-description-complete-sentence */\n isRowBeforeRenderedRows(row) {\n const first = this.getFirstRenderedRow();\n\n // Check the headers only in case when the first rendered row is -1 or 0.\n // This is an indication that the overlay is placed on the most top position.\n if (row < 0 && first <= 0) {\n return !this.isRowHeaderRendered(row);\n }\n return row < first;\n }\n\n /* eslint-disable jsdoc/require-description-complete-sentence */\n /**\n * Check if the given column index is greater than the index of the last column that\n * is currently rendered and return TRUE in that case, or FALSE otherwise.\n *\n * The negative row index is used to check the columns' headers. However,\n * keep in mind that for negative indexes, the method always returns FALSE as\n * it is not possible to render headers partially. The \"after\" index can not be\n * lower than -1.\n *\n * Headers\n * +--------------+ │\n * -3 │ │ │ │ │\n * +--------------+ │\n * -2 │ │ │ │ │ FALSE\n * +--------------+ │\n * -1 │ │ │ │ │\n * Cells +==================+ │\n * 0 ┇ ┇ ┇ ┇ <--- For fixedRowsTop: 1 │\n * +--------------+ the master overlay do ---+ first rendered row (index 1)\n * 1 │ A2 │ B2 │ C2 │ not render the first rows │\n * +--------------+ │ FALSE\n * 2 │ A3 │ B3 │ C3 │ │\n * +--------------+ ---+ last rendered row\n * │\n * │ TRUE\n *\n * @param {number} row The visual row index.\n * @memberof Table#\n * @function isRowAfterRenderedRows\n * @returns {boolean}\n */\n /* eslint-enable jsdoc/require-description-complete-sentence */\n isRowAfterRenderedRows(row) {\n return row > this.getLastRenderedRow();\n }\n\n /* eslint-disable jsdoc/require-description-complete-sentence */\n /**\n * Check if the given column index is lower than the index of the first column that\n * is currently rendered and return TRUE in that case, or FALSE otherwise.\n *\n * Negative column index is used to check the rows' headers.\n *\n * For fixedColumnsStart: 1 the master overlay\n * do not render this first columns.\n * Headers -3 -2 -1 |\n * +----+----+----║┄ ┄ +------+------+\n * │ │ │ ║ │ B1 │ C1 │\n * +--------------║┄ ┄ --------------│\n * │ │ │ ║ │ B2 │ C2 │\n * +--------------║┄ ┄ --------------│\n * │ │ │ ║ │ B3 │ C3 │\n * +----+----+----║┄ ┄ +------+------+\n * ╷ ╷\n * -------------------------+-------------+---------------->\n * TRUE first FALSE last FALSE\n * rendered rendered\n * column column\n *\n * @param {number} column The visual column index.\n * @memberof Table#\n * @function isColumnBeforeRenderedColumns\n * @returns {boolean}\n */\n /* eslint-enable jsdoc/require-description-complete-sentence */\n isColumnBeforeRenderedColumns(column) {\n const first = this.getFirstRenderedColumn();\n\n // Check the headers only in case when the first rendered column is -1 or 0.\n // This is an indication that the overlay is placed on the most left position.\n if (column < 0 && first <= 0) {\n return !this.isColumnHeaderRendered(column);\n }\n return column < first;\n }\n\n /* eslint-disable jsdoc/require-description-complete-sentence */\n /**\n * Check if the given column index is greater than the index of the last column that\n * is currently rendered and return TRUE in that case, or FALSE otherwise.\n *\n * The negative column index is used to check the rows' headers. However,\n * keep in mind that for negative indexes, the method always returns FALSE as\n * it is not possible to render headers partially. The \"after\" index can not be\n * lower than -1.\n *\n * For fixedColumnsStart: 1 the master overlay\n * do not render this first columns.\n * Headers -3 -2 -1 |\n * +----+----+----║┄ ┄ +------+------+\n * │ │ │ ║ │ B1 │ C1 │\n * +--------------║┄ ┄ --------------│\n * │ │ │ ║ │ B2 │ C2 │\n * +--------------║┄ ┄ --------------│\n * │ │ │ ║ │ B3 │ C3 │\n * +----+----+----║┄ ┄ +------+------+\n * ╷ ╷\n * -------------------------+-------------+---------------->\n * FALSE first FALSE last TRUE\n * rendered rendered\n * column column\n *\n * @param {number} column The visual column index.\n * @memberof Table#\n * @function isColumnAfterRenderedColumns\n * @returns {boolean}\n */\n /* eslint-enable jsdoc/require-description-complete-sentence */\n isColumnAfterRenderedColumns(column) {\n return this.columnFilter && column > this.getLastRenderedColumn();\n }\n isColumnAfterViewport(column) {\n return this.columnFilter && column > this.getLastVisibleColumn();\n }\n isRowAfterViewport(row) {\n return this.rowFilter && row > this.getLastVisibleRow();\n }\n isColumnBeforeViewport(column) {\n return this.columnFilter && this.columnFilter.sourceToRendered(column) < 0 && column >= 0;\n }\n isLastRowFullyVisible() {\n return this.getLastVisibleRow() === this.getLastRenderedRow();\n }\n isLastColumnFullyVisible() {\n return this.getLastVisibleColumn() === this.getLastRenderedColumn();\n }\n allRowsInViewport() {\n return this.wtSettings.getSetting('totalRows') === this.getVisibleRowsCount();\n }\n allColumnsInViewport() {\n return this.wtSettings.getSetting('totalColumns') === this.getVisibleColumnsCount();\n }\n\n /**\n * Checks if any of the row's cells content exceeds its initial height, and if so, returns the oversized height.\n *\n * @param {number} sourceRow The physical row index.\n * @returns {number}\n */\n getRowHeight(sourceRow) {\n return this.rowUtils.getHeight(sourceRow);\n }\n\n /**\n * @param {number} level The column level.\n * @returns {number}\n */\n getColumnHeaderHeight(level) {\n return this.columnUtils.getHeaderHeight(level);\n }\n\n /**\n * @param {number} sourceColumn The physical column index.\n * @returns {number}\n */\n getColumnWidth(sourceColumn) {\n return this.columnUtils.getWidth(sourceColumn);\n }\n\n /**\n * @param {number} sourceColumn The physical column index.\n * @returns {number}\n */\n getStretchedColumnWidth(sourceColumn) {\n return this.columnUtils.getStretchedColumnWidth(sourceColumn);\n }\n\n /**\n * Checks if the table has defined size. It returns `true` when the table has width and height\n * set bigger than `0px`.\n *\n * @returns {boolean}\n */\n hasDefinedSize() {\n return this.hasTableHeight && this.hasTableWidth;\n }\n\n /**\n * Gets table's width. The returned width is the width of the rendered cells that fit in the\n * current viewport. The value may change depends on the viewport position (scroll position).\n *\n * @returns {number}\n */\n getWidth() {\n return outerWidth(this.TABLE);\n }\n\n /**\n * Gets table's height. The returned height is the height of the rendered cells that fit in the\n * current viewport. The value may change depends on the viewport position (scroll position).\n *\n * @returns {number}\n */\n getHeight() {\n return outerHeight(this.TABLE);\n }\n\n /**\n * Gets table's total width. The returned width is the width of all rendered cells (including headers)\n * that can be displayed in the table.\n *\n * @returns {number}\n */\n getTotalWidth() {\n const width = outerWidth(this.hider);\n\n // when the overlay's table does not have any cells the hider returns 0, get then width from the table element\n return width !== 0 ? width : this.getWidth();\n }\n\n /**\n * Gets table's total height. The returned height is the height of all rendered cells (including headers)\n * that can be displayed in the table.\n *\n * @returns {number}\n */\n getTotalHeight() {\n const height = outerHeight(this.hider);\n\n // when the overlay's table does not have any cells the hider returns 0, get then height from the table element\n return height !== 0 ? height : this.getHeight();\n }\n\n /**\n * Checks if the table is visible. It returns `true` when the holder element (or its parents)\n * has CSS 'display' property different than 'none'.\n *\n * @returns {boolean}\n */\n isVisible() {\n return isVisible(this.TABLE);\n }\n\n /**\n * Modify row header widths provided by user in class contructor.\n *\n * @private\n * @param {Function} rowHeaderWidthFactory The function which can provide default width values for rows..\n * @returns {number}\n */\n _modifyRowHeaderWidth(rowHeaderWidthFactory) {\n let widths = isFunction(rowHeaderWidthFactory) ? rowHeaderWidthFactory() : null;\n if (Array.isArray(widths)) {\n widths = [...widths];\n widths[widths.length - 1] = this._correctRowHeaderWidth(widths[widths.length - 1]);\n } else {\n widths = this._correctRowHeaderWidth(widths);\n }\n return widths;\n }\n\n /**\n * Correct row header width if necessary.\n *\n * @private\n * @param {number} width The width to process.\n * @returns {number}\n */\n _correctRowHeaderWidth(width) {\n let rowHeaderWidth = width;\n if (typeof width !== 'number') {\n rowHeaderWidth = this.wtSettings.getSetting('defaultColumnWidth');\n }\n if (this.correctHeaderWidth) {\n rowHeaderWidth += 1;\n }\n return rowHeaderWidth;\n }\n}\nexport default Table;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class ColumnFilter\n */\nclass ColumnFilter {\n /**\n * @param {number} offset The scroll horizontal offset.\n * @param {number} total The total width of the table.\n * @param {number} countTH The number of rendered row headers.\n */\n constructor(offset, total, countTH) {\n /**\n * @type {number}\n */\n _defineProperty(this, \"offset\", void 0);\n /**\n * @type {number}\n */\n _defineProperty(this, \"total\", void 0);\n /**\n * @type {number}\n */\n _defineProperty(this, \"countTH\", void 0);\n this.offset = offset;\n this.total = total;\n this.countTH = countTH;\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n offsetted(index) {\n return index + this.offset;\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n unOffsetted(index) {\n return index - this.offset;\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n renderedToSource(index) {\n return this.offsetted(index);\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n sourceToRendered(index) {\n return this.unOffsetted(index);\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n offsettedTH(index) {\n return index - this.countTH;\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n unOffsettedTH(index) {\n return index + this.countTH;\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n visibleRowHeadedColumnToSourceColumn(index) {\n return this.renderedToSource(this.offsettedTH(index));\n }\n\n /**\n * @param {number} index The visual column index.\n * @returns {number}\n */\n sourceColumnToVisibleRowHeadedColumn(index) {\n return this.unOffsettedTH(this.sourceToRendered(index));\n }\n}\nexport default ColumnFilter;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * @class RowFilter\n */\nclass RowFilter {\n /**\n * @param {number} offset The scroll vertical offset.\n * @param {number} total The total height of the table.\n * @param {number} countTH The number of rendered column headers.\n */\n constructor(offset, total, countTH) {\n /**\n * @type {number}\n */\n _defineProperty(this, \"offset\", void 0);\n /**\n * @type {number}\n */\n _defineProperty(this, \"total\", void 0);\n /**\n * @type {number}\n */\n _defineProperty(this, \"countTH\", void 0);\n this.offset = offset;\n this.total = total;\n this.countTH = countTH;\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n offsetted(index) {\n return index + this.offset;\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n unOffsetted(index) {\n return index - this.offset;\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n renderedToSource(index) {\n return this.offsetted(index);\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n sourceToRendered(index) {\n return this.unOffsetted(index);\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n offsettedTH(index) {\n return index - this.countTH;\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n unOffsettedTH(index) {\n return index + this.countTH;\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n visibleColHeadedRowToSourceRow(index) {\n return this.renderedToSource(this.offsettedTH(index));\n }\n\n /**\n * @param {number} index The visual row index.\n * @returns {number}\n */\n sourceRowToVisibleColHeadedRow(index) {\n return this.unOffsettedTH(this.sourceToRendered(index));\n }\n}\nexport default RowFilter;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { SharedOrderView } from \"./../utils/orderView/index.mjs\";\nimport BaseRenderer from \"./_base.mjs\";\nimport { setAttribute, removeAttribute } from \"../../../../helpers/dom/element.mjs\";\nimport { A11Y_COLINDEX, A11Y_ROWHEADER, A11Y_SCOPE_ROW, A11Y_TABINDEX } from \"../../../../helpers/a11y.mjs\";\n/**\n * Row headers renderer responsible for managing (inserting, tracking, rendering) TR elements belongs to TR.\n *\n *
(root node)\n * ├
--- RowHeadersRenderer\n * ├
\\\n * ├
\\\n * ├
- CellsRenderer\n * ├
/\n * └
/.\n *\n * @class {CellsRenderer}\n */\nexport default class RowHeadersRenderer extends BaseRenderer {\n constructor() {\n super('TH');\n /**\n * Cache for OrderView classes connected to specified node.\n *\n * @type {WeakMap}\n */\n _defineProperty(this, \"orderViews\", new WeakMap());\n /**\n * Row index which specifies the row position of the processed row header.\n *\n * @type {number}\n */\n _defineProperty(this, \"sourceRowIndex\", 0);\n }\n\n /**\n * Obtains the instance of the SharedOrderView class which is responsible for rendering the nodes to the root node.\n *\n * @param {HTMLTableRowElement} rootNode The TR element, which is root element for row headers (TH).\n * @returns {SharedOrderView}\n */\n obtainOrderView(rootNode) {\n let orderView;\n if (this.orderViews.has(rootNode)) {\n orderView = this.orderViews.get(rootNode);\n } else {\n orderView = new SharedOrderView(rootNode, sourceColumnIndex => this.nodesPool.obtain(this.sourceRowIndex, sourceColumnIndex), this.nodeType);\n this.orderViews.set(rootNode, orderView);\n }\n return orderView;\n }\n\n /**\n * Renders the cells.\n */\n render() {\n const {\n rowsToRender,\n rowHeaderFunctions,\n rowHeadersCount,\n rows,\n cells\n } = this.table;\n for (let visibleRowIndex = 0; visibleRowIndex < rowsToRender; visibleRowIndex++) {\n const sourceRowIndex = this.table.renderedRowToSource(visibleRowIndex);\n const TR = rows.getRenderedNode(visibleRowIndex);\n this.sourceRowIndex = sourceRowIndex;\n const orderView = this.obtainOrderView(TR);\n const cellsView = cells.obtainOrderView(TR);\n orderView.appendView(cellsView).setSize(rowHeadersCount).setOffset(this.table.renderedColumnToSource(0)).start();\n for (let visibleColumnIndex = 0; visibleColumnIndex < rowHeadersCount; visibleColumnIndex++) {\n orderView.render();\n const TH = orderView.getCurrentNode();\n TH.className = '';\n TH.removeAttribute('style');\n\n // Remove all accessibility-related attributes for the header to start fresh.\n removeAttribute(TH, [new RegExp('aria-(.*)'), new RegExp('role')]);\n if (this.table.isAriaEnabled()) {\n setAttribute(TH, [A11Y_ROWHEADER(), A11Y_SCOPE_ROW(), A11Y_COLINDEX(visibleColumnIndex + 1), A11Y_TABINDEX(-1)]);\n }\n rowHeaderFunctions[visibleColumnIndex](sourceRowIndex, TH, visibleColumnIndex);\n }\n orderView.end();\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { WORKING_SPACE_TOP, WORKING_SPACE_BOTTOM } from \"./constants.mjs\";\nimport ViewSizeSet from \"./viewSizeSet.mjs\";\n/**\n * Executive model for each table renderer. It's responsible for injecting DOM nodes in a\n * specified order and adjusting the number of elements in the root node.\n *\n * Only this class have rights to juggling DOM elements within the root node (see render method).\n *\n * @class {OrderView}\n */\nexport default class OrderView {\n constructor(rootNode, nodesPool, childNodeType) {\n /**\n * The root node to manage with.\n *\n * @type {HTMLElement}\n */\n _defineProperty(this, \"rootNode\", void 0);\n /**\n * Factory for newly created DOM elements.\n *\n * @type {Function}\n */\n _defineProperty(this, \"nodesPool\", void 0);\n /**\n * Holder for sizing and positioning of the view.\n *\n * @type {ViewSizeSet}\n */\n _defineProperty(this, \"sizeSet\", new ViewSizeSet());\n /**\n * Node type which the order view will manage while rendering the DOM elements.\n *\n * @type {string}\n */\n _defineProperty(this, \"childNodeType\", void 0);\n /**\n * The visual index of currently processed row.\n *\n * @type {number}\n */\n _defineProperty(this, \"visualIndex\", 0);\n /**\n * The list of DOM elements which are rendered for this render cycle.\n *\n * @type {HTMLElement[]}\n */\n _defineProperty(this, \"collectedNodes\", []);\n this.rootNode = rootNode;\n this.nodesPool = nodesPool;\n this.childNodeType = childNodeType.toUpperCase();\n }\n\n /**\n * Sets the size for rendered elements. It can be a size for rows, cells or size for row\n * headers etc. It depends for what table renderer this instance was created.\n *\n * @param {number} size The size.\n * @returns {OrderView}\n */\n setSize(size) {\n this.sizeSet.setSize(size);\n return this;\n }\n\n /**\n * Sets the offset for rendered elements. The offset describes the shift between 0 and\n * the first rendered element according to the scroll position.\n *\n * @param {number} offset The offset.\n * @returns {OrderView}\n */\n setOffset(offset) {\n this.sizeSet.setOffset(offset);\n return this;\n }\n\n /**\n * Checks if this instance of the view shares the root node with another instance. This happens only once when\n * a row (TR) as a root node is managed by two OrderView instances. If this happens another DOM injection\n * algorithm is performed to achieve consistent order.\n *\n * @returns {boolean}\n */\n isSharedViewSet() {\n return this.sizeSet.isShared();\n }\n\n /**\n * Returns rendered DOM element based on visual index.\n *\n * @param {number} visualIndex The visual index.\n * @returns {HTMLElement}\n */\n getNode(visualIndex) {\n return visualIndex < this.collectedNodes.length ? this.collectedNodes[visualIndex] : null;\n }\n\n /**\n * Returns currently processed DOM element.\n *\n * @returns {HTMLElement}\n */\n getCurrentNode() {\n const length = this.collectedNodes.length;\n return length > 0 ? this.collectedNodes[length - 1] : null;\n }\n\n /**\n * Returns rendered child count for this instance.\n *\n * @returns {number}\n */\n getRenderedChildCount() {\n const {\n rootNode,\n sizeSet\n } = this;\n let childElementCount = 0;\n if (this.isSharedViewSet()) {\n let element = rootNode.firstElementChild;\n while (element) {\n if (element.tagName === this.childNodeType) {\n childElementCount += 1;\n } else if (sizeSet.isPlaceOn(WORKING_SPACE_TOP)) {\n break;\n }\n element = element.nextElementSibling;\n }\n } else {\n childElementCount = rootNode.childElementCount;\n }\n return childElementCount;\n }\n\n /**\n * Setups and prepares all necessary properties and start the rendering process.\n * This method has to be called only once (at the start) for the render cycle.\n */\n start() {\n this.collectedNodes.length = 0;\n this.visualIndex = 0;\n const {\n rootNode,\n sizeSet\n } = this;\n const isShared = this.isSharedViewSet();\n const {\n nextSize\n } = sizeSet.getViewSize();\n let childElementCount = this.getRenderedChildCount();\n while (childElementCount < nextSize) {\n const newNode = this.nodesPool();\n if (!isShared || isShared && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {\n rootNode.appendChild(newNode);\n } else {\n rootNode.insertBefore(newNode, rootNode.firstChild);\n }\n childElementCount += 1;\n }\n const isSharedPlacedOnTop = isShared && sizeSet.isPlaceOn(WORKING_SPACE_TOP);\n while (childElementCount > nextSize) {\n rootNode.removeChild(isSharedPlacedOnTop ? rootNode.firstChild : rootNode.lastChild);\n childElementCount -= 1;\n }\n }\n\n /**\n * Renders the DOM element based on visual index (which is calculated internally).\n * This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements).\n */\n render() {\n const {\n rootNode,\n sizeSet\n } = this;\n let visualIndex = this.visualIndex;\n if (this.isSharedViewSet() && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {\n visualIndex += sizeSet.sharedSize.nextSize;\n }\n let node = rootNode.childNodes[visualIndex];\n if (node.tagName !== this.childNodeType) {\n const newNode = this.nodesPool();\n rootNode.replaceChild(newNode, node);\n node = newNode;\n }\n this.collectedNodes.push(node);\n this.visualIndex += 1;\n }\n\n /**\n * Ends the render process.\n * This method has to be called only once (at the end) for the render cycle.\n */\n end() {}\n}","/**\n * Describes that ViewSizeSet instance doesn't share sizes with another\n * instance (root node can contain only one type of children nodes).\n *\n * @type {number}\n */\nexport const WORKING_SPACE_ALL = 0;\n/**\n * Describes that ViewSizeSet instance share sizes with another instance and\n * set working space for this instance to 'top' (root node can contain multiple\n * types of children and this instance will be occupied top space of the root node).\n *\n * @type {number}\n */\nexport const WORKING_SPACE_TOP = 1;\n/**\n * Describes that ViewSizeSet instance share sizes with another instance and\n * set working space for this instance to 'bottom' (root node can contain multiple\n * types of children and this instance will be occupied bottom space of the root node).\n *\n * @type {number}\n */\nexport const WORKING_SPACE_BOTTOM = 2;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport ViewSize from \"./viewSize.mjs\";\nimport { WORKING_SPACE_ALL, WORKING_SPACE_TOP, WORKING_SPACE_BOTTOM } from \"./constants.mjs\";\n/**\n * The class is a source of the truth of information about the current and\n * next size of the rendered DOM elements and current and next offset of\n * the view. That information allows us to calculate diff between current\n * DOM order and this which should be rendered without touching the DOM API at all.\n *\n * Mostly the ViewSizeSet is created for each individual renderer. But in\n * the table, there is one case where this size information should be shared\n * between two different instances (different table renderers). This is a TR\n * element which can contain TH elements - managed by own renderer and\n * TD elements - managed by another renderer. To generate correct DOM order\n * for them it is required to connect these two instances by reference\n * through `sharedSize`.\n *\n * @class {ViewSizeSet}\n */\nexport default class ViewSizeSet {\n constructor() {\n /**\n * Holder for current and next view size and offset.\n *\n * @type {ViewSize}\n */\n _defineProperty(this, \"size\", new ViewSize());\n /**\n * Defines if this instance shares its size with another instance. If it's in the shared\n * mode it defines what space it occupies ('top' or 'bottom').\n *\n * @type {number}\n */\n _defineProperty(this, \"workingSpace\", WORKING_SPACE_ALL);\n /**\n * Shared Size instance.\n *\n * @type {ViewSize}\n */\n _defineProperty(this, \"sharedSize\", null);\n }\n /**\n * Sets the size for rendered elements. It can be a size for rows, cells or size for row\n * headers etc.\n *\n * @param {number} size The size.\n */\n setSize(size) {\n this.size.setSize(size);\n }\n\n /**\n * Sets the offset for rendered elements. The offset describes the shift between 0 and\n * the first rendered element according to the scroll position.\n *\n * @param {number} offset The offset.\n */\n setOffset(offset) {\n this.size.setOffset(offset);\n }\n\n /**\n * Returns ViewSize instance.\n *\n * @returns {ViewSize}\n */\n getViewSize() {\n return this.size;\n }\n\n /**\n * Checks if this ViewSizeSet is sharing the size with another instance.\n *\n * @returns {boolean}\n */\n isShared() {\n return this.sharedSize instanceof ViewSize;\n }\n\n /**\n * Checks what working space describes this size instance.\n *\n * @param {number} workingSpace The number which describes the type of the working space (see constants.js).\n * @returns {boolean}\n */\n isPlaceOn(workingSpace) {\n return this.workingSpace === workingSpace;\n }\n\n /**\n * Appends the ViewSizeSet instance to this instance that turns it into a shared mode.\n *\n * @param {ViewSizeSet} viewSize The instance of the ViewSizeSet class.\n */\n append(viewSize) {\n this.workingSpace = WORKING_SPACE_TOP;\n viewSize.workingSpace = WORKING_SPACE_BOTTOM;\n this.sharedSize = viewSize.getViewSize();\n }\n\n /**\n * Prepends the ViewSize instance to this instance that turns it into a shared mode.\n *\n * @param {ViewSizeSet} viewSize The instance of the ViewSizeSet class.\n */\n prepend(viewSize) {\n this.workingSpace = WORKING_SPACE_BOTTOM;\n viewSize.workingSpace = WORKING_SPACE_TOP;\n this.sharedSize = viewSize.getViewSize();\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * Holder for current and next size (count of rendered and to render DOM elements) and offset.\n *\n * @class {ViewSize}\n */\nexport default class ViewSize {\n constructor() {\n /**\n * Current size of the rendered DOM elements.\n *\n * @type {number}\n */\n _defineProperty(this, \"currentSize\", 0);\n /**\n * Next size of the rendered DOM elements which should be fulfilled.\n *\n * @type {number}\n */\n _defineProperty(this, \"nextSize\", 0);\n /**\n * Current offset.\n *\n * @type {number}\n */\n _defineProperty(this, \"currentOffset\", 0);\n /**\n * Next offset.\n *\n * @type {number}\n */\n _defineProperty(this, \"nextOffset\", 0);\n }\n /**\n * Sets new size of the rendered DOM elements.\n *\n * @param {number} size The size.\n */\n setSize(size) {\n this.currentSize = this.nextSize;\n this.nextSize = size;\n }\n\n /**\n * Sets new offset.\n *\n * @param {number} offset The offset.\n */\n setOffset(offset) {\n this.currentOffset = this.nextOffset;\n this.nextOffset = offset;\n }\n}","import OrderView from \"./view.mjs\";\n/**\n * Executive model for TR root nodes.\n *\n * @class {SharedOrderView}\n */\nexport default class SharedOrderView extends OrderView {\n /**\n * The method results in merging external order view into the current order. This happens only for order views which\n * operate on the same root node.\n *\n * In the table, there is only one scenario when this happens. TR root element\n * has a common root node with cells order view and row headers order view. Both classes have to share\n * information about their order sizes to make proper diff calculations.\n *\n * @param {OrderView} orderView The order view to merging with. The view will be added at the beginning of the list.\n * @returns {SharedOrderView}\n */\n prependView(orderView) {\n this.sizeSet.prepend(orderView.sizeSet);\n orderView.sizeSet.append(this.sizeSet);\n return this;\n }\n\n /**\n * The method results in merging external order view into the current order. This happens only for order views which\n * operate on the same root node.\n *\n * In the table, there is only one scenario when this happens. TR root element\n * has a common root node with cells order view and row headers order view. Both classes have to share\n * information about their order sizes to make proper diff calculations.\n *\n * @param {OrderView} orderView The order view to merging with. The view will be added at the end of the list.\n * @returns {SharedOrderView}\n */\n appendView(orderView) {\n this.sizeSet.append(orderView.sizeSet);\n orderView.sizeSet.prepend(this.sizeSet);\n return this;\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport NodesPool from \"./../utils/nodesPool.mjs\";\n/**\n * Base renderer class, abstract logic for specialized renderers.\n *\n * @class BaseRenderer\n */\nexport default class BaseRenderer {\n constructor(nodeType, rootNode) {\n /**\n * Factory for newly created DOM elements.\n *\n * NodePool should be used for each renderer. For the first stage of the refactoring\n * process, only some of the renderers are implemented a new approach.\n *\n * @type {NodesPool|null}\n */\n _defineProperty(this, \"nodesPool\", null);\n /**\n * Node type which the renderer will manage while building the table (eg. 'TD', 'TR', 'TH').\n *\n * @type {string}\n */\n _defineProperty(this, \"nodeType\", void 0);\n /**\n * The root node to which newly created elements will be inserted.\n *\n * @type {HTMLElement}\n */\n _defineProperty(this, \"rootNode\", void 0);\n /**\n * The instance of the Table class, a wrapper for all renderers and holder for properties describe table state.\n *\n * @type {TableRenderer}\n */\n _defineProperty(this, \"table\", null);\n /**\n * Counter of nodes already added.\n *\n * @type {number}\n */\n _defineProperty(this, \"renderedNodes\", 0);\n this.nodesPool = typeof nodeType === 'string' ? new NodesPool(nodeType) : null;\n this.nodeType = nodeType;\n this.rootNode = rootNode;\n }\n\n /**\n * Sets the table renderer instance to the current renderer.\n *\n * @param {TableRenderer} table The TableRenderer instance.\n */\n setTable(table) {\n if (this.nodesPool) {\n this.nodesPool.setRootDocument(table.rootDocument);\n }\n this.table = table;\n }\n\n /**\n * Adjusts the number of rendered nodes.\n */\n adjust() {}\n\n /**\n * Renders the contents to the elements.\n */\n render() {}\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * Factory for newly created DOM elements.\n *\n * @class {NodesPool}\n */\nexport default class NodesPool {\n constructor(nodeType) {\n /**\n * Node type to generate (ew 'th', 'td').\n *\n * @type {string}\n */\n _defineProperty(this, \"nodeType\", void 0);\n this.nodeType = nodeType.toUpperCase();\n }\n\n /**\n * Set document owner for this instance.\n *\n * @param {HTMLDocument} rootDocument The document window owner.\n */\n setRootDocument(rootDocument) {\n this.rootDocument = rootDocument;\n }\n\n /**\n * Obtains an element. The returned elements in the feature can be cached.\n *\n * @returns {HTMLElement}\n */\n obtain() {\n return this.rootDocument.createElement(this.nodeType);\n }\n}","import { empty, setAttribute, removeAttribute } from \"./../../../../helpers/dom/element.mjs\";\nimport BaseRenderer from \"./_base.mjs\";\nimport { A11Y_COLINDEX, A11Y_COLUMNHEADER, A11Y_ROW, A11Y_ROWGROUP, A11Y_ROWINDEX, A11Y_SCOPE_COL, A11Y_TABINDEX } from \"../../../../helpers/a11y.mjs\";\n/**\n * Column headers renderer responsible for managing (inserting, tracking, rendering) TR and TH elements.\n *\n * (root node)\n * ├
\\\n * ├
\\\n * ├
- ColumnHeadersRenderer\n * ├
/\n * └
/.\n *\n * @class {ColumnHeadersRenderer}\n */\nexport default class ColumnHeadersRenderer extends BaseRenderer {\n constructor(rootNode) {\n super(null, rootNode); // NodePool is not implemented for this renderer yet\n }\n\n /**\n * Adjusts the number of the rendered elements.\n */\n adjust() {\n const {\n columnHeadersCount,\n rowHeadersCount\n } = this.table;\n let TR = this.rootNode.firstChild;\n if (columnHeadersCount) {\n const {\n columnsToRender\n } = this.table;\n const allColumnsToRender = columnsToRender + rowHeadersCount;\n for (let i = 0, len = columnHeadersCount; i < len; i++) {\n TR = this.rootNode.childNodes[i];\n if (!TR) {\n TR = this.table.rootDocument.createElement('tr');\n this.rootNode.appendChild(TR);\n }\n this.renderedNodes = TR.childNodes.length;\n while (this.renderedNodes < allColumnsToRender) {\n TR.appendChild(this.table.rootDocument.createElement('th'));\n this.renderedNodes += 1;\n }\n while (this.renderedNodes > allColumnsToRender) {\n TR.removeChild(TR.lastChild);\n this.renderedNodes -= 1;\n }\n }\n const theadChildrenLength = this.rootNode.childNodes.length;\n if (theadChildrenLength > columnHeadersCount) {\n for (let i = columnHeadersCount; i < theadChildrenLength; i++) {\n this.rootNode.removeChild(this.rootNode.lastChild);\n }\n }\n } else if (TR) {\n empty(TR);\n }\n }\n\n /**\n * Renders the TH elements.\n */\n render() {\n const {\n columnHeadersCount\n } = this.table;\n if (this.table.isAriaEnabled()) {\n setAttribute(this.rootNode, [A11Y_ROWGROUP()]);\n }\n for (let rowHeaderIndex = 0; rowHeaderIndex < columnHeadersCount; rowHeaderIndex += 1) {\n const {\n columnHeaderFunctions,\n columnsToRender,\n rowHeadersCount\n } = this.table;\n const TR = this.rootNode.childNodes[rowHeaderIndex];\n if (this.table.isAriaEnabled()) {\n setAttribute(TR, [A11Y_ROW(), A11Y_ROWINDEX(rowHeaderIndex + 1)]);\n }\n for (let renderedColumnIndex = -1 * rowHeadersCount; renderedColumnIndex < columnsToRender; renderedColumnIndex += 1) {\n // eslint-disable-line max-len\n const sourceColumnIndex = this.table.renderedColumnToSource(renderedColumnIndex);\n const TH = TR.childNodes[renderedColumnIndex + rowHeadersCount];\n TH.className = '';\n TH.removeAttribute('style');\n\n // Remove all accessibility-related attributes for the header to start fresh.\n removeAttribute(TH, [new RegExp('aria-(.*)'), new RegExp('role')]);\n if (this.table.isAriaEnabled()) {\n setAttribute(TH, [A11Y_COLINDEX(renderedColumnIndex + 1 + this.table.rowHeadersCount), A11Y_TABINDEX(-1), A11Y_COLUMNHEADER(), ...(renderedColumnIndex >= 0 ? [A11Y_SCOPE_COL()] : [\n // Adding `role=row` to the corner headers to prevent\n // https://github.com/handsontable/dev-handsontable/issues/1574\n A11Y_ROW()])]);\n }\n columnHeaderFunctions[rowHeaderIndex](sourceColumnIndex, TH, rowHeaderIndex);\n }\n }\n }\n}","import BaseRenderer from \"./_base.mjs\";\nimport { warn } from \"./../../../../helpers/console.mjs\";\nimport { toSingleLine } from \"./../../../../helpers/templateLiteralTag.mjs\";\nimport { addClass } from \"./../../../../helpers/dom/element.mjs\";\nlet performanceWarningAppeared = false;\n\n/**\n * Colgroup renderer responsible for managing (inserting, tracking, rendering) COL elements.\n *\n *
(root node)\n * ├
\\\n * ├
\\\n * ├
- ColGroupRenderer\n * ├
/\n * └
/.\n *\n * @class {ColGroupRenderer}\n */\nexport default class ColGroupRenderer extends BaseRenderer {\n constructor(rootNode) {\n super(null, rootNode); // NodePool is not implemented for this renderer yet\n }\n\n /**\n * Adjusts the number of the rendered elements.\n */\n adjust() {\n const {\n columnsToRender,\n rowHeadersCount\n } = this.table;\n const allColumnsToRender = columnsToRender + rowHeadersCount;\n while (this.renderedNodes < allColumnsToRender) {\n this.rootNode.appendChild(this.table.rootDocument.createElement('col'));\n this.renderedNodes += 1;\n }\n while (this.renderedNodes > allColumnsToRender) {\n this.rootNode.removeChild(this.rootNode.lastChild);\n this.renderedNodes -= 1;\n }\n }\n\n /**\n * Renders the col group elements.\n */\n render() {\n this.adjust();\n const {\n columnsToRender,\n rowHeadersCount\n } = this.table;\n if (!performanceWarningAppeared && columnsToRender > 1000) {\n performanceWarningAppeared = true;\n warn(toSingleLine`Performance tip: Handsontable rendered more than 1000 visible columns.\\x20\n Consider limiting the number of rendered columns by specifying the table width and/or\\x20\n turning off the \"renderAllColumns\" option.`);\n }\n\n // Render column nodes for row headers\n for (let visibleColumnIndex = 0; visibleColumnIndex < rowHeadersCount; visibleColumnIndex++) {\n const sourceColumnIndex = this.table.renderedColumnToSource(visibleColumnIndex);\n const width = this.table.columnUtils.getHeaderWidth(sourceColumnIndex);\n this.rootNode.childNodes[visibleColumnIndex].style.width = `${width}px`;\n }\n\n // Render column nodes for cells\n for (let visibleColumnIndex = 0; visibleColumnIndex < columnsToRender; visibleColumnIndex++) {\n const sourceColumnIndex = this.table.renderedColumnToSource(visibleColumnIndex);\n const width = this.table.columnUtils.getStretchedColumnWidth(sourceColumnIndex);\n this.rootNode.childNodes[visibleColumnIndex + rowHeadersCount].style.width = `${width}px`;\n }\n const firstChild = this.rootNode.firstChild;\n if (firstChild) {\n addClass(firstChild, 'rowHeader');\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport BaseRenderer from \"./_base.mjs\";\nimport { warn } from \"./../../../../helpers/console.mjs\";\nimport { toSingleLine } from \"./../../../../helpers/templateLiteralTag.mjs\";\nimport { OrderView } from \"./../utils/orderView/index.mjs\";\nimport { setAttribute } from \"../../../../helpers/dom/element.mjs\";\nimport { A11Y_ROW, A11Y_ROWGROUP, A11Y_ROWINDEX } from \"../../../../helpers/a11y.mjs\";\nlet performanceWarningAppeared = false;\n\n/**\n * Rows renderer responsible for managing (inserting, tracking, rendering) TR elements belongs to TBODY.\n *\n *
(root node)\n * ├
\\\n * ├
\\\n * ├
- RowsRenderer\n * ├
/\n * └
/.\n *\n * @class {RowsRenderer}\n */\nexport default class RowsRenderer extends BaseRenderer {\n constructor(rootNode) {\n super('TR', rootNode);\n /**\n * Cache for OrderView classes connected to specified node.\n *\n * @type {WeakMap}\n */\n _defineProperty(this, \"orderView\", void 0);\n this.orderView = new OrderView(rootNode, sourceRowIndex => this.nodesPool.obtain(sourceRowIndex), this.nodeType);\n }\n\n /**\n * Returns currently rendered node.\n *\n * @param {string} visualIndex Visual index of the rendered node (it always goeas from 0 to N).\n * @returns {HTMLTableRowElement}\n */\n getRenderedNode(visualIndex) {\n return this.orderView.getNode(visualIndex);\n }\n\n /**\n * Renders the cells.\n */\n render() {\n const {\n rowsToRender\n } = this.table;\n if (!performanceWarningAppeared && rowsToRender > 1000) {\n performanceWarningAppeared = true;\n warn(toSingleLine`Performance tip: Handsontable rendered more than 1000 visible rows.\\x20\n Consider limiting the number of rendered rows by specifying the table height and/or\\x20\n turning off the \"renderAllRows\" option.`);\n }\n if (this.table.isAriaEnabled()) {\n setAttribute(this.rootNode, [A11Y_ROWGROUP()]);\n }\n this.orderView.setSize(rowsToRender).setOffset(this.table.renderedRowToSource(0)).start();\n for (let visibleRowIndex = 0; visibleRowIndex < rowsToRender; visibleRowIndex++) {\n this.orderView.render();\n const TR = this.orderView.getCurrentNode();\n const sourceRowIndex = this.table.renderedRowToSource(visibleRowIndex);\n if (this.table.isAriaEnabled()) {\n var _this$table$rowUtils$, _this$table$rowUtils;\n setAttribute(TR, [A11Y_ROW(),\n // `aria-rowindex` is incremented by both tbody and thead rows.\n A11Y_ROWINDEX(sourceRowIndex + ((_this$table$rowUtils$ = (_this$table$rowUtils = this.table.rowUtils) === null || _this$table$rowUtils === void 0 || (_this$table$rowUtils = _this$table$rowUtils.dataAccessObject) === null || _this$table$rowUtils === void 0 ? void 0 : _this$table$rowUtils.columnHeaders.length) !== null && _this$table$rowUtils$ !== void 0 ? _this$table$rowUtils$ : 0) + 1)]);\n }\n }\n this.orderView.end();\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { hasClass, removeAttribute, setAttribute } from \"./../../../../helpers/dom/element.mjs\";\nimport { SharedOrderView } from \"./../utils/orderView/index.mjs\";\nimport BaseRenderer from \"./_base.mjs\";\nimport { A11Y_COLINDEX, A11Y_GRIDCELL, A11Y_TABINDEX } from \"../../../../helpers/a11y.mjs\";\n/**\n * Cell renderer responsible for managing (inserting, tracking, rendering) TD elements.\n *\n *
(root node)\n * ├
--- RowHeadersRenderer\n * ├
\\\n * ├
\\\n * ├
- CellsRenderer\n * ├
/\n * └
/.\n *\n * @class {CellsRenderer}\n */\nexport default class CellsRenderer extends BaseRenderer {\n constructor() {\n super('TD');\n /**\n * Cache for OrderView classes connected to specified node.\n *\n * @type {WeakMap}\n */\n _defineProperty(this, \"orderViews\", new WeakMap());\n /**\n * Row index which specifies the row position of the processed cell.\n *\n * @type {number}\n */\n _defineProperty(this, \"sourceRowIndex\", 0);\n }\n\n /**\n * Obtains the instance of the SharedOrderView class which is responsible for rendering the nodes to the root node.\n *\n * @param {HTMLTableRowElement} rootNode The TR element, which is root element for cells (TD).\n * @returns {SharedOrderView}\n */\n obtainOrderView(rootNode) {\n let orderView;\n if (this.orderViews.has(rootNode)) {\n orderView = this.orderViews.get(rootNode);\n } else {\n orderView = new SharedOrderView(rootNode, sourceColumnIndex => this.nodesPool.obtain(this.sourceRowIndex, sourceColumnIndex), this.nodeType);\n this.orderViews.set(rootNode, orderView);\n }\n return orderView;\n }\n\n /**\n * Renders the cells.\n */\n render() {\n const {\n rowsToRender,\n columnsToRender,\n rows,\n rowHeaders\n } = this.table;\n for (let visibleRowIndex = 0; visibleRowIndex < rowsToRender; visibleRowIndex++) {\n const sourceRowIndex = this.table.renderedRowToSource(visibleRowIndex);\n const TR = rows.getRenderedNode(visibleRowIndex);\n this.sourceRowIndex = sourceRowIndex;\n const orderView = this.obtainOrderView(TR);\n const rowHeadersView = rowHeaders.obtainOrderView(TR);\n\n // @TODO(perf-tip): For cells other than \"visual 0\" generating diff leads/commands can be skipped. New order view\n // should share state between next orderViews.\n orderView.prependView(rowHeadersView).setSize(columnsToRender).setOffset(this.table.renderedColumnToSource(0)).start();\n for (let visibleColumnIndex = 0; visibleColumnIndex < columnsToRender; visibleColumnIndex++) {\n orderView.render();\n const TD = orderView.getCurrentNode();\n const sourceColumnIndex = this.table.renderedColumnToSource(visibleColumnIndex);\n if (!hasClass(TD, 'hide')) {\n // Workaround for hidden columns plugin\n TD.className = '';\n }\n TD.removeAttribute('style');\n TD.removeAttribute('dir');\n\n // Remove all accessibility-related attributes for the cell to start fresh.\n removeAttribute(TD, [new RegExp('aria-(.*)'), new RegExp('role')]);\n this.table.cellRenderer(sourceRowIndex, sourceColumnIndex, TD);\n if (this.table.isAriaEnabled()) {\n var _this$table$rowUtils$, _this$table$rowUtils;\n setAttribute(TD, [...(TD.hasAttribute('role') ? [] : [A11Y_GRIDCELL()]), A11Y_TABINDEX(-1),\n // `aria-colindex` is incremented by both tbody and thead rows.\n A11Y_COLINDEX(sourceColumnIndex + ((_this$table$rowUtils$ = (_this$table$rowUtils = this.table.rowUtils) === null || _this$table$rowUtils === void 0 || (_this$table$rowUtils = _this$table$rowUtils.dataAccessObject) === null || _this$table$rowUtils === void 0 ? void 0 : _this$table$rowUtils.rowHeaders.length) !== null && _this$table$rowUtils$ !== void 0 ? _this$table$rowUtils$ : 0) + 1)]);\n }\n }\n orderView.end();\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TableRenderer class collects all renderers and properties necessary for table creation. It's\n * responsible for adjusting and rendering each renderer.\n *\n * Below is a diagram of the renderers together with an indication of what they are responisble for.\n *
\n *
\\ (root node)\n *
\\\n *
\\___ ColGroupRenderer\n *
/\n *
/\n *
/\n * \\ (root node)\n *
\\\n *
\\\n *
\\____ ColumnHeadersRenderer\n *
/\n *
/\n *
/\n * /\n * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\ (root node)\n *
(root node) \\\n *
--- RowHeadersRenderer\n *
\\ \\\n *
-- CellsRenderer \\\n *
/ \\\n *
\\\n *
(root node) \\\n *
--- RowHeadersRenderer \\\n *
\\ \\___ RowsRenderer\n *
-- CellsRenderer /\n *
/ /\n *
/\n *
(root node) /\n *
--- RowHeadersRenderer /\n *
\\ /\n *
-- CellsRenderer /\n *
/ /\n *
/\n * ___________________/\n *
.\n *\n * @class {RowsRenderer}\n */\nexport default class TableRenderer {\n constructor(rootNode) {\n let {\n cellRenderer\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n /**\n * Table element which will be used to render the children element.\n *\n * @type {HTMLTableElement}\n */\n _defineProperty(this, \"rootNode\", void 0);\n /**\n * Document owner of the root node.\n *\n * @type {HTMLDocument}\n */\n _defineProperty(this, \"rootDocument\", void 0);\n /**\n * Renderer class responsible for rendering row headers.\n *\n * @type {RowsRenderer}\n */\n _defineProperty(this, \"rowHeaders\", null);\n /**\n * Renderer class responsible for rendering column headers.\n *\n * @type {ColumnHeadersRenderer}\n */\n _defineProperty(this, \"columnHeaders\", null);\n /**\n * Renderer class responsible for rendering col in colgroup.\n *\n * @type {ColGroupRenderer}\n */\n _defineProperty(this, \"colGroup\", null);\n /**\n * Renderer class responsible for rendering rows in tbody.\n *\n * @type {RowsRenderer}\n */\n _defineProperty(this, \"rows\", null);\n /**\n * Renderer class responsible for rendering cells.\n *\n * @type {CellsRenderer}\n */\n _defineProperty(this, \"cells\", null);\n /**\n * Row filter which contains all necessary information about row index transformation.\n *\n * @type {RowFilter}\n */\n _defineProperty(this, \"rowFilter\", null);\n /**\n * Column filter which contains all necessary information about column index transformation.\n *\n * @type {ColumnFilter}\n */\n _defineProperty(this, \"columnFilter\", null);\n /**\n * Row utils class which contains all necessary information about sizes of the rows.\n *\n * @type {RowUtils}\n */\n _defineProperty(this, \"rowUtils\", null);\n /**\n * Column utils class which contains all necessary information about sizes of the columns.\n *\n * @type {ColumnUtils}\n */\n _defineProperty(this, \"columnUtils\", null);\n /**\n * Indicates how much rows should be rendered to fill whole table viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"rowsToRender\", 0);\n /**\n * Indicates how much columns should be rendered to fill whole table viewport.\n *\n * @type {number}\n */\n _defineProperty(this, \"columnsToRender\", 0);\n /**\n * An array of functions to be used as a content factory to row headers.\n *\n * @type {Function[]}\n */\n _defineProperty(this, \"rowHeaderFunctions\", []);\n /**\n * Count of the function used to render row headers.\n *\n * @type {number}\n */\n _defineProperty(this, \"rowHeadersCount\", 0);\n /**\n * An array of functions to be used as a content factory to column headers.\n *\n * @type {Function[]}\n */\n _defineProperty(this, \"columnHeaderFunctions\", []);\n /**\n * Count of the function used to render column headers.\n *\n * @type {number}\n */\n _defineProperty(this, \"columnHeadersCount\", 0);\n /**\n * Cell renderer used to render cells content.\n *\n * @type {Function}\n */\n _defineProperty(this, \"cellRenderer\", void 0);\n /**\n * Holds the name of the currently active overlay.\n *\n * @type {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'|'master'}\n */\n _defineProperty(this, \"activeOverlayName\", void 0);\n this.rootNode = rootNode;\n this.rootDocument = this.rootNode.ownerDocument;\n this.cellRenderer = cellRenderer;\n }\n\n /**\n * Sets the overlay that is currently rendered. If `null` is provided, the master overlay is set.\n *\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'|'master'} overlayName The overlay name.\n */\n setActiveOverlayName(overlayName) {\n this.activeOverlayName = overlayName;\n }\n\n /**\n * Set row and column util classes.\n *\n * @param {RowUtils} rowUtils RowUtils instance which provides useful methods related to row sizes.\n * @param {ColumnUtils} columnUtils ColumnUtils instance which provides useful methods related to row sizes.\n */\n setAxisUtils(rowUtils, columnUtils) {\n this.rowUtils = rowUtils;\n this.columnUtils = columnUtils;\n }\n\n /**\n * Sets viewport size of the table.\n *\n * @param {number} rowsCount An amount of rows to render.\n * @param {number} columnsCount An amount of columns to render.\n */\n setViewportSize(rowsCount, columnsCount) {\n this.rowsToRender = rowsCount;\n this.columnsToRender = columnsCount;\n }\n\n /**\n * Sets row and column filter instances.\n *\n * @param {RowFilter} rowFilter Row filter instance which contains all necessary information about row index transformation.\n * @param {ColumnFilter} columnFilter Column filter instance which contains all necessary information about row\n * index transformation.\n */\n setFilters(rowFilter, columnFilter) {\n this.rowFilter = rowFilter;\n this.columnFilter = columnFilter;\n }\n\n /**\n * Sets row and column header functions.\n *\n * @param {Function[]} rowHeaders Row header functions. Factories for creating content for row headers.\n * @param {Function[]} columnHeaders Column header functions. Factories for creating content for column headers.\n */\n setHeaderContentRenderers(rowHeaders, columnHeaders) {\n this.rowHeaderFunctions = rowHeaders;\n this.rowHeadersCount = rowHeaders.length;\n this.columnHeaderFunctions = columnHeaders;\n this.columnHeadersCount = columnHeaders.length;\n }\n\n /**\n * Sets table renderers.\n *\n * @param {renderers} renderers The renderer units.\n * @param {RowHeadersRenderer} renderers.rowHeaders Row headers renderer.\n * @param {ColumnHeadersRenderer} renderers.columnHeaders Column headers renderer.\n * @param {ColGroupRenderer} renderers.colGroup Col group renderer.\n * @param {RowsRenderer} renderers.rows Rows renderer.\n * @param {CellsRenderer} renderers.cells Cells renderer.\n */\n setRenderers() {\n let {\n rowHeaders,\n columnHeaders,\n colGroup,\n rows,\n cells\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n rowHeaders.setTable(this);\n columnHeaders.setTable(this);\n colGroup.setTable(this);\n rows.setTable(this);\n cells.setTable(this);\n this.rowHeaders = rowHeaders;\n this.columnHeaders = columnHeaders;\n this.colGroup = colGroup;\n this.rows = rows;\n this.cells = cells;\n }\n\n /**\n * Transforms visual/rendered row index to source index.\n *\n * @param {number} rowIndex Rendered index.\n * @returns {number}\n */\n renderedRowToSource(rowIndex) {\n return this.rowFilter.renderedToSource(rowIndex);\n }\n\n /**\n * Transforms visual/rendered column index to source index.\n *\n * @param {number} columnIndex Rendered index.\n * @returns {number}\n */\n renderedColumnToSource(columnIndex) {\n return this.columnFilter.renderedToSource(columnIndex);\n }\n\n /**\n * Returns `true` if the accessibility-related ARIA tags should be added to the table, `false` otherwise.\n *\n * @returns {boolean}\n */\n isAriaEnabled() {\n return this.rowUtils.wtSettings.getSetting('ariaTags');\n }\n\n /**\n * Renders the table.\n */\n render() {\n this.colGroup.adjust();\n this.columnHeaders.adjust();\n this.rows.adjust();\n this.rowHeaders.adjust();\n this.columnHeaders.render();\n this.rows.render();\n this.rowHeaders.render();\n this.cells.render();\n\n // After the cells are rendered calculate columns width (or columns stretch width) to prepare proper values\n // for colGroup renderer (which renders COL elements).\n this.columnUtils.calculateWidths();\n this.colGroup.render();\n const {\n rowsToRender,\n rows\n } = this;\n\n // Fix for multi-line content and for supporting `rowHeights` option.\n for (let visibleRowIndex = 0; visibleRowIndex < rowsToRender; visibleRowIndex++) {\n const TR = rows.getRenderedNode(visibleRowIndex);\n if (TR.firstChild) {\n const sourceRowIndex = this.renderedRowToSource(visibleRowIndex);\n const rowHeight = this.rowUtils.getHeightByOverlayName(sourceRowIndex, this.activeOverlayName);\n if (rowHeight) {\n // Decrease height. 1 pixel will be \"replaced\" by 1px border top\n TR.firstChild.style.height = `${rowHeight - 1}px`;\n } else {\n TR.firstChild.style.height = '';\n }\n }\n }\n }\n}","import RowHeadersRenderer from \"./rowHeaders.mjs\";\nimport ColumnHeadersRenderer from \"./columnHeaders.mjs\";\nimport ColGroupRenderer from \"./colGroup.mjs\";\nimport RowsRenderer from \"./rows.mjs\";\nimport CellsRenderer from \"./cells.mjs\";\nimport TableRenderer from \"./table.mjs\";\n/**\n * Content renderer.\n *\n * @class Renderer\n */\nclass Renderer {\n constructor() {\n let {\n TABLE,\n THEAD,\n COLGROUP,\n TBODY,\n rowUtils,\n columnUtils,\n cellRenderer\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n /**\n * General renderer class used to render Walkontable content on screen.\n *\n * @type {TableRenderer}\n */\n this.renderer = new TableRenderer(TABLE, {\n cellRenderer\n });\n this.renderer.setRenderers({\n rowHeaders: new RowHeadersRenderer(),\n columnHeaders: new ColumnHeadersRenderer(THEAD),\n colGroup: new ColGroupRenderer(COLGROUP),\n rows: new RowsRenderer(TBODY),\n cells: new CellsRenderer()\n });\n this.renderer.setAxisUtils(rowUtils, columnUtils);\n }\n\n /**\n * Sets the overlay that is currently rendered. If `null` is provided, the master overlay is set.\n *\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'|'master'} overlayName The overlay name.\n * @returns {Renderer}\n */\n setActiveOverlayName(overlayName) {\n this.renderer.setActiveOverlayName(overlayName);\n return this;\n }\n\n /**\n * Sets filter calculators for newly calculated row and column position. The filters are used to transform visual\n * indexes (0 to N) to source indexes provided by Handsontable.\n *\n * @param {RowFilter} rowFilter The row filter instance.\n * @param {ColumnFilter} columnFilter The column filter instance.\n * @returns {Renderer}\n */\n setFilters(rowFilter, columnFilter) {\n this.renderer.setFilters(rowFilter, columnFilter);\n return this;\n }\n\n /**\n * Sets the viewport size of the rendered table.\n *\n * @param {number} rowsCount An amount of rows to render.\n * @param {number} columnsCount An amount of columns to render.\n * @returns {Renderer}\n */\n setViewportSize(rowsCount, columnsCount) {\n this.renderer.setViewportSize(rowsCount, columnsCount);\n return this;\n }\n\n /**\n * Sets row and column header functions.\n *\n * @param {Function[]} rowHeaders Row header functions. Factories for creating content for row headers.\n * @param {Function[]} columnHeaders Column header functions. Factories for creating content for column headers.\n * @returns {Renderer}\n */\n setHeaderContentRenderers(rowHeaders, columnHeaders) {\n this.renderer.setHeaderContentRenderers(rowHeaders, columnHeaders);\n return this;\n }\n\n /**\n * Adjusts the table (preparing for render).\n */\n adjust() {\n this.renderer.adjust();\n }\n\n /**\n * Renders the table.\n */\n render() {\n this.renderer.render();\n }\n}\nexport { RowHeadersRenderer, ColumnHeadersRenderer, ColGroupRenderer, RowsRenderer, CellsRenderer, TableRenderer, Renderer };","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { getScrollbarWidth } from \"./../../../../helpers/dom/element.mjs\";\nimport { ColumnStretching } from \"./columnStretching.mjs\";\n/**\n * Column utils class contains all necessary information about sizes of the columns.\n *\n * @class {ColumnUtils}\n */\nexport default class ColumnUtils {\n /**\n * @param {TableDao} dataAccessObject The table Data Access Object.\n * @param {Settings} wtSettings The walkontable settings.\n */\n constructor(dataAccessObject, wtSettings) {\n /**\n * @type {TableDao}\n */\n _defineProperty(this, \"dataAccessObject\", void 0);\n /**\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", void 0);\n /**\n * @type {Map}\n */\n _defineProperty(this, \"headerWidths\", new Map());\n /**\n * @type {ColumnStretching}\n */\n _defineProperty(this, \"stretching\", void 0);\n this.dataAccessObject = dataAccessObject;\n this.wtSettings = wtSettings;\n this.stretching = new ColumnStretching({\n totalColumns: () => this.wtSettings.getSetting('totalColumns'),\n stretchMode: () => this.wtSettings.getSetting('stretchH'),\n stretchingColumnWidthFn: (stretchedWidth, column) => this.wtSettings.getSetting('onBeforeStretchingColumnWidth', stretchedWidth, column),\n columnWidthFn: sourceCol => this.dataAccessObject.wtTable.getColumnWidth(sourceCol)\n });\n }\n\n /**\n * Returns column width based on passed source index.\n *\n * @param {number} sourceIndex Column source index.\n * @returns {number}\n */\n getWidth(sourceIndex) {\n const width = this.wtSettings.getSetting('columnWidth', sourceIndex) || this.wtSettings.getSetting('defaultColumnWidth');\n return width;\n }\n\n /**\n * Returns stretched column width based on passed source index.\n *\n * @param {number} sourceIndex Column source index.\n * @returns {number}\n */\n getStretchedColumnWidth(sourceIndex) {\n let width = this.getWidth(sourceIndex);\n const stretchedWidth = this.stretching.getStretchedColumnWidth(sourceIndex, width);\n if (stretchedWidth) {\n width = stretchedWidth;\n }\n return width;\n }\n\n /**\n * Returns column header height based on passed header level.\n *\n * @param {number} level Column header level.\n * @returns {number}\n */\n getHeaderHeight(level) {\n let height = this.wtSettings.getSetting('defaultRowHeight');\n const oversizedHeight = this.dataAccessObject.wtViewport.oversizedColumnHeaders[level];\n if (oversizedHeight !== undefined) {\n height = height ? Math.max(height, oversizedHeight) : oversizedHeight;\n }\n return height;\n }\n\n /**\n * Returns column header width based on passed source index.\n *\n * @param {number} sourceIndex Column source index.\n * @returns {number}\n */\n getHeaderWidth(sourceIndex) {\n return this.headerWidths.get(this.dataAccessObject.wtTable.columnFilter.sourceToRendered(sourceIndex));\n }\n\n /**\n * Refreshes the stretching column width by recalculating the widths of the columns.\n */\n refreshStretching() {\n const {\n wtTable,\n wtViewport,\n cloneSource\n } = this.dataAccessObject;\n const mainHolder = cloneSource ? cloneSource.wtTable.holder : wtTable.holder;\n const scrollbarCompensation = mainHolder.offsetHeight < mainHolder.scrollHeight ? getScrollbarWidth() : 0;\n this.stretching.refreshStretching(wtViewport.getViewportWidth() - scrollbarCompensation);\n }\n\n /**\n * Calculates column header widths that can be retrieved from the cache.\n */\n calculateWidths() {\n const {\n wtSettings\n } = this;\n let rowHeaderWidthSetting = wtSettings.getSetting('rowHeaderWidth');\n this.refreshStretching();\n rowHeaderWidthSetting = wtSettings.getSetting('onModifyRowHeaderWidth', rowHeaderWidthSetting);\n if (rowHeaderWidthSetting !== null && rowHeaderWidthSetting !== undefined) {\n const rowHeadersCount = wtSettings.getSetting('rowHeaders').length;\n const defaultColumnWidth = wtSettings.getSetting('defaultColumnWidth');\n for (let visibleColumnIndex = 0; visibleColumnIndex < rowHeadersCount; visibleColumnIndex++) {\n let width = Array.isArray(rowHeaderWidthSetting) ? rowHeaderWidthSetting[visibleColumnIndex] : rowHeaderWidthSetting;\n width = width === null || width === undefined ? defaultColumnWidth : width;\n this.headerWidths.set(visibleColumnIndex, width);\n }\n }\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { DEFAULT_COLUMN_WIDTH } from \"../calculator/index.mjs\";\n/**\n * @typedef {object} ColumnStretchingOptions\n * @property {number} totalColumns Total number of columns.\n * @property {Function} columnWidthFn Function that returns the width of the column at a given index (in px).\n * @property {'all' | 'last' | 'none'} stretchMode Stretch mode 'all', 'last' or 'none'.\n * @property {Function} stretchingColumnWidthFn Function that returns the new width of the stretched column.\n */\n/**\n * @class ColumnStretching\n */\nvar _totalTargetWidth = /*#__PURE__*/new WeakMap();\nvar _totalColumns = /*#__PURE__*/new WeakMap();\nvar _stretchingColumnWidthFn = /*#__PURE__*/new WeakMap();\nvar _columnWidthFn = /*#__PURE__*/new WeakMap();\nvar _stretchMode = /*#__PURE__*/new WeakMap();\nexport class ColumnStretching {\n /**\n * @param {ColumnStretchingOptions} options Object with all options specified for column viewport calculation.\n */\n constructor(_ref) {\n let {\n totalColumns,\n stretchMode,\n stretchingColumnWidthFn,\n columnWidthFn\n } = _ref;\n /**\n * @type {number}\n */\n _defineProperty(this, \"stretchAllRatio\", 0);\n /**\n * @type {number}\n */\n _defineProperty(this, \"stretchLastWidth\", 0);\n /**\n * @type {number[]}\n */\n _defineProperty(this, \"stretchAllColumnsWidth\", []);\n /**\n * @type {number}\n */\n _classPrivateFieldInitSpec(this, _totalTargetWidth, 0);\n /**\n * @type {boolean}\n */\n _defineProperty(this, \"needVerifyLastColumnWidth\", true);\n /**\n * The total number of columns.\n *\n * @type {function(): number}\n */\n _classPrivateFieldInitSpec(this, _totalColumns, () => 0);\n /**\n * Function that returns the width of the stretched column at a given index (in px).\n *\n * @type {function(): number}\n */\n _classPrivateFieldInitSpec(this, _stretchingColumnWidthFn, width => width);\n /**\n * Function that returns the width of the column at a given index (in px).\n *\n * @type {function(): number}\n */\n _classPrivateFieldInitSpec(this, _columnWidthFn, width => width);\n /**\n * Stretch mode.\n *\n * @type {function(): 'all' | 'last' | 'none'}\n */\n _classPrivateFieldInitSpec(this, _stretchMode, () => 'none');\n _classPrivateFieldSet(_totalColumns, this, totalColumns);\n _classPrivateFieldSet(_stretchMode, this, stretchMode);\n _classPrivateFieldSet(_stretchingColumnWidthFn, this, stretchingColumnWidthFn !== null && stretchingColumnWidthFn !== void 0 ? stretchingColumnWidthFn : _classPrivateFieldGet(_stretchingColumnWidthFn, this));\n _classPrivateFieldSet(_columnWidthFn, this, columnWidthFn !== null && columnWidthFn !== void 0 ? columnWidthFn : _classPrivateFieldGet(_columnWidthFn, this));\n }\n\n /**\n * Recalculate columns stretching.\n *\n * @param {number} totalWidth The total width of the table.\n */\n refreshStretching(totalWidth) {\n if (_classPrivateFieldGet(_stretchMode, this).call(this) === 'none') {\n return;\n }\n this.stretchAllRatio = 0;\n this.stretchAllColumnsWidth = [];\n this.needVerifyLastColumnWidth = true;\n this.stretchLastWidth = 0;\n _classPrivateFieldSet(_totalTargetWidth, this, totalWidth);\n let sumAll = 0;\n for (let i = 0; i < _classPrivateFieldGet(_totalColumns, this).call(this); i++) {\n const columnWidth = this._getColumnWidth(i);\n const permanentColumnWidth = _classPrivateFieldGet(_stretchingColumnWidthFn, this).call(this, undefined, i);\n if (typeof permanentColumnWidth === 'number') {\n totalWidth -= permanentColumnWidth;\n } else {\n sumAll += columnWidth;\n }\n }\n const remainingSize = totalWidth - sumAll;\n if (_classPrivateFieldGet(_stretchMode, this).call(this) === 'all' && remainingSize > 0) {\n this.stretchAllRatio = totalWidth / sumAll;\n this.stretchAllColumnsWidth = [];\n this.needVerifyLastColumnWidth = true;\n } else if (_classPrivateFieldGet(_stretchMode, this).call(this) === 'last' && totalWidth !== Infinity) {\n const columnWidth = this._getColumnWidth(_classPrivateFieldGet(_totalColumns, this).call(this) - 1);\n const lastColumnWidth = remainingSize + columnWidth;\n this.stretchLastWidth = lastColumnWidth >= 0 ? lastColumnWidth : columnWidth;\n }\n }\n\n /**\n * Get stretched column width based on stretchH (all or last) setting passed in handsontable instance.\n *\n * @param {number} column The visual column index.\n * @param {number} baseWidth The default column width.\n * @returns {number|null}\n */\n getStretchedColumnWidth(column, baseWidth) {\n let result = null;\n if (_classPrivateFieldGet(_stretchMode, this).call(this) === 'all' && this.stretchAllRatio !== 0) {\n result = this._getStretchedAllColumnWidth(column, baseWidth);\n } else if (_classPrivateFieldGet(_stretchMode, this).call(this) === 'last' && this.stretchLastWidth !== 0) {\n result = this._getStretchedLastColumnWidth(column);\n }\n return result;\n }\n\n /**\n * @param {number} column The visual column index.\n * @param {number} baseWidth The default column width.\n * @returns {number}\n * @private\n */\n _getStretchedAllColumnWidth(column, baseWidth) {\n let sumRatioWidth = 0;\n if (!this.stretchAllColumnsWidth[column]) {\n const stretchedWidth = Math.round(baseWidth * this.stretchAllRatio);\n const newStretchedWidth = _classPrivateFieldGet(_stretchingColumnWidthFn, this).call(this, stretchedWidth, column);\n if (newStretchedWidth === undefined) {\n this.stretchAllColumnsWidth[column] = stretchedWidth;\n } else {\n this.stretchAllColumnsWidth[column] = isNaN(newStretchedWidth) ? this._getColumnWidth(column) : newStretchedWidth;\n }\n }\n if (this.stretchAllColumnsWidth.length === _classPrivateFieldGet(_totalColumns, this).call(this) && this.needVerifyLastColumnWidth) {\n this.needVerifyLastColumnWidth = false;\n for (let i = 0; i < this.stretchAllColumnsWidth.length; i++) {\n sumRatioWidth += this.stretchAllColumnsWidth[i];\n }\n if (sumRatioWidth !== _classPrivateFieldGet(_totalTargetWidth, this)) {\n this.stretchAllColumnsWidth[this.stretchAllColumnsWidth.length - 1] += _classPrivateFieldGet(_totalTargetWidth, this) - sumRatioWidth;\n }\n }\n return this.stretchAllColumnsWidth[column];\n }\n\n /**\n * @param {number} column The visual column index.\n * @returns {number|null}\n * @private\n */\n _getStretchedLastColumnWidth(column) {\n if (column === _classPrivateFieldGet(_totalColumns, this).call(this) - 1) {\n return this.stretchLastWidth;\n }\n return null;\n }\n\n /**\n * @param {number} column The visual column index.\n * @returns {number}\n * @private\n */\n _getColumnWidth(column) {\n let width = _classPrivateFieldGet(_columnWidthFn, this).call(this, column);\n if (isNaN(width)) {\n width = DEFAULT_COLUMN_WIDTH;\n }\n return width;\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * Row utils class contains all necessary information about sizes of the rows.\n *\n * @class {RowUtils}\n */\nexport default class RowUtils {\n /**\n * @param {TableDao} dataAccessObject The table Data Access Object.\n * @param {Settings} wtSettings The walkontable settings.\n */\n constructor(dataAccessObject, wtSettings) {\n /**\n * @type {TableDao}\n */\n _defineProperty(this, \"dataAccessObject\", void 0);\n /**\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", void 0);\n this.dataAccessObject = dataAccessObject;\n this.wtSettings = wtSettings;\n }\n\n /**\n * Returns row height based on passed source index.\n *\n * @param {number} sourceIndex Row source index.\n * @returns {number}\n */\n getHeight(sourceIndex) {\n let height = this.wtSettings.getSetting('rowHeight', sourceIndex);\n const oversizedHeight = this.dataAccessObject.wtViewport.oversizedRows[sourceIndex];\n if (oversizedHeight !== undefined) {\n height = height === undefined ? oversizedHeight : Math.max(height, oversizedHeight);\n }\n return height;\n }\n\n /**\n * Returns row height based on passed source index for the specified overlay type.\n *\n * @param {number} sourceIndex Row source index.\n * @param {'inline_start'|'top'|'top_inline_start_corner'|'bottom'|'bottom_inline_start_corner'|'master'} overlayName The overlay name.\n * @returns {number}\n */\n getHeightByOverlayName(sourceIndex, overlayName) {\n let height = this.wtSettings.getSetting('rowHeightByOverlayName', sourceIndex, overlayName);\n const oversizedHeight = this.dataAccessObject.wtViewport.oversizedRows[sourceIndex];\n if (oversizedHeight !== undefined) {\n height = height === undefined ? oversizedHeight : Math.max(height, oversizedHeight);\n }\n return height;\n }\n}","import { defineGetter } from \"../../../../../helpers/object.mjs\";\nconst MIXIN_NAME = 'stickyRowsBottom';\n\n/**\n * Mixin for the subclasses of `Table` with implementations of\n * helper methods that are related to rows.\n * This mixin is meant to be applied in the subclasses of `Table`\n * that use sticky rendering of the bottom rows in the vertical axis.\n *\n * @type {object}\n */\nconst stickyRowsBottom = {\n /**\n * Get the source index of the first rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstRenderedRow() {\n const totalRows = this.wtSettings.getSetting('totalRows');\n const fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');\n const index = totalRows - fixedRowsBottom;\n if (totalRows === 0 || fixedRowsBottom === 0) {\n return -1;\n }\n if (index < 0) {\n return 0;\n }\n return index;\n },\n /**\n * Get the source index of the first row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstVisibleRow() {\n return this.getFirstRenderedRow();\n },\n /**\n * Get the source index of the first row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstPartiallyVisibleRow() {\n return this.getFirstRenderedRow();\n },\n /**\n * Get the source index of the last rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastRenderedRow() {\n return this.wtSettings.getSetting('totalRows') - 1;\n },\n /**\n * Get the source index of the last row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastVisibleRow() {\n return this.getLastRenderedRow();\n },\n /**\n * Get the source index of the last row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastPartiallyVisibleRow() {\n return this.getLastRenderedRow();\n },\n /**\n * Get the number of rendered rows.\n *\n * @returns {number}\n * @this Table\n */\n getRenderedRowsCount() {\n const totalRows = this.wtSettings.getSetting('totalRows');\n return Math.min(this.wtSettings.getSetting('fixedRowsBottom'), totalRows);\n },\n /**\n * Get the number of fully visible rows in the viewport.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getVisibleRowsCount() {\n return this.getRenderedRowsCount();\n },\n /**\n * Get the number of rendered column headers.\n *\n * @returns {number}\n * @this Table\n */\n getColumnHeadersCount() {\n return 0;\n }\n};\ndefineGetter(stickyRowsBottom, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default stickyRowsBottom;","import { defineGetter } from \"../../../../../helpers/object.mjs\";\nconst MIXIN_NAME = 'stickyColumnsStart';\n\n/**\n * Mixin for the subclasses of `Table` with implementations of\n * helper methods that are related to columns.\n * This mixin is meant to be applied in the subclasses of `Table`\n * that use sticky rendering of the first columns in the horizontal axis.\n *\n * @type {object}\n */\nconst stickyColumnsStart = {\n /**\n * Get the source index of the first rendered column. If no columns are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstRenderedColumn() {\n const totalColumns = this.wtSettings.getSetting('totalColumns');\n if (totalColumns === 0) {\n return -1;\n }\n return 0;\n },\n /**\n * Get the source index of the first column fully visible in the viewport. If no columns are fully visible, returns an error code: -1.\n * Assumes that all rendered columns are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstVisibleColumn() {\n return this.getFirstRenderedColumn();\n },\n /**\n * Get the source index of the first column partially visible in the viewport. If no columns are partially visible, returns an error code: -1.\n * Assumes that all rendered columns are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstPartiallyVisibleColumn() {\n return this.getFirstRenderedColumn();\n },\n /**\n * Get the source index of the last rendered column. If no columns are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastRenderedColumn() {\n return this.getRenderedColumnsCount() - 1;\n },\n /**\n * Get the source index of the last column fully visible in the viewport. If no columns are fully visible, returns an error code: -1.\n * Assumes that all rendered columns are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastVisibleColumn() {\n return this.getLastRenderedColumn();\n },\n /**\n * Get the source index of the last column partially visible in the viewport. If no columns are partially visible, returns an error code: -1.\n * Assumes that all rendered columns are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastPartiallyVisibleColumn() {\n return this.getLastRenderedColumn();\n },\n /**\n * Get the number of rendered columns.\n *\n * @returns {number}\n * @this Table\n */\n getRenderedColumnsCount() {\n const totalColumns = this.wtSettings.getSetting('totalColumns');\n return Math.min(this.wtSettings.getSetting('fixedColumnsStart'), totalColumns);\n },\n /**\n * Get the number of fully visible columns in the viewport.\n * Assumes that all rendered columns are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getVisibleColumnsCount() {\n return this.getRenderedColumnsCount();\n },\n /**\n * Get the number of rendered row headers.\n *\n * @returns {number}\n * @this Table\n */\n getRowHeadersCount() {\n return this.dataAccessObject.rowHeaders.length;\n }\n};\ndefineGetter(stickyColumnsStart, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default stickyColumnsStart;","import Table from \"../table.mjs\";\nimport stickyRowsBottom from \"./mixin/stickyRowsBottom.mjs\";\nimport stickyColumnsStart from \"./mixin/stickyColumnsStart.mjs\";\nimport { mixin } from \"../../../../helpers/object.mjs\";\nimport { CLONE_BOTTOM_INLINE_START_CORNER } from \"../overlay/index.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to bottomInlineStartCornerOverlay\n * (in RTL mode the overlay sits on the right of the screen), implemented through mixins.\n *\n * @mixes stickyRowsBottom\n * @mixes stickyColumnsStart\n */\nclass BottomInlineStartCornerOverlayTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, CLONE_BOTTOM_INLINE_START_CORNER);\n }\n}\nmixin(BottomInlineStartCornerOverlayTable, stickyRowsBottom);\nmixin(BottomInlineStartCornerOverlayTable, stickyColumnsStart);\nexport default BottomInlineStartCornerOverlayTable;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { getScrollableElement, getTrimmingContainer, getScrollbarWidth, setAttribute } from \"../../../../helpers/dom/element.mjs\";\nimport { defineGetter } from \"../../../../helpers/object.mjs\";\nimport { warn } from \"../../../../helpers/console.mjs\";\nimport { CLONE_TYPES, CLONE_CLASS_NAMES, CLONE_TOP, CLONE_INLINE_START } from \"./constants.mjs\";\nimport Clone from \"../core/clone.mjs\";\nimport { A11Y_PRESENTATION } from \"../../../../helpers/a11y.mjs\";\n/**\n * Creates an overlay over the original Walkontable instance. The overlay renders the clone of the original Walkontable\n * and (optionally) implements behavior needed for native horizontal and vertical scrolling.\n *\n * @abstract\n * @class Overlay\n * @property {Walkontable} wot The Walkontable instance.\n */\nexport class Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {CLONE_TYPES_ENUM} type The overlay type name (clone name).\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n */\n constructor(wotInstance, facadeGetter, type, wtSettings, domBindings) {\n /**\n * The Walkontable settings.\n *\n * @private\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", null);\n defineGetter(this, 'wot', wotInstance, {\n writable: false\n });\n this.domBindings = domBindings;\n this.facadeGetter = facadeGetter;\n this.wtSettings = wtSettings;\n const {\n TABLE,\n hider,\n spreader,\n holder,\n wtRootElement\n } = this.wot.wtTable; // todo ioc\n\n // legacy support, deprecated in the future\n this.instance = this.wot;\n this.type = type;\n this.mainTableScrollableElement = null;\n this.TABLE = TABLE;\n this.hider = hider;\n this.spreader = spreader;\n this.holder = holder;\n this.wtRootElement = wtRootElement;\n this.trimmingContainer = getTrimmingContainer(this.hider.parentNode.parentNode);\n this.needFullRender = this.shouldBeRendered();\n this.clone = this.makeClone();\n }\n\n /**\n * Checks if the overlay rendering state has changed.\n *\n * @returns {boolean}\n */\n hasRenderingStateChanged() {\n return this.needFullRender !== this.shouldBeRendered();\n }\n\n /**\n * Updates internal state with an information about the need of full rendering of the overlay in the next draw cycles.\n *\n * If the state is changed to render the overlay, the `needFullRender` property is set to `true` which means that\n * the overlay will be fully rendered in the current draw cycle. If the state is changed to not render the overlay,\n * the `needFullRender` property is set to `false` which means that the overlay will be fully rendered in the\n * current draw cycle but it will not be rendered in the next draw cycles.\n *\n * @param {'before' | 'after'} drawPhase The phase of the rendering process.\n */\n updateStateOfRendering(drawPhase) {\n if (drawPhase === 'before' && this.shouldBeRendered()) {\n this.needFullRender = true;\n } else if (drawPhase === 'after' && !this.shouldBeRendered()) {\n this.needFullRender = false;\n }\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return true;\n }\n\n /**\n * Update the trimming container.\n */\n updateTrimmingContainer() {\n this.trimmingContainer = getTrimmingContainer(this.hider.parentNode.parentNode);\n }\n\n /**\n * Update the main scrollable element.\n */\n updateMainScrollableElement() {\n const {\n wtTable\n } = this.wot;\n const {\n rootWindow\n } = this.domBindings;\n if (rootWindow.getComputedStyle(wtTable.wtRootElement.parentNode).getPropertyValue('overflow') === 'hidden') {\n this.mainTableScrollableElement = this.wot.wtTable.holder;\n } else {\n this.mainTableScrollableElement = getScrollableElement(wtTable.TABLE);\n }\n }\n\n /**\n * Calculates coordinates of the provided element, relative to the root Handsontable element.\n * NOTE: The element needs to be a child of the overlay in order for the method to work correctly.\n *\n * @param {HTMLElement} element The cell element to calculate the position for.\n * @param {number} rowIndex Visual row index.\n * @param {number} columnIndex Visual column index.\n * @returns {{top: number, start: number}|undefined}\n */\n getRelativeCellPosition(element, rowIndex, columnIndex) {\n if (this.clone.wtTable.holder.contains(element) === false) {\n warn(`The provided element is not a child of the ${this.type} overlay`);\n return;\n }\n const windowScroll = this.mainTableScrollableElement === this.domBindings.rootWindow;\n const fixedColumnStart = columnIndex < this.wtSettings.getSetting('fixedColumnsStart');\n const fixedRowTop = rowIndex < this.wtSettings.getSetting('fixedRowsTop');\n const fixedRowBottom = rowIndex >= this.wtSettings.getSetting('totalRows') - this.wtSettings.getSetting('fixedRowsBottom');\n const spreader = this.clone.wtTable.spreader;\n const spreaderOffset = {\n start: this.getRelativeStartPosition(spreader),\n top: spreader.offsetTop\n };\n const elementOffset = {\n start: this.getRelativeStartPosition(element),\n top: element.offsetTop\n };\n let offsetObject = null;\n if (windowScroll) {\n offsetObject = this.getRelativeCellPositionWithinWindow(fixedRowTop, fixedColumnStart, elementOffset, spreaderOffset);\n } else {\n offsetObject = this.getRelativeCellPositionWithinHolder(fixedRowTop, fixedRowBottom, fixedColumnStart, elementOffset, spreaderOffset);\n }\n return offsetObject;\n }\n\n /**\n * Get inline start value depending of direction.\n *\n * @param {HTMLElement} el Element.\n * @returns {number}\n */\n getRelativeStartPosition(el) {\n return this.isRtl() ? el.offsetParent.offsetWidth - el.offsetLeft - el.offsetWidth : el.offsetLeft;\n }\n\n /**\n * Calculates coordinates of the provided element, relative to the root Handsontable element within a table with window\n * as a scrollable element.\n *\n * @private\n * @param {boolean} onFixedRowTop `true` if the coordinates point to a place within the top fixed rows.\n * @param {boolean} onFixedColumn `true` if the coordinates point to a place within the fixed columns.\n * @param {number} elementOffset Offset position of the cell element.\n * @param {number} spreaderOffset Offset position of the spreader element.\n * @returns {{top: number, left: number}}\n */\n getRelativeCellPositionWithinWindow(onFixedRowTop, onFixedColumn, elementOffset, spreaderOffset) {\n const absoluteRootElementPosition = this.wot.wtTable.wtRootElement.getBoundingClientRect(); // todo refactoring: DEMETER\n let horizontalOffset = 0;\n let verticalOffset = 0;\n if (!onFixedColumn) {\n horizontalOffset = spreaderOffset.start;\n } else {\n let absoluteRootElementStartPosition = absoluteRootElementPosition.left;\n if (this.isRtl()) {\n absoluteRootElementStartPosition = this.domBindings.rootWindow.innerWidth - (absoluteRootElementPosition.left + absoluteRootElementPosition.width + getScrollbarWidth());\n }\n horizontalOffset = absoluteRootElementStartPosition <= 0 ? -1 * absoluteRootElementStartPosition : 0;\n }\n if (onFixedRowTop) {\n const absoluteOverlayPosition = this.clone.wtTable.TABLE.getBoundingClientRect();\n verticalOffset = absoluteOverlayPosition.top - absoluteRootElementPosition.top;\n } else {\n verticalOffset = spreaderOffset.top;\n }\n return {\n start: elementOffset.start + horizontalOffset,\n top: elementOffset.top + verticalOffset\n };\n }\n\n /**\n * Calculates coordinates of the provided element, relative to the root Handsontable element within a table with window\n * as a scrollable element.\n *\n * @private\n * @param {boolean} onFixedRowTop `true` if the coordinates point to a place within the top fixed rows.\n * @param {boolean} onFixedRowBottom `true` if the coordinates point to a place within the bottom fixed rows.\n * @param {boolean} onFixedColumn `true` if the coordinates point to a place within the fixed columns.\n * @param {number} elementOffset Offset position of the cell element.\n * @param {number} spreaderOffset Offset position of the spreader element.\n * @returns {{top: number, left: number}}\n */\n getRelativeCellPositionWithinHolder(onFixedRowTop, onFixedRowBottom, onFixedColumn, elementOffset, spreaderOffset) {\n const tableScrollPosition = {\n horizontal: this.wot.wtOverlays.inlineStartOverlay.getScrollPosition(),\n vertical: this.wot.wtOverlays.topOverlay.getScrollPosition()\n };\n let horizontalOffset = 0;\n let verticalOffset = 0;\n if (!onFixedColumn) {\n horizontalOffset = tableScrollPosition.horizontal - spreaderOffset.start;\n }\n if (onFixedRowBottom) {\n const absoluteRootElementPosition = this.wot.wtTable.wtRootElement.getBoundingClientRect(); // todo refactoring: DEMETER\n const absoluteOverlayPosition = this.clone.wtTable.TABLE.getBoundingClientRect(); // todo refactoring: DEMETER\n\n verticalOffset = absoluteOverlayPosition.top * -1 + absoluteRootElementPosition.top;\n } else if (!onFixedRowTop) {\n verticalOffset = tableScrollPosition.vertical - spreaderOffset.top;\n }\n return {\n start: elementOffset.start - horizontalOffset,\n top: elementOffset.top - verticalOffset\n };\n }\n\n /**\n * Make a clone of table for overlay.\n *\n * @returns {Clone}\n */\n makeClone() {\n if (CLONE_TYPES.indexOf(this.type) === -1) {\n throw new Error(`Clone type \"${this.type}\" is not supported.`);\n }\n const {\n wtTable,\n wtSettings\n } = this.wot;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const clone = rootDocument.createElement('div');\n const clonedTable = rootDocument.createElement('table');\n const tableParent = wtTable.wtRootElement.parentNode;\n clone.className = `${CLONE_CLASS_NAMES.get(this.type)} handsontable`;\n clone.setAttribute('dir', this.isRtl() ? 'rtl' : 'ltr');\n clone.style.position = 'absolute';\n clone.style.top = 0;\n clone.style.overflow = 'visible';\n if (this.isRtl()) {\n clone.style.right = 0;\n } else {\n clone.style.left = 0;\n }\n if (wtSettings.getSetting('ariaTags')) {\n setAttribute(clone, [A11Y_PRESENTATION()]);\n }\n clonedTable.className = wtTable.TABLE.className;\n\n // Clone the main table's `role` attribute to the cloned table.\n const mainTableRole = wtTable.TABLE.getAttribute('role');\n if (mainTableRole) {\n clonedTable.setAttribute('role', wtTable.TABLE.getAttribute('role'));\n }\n clone.appendChild(clonedTable);\n tableParent.appendChild(clone);\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (preventOverflow === true || preventOverflow === 'horizontal' && this.type === CLONE_TOP || preventOverflow === 'vertical' && this.type === CLONE_INLINE_START) {\n this.mainTableScrollableElement = rootWindow;\n } else if (rootWindow.getComputedStyle(tableParent).getPropertyValue('overflow') === 'hidden') {\n this.mainTableScrollableElement = wtTable.holder;\n } else {\n this.mainTableScrollableElement = getScrollableElement(wtTable.TABLE);\n }\n\n // Create a new instance of the Walkontable class\n return new Clone(clonedTable, this.wtSettings, {\n // todo ioc factory\n source: this.wot,\n overlay: this,\n viewport: this.wot.wtViewport,\n // todo ioc , or factor func if used only here\n event: this.wot.wtEvent,\n // todo ioc , or factory func if used only here\n selectionManager: this.wot.selectionManager // todo ioc , or factory func if used only here\n });\n }\n\n /**\n * Refresh/Redraw overlay.\n *\n * @param {boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering\n * the data. It will only work if Table.draw() does not force\n * rendering anyway.\n */\n refresh() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n if (this.needFullRender) {\n this.clone.draw(fastDraw);\n }\n }\n\n /**\n * Reset overlay styles to initial values.\n */\n reset() {\n const holder = this.clone.wtTable.holder; // todo refactoring: DEMETER\n const hider = this.clone.wtTable.hider; // todo refactoring: DEMETER\n const holderStyle = holder.style;\n const hiderStyle = hider.style;\n const rootStyle = holder.parentNode.style;\n [holderStyle, hiderStyle, rootStyle].forEach(style => {\n style.width = '';\n style.height = '';\n });\n }\n\n /**\n * Determine if Walkontable is running in RTL mode.\n *\n * @returns {boolean}\n */\n isRtl() {\n return this.wtSettings.getSetting('rtlMode');\n }\n\n /**\n * Destroy overlay instance.\n */\n destroy() {\n this.clone.eventManager.destroy(); // todo check if it is good place for that operation\n }\n}","/**\n * @typedef {'top'|'bottom'|'inline_start'|'top_inline_start_corner'|'bottom_inline_start_corner'} CLONE_TYPES_ENUM\n */\nexport const CLONE_TOP = 'top';\nexport const CLONE_BOTTOM = 'bottom';\nexport const CLONE_INLINE_START = 'inline_start';\nexport const CLONE_TOP_INLINE_START_CORNER = 'top_inline_start_corner';\nexport const CLONE_BOTTOM_INLINE_START_CORNER = 'bottom_inline_start_corner';\nexport const CLONE_TYPES = [CLONE_TOP, CLONE_BOTTOM, CLONE_INLINE_START, CLONE_TOP_INLINE_START_CORNER, CLONE_BOTTOM_INLINE_START_CORNER];\nexport const CLONE_CLASS_NAMES = new Map([[CLONE_TOP, `ht_clone_${CLONE_TOP}`], [CLONE_BOTTOM, `ht_clone_${CLONE_BOTTOM}`], [CLONE_INLINE_START, `ht_clone_${CLONE_INLINE_START} ht_clone_left`], [CLONE_TOP_INLINE_START_CORNER, `ht_clone_${CLONE_TOP_INLINE_START_CORNER} ht_clone_top_left_corner`], [CLONE_BOTTOM_INLINE_START_CORNER, `ht_clone_${CLONE_BOTTOM_INLINE_START_CORNER} ht_clone_bottom_left_corner`]]);","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport Event from \"../event.mjs\";\nimport CoreAbstract from \"./_base.mjs\";\n/**\n * @class Walkontable\n */\nexport default class Clone extends CoreAbstract {\n /**\n * @param {HTMLTableElement} table Main table.\n * @param {SettingsPure|Settings} settings The Walkontable settings.\n * @param {WalkontableCloneOptions} clone Clone data.\n */\n constructor(table, settings, clone) {\n super(table, settings);\n /**\n * @type {Walkontable}\n */\n _defineProperty(this, \"cloneSource\", void 0);\n /**\n * @type {Overlay}\n */\n _defineProperty(this, \"cloneOverlay\", void 0);\n const facadeGetter = this.wtSettings.getSetting('facade', this);\n this.cloneSource = clone.source;\n this.cloneOverlay = clone.overlay;\n this.wtTable = this.cloneOverlay.createTable(this.getTableDao(), facadeGetter, this.domBindings, this.wtSettings);\n this.wtViewport = clone.viewport;\n this.selectionManager = clone.selectionManager;\n this.wtEvent = new Event(facadeGetter, this.domBindings, this.wtSettings, this.eventManager, this.wtTable, this.selectionManager, clone.event);\n this.findOriginalHeaders();\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { fastInnerText } from \"../../../../helpers/dom/element.mjs\";\nimport { randomString } from \"../../../../helpers/string.mjs\";\nimport EventManager from \"../../../../eventManager.mjs\";\nimport Scroll from \"../scroll.mjs\";\nimport CellCoords from \"../cell/coords.mjs\";\nimport CellRange from \"../cell/range.mjs\";\n/**\n * @abstract\n * @class Walkontable\n */\nexport default class CoreAbstract {\n get eventManager() {\n return new EventManager(this);\n }\n\n /**\n * @param {HTMLTableElement} table Main table.\n * @param {Settings} settings The Walkontable settings.\n */\n constructor(table, settings) {\n _defineProperty(this, \"wtTable\", void 0);\n _defineProperty(this, \"wtScroll\", void 0);\n _defineProperty(this, \"wtViewport\", void 0);\n _defineProperty(this, \"wtOverlays\", void 0);\n _defineProperty(this, \"selectionManager\", void 0);\n _defineProperty(this, \"wtEvent\", void 0);\n /**\n * The walkontable instance id.\n *\n * @public\n * @type {Readonly}\n */\n _defineProperty(this, \"guid\", `wt_${randomString()}`);\n _defineProperty(this, \"drawInterrupted\", false);\n _defineProperty(this, \"drawn\", false);\n /**\n * The DOM bindings.\n *\n * @public\n * @type {DomBindings}\n */\n _defineProperty(this, \"domBindings\", void 0);\n /**\n * Settings.\n *\n * @public\n * @type {Settings}\n */\n _defineProperty(this, \"wtSettings\", void 0);\n this.domBindings = {\n rootTable: table,\n rootDocument: table.ownerDocument,\n rootWindow: table.ownerDocument.defaultView\n };\n this.wtSettings = settings;\n this.wtScroll = new Scroll(this.createScrollDao());\n }\n findOriginalHeaders() {\n const originalHeaders = [];\n\n // find original headers\n if (this.wtTable.THEAD.childNodes.length && this.wtTable.THEAD.childNodes[0].childNodes.length) {\n for (let c = 0, clen = this.wtTable.THEAD.childNodes[0].childNodes.length; c < clen; c++) {\n originalHeaders.push(this.wtTable.THEAD.childNodes[0].childNodes[c].innerHTML);\n }\n if (!this.wtSettings.getSetting('columnHeaders').length) {\n this.wtSettings.update('columnHeaders', [function (column, TH) {\n fastInnerText(TH, originalHeaders[column]);\n }]);\n }\n }\n }\n\n /**\n * Creates and returns the CellCoords object.\n *\n * @param {*} row The row index.\n * @param {*} column The column index.\n * @returns {CellCoords}\n */\n createCellCoords(row, column) {\n return new CellCoords(row, column, this.wtSettings.getSetting('rtlMode'));\n }\n\n /**\n * Creates and returns the CellRange object.\n *\n * @param {CellCoords} highlight The highlight coordinates.\n * @param {CellCoords} from The from coordinates.\n * @param {CellCoords} to The to coordinates.\n * @returns {CellRange}\n */\n createCellRange(highlight, from, to) {\n return new CellRange(highlight, from, to, this.wtSettings.getSetting('rtlMode'));\n }\n\n /**\n * Force rerender of Walkontable.\n *\n * @param {boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering\n * the data. It will only work if Table.draw() does not force\n * rendering anyway.\n * @returns {Walkontable}\n */\n draw() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n this.drawInterrupted = false;\n if (!this.wtTable.isVisible()) {\n // draw interrupted because TABLE is not visible\n this.drawInterrupted = true;\n } else {\n this.wtTable.draw(fastDraw);\n }\n return this;\n }\n\n /**\n * Returns the TD at coords. If topmost is set to true, returns TD from the topmost overlay layer,\n * if not set or set to false, returns TD from the master table.\n *\n * @param {CellCoords} coords The cell coordinates.\n * @param {boolean} [topmost=false] If set to `true`, it returns the TD element from the topmost overlay. For example,\n * if the wanted cell is in the range of fixed rows, it will return a TD element\n * from the top overlay.\n * @returns {HTMLElement}\n */\n getCell(coords) {\n let topmost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n if (!topmost) {\n return this.wtTable.getCell(coords);\n }\n const totalRows = this.wtSettings.getSetting('totalRows');\n const fixedRowsTop = this.wtSettings.getSetting('fixedRowsTop');\n const fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');\n const fixedColumnsStart = this.wtSettings.getSetting('fixedColumnsStart');\n if (coords.row < fixedRowsTop && coords.col < fixedColumnsStart) {\n return this.wtOverlays.topInlineStartCornerOverlay.clone.wtTable.getCell(coords);\n } else if (coords.row < fixedRowsTop) {\n return this.wtOverlays.topOverlay.clone.wtTable.getCell(coords);\n } else if (coords.col < fixedColumnsStart && coords.row >= totalRows - fixedRowsBottom) {\n if (this.wtOverlays.bottomInlineStartCornerOverlay && this.wtOverlays.bottomInlineStartCornerOverlay.clone) {\n return this.wtOverlays.bottomInlineStartCornerOverlay.clone.wtTable.getCell(coords);\n }\n } else if (coords.col < fixedColumnsStart) {\n return this.wtOverlays.inlineStartOverlay.clone.wtTable.getCell(coords);\n } else if (coords.row < totalRows && coords.row >= totalRows - fixedRowsBottom) {\n if (this.wtOverlays.bottomOverlay && this.wtOverlays.bottomOverlay.clone) {\n return this.wtOverlays.bottomOverlay.clone.wtTable.getCell(coords);\n }\n }\n return this.wtTable.getCell(coords);\n }\n\n /**\n * Scrolls the viewport to a cell (rerenders if needed).\n *\n * @param {CellCoords} coords The cell coordinates to scroll to.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.\n * @returns {boolean}\n */\n scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft) {\n if (coords.col < 0 || coords.row < 0) {\n return false;\n }\n return this.wtScroll.scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft);\n }\n\n /**\n * Scrolls the viewport to a column (rerenders if needed).\n *\n * @param {number} column Visual column index.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.\n * @returns {boolean}\n */\n scrollViewportHorizontally(column, snapToRight, snapToLeft) {\n if (column < 0) {\n return false;\n }\n return this.wtScroll.scrollViewportHorizontally(column, snapToRight, snapToLeft);\n }\n\n /**\n * Scrolls the viewport to a row (rerenders if needed).\n *\n * @param {number} row Visual row index.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.\n * @returns {boolean}\n */\n scrollViewportVertically(row, snapToTop, snapToBottom) {\n if (row < 0) {\n return false;\n }\n return this.wtScroll.scrollViewportVertically(row, snapToTop, snapToBottom);\n }\n\n /**\n * @returns {Array}\n */\n getViewport() {\n return [this.wtTable.getFirstVisibleRow(), this.wtTable.getFirstVisibleColumn(), this.wtTable.getLastVisibleRow(), this.wtTable.getLastVisibleColumn()];\n }\n\n /**\n * Destroy instance.\n */\n destroy() {\n this.wtOverlays.destroy();\n this.wtEvent.destroy();\n }\n\n /**\n * Create data access object for scroll.\n *\n * @protected\n * @returns {ScrollDao}\n */\n createScrollDao() {\n const wot = this;\n return {\n get drawn() {\n return wot.drawn; // TODO refactoring: consider about injecting `isDrawn` function : ()=>return wot.drawn. (it'll enables remove dao layer)\n },\n get topOverlay() {\n return wot.wtOverlays.topOverlay; // TODO refactoring: move outside dao, use IOC\n },\n get inlineStartOverlay() {\n return wot.wtOverlays.inlineStartOverlay; // TODO refactoring: move outside dao, use IOC\n },\n get wtTable() {\n return wot.wtTable; // TODO refactoring: move outside dao, use IOC\n },\n get wtViewport() {\n return wot.wtViewport; // TODO refactoring: move outside dao, use IOC\n },\n get wtSettings() {\n return wot.wtSettings;\n },\n get rootWindow() {\n return wot.domBindings.rootWindow; // TODO refactoring: move outside dao\n },\n // TODO refactoring, consider about using injecting wtSettings into scroll (it'll enables remove dao layer)\n get totalRows() {\n return wot.wtSettings.getSetting('totalRows');\n },\n get totalColumns() {\n return wot.wtSettings.getSetting('totalColumns');\n },\n get fixedRowsTop() {\n return wot.wtSettings.getSetting('fixedRowsTop');\n },\n get fixedRowsBottom() {\n return wot.wtSettings.getSetting('fixedRowsBottom');\n },\n get fixedColumnsStart() {\n return wot.wtSettings.getSetting('fixedColumnsStart');\n }\n };\n }\n // TODO refactoring: it will be much better to not use DAO objects. They are needed for now to provide\n // dynamically access to related objects\n /**\n * Create data access object for wtTable.\n *\n * @protected\n * @returns {TableDao}\n */\n getTableDao() {\n const wot = this;\n return {\n get wot() {\n return wot;\n },\n get parentTableOffset() {\n return wot.cloneSource.wtTable.tableOffset; // TODO rethink: cloneSource exists only in Clone type.\n },\n get cloneSource() {\n return wot.cloneSource; // TODO rethink: cloneSource exists only in Clone type.\n },\n get workspaceWidth() {\n return wot.wtViewport.getWorkspaceWidth();\n },\n get wtViewport() {\n return wot.wtViewport; // TODO refactoring: move outside dao, use IOC\n },\n get wtOverlays() {\n return wot.wtOverlays; // TODO refactoring: move outside dao, use IOC\n },\n get selectionManager() {\n return wot.selectionManager; // TODO refactoring: move outside dao, use IOC\n },\n get drawn() {\n return wot.drawn;\n },\n set drawn(v) {\n // TODO rethink: this breaks assumes of data access object, however it is required until invent better way to handle WOT state.\n wot.drawn = v;\n },\n get wtTable() {\n return wot.wtTable; // TODO refactoring: it provides itself\n },\n get startColumnRendered() {\n return wot.wtViewport.columnsRenderCalculator.startColumn;\n },\n get startColumnVisible() {\n return wot.wtViewport.columnsVisibleCalculator.startColumn;\n },\n get startColumnPartiallyVisible() {\n return wot.wtViewport.columnsPartiallyVisibleCalculator.startColumn;\n },\n get endColumnRendered() {\n return wot.wtViewport.columnsRenderCalculator.endColumn;\n },\n get endColumnVisible() {\n return wot.wtViewport.columnsVisibleCalculator.endColumn;\n },\n get endColumnPartiallyVisible() {\n return wot.wtViewport.columnsPartiallyVisibleCalculator.endColumn;\n },\n get countColumnsRendered() {\n return wot.wtViewport.columnsRenderCalculator.count;\n },\n get countColumnsVisible() {\n return wot.wtViewport.columnsVisibleCalculator.count;\n },\n get startRowRendered() {\n return wot.wtViewport.rowsRenderCalculator.startRow;\n },\n get startRowVisible() {\n return wot.wtViewport.rowsVisibleCalculator.startRow;\n },\n get startRowPartiallyVisible() {\n return wot.wtViewport.rowsPartiallyVisibleCalculator.startRow;\n },\n get endRowRendered() {\n return wot.wtViewport.rowsRenderCalculator.endRow;\n },\n get endRowVisible() {\n return wot.wtViewport.rowsVisibleCalculator.endRow;\n },\n get endRowPartiallyVisible() {\n return wot.wtViewport.rowsPartiallyVisibleCalculator.endRow;\n },\n get countRowsRendered() {\n return wot.wtViewport.rowsRenderCalculator.count;\n },\n get countRowsVisible() {\n return wot.wtViewport.rowsVisibleCalculator.count;\n },\n get columnHeaders() {\n return wot.wtSettings.getSetting('columnHeaders');\n },\n get rowHeaders() {\n return wot.wtSettings.getSetting('rowHeaders');\n }\n };\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { innerHeight, innerWidth, getScrollLeft, getScrollTop, offset } from \"../../../helpers/dom/element.mjs\";\n/**\n * @class Scroll\n */\nvar _Scroll_brand = /*#__PURE__*/new WeakSet();\nclass Scroll {\n /**\n * @param {ScrollDao} dataAccessObject Tha data access object.\n */\n constructor(dataAccessObject) {\n /**\n * Get last visible column based on virtual dom and how table is visible in browser window viewport.\n *\n * @param {number} lastColumnIndex The last visible column index.\n * @returns {number}\n */\n _classPrivateMethodInitSpec(this, _Scroll_brand);\n /**\n * The data access object.\n *\n * @protected\n * @type {ScrollDao}\n */\n _defineProperty(this, \"dataAccessObject\", void 0);\n this.dataAccessObject = dataAccessObject;\n }\n\n /**\n * Scrolls viewport to a cell.\n *\n * @param {CellCoords} coords The cell coordinates.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.\n * @returns {boolean}\n */\n scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft) {\n const scrolledHorizontally = this.scrollViewportHorizontally(coords.col, snapToRight, snapToLeft);\n const scrolledVertically = this.scrollViewportVertically(coords.row, snapToTop, snapToBottom);\n return scrolledHorizontally || scrolledVertically;\n }\n\n /**\n * Scrolls viewport to a column.\n *\n * @param {number} column Visual column index.\n * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.\n * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.\n * @returns {boolean}\n */\n scrollViewportHorizontally(column, snapToRight, snapToLeft) {\n const {\n drawn,\n totalColumns\n } = this.dataAccessObject;\n\n // do not scroll the viewport when the column points to a range outside of the dataset\n if (!drawn || !Number.isInteger(column) || column < 0 || column > totalColumns) {\n return false;\n }\n const autoSnapping = snapToRight === undefined && snapToLeft === undefined;\n const {\n fixedColumnsStart,\n inlineStartOverlay\n } = this.dataAccessObject;\n\n // for auto-snapping (both snap* arguments are undefined) do not scroll the viewport\n // when the columns points to the overlays\n if (autoSnapping && column < fixedColumnsStart) {\n return false;\n }\n column = this.dataAccessObject.wtSettings.getSetting('onBeforeViewportScrollHorizontally', column);\n if (!Number.isInteger(column) || column < 0 || column > totalColumns) {\n return false;\n }\n const firstColumn = this.getFirstVisibleColumn();\n const lastColumn = this.getLastVisibleColumn();\n let result = false;\n if (autoSnapping && (column < firstColumn || column > lastColumn) || !autoSnapping) {\n // if there is at least one fully visible column determine the snapping direction based on\n // that columns or by snapToRight/snapToLeft flags, if provided.\n result = inlineStartOverlay.scrollTo(column, autoSnapping ? column >= this.getLastPartiallyVisibleColumn() : snapToRight);\n }\n return result;\n }\n\n /**\n * Scrolls viewport to a row.\n *\n * @param {number} row Visual row index.\n * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.\n * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.\n * @returns {boolean}\n */\n scrollViewportVertically(row, snapToTop, snapToBottom) {\n const {\n drawn,\n totalRows\n } = this.dataAccessObject;\n\n // do not scroll the viewport when the row points to a range outside of the dataset\n if (!drawn || !Number.isInteger(row) || row < 0 || row > totalRows) {\n return false;\n }\n const autoSnapping = snapToTop === undefined && snapToBottom === undefined;\n const {\n fixedRowsBottom,\n fixedRowsTop,\n topOverlay\n } = this.dataAccessObject;\n\n // for auto-snapping (both snap* arguments are undefined) do not scroll the viewport\n // when the rows points to the overlays\n if (autoSnapping && (row < fixedRowsTop || row > totalRows - fixedRowsBottom - 1)) {\n return false;\n }\n row = this.dataAccessObject.wtSettings.getSetting('onBeforeViewportScrollVertically', row);\n if (!Number.isInteger(row) || row < 0 || row > totalRows) {\n return false;\n }\n const firstRow = this.getFirstVisibleRow();\n const lastRow = this.getLastVisibleRow();\n let result = false;\n if (autoSnapping && (row < firstRow || row > lastRow) || !autoSnapping) {\n // if there is at least one fully visible row determine the snapping direction based on\n // that rows or by snapToTop/snapToBottom flags, if provided.\n result = topOverlay.scrollTo(row, autoSnapping ? row >= this.getLastPartiallyVisibleRow() : snapToBottom);\n }\n return result;\n }\n\n /**\n * Get first visible row based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getFirstVisibleRow() {\n return this.dataAccessObject.wtTable.getFirstVisibleRow();\n }\n\n /**\n * Get last visible row based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getLastVisibleRow() {\n return _assertClassBrand(_Scroll_brand, this, _getLastRowIndex).call(this, this.dataAccessObject.wtTable.getLastVisibleRow());\n }\n\n /**\n * Get first partially visible row based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getFirstPartiallyVisibleRow() {\n return this.dataAccessObject.wtTable.getFirstPartiallyVisibleRow();\n }\n\n /**\n * Get last visible row based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getLastPartiallyVisibleRow() {\n return _assertClassBrand(_Scroll_brand, this, _getLastRowIndex).call(this, this.dataAccessObject.wtTable.getLastPartiallyVisibleRow());\n }\n\n /**\n * Get first visible column based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getFirstVisibleColumn() {\n return this.dataAccessObject.wtTable.getFirstVisibleColumn();\n }\n\n /**\n * Get last visible column based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getLastVisibleColumn() {\n return _assertClassBrand(_Scroll_brand, this, _getLastColumnIndex).call(this, this.dataAccessObject.wtTable.getLastVisibleColumn());\n }\n\n /**\n * Get first partially visible column based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getFirstPartiallyVisibleColumn() {\n return this.dataAccessObject.wtTable.getFirstPartiallyVisibleColumn();\n }\n\n /**\n * Get last partially visible column based on virtual dom and how table is visible in browser window viewport.\n *\n * @returns {number}\n */\n getLastPartiallyVisibleColumn() {\n return _assertClassBrand(_Scroll_brand, this, _getLastColumnIndex).call(this, this.dataAccessObject.wtTable.getLastPartiallyVisibleColumn());\n }\n}\nfunction _getLastColumnIndex(lastColumnIndex) {\n const {\n wtSettings,\n inlineStartOverlay,\n wtTable,\n wtViewport,\n totalColumns,\n rootWindow\n } = this.dataAccessObject;\n if (inlineStartOverlay.mainTableScrollableElement === rootWindow) {\n const isRtl = wtSettings.getSetting('rtlMode');\n let inlineStartRootElementOffset = null;\n if (isRtl) {\n const tableRect = wtTable.TABLE.getBoundingClientRect();\n const rootDocument = this.dataAccessObject.rootWindow.document;\n const docOffsetWidth = rootDocument.documentElement.offsetWidth;\n inlineStartRootElementOffset = Math.abs(tableRect.right - docOffsetWidth);\n } else {\n const rootElementOffset = offset(wtTable.wtRootElement);\n inlineStartRootElementOffset = rootElementOffset.left;\n }\n const windowScrollLeft = Math.abs(getScrollLeft(rootWindow, rootWindow));\n\n // Only calculate lastColumnIndex when table didn't filled (from right) whole viewport space\n if (inlineStartRootElementOffset > windowScrollLeft) {\n const windowWidth = innerWidth(rootWindow);\n let columnsWidth = wtViewport.getRowHeaderWidth();\n for (let column = 1; column <= totalColumns; column++) {\n columnsWidth += inlineStartOverlay.sumCellSizes(column - 1, column);\n if (inlineStartRootElementOffset + columnsWidth - windowScrollLeft >= windowWidth) {\n // Return physical column - 1 (-2 because rangeEach gives column index + 1 - sumCellSizes requirements)\n lastColumnIndex = column - 2;\n break;\n }\n }\n }\n }\n return lastColumnIndex;\n}\n/**\n * Get last visible row based on virtual dom and how table is visible in browser window viewport.\n *\n * @param {number} lastRowIndex The last visible row index.\n * @returns {number}\n */\nfunction _getLastRowIndex(lastRowIndex) {\n const {\n topOverlay,\n wtTable,\n wtViewport,\n totalRows,\n rootWindow\n } = this.dataAccessObject;\n if (topOverlay.mainTableScrollableElement === rootWindow) {\n const rootElementOffset = offset(wtTable.wtRootElement);\n const windowScrollTop = getScrollTop(rootWindow, rootWindow);\n\n // Only calculate lastRowIndex when table didn't filled (from bottom) whole viewport space\n if (rootElementOffset.top > windowScrollTop) {\n const windowHeight = innerHeight(rootWindow);\n let rowsHeight = wtViewport.getColumnHeaderHeight();\n for (let row = 1; row <= totalRows; row++) {\n rowsHeight += topOverlay.sumCellSizes(row - 1, row);\n if (rootElementOffset.top + rowsHeight - windowScrollTop >= windowHeight) {\n // Return physical row - 1 (-2 because rangeEach gives row index + 1 - sumCellSizes requirements)\n lastRowIndex = row - 2;\n break;\n }\n }\n }\n }\n return lastRowIndex;\n}\nexport default Scroll;","import { getScrollbarWidth, outerHeight, outerWidth, resetCssTransform } from \"../../../../helpers/dom/element.mjs\";\nimport BottomInlineStartCornerOverlayTable from \"../table/bottomInlineStartCorner.mjs\";\nimport { Overlay } from \"./_base.mjs\";\nimport { CLONE_BOTTOM_INLINE_START_CORNER } from \"./constants.mjs\";\n/**\n * @class BottomInlineStartCornerOverlay\n */\nexport class BottomInlineStartCornerOverlay extends Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n * @param {BottomOverlay} bottomOverlay The instance of the Top overlay.\n * @param {InlineStartOverlay} inlineStartOverlay The instance of the InlineStart overlay.\n */\n constructor(wotInstance, facadeGetter, wtSettings, domBindings, bottomOverlay, inlineStartOverlay) {\n super(wotInstance, facadeGetter, CLONE_BOTTOM_INLINE_START_CORNER, wtSettings, domBindings);\n this.bottomOverlay = bottomOverlay;\n this.inlineStartOverlay = inlineStartOverlay;\n }\n\n /**\n * Factory method to create a subclass of `Table` that is relevant to this overlay.\n *\n * @see Table#constructor\n * @param {...*} args Parameters that will be forwarded to the `Table` constructor.\n * @returns {BottomInlineStartCornerOverlayTable}\n */\n createTable() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new BottomInlineStartCornerOverlayTable(...args);\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return this.wtSettings.getSetting('shouldRenderBottomOverlay') && this.wtSettings.getSetting('shouldRenderInlineStartOverlay');\n }\n\n /**\n * Updates the corner overlay position.\n *\n * @returns {boolean}\n */\n resetFixedPosition() {\n const {\n wot\n } = this;\n this.updateTrimmingContainer();\n if (!wot.wtTable.holder.parentNode) {\n // removed from DOM\n return false;\n }\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n overlayRoot.style.top = '';\n if (this.trimmingContainer === this.domBindings.rootWindow) {\n const inlineStartOffset = this.inlineStartOverlay.getOverlayOffset();\n const bottom = this.bottomOverlay.getOverlayOffset();\n overlayRoot.style[this.isRtl() ? 'right' : 'left'] = `${inlineStartOffset}px`;\n overlayRoot.style.bottom = `${bottom}px`;\n } else {\n resetCssTransform(overlayRoot);\n this.repositionOverlay();\n }\n let tableHeight = outerHeight(this.clone.wtTable.TABLE);\n const tableWidth = outerWidth(this.clone.wtTable.TABLE);\n if (!this.wot.wtTable.hasDefinedSize()) {\n tableHeight = 0;\n }\n overlayRoot.style.height = `${tableHeight}px`;\n overlayRoot.style.width = `${tableWidth}px`;\n return false;\n }\n\n /**\n * Reposition the overlay.\n */\n repositionOverlay() {\n const {\n wtTable,\n wtViewport\n } = this.wot;\n const {\n rootDocument\n } = this.domBindings;\n const cloneRoot = this.clone.wtTable.holder.parentNode;\n let bottomOffset = 0;\n if (!wtViewport.hasVerticalScroll()) {\n bottomOffset += wtViewport.getWorkspaceHeight() - wtTable.getTotalHeight();\n }\n if (wtViewport.hasVerticalScroll() && wtViewport.hasHorizontalScroll()) {\n bottomOffset += getScrollbarWidth(rootDocument);\n }\n cloneRoot.style.bottom = `${bottomOffset}px`;\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { addClass, getScrollbarWidth, getScrollTop, getWindowScrollLeft, hasClass, outerHeight, removeClass } from \"../../../../helpers/dom/element.mjs\";\nimport BottomOverlayTable from \"./../table/bottom.mjs\";\nimport { Overlay } from \"./_base.mjs\";\nimport { CLONE_BOTTOM } from \"./constants.mjs\";\n/**\n * @class BottomOverlay\n */\nexport class BottomOverlay extends Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n */\n constructor(wotInstance, facadeGetter, wtSettings, domBindings) {\n super(wotInstance, facadeGetter, CLONE_BOTTOM, wtSettings, domBindings);\n /**\n * Cached value which holds the previous value of the `fixedRowsBottom` option.\n * It is used as a comparison value that can be used to detect changes in that value.\n *\n * @type {number}\n */\n _defineProperty(this, \"cachedFixedRowsBottom\", -1);\n this.cachedFixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');\n }\n\n /**\n * Factory method to create a subclass of `Table` that is relevant to this overlay.\n *\n * @see Table#constructor\n * @param {...*} args Parameters that will be forwarded to the `Table` constructor.\n * @returns {BottomOverlayTable}\n */\n createTable() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new BottomOverlayTable(...args);\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return this.wtSettings.getSetting('shouldRenderBottomOverlay');\n }\n\n /**\n * Updates the top overlay position.\n *\n * @returns {boolean}\n */\n resetFixedPosition() {\n if (!this.needFullRender || !this.shouldBeRendered() || !this.wot.wtTable.holder.parentNode) {\n // removed from DOM\n return false;\n }\n const {\n rootWindow\n } = this.domBindings;\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n overlayRoot.style.top = '';\n let overlayPosition = 0;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'vertical')) {\n overlayPosition = this.getOverlayOffset();\n overlayRoot.style.bottom = `${overlayPosition}px`;\n } else {\n overlayPosition = this.getScrollPosition();\n this.repositionOverlay();\n }\n const positionChanged = this.adjustHeaderBordersPosition(overlayPosition);\n this.adjustElementsSize();\n return positionChanged;\n }\n\n /**\n * Updates the bottom overlay position.\n */\n repositionOverlay() {\n const {\n wtTable,\n wtViewport\n } = this.wot;\n const {\n rootDocument\n } = this.domBindings;\n const cloneRoot = this.clone.wtTable.holder.parentNode;\n let bottomOffset = 0;\n if (!wtViewport.hasVerticalScroll()) {\n bottomOffset += wtViewport.getWorkspaceHeight() - wtTable.getTotalHeight();\n }\n if (wtViewport.hasVerticalScroll() && wtViewport.hasHorizontalScroll()) {\n bottomOffset += getScrollbarWidth(rootDocument);\n }\n cloneRoot.style.bottom = `${bottomOffset}px`;\n }\n\n /**\n * Sets the main overlay's vertical scroll position.\n *\n * @param {number} pos The scroll position.\n * @returns {boolean}\n */\n setScrollPosition(pos) {\n const {\n rootWindow\n } = this.domBindings;\n let result = false;\n if (this.mainTableScrollableElement === rootWindow) {\n rootWindow.scrollTo(getWindowScrollLeft(rootWindow), pos);\n result = true;\n } else if (this.mainTableScrollableElement.scrollTop !== pos) {\n this.mainTableScrollableElement.scrollTop = pos;\n result = true;\n }\n return result;\n }\n\n /**\n * Triggers onScroll hook callback.\n */\n onScroll() {\n this.wtSettings.getSetting('onScrollHorizontally');\n }\n\n /**\n * Calculates total sum cells height.\n *\n * @param {number} from Row index which calculates started from.\n * @param {number} to Row index where calculation is finished.\n * @returns {number} Height sum.\n */\n sumCellSizes(from, to) {\n const {\n wtTable,\n wtSettings\n } = this.wot;\n const defaultRowHeight = wtSettings.getSetting('defaultRowHeight');\n let row = from;\n let sum = 0;\n while (row < to) {\n const height = wtTable.getRowHeight(row);\n sum += height === undefined ? defaultRowHeight : height;\n row += 1;\n }\n return sum;\n }\n\n /**\n * Adjust overlay root element, children and master table element sizes (width, height).\n */\n adjustElementsSize() {\n this.updateTrimmingContainer();\n if (this.needFullRender) {\n this.adjustRootElementSize();\n this.adjustRootChildrenSize();\n }\n }\n\n /**\n * Adjust overlay root element size (width and height).\n */\n adjustRootElementSize() {\n const {\n wtTable,\n wtViewport\n } = this.wot;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const scrollbarWidth = getScrollbarWidth(rootDocument);\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n const overlayRootStyle = overlayRoot.style;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (this.trimmingContainer !== rootWindow || preventOverflow === 'horizontal') {\n let width = wtViewport.getWorkspaceWidth();\n if (this.wot.wtOverlays.hasScrollbarRight) {\n width -= scrollbarWidth;\n }\n width = Math.min(width, wtTable.wtRootElement.scrollWidth);\n overlayRootStyle.width = `${width}px`;\n } else {\n overlayRootStyle.width = '';\n }\n this.clone.wtTable.holder.style.width = overlayRootStyle.width;\n let tableHeight = outerHeight(this.clone.wtTable.TABLE);\n if (!this.wot.wtTable.hasDefinedSize()) {\n tableHeight = 0;\n }\n overlayRootStyle.height = `${tableHeight}px`;\n }\n\n /**\n * Adjust overlay root childs size.\n */\n adjustRootChildrenSize() {\n const {\n holder\n } = this.clone.wtTable;\n this.clone.wtTable.hider.style.width = this.hider.style.width;\n holder.style.width = holder.parentNode.style.width;\n holder.style.height = holder.parentNode.style.height;\n }\n\n /**\n * Adjust the overlay dimensions and position.\n */\n applyToDOM() {\n const total = this.wtSettings.getSetting('totalRows');\n if (typeof this.wot.wtViewport.rowsRenderCalculator.startPosition === 'number') {\n this.spreader.style.top = `${this.wot.wtViewport.rowsRenderCalculator.startPosition}px`;\n } else if (total === 0) {\n // can happen if there are 0 rows\n this.spreader.style.top = '0';\n } else {\n throw new Error('Incorrect value of the rowsRenderCalculator');\n }\n this.spreader.style.bottom = '';\n if (this.needFullRender) {\n this.syncOverlayOffset();\n }\n }\n\n /**\n * Synchronize calculated left position to an element.\n */\n syncOverlayOffset() {\n const styleProperty = this.isRtl() ? 'right' : 'left';\n const {\n spreader\n } = this.clone.wtTable;\n if (typeof this.wot.wtViewport.columnsRenderCalculator.startPosition === 'number') {\n spreader.style[styleProperty] = `${this.wot.wtViewport.columnsRenderCalculator.startPosition}px`;\n } else {\n spreader.style[styleProperty] = '';\n }\n }\n\n /**\n * Scrolls vertically to a row.\n *\n * @param {number} sourceRow Row index which you want to scroll to.\n * @param {boolean} [bottomEdge=false] If `true`, scrolls according to the bottom edge (top edge is by default).\n */\n scrollTo(sourceRow, bottomEdge) {\n let newY = this.getTableParentOffset();\n const sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;\n const mainHolder = sourceInstance.wtTable.holder;\n let scrollbarCompensation = 0;\n if (bottomEdge && mainHolder.offsetHeight !== mainHolder.clientHeight) {\n scrollbarCompensation = getScrollbarWidth(this.domBindings.rootDocument);\n }\n if (bottomEdge) {\n newY += this.sumCellSizes(0, sourceRow + 1);\n newY -= this.wot.wtViewport.getViewportHeight();\n // Fix 1 pixel offset when cell is selected\n newY += 1;\n } else {\n newY += this.sumCellSizes(this.wtSettings.getSetting('fixedRowsBottom'), sourceRow);\n }\n newY += scrollbarCompensation;\n this.setScrollPosition(newY);\n }\n\n /**\n * Gets table parent top position.\n *\n * @returns {number}\n */\n getTableParentOffset() {\n if (this.mainTableScrollableElement === this.domBindings.rootWindow) {\n return this.wot.wtTable.holderOffset.top;\n }\n return 0;\n }\n\n /**\n * Gets the main overlay's vertical scroll position.\n *\n * @returns {number} Main table's vertical scroll position.\n */\n getScrollPosition() {\n return getScrollTop(this.mainTableScrollableElement, this.domBindings.rootWindow);\n }\n\n /**\n * Gets the main overlay's vertical overlay offset.\n *\n * @returns {number} Main table's vertical overlay offset.\n */\n getOverlayOffset() {\n const {\n rootWindow\n } = this.domBindings;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let overlayOffset = 0;\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'vertical')) {\n const rootHeight = this.wot.wtTable.getTotalHeight();\n const overlayRootHeight = this.clone.wtTable.getTotalHeight();\n const maxOffset = rootHeight - overlayRootHeight;\n const docClientHeight = this.domBindings.rootDocument.documentElement.clientHeight;\n overlayOffset = Math.max(this.getTableParentOffset() - this.getScrollPosition() - docClientHeight + rootHeight, 0);\n if (overlayOffset > maxOffset) {\n overlayOffset = 0;\n }\n }\n return overlayOffset;\n }\n\n /**\n * Adds css classes to hide the header border's header (cell-selection border hiding issue).\n *\n * @param {number} position Header Y position if trimming container is window or scroll top if not.\n * @returns {boolean}\n */\n adjustHeaderBordersPosition(position) {\n const fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');\n const areFixedRowsBottomChanged = this.cachedFixedRowsBottom !== fixedRowsBottom;\n const columnHeaders = this.wtSettings.getSetting('columnHeaders');\n let positionChanged = false;\n if ((areFixedRowsBottomChanged || fixedRowsBottom === 0) && columnHeaders.length > 0) {\n const masterParent = this.wot.wtTable.holder.parentNode;\n const previousState = hasClass(masterParent, 'innerBorderBottom');\n this.cachedFixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');\n if (position || this.wtSettings.getSetting('totalRows') === 0) {\n addClass(masterParent, 'innerBorderBottom');\n positionChanged = !previousState;\n } else {\n removeClass(masterParent, 'innerBorderBottom');\n positionChanged = previousState;\n }\n }\n return positionChanged;\n }\n}","import { defineGetter } from \"../../../../../helpers/object.mjs\";\nconst MIXIN_NAME = 'calculatedColumns';\n\n/**\n * Mixin for the subclasses of `Table` with implementations of\n * helper methods that are related to columns.\n * This mixin is meant to be applied in the subclasses of `Table`\n * that use virtual rendering in the horizontal axis.\n *\n * @type {object}\n */\nconst calculatedColumns = {\n /**\n * Get the source index of the first rendered column. If no columns are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstRenderedColumn() {\n const startColumn = this.dataAccessObject.startColumnRendered;\n if (startColumn === null) {\n return -1;\n }\n return startColumn;\n },\n /**\n * Get the source index of the first column fully visible in the viewport. If no columns are fully visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstVisibleColumn() {\n const startColumn = this.dataAccessObject.startColumnVisible;\n if (startColumn === null) {\n return -1;\n }\n return startColumn;\n },\n /**\n * Get the source index of the first column partially visible in the viewport. If no columns are partially visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstPartiallyVisibleColumn() {\n const startColumn = this.dataAccessObject.startColumnPartiallyVisible;\n if (startColumn === null) {\n return -1;\n }\n return startColumn;\n },\n /**\n * Get the source index of the last rendered column. If no columns are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastRenderedColumn() {\n const endColumn = this.dataAccessObject.endColumnRendered;\n if (endColumn === null) {\n return -1;\n }\n return endColumn;\n },\n /**\n * Get the source index of the last column fully visible in the viewport. If no columns are fully visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastVisibleColumn() {\n const endColumn = this.dataAccessObject.endColumnVisible;\n if (endColumn === null) {\n return -1;\n }\n return endColumn;\n },\n /**\n * Get the source index of the last column partially visible in the viewport. If no columns are partially visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastPartiallyVisibleColumn() {\n const endColumn = this.dataAccessObject.endColumnPartiallyVisible;\n if (endColumn === null) {\n return -1;\n }\n return endColumn;\n },\n /**\n * Get the number of rendered columns.\n *\n * @returns {number}\n * @this Table\n */\n getRenderedColumnsCount() {\n return this.dataAccessObject.countColumnsRendered;\n },\n /**\n * Get the number of fully visible columns in the viewport.\n *\n * @returns {number}\n * @this Table\n */\n getVisibleColumnsCount() {\n return this.dataAccessObject.countColumnsVisible;\n },\n /**\n * Get the number of rendered row headers.\n *\n * @returns {number}\n * @this Table\n */\n getRowHeadersCount() {\n return this.dataAccessObject.rowHeaders.length;\n }\n};\ndefineGetter(calculatedColumns, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default calculatedColumns;","import Table from \"../table.mjs\";\nimport stickyRowsBottom from \"./mixin/stickyRowsBottom.mjs\";\nimport calculatedColumns from \"./mixin/calculatedColumns.mjs\";\nimport { mixin } from \"../../../../helpers/object.mjs\";\nimport { CLONE_BOTTOM } from \"../overlay/index.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to BottomOverlay, implemented through mixins.\n *\n * @mixes stickyRowsBottom\n * @mixes calculatedColumns\n */\nclass BottomOverlayTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, CLONE_BOTTOM);\n }\n}\nmixin(BottomOverlayTable, stickyRowsBottom);\nmixin(BottomOverlayTable, calculatedColumns);\nexport default BottomOverlayTable;","import \"core-js/modules/es.error.cause.js\";\nimport { addClass, getScrollbarWidth, getScrollLeft, getMaximumScrollLeft, getWindowScrollTop, hasClass, outerWidth, removeClass, setOverlayPosition, resetCssTransform } from \"../../../../helpers/dom/element.mjs\";\nimport InlineStartOverlayTable from \"../table/inlineStart.mjs\";\nimport { Overlay } from \"./_base.mjs\";\nimport { CORNER_DEFAULT_STYLE } from \"../selection/index.mjs\";\nimport { CLONE_INLINE_START } from \"./constants.mjs\";\n/**\n * @class InlineStartOverlay\n */\nexport class InlineStartOverlay extends Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n */\n constructor(wotInstance, facadeGetter, wtSettings, domBindings) {\n super(wotInstance, facadeGetter, CLONE_INLINE_START, wtSettings, domBindings);\n }\n\n /**\n * Factory method to create a subclass of `Table` that is relevant to this overlay.\n *\n * @see Table#constructor\n * @param {...*} args Parameters that will be forwarded to the `Table` constructor.\n * @returns {InlineStartOverlayTable}\n */\n createTable() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new InlineStartOverlayTable(...args);\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return this.wtSettings.getSetting('shouldRenderInlineStartOverlay');\n }\n\n /**\n * Updates the left overlay position.\n *\n * @returns {boolean}\n */\n resetFixedPosition() {\n const {\n wtTable\n } = this.wot;\n if (!this.needFullRender || !this.shouldBeRendered() || !wtTable.holder.parentNode) {\n // removed from DOM\n return false;\n }\n const {\n rootWindow\n } = this.domBindings;\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let overlayPosition = 0;\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'horizontal')) {\n overlayPosition = this.getOverlayOffset() * (this.isRtl() ? -1 : 1);\n setOverlayPosition(overlayRoot, `${overlayPosition}px`, '0px');\n } else {\n overlayPosition = this.getScrollPosition();\n resetCssTransform(overlayRoot);\n }\n const positionChanged = this.adjustHeaderBordersPosition(overlayPosition);\n this.adjustElementsSize();\n return positionChanged;\n }\n\n /**\n * Sets the main overlay's horizontal scroll position.\n *\n * @param {number} pos The scroll position.\n * @returns {boolean}\n */\n setScrollPosition(pos) {\n const {\n rootWindow\n } = this.domBindings;\n let result = false;\n if (this.isRtl()) {\n pos = -pos;\n }\n if (this.mainTableScrollableElement === rootWindow && rootWindow.scrollX !== pos) {\n rootWindow.scrollTo(pos, getWindowScrollTop(rootWindow));\n result = true;\n } else if (this.mainTableScrollableElement.scrollLeft !== pos) {\n this.mainTableScrollableElement.scrollLeft = pos;\n result = true;\n }\n return result;\n }\n\n /**\n * Triggers onScroll hook callback.\n */\n onScroll() {\n this.wtSettings.getSetting('onScrollVertically');\n }\n\n /**\n * Calculates total sum cells width.\n *\n * @param {number} from Column index which calculates started from.\n * @param {number} to Column index where calculation is finished.\n * @returns {number} Width sum.\n */\n sumCellSizes(from, to) {\n const defaultColumnWidth = this.wtSettings.getSetting('defaultColumnWidth');\n let column = from;\n let sum = 0;\n while (column < to) {\n sum += this.wot.wtTable.getStretchedColumnWidth(column) || defaultColumnWidth;\n column += 1;\n }\n return sum;\n }\n\n /**\n * Adjust overlay root element, children and master table element sizes (width, height).\n */\n adjustElementsSize() {\n this.updateTrimmingContainer();\n if (this.needFullRender) {\n this.adjustRootElementSize();\n this.adjustRootChildrenSize();\n }\n }\n\n /**\n * Adjust overlay root element size (width and height).\n */\n adjustRootElementSize() {\n const {\n wtTable\n } = this.wot;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const scrollbarHeight = getScrollbarWidth(rootDocument);\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n const overlayRootStyle = overlayRoot.style;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (this.trimmingContainer !== rootWindow || preventOverflow === 'vertical') {\n let height = this.wot.wtViewport.getWorkspaceHeight();\n if (this.wot.wtOverlays.hasScrollbarBottom) {\n height -= scrollbarHeight;\n }\n height = Math.min(height, wtTable.wtRootElement.scrollHeight);\n overlayRootStyle.height = `${height}px`;\n } else {\n overlayRootStyle.height = '';\n }\n this.clone.wtTable.holder.style.height = overlayRootStyle.height;\n const tableWidth = outerWidth(this.clone.wtTable.TABLE);\n overlayRootStyle.width = `${tableWidth}px`;\n }\n\n /**\n * Adjust overlay root childs size.\n */\n adjustRootChildrenSize() {\n const {\n holder\n } = this.clone.wtTable;\n const selectionCornerOffset = this.wot.selectionManager.getFocusSelection() ? parseInt(CORNER_DEFAULT_STYLE.width, 10) / 2 : 0;\n this.clone.wtTable.hider.style.height = this.hider.style.height;\n holder.style.height = holder.parentNode.style.height;\n // Add selection corner protruding part to the holder total width to make sure that\n // borders' corner won't be cut after horizontal scroll (#6937).\n holder.style.width = `${parseInt(holder.parentNode.style.width, 10) + selectionCornerOffset}px`;\n }\n\n /**\n * Adjust the overlay dimensions and position.\n */\n applyToDOM() {\n const total = this.wtSettings.getSetting('totalColumns');\n const styleProperty = this.isRtl() ? 'right' : 'left';\n if (typeof this.wot.wtViewport.columnsRenderCalculator.startPosition === 'number') {\n this.spreader.style[styleProperty] = `${this.wot.wtViewport.columnsRenderCalculator.startPosition}px`;\n } else if (total === 0) {\n this.spreader.style[styleProperty] = '0';\n } else {\n throw new Error('Incorrect value of the columnsRenderCalculator');\n }\n if (this.isRtl()) {\n this.spreader.style.left = '';\n } else {\n this.spreader.style.right = '';\n }\n if (this.needFullRender) {\n this.syncOverlayOffset();\n }\n }\n\n /**\n * Synchronize calculated top position to an element.\n */\n syncOverlayOffset() {\n if (typeof this.wot.wtViewport.rowsRenderCalculator.startPosition === 'number') {\n this.clone.wtTable.spreader.style.top = `${this.wot.wtViewport.rowsRenderCalculator.startPosition}px`;\n } else {\n this.clone.wtTable.spreader.style.top = '';\n }\n }\n\n /**\n * Scrolls horizontally to a column at the left edge of the viewport.\n *\n * @param {number} sourceCol Column index which you want to scroll to.\n * @param {boolean} [beyondRendered] If `true`, scrolls according to the right\n * edge (left edge is by default).\n * @returns {boolean}\n */\n scrollTo(sourceCol, beyondRendered) {\n const {\n wtSettings\n } = this;\n const rowHeaders = wtSettings.getSetting('rowHeaders');\n const fixedColumnsStart = wtSettings.getSetting('fixedColumnsStart');\n const sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;\n const mainHolder = sourceInstance.wtTable.holder;\n const rowHeaderBorderCompensation = fixedColumnsStart === 0 && rowHeaders.length > 0 && !hasClass(mainHolder.parentNode, 'innerBorderInlineStart') ? 1 : 0;\n let newX = this.getTableParentOffset();\n let scrollbarCompensation = 0;\n if (beyondRendered) {\n const columnWidth = this.wot.wtTable.getColumnWidth(sourceCol);\n const viewportWidth = this.wot.wtViewport.getViewportWidth();\n if (columnWidth > viewportWidth) {\n beyondRendered = false;\n }\n }\n if (beyondRendered && mainHolder.offsetWidth !== mainHolder.clientWidth) {\n scrollbarCompensation = getScrollbarWidth(this.domBindings.rootDocument);\n }\n if (beyondRendered) {\n newX += this.sumCellSizes(0, sourceCol + 1);\n newX -= this.wot.wtViewport.getViewportWidth();\n // Compensate for the right header border if scrolled from the absolute left.\n newX += rowHeaderBorderCompensation;\n } else {\n newX += this.sumCellSizes(this.wtSettings.getSetting('fixedColumnsStart'), sourceCol);\n }\n newX += scrollbarCompensation;\n\n // If the table is scrolled all the way left when starting the scroll and going to be scrolled to the far right,\n // we need to compensate for the potential header border width.\n if (getMaximumScrollLeft(this.mainTableScrollableElement) === newX - rowHeaderBorderCompensation && rowHeaderBorderCompensation > 0) {\n this.wot.wtOverlays.expandHiderHorizontallyBy(rowHeaderBorderCompensation);\n }\n return this.setScrollPosition(newX);\n }\n\n /**\n * Gets table parent left position.\n *\n * @returns {number}\n */\n getTableParentOffset() {\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let offset = 0;\n if (!preventOverflow && this.trimmingContainer === this.domBindings.rootWindow) {\n offset = this.wot.wtTable.holderOffset.left;\n }\n return offset;\n }\n\n /**\n * Gets the main overlay's horizontal scroll position.\n *\n * @returns {number} Main table's horizontal scroll position.\n */\n getScrollPosition() {\n return Math.abs(getScrollLeft(this.mainTableScrollableElement, this.domBindings.rootWindow));\n }\n\n /**\n * Gets the main overlay's horizontal overlay offset.\n *\n * @returns {number} Main table's horizontal overlay offset.\n */\n getOverlayOffset() {\n const {\n rootWindow\n } = this.domBindings;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let overlayOffset = 0;\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'horizontal')) {\n if (this.isRtl()) {\n overlayOffset = Math.abs(Math.min(this.getTableParentOffset() - this.getScrollPosition(), 0));\n } else {\n overlayOffset = Math.max(this.getScrollPosition() - this.getTableParentOffset(), 0);\n }\n const rootWidth = this.wot.wtTable.getTotalWidth();\n const overlayRootWidth = this.clone.wtTable.getTotalWidth();\n const maxOffset = rootWidth - overlayRootWidth;\n if (overlayOffset > maxOffset) {\n overlayOffset = 0;\n }\n }\n return overlayOffset;\n }\n\n /**\n * Adds css classes to hide the header border's header (cell-selection border hiding issue).\n *\n * @param {number} position Header X position if trimming container is window or scroll top if not.\n * @returns {boolean}\n */\n adjustHeaderBordersPosition(position) {\n const {\n wtSettings\n } = this;\n const masterParent = this.wot.wtTable.holder.parentNode;\n const rowHeaders = wtSettings.getSetting('rowHeaders');\n const fixedColumnsStart = wtSettings.getSetting('fixedColumnsStart');\n const totalRows = wtSettings.getSetting('totalRows');\n const preventVerticalOverflow = wtSettings.getSetting('preventOverflow') === 'vertical';\n if (totalRows) {\n removeClass(masterParent, 'emptyRows');\n } else {\n addClass(masterParent, 'emptyRows');\n }\n let positionChanged = false;\n if (!preventVerticalOverflow) {\n if (fixedColumnsStart && !rowHeaders.length) {\n // \"innerBorderLeft\" is for backward compatibility\n addClass(masterParent, 'innerBorderLeft innerBorderInlineStart');\n } else if (!fixedColumnsStart && rowHeaders.length) {\n const previousState = hasClass(masterParent, 'innerBorderInlineStart');\n if (position) {\n addClass(masterParent, 'innerBorderLeft innerBorderInlineStart');\n positionChanged = !previousState;\n } else {\n removeClass(masterParent, 'innerBorderLeft innerBorderInlineStart');\n positionChanged = previousState;\n }\n }\n }\n return positionChanged;\n }\n}","import { defineGetter } from \"../../../../../helpers/object.mjs\";\nconst MIXIN_NAME = 'calculatedRows';\n\n/**\n * Mixin for the subclasses of `Table` with implementations of\n * helper methods that are related to rows.\n * This mixin is meant to be applied in the subclasses of `Table`\n * that use virtual rendering in the vertical axis.\n *\n * @type {object}\n */\nconst calculatedRows = {\n /**\n * Get the source index of the first rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstRenderedRow() {\n const startRow = this.dataAccessObject.startRowRendered;\n if (startRow === null) {\n return -1;\n }\n return startRow;\n },\n /**\n * Get the source index of the first row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstVisibleRow() {\n const startRow = this.dataAccessObject.startRowVisible;\n if (startRow === null) {\n return -1;\n }\n return startRow;\n },\n /**\n * Get the source index of the first row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstPartiallyVisibleRow() {\n const startRow = this.dataAccessObject.startRowPartiallyVisible;\n if (startRow === null) {\n return -1;\n }\n return startRow;\n },\n /**\n * Get the source index of the last rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastRenderedRow() {\n const endRow = this.dataAccessObject.endRowRendered;\n if (endRow === null) {\n return -1;\n }\n return endRow;\n },\n /**\n * Get the source index of the last row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastVisibleRow() {\n const endRow = this.dataAccessObject.endRowVisible;\n if (endRow === null) {\n return -1;\n }\n return endRow;\n },\n /**\n * Get the source index of the last row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastPartiallyVisibleRow() {\n const endRow = this.dataAccessObject.endRowPartiallyVisible;\n if (endRow === null) {\n return -1;\n }\n return endRow;\n },\n /**\n * Get the number of rendered rows.\n *\n * @returns {number}\n * @this Table\n */\n getRenderedRowsCount() {\n return this.dataAccessObject.countRowsRendered;\n },\n /**\n * Get the number of fully visible rows in the viewport.\n *\n * @returns {number}\n * @this Table\n */\n getVisibleRowsCount() {\n return this.dataAccessObject.countRowsVisible;\n },\n /**\n * Get the number of rendered column headers.\n *\n * @returns {number}\n * @this Table\n */\n getColumnHeadersCount() {\n return this.dataAccessObject.columnHeaders.length;\n }\n};\ndefineGetter(calculatedRows, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default calculatedRows;","import Table from \"../table.mjs\";\nimport calculatedRows from \"./mixin/calculatedRows.mjs\";\nimport stickyColumnsStart from \"./mixin/stickyColumnsStart.mjs\";\nimport { mixin } from \"../../../../helpers/object.mjs\";\nimport { CLONE_INLINE_START } from \"../overlay/index.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to InlineStartOverlayTable, implemented through mixins.\n */\nclass InlineStartOverlayTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, CLONE_INLINE_START);\n }\n}\nmixin(InlineStartOverlayTable, calculatedRows);\nmixin(InlineStartOverlayTable, stickyColumnsStart);\nexport default InlineStartOverlayTable;","import \"core-js/modules/es.array.push.js\";\nimport { defineGetter } from \"./../helpers/object.mjs\";\nimport { fastCall } from \"./../helpers/function.mjs\";\nconst MIXIN_NAME = 'localHooks';\n\n/**\n * Mixin object to extend objects functionality for local hooks.\n *\n * @type {object}\n */\nconst localHooks = {\n /**\n * Internal hooks storage.\n */\n _localHooks: Object.create(null),\n /**\n * Add hook to the collection.\n *\n * @param {string} key The hook name.\n * @param {Function} callback The hook callback.\n * @returns {object}\n */\n addLocalHook(key, callback) {\n if (!this._localHooks[key]) {\n this._localHooks[key] = [];\n }\n this._localHooks[key].push(callback);\n return this;\n },\n /**\n * Run hooks.\n *\n * @param {string} key The name of the hook to run.\n * @param {*} [arg1] An additional parameter passed to the callback function.\n * @param {*} [arg2] An additional parameter passed to the callback function.\n * @param {*} [arg3] An additional parameter passed to the callback function.\n * @param {*} [arg4] An additional parameter passed to the callback function.\n * @param {*} [arg5] An additional parameter passed to the callback function.\n * @param {*} [arg6] An additional parameter passed to the callback function.\n */\n runLocalHooks(key, arg1, arg2, arg3, arg4, arg5, arg6) {\n if (this._localHooks[key]) {\n const length = this._localHooks[key].length;\n\n // don't optimize this loop with the `arrayEach()` method or arrow functions\n // otherwise, performance will decrease because of garbage collection\n // using the `...rest` syntax (ES6 and later) will decrease performance as well\n for (let i = 0; i < length; i++) {\n fastCall(this._localHooks[key][i], this, arg1, arg2, arg3, arg4, arg5, arg6);\n }\n }\n },\n /**\n * Clear all added hooks.\n *\n * @returns {object}\n */\n clearLocalHooks() {\n this._localHooks = {};\n return this;\n }\n};\ndefineGetter(localHooks, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default localHooks;","import { mixin } from \"../../../../helpers/object.mjs\";\nimport localHooks from \"../../../../mixins/localHooks.mjs\";\n/**\n * The Selection class allows highlighting (by applying CSS class) the table's cells or headers\n * and setting up the borders if defined in the settings.\n *\n * The Selection coordinates may point to the cells (positive numbers) or headers (negative numbers).\n *\n * @class Selection\n */\nclass Selection {\n /**\n * @param {object} settings The selection settings object. @todo type.\n * @param {CellRange} cellRange The cell range instance.\n */\n constructor(settings, cellRange) {\n this.settings = settings;\n this.cellRange = cellRange || null;\n }\n\n /**\n * Checks if selection is empty.\n *\n * @returns {boolean}\n */\n isEmpty() {\n return this.cellRange === null;\n }\n\n /**\n * Adds a cell coords to the selection.\n *\n * @param {CellCoords} coords The cell coordinates to add.\n * @returns {Selection}\n */\n add(coords) {\n if (this.isEmpty()) {\n this.cellRange = this.settings.createCellRange(coords);\n } else {\n this.cellRange.expand(coords);\n }\n return this;\n }\n\n /**\n * If selection range from or to property equals oldCoords, replace it with newCoords. Return boolean\n * information about success.\n *\n * @param {CellCoords} oldCoords An old cell coordinates to replace.\n * @param {CellCoords} newCoords The new cell coordinates.\n * @returns {boolean}\n */\n replace(oldCoords, newCoords) {\n if (!this.isEmpty()) {\n if (this.cellRange.from.isEqual(oldCoords)) {\n this.cellRange.from = newCoords;\n return true;\n }\n if (this.cellRange.to.isEqual(oldCoords)) {\n this.cellRange.to = newCoords;\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clears selection.\n *\n * @returns {Selection}\n */\n clear() {\n this.cellRange = null;\n return this;\n }\n\n /**\n * Returns the top left (or top right in RTL) and bottom right (or bottom left in RTL) selection coordinates.\n *\n * @returns {number[]} Returns array of coordinates for example `[1, 1, 5, 5]`.\n */\n getCorners() {\n const topStart = this.cellRange.getOuterTopStartCorner();\n const bottomEnd = this.cellRange.getOuterBottomEndCorner();\n return [topStart.row, topStart.col, bottomEnd.row, bottomEnd.col];\n }\n\n /**\n * Destroys the instance.\n */\n destroy() {\n this.runLocalHooks('destroy');\n }\n}\nmixin(Selection, localHooks);\nexport default Selection;","/**\n * Selection type that is visible only if the row or column header is clicked. If that happened\n * all row or column header layers are highlighted.\n *\n * @type {string}\n */\nexport const ACTIVE_HEADER_TYPE = 'active-header';\n/**\n * Selection type that is visible only if the a cell or cells are clicked. If that happened\n * only the most closest to the cells row or column header is highlighted.\n *\n * @type {string}\n */\nexport const HEADER_TYPE = 'header';\n/**\n * Selection type that is visible when a cell or cells are clicked. The selected cells are\n * highlighted.\n *\n * @type {string}\n */\nexport const AREA_TYPE = 'area';\n/**\n * Selection type defines a cell that follows the user (keyboard navigation).\n *\n * @type {string}\n */\nexport const FOCUS_TYPE = 'focus';\n/**\n * Selection type defines borders for the autofill functionality.\n *\n * @type {string}\n */\nexport const FILL_TYPE = 'fill';\n/**\n * Selection type defines highlights for the `currentRowClassName` option.\n *\n * @type {string}\n */\nexport const ROW_TYPE = 'row';\n/**\n * Selection type defines highlights for the `currentColumnClassName` option.\n *\n * @type {string}\n */\nexport const COLUMN_TYPE = 'column';\n/**\n * Selection type defines highlights managed by the CustomBorders plugin.\n *\n * @type {string}\n */\nexport const CUSTOM_SELECTION_TYPE = 'custom-selection';","/**\n * Default border corner style.\n *\n * @type {object}\n */\nexport const CORNER_DEFAULT_STYLE = Object.freeze({\n width: '6px',\n height: '6px',\n borderWidth: '1px',\n borderStyle: 'solid',\n borderColor: '#FFF'\n});","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/es.array.unscopables.flat.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { removeClass, addClass, setAttribute, removeAttribute } from \"../../../../helpers/dom/element.mjs\";\nimport { SelectionScanner } from \"./scanner.mjs\";\nimport Border from \"./border/border.mjs\";\n/**\n * Module responsible for rendering selections (CSS classes) and borders based on the\n * collection of the Selection instances provided throughout the `selections` Walkontable\n * setting.\n *\n * @private\n */\nvar _activeOverlaysWot = /*#__PURE__*/new WeakMap();\nvar _selections = /*#__PURE__*/new WeakMap();\nvar _scanner = /*#__PURE__*/new WeakMap();\nvar _appliedClasses = /*#__PURE__*/new WeakMap();\nvar _destroyListeners = /*#__PURE__*/new WeakMap();\nvar _selectionBorders = /*#__PURE__*/new WeakMap();\nvar _SelectionManager_brand = /*#__PURE__*/new WeakSet();\nexport class SelectionManager {\n constructor(selections) {\n /**\n * Resets the elements to their initial state (remove the CSS classes that are added in the\n * previous render cycle).\n */\n _classPrivateMethodInitSpec(this, _SelectionManager_brand);\n /**\n * The overlay's Walkontable instance that are currently processed.\n *\n * @type {Walkontable}\n */\n _classPrivateFieldInitSpec(this, _activeOverlaysWot, void 0);\n /**\n * The Highlight instance that holds Selections instances within it.\n *\n * @type {Highlight|null}\n */\n _classPrivateFieldInitSpec(this, _selections, void 0);\n /**\n * The SelectionScanner allows to scan and collect the cell and header elements that matches\n * to the coords defined in the selections.\n *\n * @type {SelectionScanner}\n */\n _classPrivateFieldInitSpec(this, _scanner, new SelectionScanner());\n /**\n * The Map tracks applied CSS classes. It's used to reset the elements state to their initial state.\n *\n * @type {WeakMap}\n */\n _classPrivateFieldInitSpec(this, _appliedClasses, new WeakMap());\n /**\n * The Map tracks applied \"destroy\" listeners for Selection instances.\n *\n * @type {WeakMap}\n */\n _classPrivateFieldInitSpec(this, _destroyListeners, new WeakSet());\n /**\n * The Map holds references to Border classes for Selection instances which requires that when\n * the \"border\" setting is defined.\n *\n * @type {Map}\n */\n _classPrivateFieldInitSpec(this, _selectionBorders, new Map());\n _classPrivateFieldSet(_selections, this, selections);\n }\n\n /**\n * Sets the active Walkontable instance.\n *\n * @param {Walkontable} activeWot The overlays or master Walkontable instance.\n * @returns {SelectionManager}\n */\n setActiveOverlay(activeWot) {\n _classPrivateFieldSet(_activeOverlaysWot, this, activeWot);\n _classPrivateFieldGet(_scanner, this).setActiveOverlay(_classPrivateFieldGet(_activeOverlaysWot, this));\n if (!_classPrivateFieldGet(_appliedClasses, this).has(_classPrivateFieldGet(_activeOverlaysWot, this))) {\n _classPrivateFieldGet(_appliedClasses, this).set(_classPrivateFieldGet(_activeOverlaysWot, this), new Set());\n }\n return this;\n }\n\n /**\n * Gets the Selection instance of the \"focus\" type.\n *\n * @returns {Selection|null}\n */\n getFocusSelection() {\n return _classPrivateFieldGet(_selections, this) !== null ? _classPrivateFieldGet(_selections, this).getFocus() : null;\n }\n\n /**\n * Gets the Selection instance of the \"area\" type.\n *\n * @returns {Selection|null}\n */\n getAreaSelection() {\n return _classPrivateFieldGet(_selections, this) !== null ? _classPrivateFieldGet(_selections, this).createLayeredArea() : null;\n }\n\n /**\n * Gets the Border instance associated with Selection instance.\n *\n * @param {Selection} selection The selection instance.\n * @returns {Border|null} Returns the Border instance (new for each overlay Walkontable instance).\n */\n getBorderInstance(selection) {\n if (!selection.settings.border) {\n return null;\n }\n if (_classPrivateFieldGet(_selectionBorders, this).has(selection)) {\n const borders = _classPrivateFieldGet(_selectionBorders, this).get(selection);\n if (borders.has(_classPrivateFieldGet(_activeOverlaysWot, this))) {\n return borders.get(_classPrivateFieldGet(_activeOverlaysWot, this));\n }\n const border = new Border(_classPrivateFieldGet(_activeOverlaysWot, this), selection.settings);\n borders.set(_classPrivateFieldGet(_activeOverlaysWot, this), border);\n return border;\n }\n const border = new Border(_classPrivateFieldGet(_activeOverlaysWot, this), selection.settings);\n _classPrivateFieldGet(_selectionBorders, this).set(selection, new Map([[_classPrivateFieldGet(_activeOverlaysWot, this), border]]));\n return border;\n }\n\n /**\n * Gets all Border instances associated with Selection instance for all overlays.\n *\n * @param {Selection} selection The selection instance.\n * @returns {Border[]}\n */\n getBorderInstances(selection) {\n var _classPrivateFieldGet2, _classPrivateFieldGet3;\n return Array.from((_classPrivateFieldGet2 = (_classPrivateFieldGet3 = _classPrivateFieldGet(_selectionBorders, this).get(selection)) === null || _classPrivateFieldGet3 === void 0 ? void 0 : _classPrivateFieldGet3.values()) !== null && _classPrivateFieldGet2 !== void 0 ? _classPrivateFieldGet2 : []);\n }\n\n /**\n * Destroys the Border instance associated with Selection instance.\n *\n * @param {Selection} selection The selection instance.\n */\n destroyBorders(selection) {\n _classPrivateFieldGet(_selectionBorders, this).get(selection).forEach(border => border.destroy());\n _classPrivateFieldGet(_selectionBorders, this).delete(selection);\n }\n\n /**\n * Renders all the selections (add CSS classes to cells and draw borders).\n *\n * @param {boolean} fastDraw Indicates the render cycle type (fast/slow).\n */\n render(fastDraw) {\n if (_classPrivateFieldGet(_selections, this) === null) {\n return;\n }\n if (fastDraw) {\n // there was no rerender, so we need to remove classNames by ourselves\n _assertClassBrand(_SelectionManager_brand, this, _resetCells).call(this);\n }\n const selections = Array.from(_classPrivateFieldGet(_selections, this));\n const classNamesMap = new Map();\n const headerAttributesMap = new Map();\n for (let i = 0; i < selections.length; i++) {\n const selection = selections[i];\n const {\n className,\n headerAttributes,\n createLayers,\n selectionType\n } = selection.settings;\n if (!_classPrivateFieldGet(_destroyListeners, this).has(selection)) {\n _classPrivateFieldGet(_destroyListeners, this).add(selection);\n selection.addLocalHook('destroy', () => this.destroyBorders(selection));\n }\n const borderInstance = this.getBorderInstance(selection);\n if (selection.isEmpty()) {\n borderInstance === null || borderInstance === void 0 || borderInstance.disappear();\n continue; // eslint-disable-line no-continue\n }\n if (className) {\n const elements = _classPrivateFieldGet(_scanner, this).setActiveSelection(selection).scan();\n elements.forEach(element => {\n if (classNamesMap.has(element)) {\n const classNamesLayers = classNamesMap.get(element);\n if (classNamesLayers.has(className) && createLayers === true) {\n classNamesLayers.set(className, classNamesLayers.get(className) + 1);\n } else {\n classNamesLayers.set(className, 1);\n }\n } else {\n classNamesMap.set(element, new Map([[className, 1]]));\n }\n if (headerAttributes) {\n if (!headerAttributesMap.has(element)) {\n headerAttributesMap.set(element, []);\n }\n if (element.nodeName === 'TH') {\n headerAttributesMap.get(element).push(...headerAttributes);\n }\n }\n });\n }\n const corners = selection.getCorners();\n _classPrivateFieldGet(_activeOverlaysWot, this).getSetting('onBeforeDrawBorders', corners, selectionType);\n borderInstance === null || borderInstance === void 0 || borderInstance.appear(corners);\n }\n classNamesMap.forEach((classNamesLayers, element) => {\n var _classPrivateFieldGet4;\n const classNames = Array.from(classNamesLayers).map(_ref => {\n let [className, occurrenceCount] = _ref;\n if (occurrenceCount === 1) {\n return className;\n }\n return [className, ...Array.from({\n length: occurrenceCount - 1\n }, (_, i) => `${className}-${i + 1}`)];\n }).flat();\n classNames.forEach(className => _classPrivateFieldGet(_appliedClasses, this).get(_classPrivateFieldGet(_activeOverlaysWot, this)).add(className));\n addClass(element, classNames);\n if (element.nodeName === 'TD' && Array.isArray((_classPrivateFieldGet4 = _classPrivateFieldGet(_selections, this).options) === null || _classPrivateFieldGet4 === void 0 ? void 0 : _classPrivateFieldGet4.cellAttributes)) {\n setAttribute(element, _classPrivateFieldGet(_selections, this).options.cellAttributes);\n }\n });\n\n // Set the attributes for the headers if they're focused.\n Array.from(headerAttributesMap.keys()).forEach(element => {\n setAttribute(element, [...headerAttributesMap.get(element)]);\n });\n }\n}\nfunction _resetCells() {\n const appliedOverlaysClasses = _classPrivateFieldGet(_appliedClasses, this).get(_classPrivateFieldGet(_activeOverlaysWot, this));\n const classesToRemove = _classPrivateFieldGet(_activeOverlaysWot, this).wtSettings.getSetting('onBeforeRemoveCellClassNames');\n if (Array.isArray(classesToRemove)) {\n for (let i = 0; i < classesToRemove.length; i++) {\n appliedOverlaysClasses.add(classesToRemove[i]);\n }\n }\n appliedOverlaysClasses.forEach(className => {\n var _classPrivateFieldGet5, _classPrivateFieldGet6;\n const nodes = _classPrivateFieldGet(_activeOverlaysWot, this).wtTable.TABLE.querySelectorAll(`.${className}`);\n let cellAttributes = [];\n if (Array.isArray((_classPrivateFieldGet5 = _classPrivateFieldGet(_selections, this).options) === null || _classPrivateFieldGet5 === void 0 ? void 0 : _classPrivateFieldGet5.cellAttributes)) {\n cellAttributes = _classPrivateFieldGet(_selections, this).options.cellAttributes.map(el => el[0]);\n }\n if (Array.isArray((_classPrivateFieldGet6 = _classPrivateFieldGet(_selections, this).options) === null || _classPrivateFieldGet6 === void 0 ? void 0 : _classPrivateFieldGet6.headerAttributes)) {\n cellAttributes = [...cellAttributes, ..._classPrivateFieldGet(_selections, this).options.headerAttributes.map(el => el[0])];\n }\n for (let i = 0, len = nodes.length; i < len; i++) {\n removeClass(nodes[i], className);\n removeAttribute(nodes[i], cellAttributes);\n }\n });\n appliedOverlaysClasses.clear();\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\n/* eslint-disable no-continue */\nimport { addClass } from \"../../../../helpers/dom/element.mjs\";\n/**\n * Selection scanner module scans the rendered cells and headers and if it finds an intersection with\n * the coordinates of the Selection class (highlight) it returns the DOM elements.\n *\n * @private\n */\nvar _selection = /*#__PURE__*/new WeakMap();\nvar _activeOverlaysWot = /*#__PURE__*/new WeakMap();\nvar _SelectionScanner_brand = /*#__PURE__*/new WeakSet();\nexport class SelectionScanner {\n constructor() {\n /**\n * The method triggers a callback for each rendered cell.\n *\n * @param {function(number, number): void} callback The callback function to trigger.\n */\n _classPrivateMethodInitSpec(this, _SelectionScanner_brand);\n /**\n * Active Selection instance to process.\n *\n * @type {Selection}\n */\n _classPrivateFieldInitSpec(this, _selection, void 0);\n /**\n * The Walkontable instance that the scans depends on.\n *\n * @type {Walkontable}\n */\n _classPrivateFieldInitSpec(this, _activeOverlaysWot, void 0);\n }\n /**\n * Sets the Walkontable instance that will be taking into account while scanning the table.\n *\n * @param {Walkontable} activeOverlaysWot The Walkontable instance.\n * @returns {SelectionScanner}\n */\n setActiveOverlay(activeOverlaysWot) {\n _classPrivateFieldSet(_activeOverlaysWot, this, activeOverlaysWot);\n return this;\n }\n\n /**\n * Sets the Selection instance to process.\n *\n * @param {Selection} selection The Selection instance.\n * @returns {SelectionScanner}\n */\n setActiveSelection(selection) {\n _classPrivateFieldSet(_selection, this, selection);\n return this;\n }\n\n /**\n * Scans the rendered table with selection and returns elements that intersects\n * with selection coordinates.\n *\n * @returns {HTMLTableElement[]}\n */\n scan() {\n const selectionType = _classPrivateFieldGet(_selection, this).settings.selectionType;\n const elements = new Set();\n\n // TODO(improvement): use heuristics from coords to detect what type of scan\n // the Selection needs instead of using `selectionType` property.\n if (selectionType === 'active-header') {\n this.scanColumnsInHeadersRange(element => elements.add(element));\n this.scanRowsInHeadersRange(element => elements.add(element));\n } else if (selectionType === 'area') {\n this.scanCellsRange(element => elements.add(element));\n } else if (selectionType === 'focus') {\n this.scanColumnsInHeadersRange(element => elements.add(element));\n this.scanRowsInHeadersRange(element => elements.add(element));\n this.scanCellsRange(element => elements.add(element));\n } else if (selectionType === 'fill') {\n this.scanCellsRange(element => elements.add(element));\n } else if (selectionType === 'header') {\n this.scanColumnsInHeadersRange(element => elements.add(element));\n this.scanRowsInHeadersRange(element => elements.add(element));\n } else if (selectionType === 'row') {\n this.scanRowsInHeadersRange(element => elements.add(element));\n this.scanRowsInCellsRange(element => elements.add(element));\n } else if (selectionType === 'column') {\n this.scanColumnsInHeadersRange(element => elements.add(element));\n this.scanColumnsInCellsRange(element => elements.add(element));\n }\n return elements;\n }\n\n /**\n * Scans the table (only rendered headers) and collect all column headers (TH) that match\n * the coordinates passed in the Selection instance.\n *\n * @param {function(HTMLTableElement): void} callback The callback function to trigger.\n */\n scanColumnsInHeadersRange(callback) {\n const [topRow, topColumn, bottomRow, bottomColumn] = _classPrivateFieldGet(_selection, this).getCorners();\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n const renderedColumnsCount = wtTable.getRenderedColumnsCount();\n const columnHeadersCount = wtTable.getColumnHeadersCount();\n let cursor = 0;\n for (let column = -wtTable.getRowHeadersCount(); column < renderedColumnsCount; column++) {\n const sourceColumn = wtTable.columnFilter.renderedToSource(column);\n if (sourceColumn < topColumn || sourceColumn > bottomColumn) {\n continue;\n }\n for (let headerLevel = -columnHeadersCount; headerLevel < 0; headerLevel++) {\n if (headerLevel < topRow || headerLevel > bottomRow) {\n continue;\n }\n const positiveBasedHeaderLevel = headerLevel + columnHeadersCount;\n let TH = wtTable.getColumnHeader(sourceColumn, positiveBasedHeaderLevel);\n const newSourceCol = _classPrivateFieldGet(_activeOverlaysWot, this).getSetting('onBeforeHighlightingColumnHeader', sourceColumn, positiveBasedHeaderLevel, {\n selectionType: _classPrivateFieldGet(_selection, this).settings.selectionType,\n columnCursor: cursor,\n selectionWidth: bottomColumn - topColumn + 1\n });\n if (newSourceCol === null) {\n continue;\n }\n if (newSourceCol !== sourceColumn) {\n TH = wtTable.getColumnHeader(newSourceCol, positiveBasedHeaderLevel);\n }\n callback(TH);\n }\n cursor += 1;\n }\n }\n\n /**\n * Scans the table (only rendered headers) and collect all row headers (TH) that match\n * the coordinates passed in the Selection instance.\n *\n * @param {function(HTMLTableElement): void} callback The callback function to trigger.\n */\n scanRowsInHeadersRange(callback) {\n const [topRow, topColumn, bottomRow, bottomColumn] = _classPrivateFieldGet(_selection, this).getCorners();\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n const renderedRowsCount = wtTable.getRenderedRowsCount();\n const rowHeadersCount = wtTable.getRowHeadersCount();\n let cursor = 0;\n for (let row = -wtTable.getColumnHeadersCount(); row < renderedRowsCount; row++) {\n const sourceRow = wtTable.rowFilter.renderedToSource(row);\n if (sourceRow < topRow || sourceRow > bottomRow) {\n continue;\n }\n for (let headerLevel = -rowHeadersCount; headerLevel < 0; headerLevel++) {\n if (headerLevel < topColumn || headerLevel > bottomColumn) {\n continue;\n }\n const positiveBasedHeaderLevel = headerLevel + rowHeadersCount;\n let TH = wtTable.getRowHeader(sourceRow, positiveBasedHeaderLevel);\n const newSourceRow = _classPrivateFieldGet(_activeOverlaysWot, this).getSetting('onBeforeHighlightingRowHeader', sourceRow, positiveBasedHeaderLevel, {\n selectionType: _classPrivateFieldGet(_selection, this).settings.selectionType,\n rowCursor: cursor,\n selectionHeight: bottomRow - topRow + 1\n });\n if (newSourceRow === null) {\n continue;\n }\n if (newSourceRow !== sourceRow) {\n TH = wtTable.getRowHeader(newSourceRow, positiveBasedHeaderLevel);\n }\n callback(TH);\n }\n cursor += 1;\n }\n }\n\n /**\n * Scans the table (only rendered cells) and collect all cells (TR) that match\n * the coordinates passed in the Selection instance.\n *\n * @param {function(HTMLTableElement): void} callback The callback function to trigger.\n */\n scanCellsRange(callback) {\n const [topRow, topColumn, bottomRow, bottomColumn] = _classPrivateFieldGet(_selection, this).getCorners();\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n _assertClassBrand(_SelectionScanner_brand, this, _scanCellsRange).call(this, (sourceRow, sourceColumn) => {\n if (sourceRow >= topRow && sourceRow <= bottomRow && sourceColumn >= topColumn && sourceColumn <= bottomColumn) {\n const cell = wtTable.getCell(_classPrivateFieldGet(_activeOverlaysWot, this).createCellCoords(sourceRow, sourceColumn));\n\n // support for old API\n const additionalSelectionClass = _classPrivateFieldGet(_activeOverlaysWot, this).getSetting('onAfterDrawSelection', sourceRow, sourceColumn, _classPrivateFieldGet(_selection, this).settings.layerLevel);\n if (typeof additionalSelectionClass === 'string') {\n addClass(cell, additionalSelectionClass);\n }\n callback(cell);\n }\n });\n }\n\n /**\n * Scans the table (only rendered cells) and collects all cells (TR) that match the coordinates\n * passed in the Selection instance but only for the X axis (rows).\n *\n * @param {function(HTMLTableElement): void} callback The callback function to trigger.\n */\n scanRowsInCellsRange(callback) {\n // eslint-disable-next-line comma-spacing\n const [topRow,, bottomRow] = _classPrivateFieldGet(_selection, this).getCorners();\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n _assertClassBrand(_SelectionScanner_brand, this, _scanCellsRange).call(this, (sourceRow, sourceColumn) => {\n if (sourceRow >= topRow && sourceRow <= bottomRow) {\n const cell = wtTable.getCell(_classPrivateFieldGet(_activeOverlaysWot, this).createCellCoords(sourceRow, sourceColumn));\n callback(cell);\n }\n });\n }\n\n /**\n * Scans the table (only rendered cells) and collects all cells (TR) that match the coordinates\n * passed in the Selection instance but only for the Y axis (columns).\n *\n * @param {function(HTMLTableElement): void} callback The callback function to trigger.\n */\n scanColumnsInCellsRange(callback) {\n const [, topColumn,, bottomColumn] = _classPrivateFieldGet(_selection, this).getCorners();\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n _assertClassBrand(_SelectionScanner_brand, this, _scanCellsRange).call(this, (sourceRow, sourceColumn) => {\n if (sourceColumn >= topColumn && sourceColumn <= bottomColumn) {\n const cell = wtTable.getCell(_classPrivateFieldGet(_activeOverlaysWot, this).createCellCoords(sourceRow, sourceColumn));\n callback(cell);\n }\n });\n }\n}\nfunction _scanCellsRange(callback) {\n const {\n wtTable\n } = _classPrivateFieldGet(_activeOverlaysWot, this);\n const renderedRowsCount = wtTable.getRenderedRowsCount();\n const renderedColumnsCount = wtTable.getRenderedColumnsCount();\n for (let row = 0; row < renderedRowsCount; row += 1) {\n const sourceRow = wtTable.rowFilter.renderedToSource(row);\n for (let column = 0; column < renderedColumnsCount; column += 1) {\n callback(sourceRow, wtTable.columnFilter.renderedToSource(column));\n }\n }\n}","import { addClass, hasClass, removeClass, getComputedStyle, getTrimmingContainer, innerWidth, innerHeight, offset, outerHeight, outerWidth } from \"../../../../../helpers/dom/element.mjs\";\nimport { stopImmediatePropagation } from \"../../../../../helpers/dom/event.mjs\";\nimport { objectEach } from \"../../../../../helpers/object.mjs\";\nimport { isMobileBrowser } from \"../../../../../helpers/browser.mjs\";\nimport { CORNER_DEFAULT_STYLE } from \"./constants.mjs\";\n/**\n *\n */\nclass Border {\n // TODO As this is an internal class, should be designed for using {Walkontable}. It uses the facade,\n // TODO Con. Because the class is created on place where the instance reference comes from external origin.\n // TODO Imho, the discrimination for handling both, facade and non-facade should be handled.\n /**\n * @param {WalkontableFacade} wotInstance The Walkontable instance.\n * @param {object} settings The border settings.\n */\n constructor(wotInstance, settings) {\n if (!settings) {\n return;\n }\n this.eventManager = wotInstance.eventManager;\n this.instance = wotInstance;\n this.wot = wotInstance;\n this.settings = settings;\n this.mouseDown = false;\n this.main = null;\n this.top = null;\n this.bottom = null;\n this.start = null;\n this.end = null;\n this.topStyle = null;\n this.bottomStyle = null;\n this.startStyle = null;\n this.endStyle = null;\n this.cornerDefaultStyle = CORNER_DEFAULT_STYLE;\n // Offset to moving the corner to be centered relative to the grid.\n this.cornerCenterPointOffset = -(parseInt(this.cornerDefaultStyle.width, 10) / 2);\n this.corner = null;\n this.cornerStyle = null;\n this.createBorders(settings);\n this.registerListeners();\n }\n\n /**\n * Register all necessary events.\n */\n registerListeners() {\n const documentBody = this.wot.rootDocument.body;\n this.eventManager.addEventListener(documentBody, 'mousedown', () => this.onMouseDown());\n this.eventManager.addEventListener(documentBody, 'mouseup', () => this.onMouseUp());\n for (let c = 0, len = this.main.childNodes.length; c < len; c++) {\n const element = this.main.childNodes[c];\n this.eventManager.addEventListener(element, 'mouseenter', event => this.onMouseEnter(event, this.main.childNodes[c]));\n }\n }\n\n /**\n * Mouse down listener.\n *\n * @private\n */\n onMouseDown() {\n this.mouseDown = true;\n }\n\n /**\n * Mouse up listener.\n *\n * @private\n */\n onMouseUp() {\n this.mouseDown = false;\n }\n\n /**\n * Mouse enter listener for fragment selection functionality.\n *\n * @private\n * @param {Event} event Dom event.\n * @param {HTMLElement} parentElement Part of border element.\n */\n onMouseEnter(event, parentElement) {\n if (!this.mouseDown || !this.wot.getSetting('hideBorderOnMouseDownOver')) {\n return;\n }\n event.preventDefault();\n stopImmediatePropagation(event);\n const _this = this;\n const documentBody = this.wot.rootDocument.body;\n const bounds = parentElement.getBoundingClientRect();\n\n // Hide border to prevents selection jumping when fragmentSelection is enabled.\n parentElement.style.display = 'none';\n\n /**\n * @param {Event} mouseEvent The mouse event object.\n * @returns {boolean}\n */\n function isOutside(mouseEvent) {\n if (mouseEvent.clientY < Math.floor(bounds.top)) {\n return true;\n }\n if (mouseEvent.clientY > Math.ceil(bounds.top + bounds.height)) {\n return true;\n }\n if (mouseEvent.clientX < Math.floor(bounds.left)) {\n return true;\n }\n if (mouseEvent.clientX > Math.ceil(bounds.left + bounds.width)) {\n return true;\n }\n }\n\n /**\n * @param {Event} handlerEvent The mouse event object.\n */\n function handler(handlerEvent) {\n if (isOutside(handlerEvent)) {\n _this.eventManager.removeEventListener(documentBody, 'mousemove', handler);\n parentElement.style.display = 'block';\n }\n }\n this.eventManager.addEventListener(documentBody, 'mousemove', handler);\n }\n\n /**\n * Create border elements.\n *\n * @param {object} settings The border settings.\n */\n createBorders(settings) {\n const {\n rootDocument\n } = this.wot;\n this.main = rootDocument.createElement('div');\n const borderDivs = ['top', 'start', 'bottom', 'end', 'corner'];\n let style = this.main.style;\n style.position = 'absolute';\n style.top = 0;\n style.left = 0;\n for (let i = 0; i < 5; i++) {\n const position = borderDivs[i];\n const div = rootDocument.createElement('div');\n div.className = `wtBorder ${this.settings.className || ''}`; // + borderDivs[i];\n\n if (this.settings[position] && this.settings[position].hide) {\n div.className += ' hidden';\n }\n style = div.style;\n style.backgroundColor = this.settings[position] && this.settings[position].color ? this.settings[position].color : settings.border.color;\n style.height = this.settings[position] && this.settings[position].width ? `${this.settings[position].width}px` : `${settings.border.width}px`;\n style.width = this.settings[position] && this.settings[position].width ? `${this.settings[position].width}px` : `${settings.border.width}px`;\n this.main.appendChild(div);\n }\n this.top = this.main.childNodes[0];\n this.start = this.main.childNodes[1];\n this.bottom = this.main.childNodes[2];\n this.end = this.main.childNodes[3];\n this.topStyle = this.top.style;\n this.startStyle = this.start.style;\n this.bottomStyle = this.bottom.style;\n this.endStyle = this.end.style;\n this.corner = this.main.childNodes[4];\n this.corner.className += ' corner';\n this.cornerStyle = this.corner.style;\n this.cornerStyle.width = this.cornerDefaultStyle.width;\n this.cornerStyle.height = this.cornerDefaultStyle.height;\n this.cornerStyle.border = [this.cornerDefaultStyle.borderWidth, this.cornerDefaultStyle.borderStyle, this.cornerDefaultStyle.borderColor].join(' ');\n if (isMobileBrowser() && this.instance.getSetting('isDataViewInstance')) {\n this.createMultipleSelectorHandles();\n }\n this.disappear();\n const {\n wtTable\n } = this.wot;\n let bordersHolder = wtTable.bordersHolder;\n if (!bordersHolder) {\n bordersHolder = rootDocument.createElement('div');\n bordersHolder.className = 'htBorders';\n wtTable.bordersHolder = bordersHolder;\n wtTable.spreader.appendChild(bordersHolder);\n }\n bordersHolder.appendChild(this.main);\n }\n\n /**\n * Create multiple selector handler for mobile devices.\n */\n createMultipleSelectorHandles() {\n const {\n rootDocument\n } = this.wot;\n this.selectionHandles = {\n top: rootDocument.createElement('DIV'),\n topHitArea: rootDocument.createElement('DIV'),\n bottom: rootDocument.createElement('DIV'),\n bottomHitArea: rootDocument.createElement('DIV')\n };\n const width = 10;\n const hitAreaWidth = 40;\n this.selectionHandles.top.className = 'topSelectionHandle topLeftSelectionHandle';\n this.selectionHandles.topHitArea.className = 'topSelectionHandle-HitArea topLeftSelectionHandle-HitArea';\n this.selectionHandles.bottom.className = 'bottomSelectionHandle bottomRightSelectionHandle';\n this.selectionHandles.bottomHitArea.className = 'bottomSelectionHandle-HitArea bottomRightSelectionHandle-HitArea';\n this.selectionHandles.styles = {\n top: this.selectionHandles.top.style,\n topHitArea: this.selectionHandles.topHitArea.style,\n bottom: this.selectionHandles.bottom.style,\n bottomHitArea: this.selectionHandles.bottomHitArea.style\n };\n const hitAreaStyle = {\n position: 'absolute',\n height: `${hitAreaWidth}px`,\n width: `${hitAreaWidth}px`,\n 'border-radius': `${parseInt(hitAreaWidth / 1.5, 10)}px`\n };\n objectEach(hitAreaStyle, (value, key) => {\n this.selectionHandles.styles.bottomHitArea[key] = value;\n this.selectionHandles.styles.topHitArea[key] = value;\n });\n const handleStyle = {\n position: 'absolute',\n height: `${width}px`,\n width: `${width}px`,\n 'border-radius': `${parseInt(width / 1.5, 10)}px`,\n background: '#F5F5FF',\n border: '1px solid #4285c8'\n };\n objectEach(handleStyle, (value, key) => {\n this.selectionHandles.styles.bottom[key] = value;\n this.selectionHandles.styles.top[key] = value;\n });\n this.main.appendChild(this.selectionHandles.top);\n this.main.appendChild(this.selectionHandles.bottom);\n this.main.appendChild(this.selectionHandles.topHitArea);\n this.main.appendChild(this.selectionHandles.bottomHitArea);\n }\n\n /**\n * @param {number} row The visual row index.\n * @param {number} col The visual column index.\n * @returns {boolean}\n */\n isPartRange(row, col) {\n const areaSelection = this.wot.selectionManager.getAreaSelection();\n if (areaSelection.cellRange) {\n if (row !== areaSelection.cellRange.to.row || col !== areaSelection.cellRange.to.col) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @param {number} row The visual row index.\n * @param {number} col The visual column index.\n * @param {number} top The top position of the handler.\n * @param {number} left The left position of the handler.\n * @param {number} width The width of the handler.\n * @param {number} height The height of the handler.\n */\n updateMultipleSelectionHandlesPosition(row, col, top, left, width, height) {\n const isRtl = this.wot.wtSettings.getSetting('rtlMode');\n const inlinePosProperty = isRtl ? 'right' : 'left';\n const {\n top: topStyles,\n topHitArea: topHitAreaStyles,\n bottom: bottomStyles,\n bottomHitArea: bottomHitAreaStyles\n } = this.selectionHandles.styles;\n const handleBorderSize = parseInt(topStyles.borderWidth, 10);\n const handleSize = parseInt(topStyles.width, 10);\n const hitAreaSize = parseInt(topHitAreaStyles.width, 10);\n const totalTableWidth = this.wot.wtTable.getWidth();\n const totalTableHeight = this.wot.wtTable.getHeight();\n topStyles.top = `${parseInt(top - handleSize - 1, 10)}px`;\n topStyles[inlinePosProperty] = `${parseInt(left - handleSize - 1, 10)}px`;\n topHitAreaStyles.top = `${parseInt(top - hitAreaSize / 4 * 3, 10)}px`;\n topHitAreaStyles[inlinePosProperty] = `${parseInt(left - hitAreaSize / 4 * 3, 10)}px`;\n const bottomHandlerInline = Math.min(parseInt(left + width, 10), totalTableWidth - handleSize - handleBorderSize * 2);\n const bottomHandlerAreaInline = Math.min(parseInt(left + width - hitAreaSize / 4, 10), totalTableWidth - hitAreaSize - handleBorderSize * 2);\n bottomStyles[inlinePosProperty] = `${bottomHandlerInline}px`;\n bottomHitAreaStyles[inlinePosProperty] = `${bottomHandlerAreaInline}px`;\n const bottomHandlerTop = Math.min(parseInt(top + height, 10), totalTableHeight - handleSize - handleBorderSize * 2);\n const bottomHandlerAreaTop = Math.min(parseInt(top + height - hitAreaSize / 4, 10), totalTableHeight - hitAreaSize - handleBorderSize * 2);\n bottomStyles.top = `${bottomHandlerTop}px`;\n bottomHitAreaStyles.top = `${bottomHandlerAreaTop}px`;\n if (this.settings.border.cornerVisible && this.settings.border.cornerVisible()) {\n topStyles.display = 'block';\n topHitAreaStyles.display = 'block';\n if (this.isPartRange(row, col)) {\n bottomStyles.display = 'none';\n bottomHitAreaStyles.display = 'none';\n } else {\n bottomStyles.display = 'block';\n bottomHitAreaStyles.display = 'block';\n }\n } else {\n topStyles.display = 'none';\n bottomStyles.display = 'none';\n topHitAreaStyles.display = 'none';\n bottomHitAreaStyles.display = 'none';\n }\n if (row === this.wot.wtSettings.getSetting('fixedRowsTop') || col === this.wot.wtSettings.getSetting('fixedColumnsStart')) {\n topStyles.zIndex = '9999';\n topHitAreaStyles.zIndex = '9999';\n } else {\n topStyles.zIndex = '';\n topHitAreaStyles.zIndex = '';\n }\n }\n\n /**\n * Show border around one or many cells.\n *\n * @param {Array} corners The corner coordinates.\n */\n appear(corners) {\n if (this.disabled) {\n return;\n }\n const {\n wtTable,\n rootDocument,\n rootWindow\n } = this.wot; // todo refactoring: consider about using internal facade (it is given by external code)\n let fromRow;\n let toRow;\n let fromColumn;\n let toColumn;\n let rowHeader;\n let columnHeader;\n const rowsCount = wtTable.getRenderedRowsCount();\n for (let i = 0; i < rowsCount; i += 1) {\n const s = wtTable.rowFilter.renderedToSource(i);\n if (s >= corners[0] && s <= corners[2]) {\n fromRow = s;\n rowHeader = corners[0];\n break;\n }\n }\n for (let i = rowsCount - 1; i >= 0; i -= 1) {\n const s = wtTable.rowFilter.renderedToSource(i);\n if (s >= corners[0] && s <= corners[2]) {\n toRow = s;\n break;\n }\n }\n const columnsCount = wtTable.getRenderedColumnsCount();\n for (let i = 0; i < columnsCount; i += 1) {\n const s = wtTable.columnFilter.renderedToSource(i);\n if (s >= corners[1] && s <= corners[3]) {\n fromColumn = s;\n columnHeader = corners[1];\n break;\n }\n }\n for (let i = columnsCount - 1; i >= 0; i -= 1) {\n const s = wtTable.columnFilter.renderedToSource(i);\n if (s >= corners[1] && s <= corners[3]) {\n toColumn = s;\n break;\n }\n }\n if (fromRow === undefined || fromColumn === undefined) {\n this.disappear();\n return;\n }\n let fromTD = wtTable.getCell(this.wot.createCellCoords(fromRow, fromColumn));\n const isMultiple = fromRow !== toRow || fromColumn !== toColumn;\n const toTD = isMultiple ? wtTable.getCell(this.wot.createCellCoords(toRow, toColumn)) : fromTD;\n const fromOffset = offset(fromTD);\n const toOffset = isMultiple ? offset(toTD) : fromOffset;\n const containerOffset = offset(wtTable.TABLE);\n const containerWidth = outerWidth(wtTable.TABLE);\n const minTop = fromOffset.top;\n const minLeft = fromOffset.left;\n const isRtl = this.wot.wtSettings.getSetting('rtlMode');\n let inlineStartPos = 0;\n let width = 0;\n if (isRtl) {\n const fromWidth = outerWidth(fromTD);\n const gridRightPos = rootWindow.innerWidth - containerOffset.left - containerWidth;\n width = minLeft + fromWidth - toOffset.left;\n inlineStartPos = rootWindow.innerWidth - minLeft - fromWidth - gridRightPos - 1;\n } else {\n width = toOffset.left + outerWidth(toTD) - minLeft;\n inlineStartPos = minLeft - containerOffset.left - 1;\n }\n if (this.isEntireColumnSelected(fromRow, toRow)) {\n const modifiedValues = this.getDimensionsFromHeader('columns', fromColumn, toColumn, rowHeader, containerOffset);\n let fromTH = null;\n if (modifiedValues) {\n [fromTH, inlineStartPos, width] = modifiedValues;\n }\n if (fromTH) {\n fromTD = fromTH;\n }\n }\n let top = minTop - containerOffset.top - 1;\n let height = toOffset.top + outerHeight(toTD) - minTop;\n if (this.isEntireRowSelected(fromColumn, toColumn)) {\n const modifiedValues = this.getDimensionsFromHeader('rows', fromRow, toRow, columnHeader, containerOffset);\n let fromTH = null;\n if (modifiedValues) {\n [fromTH, top, height] = modifiedValues;\n }\n if (fromTH) {\n fromTD = fromTH;\n }\n }\n const style = getComputedStyle(fromTD, rootWindow);\n if (parseInt(style.borderTopWidth, 10) > 0) {\n top += 1;\n height = height > 0 ? height - 1 : 0;\n }\n if (parseInt(style[isRtl ? 'borderRightWidth' : 'borderLeftWidth'], 10) > 0) {\n inlineStartPos += 1;\n width = width > 0 ? width - 1 : 0;\n }\n const inlinePosProperty = isRtl ? 'right' : 'left';\n this.topStyle.top = `${top}px`;\n this.topStyle[inlinePosProperty] = `${inlineStartPos}px`;\n this.topStyle.width = `${width}px`;\n this.topStyle.display = 'block';\n this.startStyle.top = `${top}px`;\n this.startStyle[inlinePosProperty] = `${inlineStartPos}px`;\n this.startStyle.height = `${height}px`;\n this.startStyle.display = 'block';\n const delta = Math.floor(this.settings.border.width / 2);\n this.bottomStyle.top = `${top + height - delta}px`;\n this.bottomStyle[inlinePosProperty] = `${inlineStartPos}px`;\n this.bottomStyle.width = `${width}px`;\n this.bottomStyle.display = 'block';\n this.endStyle.top = `${top}px`;\n this.endStyle[inlinePosProperty] = `${inlineStartPos + width - delta}px`;\n this.endStyle.height = `${height + 1}px`;\n this.endStyle.display = 'block';\n let cornerVisibleSetting = this.settings.border.cornerVisible;\n cornerVisibleSetting = typeof cornerVisibleSetting === 'function' ? cornerVisibleSetting(this.settings.layerLevel) : cornerVisibleSetting;\n const hookResult = this.wot.getSetting('onModifyGetCellCoords', toRow, toColumn);\n let [checkRow, checkCol] = [toRow, toColumn];\n if (hookResult && Array.isArray(hookResult)) {\n [,, checkRow, checkCol] = hookResult;\n }\n if (isMobileBrowser() || !cornerVisibleSetting || this.isPartRange(checkRow, checkCol)) {\n this.cornerStyle.display = 'none';\n } else {\n this.cornerStyle.top = `${top + height + this.cornerCenterPointOffset - 1}px`;\n this.cornerStyle[inlinePosProperty] = `${inlineStartPos + width + this.cornerCenterPointOffset - 1}px`;\n this.cornerStyle.borderRightWidth = this.cornerDefaultStyle.borderWidth;\n this.cornerStyle.width = this.cornerDefaultStyle.width;\n\n // Hide the fill handle, so the possible further adjustments won't force unneeded scrollbars.\n this.cornerStyle.display = 'none';\n let trimmingContainer = getTrimmingContainer(wtTable.TABLE);\n const trimToWindow = trimmingContainer === rootWindow;\n if (trimToWindow) {\n trimmingContainer = rootDocument.documentElement;\n }\n const cornerHalfWidth = parseInt(this.cornerDefaultStyle.width, 10) / 2;\n const cornerHalfHeight = parseInt(this.cornerDefaultStyle.height, 10) / 2;\n if (toColumn === this.wot.getSetting('totalColumns') - 1) {\n const toTdOffsetLeft = trimToWindow ? toTD.getBoundingClientRect().left : toTD.offsetLeft;\n let cornerOverlappingContainer = false;\n let cornerEdge = 0;\n if (isRtl) {\n cornerEdge = toTdOffsetLeft - parseInt(this.cornerDefaultStyle.width, 10) / 2;\n cornerOverlappingContainer = cornerEdge < 0;\n } else {\n cornerEdge = toTdOffsetLeft + outerWidth(toTD) + parseInt(this.cornerDefaultStyle.width, 10) / 2;\n cornerOverlappingContainer = cornerEdge >= innerWidth(trimmingContainer);\n }\n if (cornerOverlappingContainer) {\n this.cornerStyle[inlinePosProperty] = `${Math.floor(inlineStartPos + width + this.cornerCenterPointOffset - cornerHalfWidth)}px`;\n this.cornerStyle[isRtl ? 'borderLeftWidth' : 'borderRightWidth'] = 0;\n }\n }\n if (toRow === this.wot.getSetting('totalRows') - 1) {\n const toTdOffsetTop = trimToWindow ? toTD.getBoundingClientRect().top : toTD.offsetTop;\n const cornerBottomEdge = toTdOffsetTop + outerHeight(toTD) + parseInt(this.cornerDefaultStyle.height, 10) / 2;\n const cornerOverlappingContainer = cornerBottomEdge >= innerHeight(trimmingContainer);\n if (cornerOverlappingContainer) {\n this.cornerStyle.top = `${Math.floor(top + height + this.cornerCenterPointOffset - cornerHalfHeight)}px`;\n this.cornerStyle.borderBottomWidth = 0;\n }\n }\n this.cornerStyle.display = 'block';\n }\n if (isMobileBrowser() && this.instance.getSetting('isDataViewInstance')) {\n this.updateMultipleSelectionHandlesPosition(toRow, toColumn, top, inlineStartPos, width, height);\n }\n }\n\n /**\n * Check whether an entire column of cells is selected.\n *\n * @private\n * @param {number} startRowIndex Start row index.\n * @param {number} endRowIndex End row index.\n * @returns {boolean}\n */\n isEntireColumnSelected(startRowIndex, endRowIndex) {\n return startRowIndex === this.wot.wtTable.getFirstRenderedRow() && endRowIndex === this.wot.wtTable.getLastRenderedRow();\n }\n\n /**\n * Check whether an entire row of cells is selected.\n *\n * @private\n * @param {number} startColumnIndex Start column index.\n * @param {number} endColumnIndex End column index.\n * @returns {boolean}\n */\n isEntireRowSelected(startColumnIndex, endColumnIndex) {\n return startColumnIndex === this.wot.wtTable.getFirstRenderedColumn() && endColumnIndex === this.wot.wtTable.getLastRenderedColumn();\n }\n\n /**\n * Get left/top index and width/height depending on the `direction` provided.\n *\n * @private\n * @param {string} direction `rows` or `columns`, defines if an entire column or row is selected.\n * @param {number} fromIndex Start index of the selection.\n * @param {number} toIndex End index of the selection.\n * @param {number} headerIndex The header index as negative value.\n * @param {number} containerOffset Offset of the container.\n * @returns {Array|boolean} Returns an array of [headerElement, left, width] or [headerElement, top, height], depending on `direction` (`false` in case of an error getting the headers).\n */\n getDimensionsFromHeader(direction, fromIndex, toIndex, headerIndex, containerOffset) {\n const {\n wtTable\n } = this.wot;\n const rootHotElement = wtTable.wtRootElement.parentNode;\n let getHeaderFn = null;\n let dimensionFn = null;\n let entireSelectionClassname = null;\n let index = null;\n let dimension = null;\n let dimensionProperty = null;\n let startHeader = null;\n let endHeader = null;\n switch (direction) {\n case 'rows':\n getHeaderFn = function () {\n return wtTable.getRowHeader(...arguments);\n };\n dimensionFn = function () {\n return outerHeight(...arguments);\n };\n entireSelectionClassname = 'ht__selection--rows';\n dimensionProperty = 'top';\n break;\n case 'columns':\n getHeaderFn = function () {\n return wtTable.getColumnHeader(...arguments);\n };\n dimensionFn = function () {\n return outerWidth(...arguments);\n };\n entireSelectionClassname = 'ht__selection--columns';\n dimensionProperty = 'left';\n break;\n default:\n }\n if (rootHotElement.classList.contains(entireSelectionClassname)) {\n const columnHeaderLevelCount = this.wot.getSetting('columnHeaders').length;\n startHeader = getHeaderFn(fromIndex, columnHeaderLevelCount - headerIndex);\n endHeader = getHeaderFn(toIndex, columnHeaderLevelCount - headerIndex);\n if (!startHeader || !endHeader) {\n return false;\n }\n const startHeaderOffset = offset(startHeader);\n const endOffset = offset(endHeader);\n if (startHeader && endHeader) {\n index = startHeaderOffset[dimensionProperty] - containerOffset[dimensionProperty] - 1;\n dimension = endOffset[dimensionProperty] + dimensionFn(endHeader) - startHeaderOffset[dimensionProperty];\n }\n return [startHeader, index, dimension];\n }\n return false;\n }\n\n /**\n * Change border style.\n *\n * @private\n * @param {string} borderElement Coordinate where add/remove border: top, bottom, start, end.\n * @param {object} border The border object descriptor.\n */\n changeBorderStyle(borderElement, border) {\n const style = this[borderElement].style;\n const borderStyle = border[borderElement];\n if (!borderStyle || borderStyle.hide) {\n addClass(this[borderElement], 'hidden');\n } else {\n if (hasClass(this[borderElement], 'hidden')) {\n removeClass(this[borderElement], 'hidden');\n }\n style.backgroundColor = borderStyle.color;\n if (borderElement === 'top' || borderElement === 'bottom') {\n style.height = `${borderStyle.width}px`;\n }\n if (borderElement === 'start' || borderElement === 'end') {\n style.width = `${borderStyle.width}px`;\n }\n }\n }\n\n /**\n * Change border style to default.\n *\n * @private\n * @param {string} position The position type (\"top\", \"bottom\", \"start\", \"end\") to change.\n */\n changeBorderToDefaultStyle(position) {\n const defaultBorder = {\n width: 1,\n color: '#000'\n };\n const style = this[position].style;\n style.backgroundColor = defaultBorder.color;\n style.width = `${defaultBorder.width}px`;\n style.height = `${defaultBorder.width}px`;\n }\n\n /**\n * Toggle class 'hidden' to element.\n *\n * @private\n * @param {string} borderElement Coordinate where add/remove border: top, bottom, start, end.\n * @param {boolean} [remove] Defines type of the action to perform.\n */\n toggleHiddenClass(borderElement, remove) {\n this.changeBorderToDefaultStyle(borderElement);\n if (remove) {\n addClass(this[borderElement], 'hidden');\n } else {\n removeClass(this[borderElement], 'hidden');\n }\n }\n\n /**\n * Hide border.\n */\n disappear() {\n this.topStyle.display = 'none';\n this.bottomStyle.display = 'none';\n this.startStyle.display = 'none';\n this.endStyle.display = 'none';\n this.cornerStyle.display = 'none';\n if (isMobileBrowser() && this.instance.getSetting('isDataViewInstance')) {\n this.selectionHandles.styles.top.display = 'none';\n this.selectionHandles.styles.topHitArea.display = 'none';\n this.selectionHandles.styles.bottom.display = 'none';\n this.selectionHandles.styles.bottomHitArea.display = 'none';\n }\n }\n\n /**\n * Cleans up all the DOM state related to a Border instance. Call this prior to deleting a Border instance.\n */\n destroy() {\n this.eventManager.destroyWithOwnEventsOnly();\n this.main.parentNode.removeChild(this.main);\n }\n}\nexport default Border;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { outerHeight, outerWidth, setOverlayPosition, resetCssTransform } from \"../../../../helpers/dom/element.mjs\";\nimport TopInlineStartCornerOverlayTable from \"../table/topInlineStartCorner.mjs\";\nimport { Overlay } from \"./_base.mjs\";\nimport { CLONE_TOP_INLINE_START_CORNER } from \"./constants.mjs\";\n/**\n * @class TopInlineStartCornerOverlay\n */\nexport class TopInlineStartCornerOverlay extends Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n * @param {TopOverlay} topOverlay The instance of the Top overlay.\n * @param {InlineStartOverlay} inlineStartOverlay The instance of the InlineStart overlay.\n */\n constructor(wotInstance, facadeGetter, wtSettings, domBindings, topOverlay, inlineStartOverlay) {\n super(wotInstance, facadeGetter, CLONE_TOP_INLINE_START_CORNER, wtSettings, domBindings);\n /**\n * The instance of the Top overlay.\n *\n * @type {TopOverlay}\n */\n _defineProperty(this, \"topOverlay\", void 0);\n /**\n * The instance of the InlineStart overlay.\n *\n * @type {InlineStartOverlay}\n */\n _defineProperty(this, \"inlineStartOverlay\", void 0);\n this.topOverlay = topOverlay;\n this.inlineStartOverlay = inlineStartOverlay;\n }\n\n /**\n * Factory method to create a subclass of `Table` that is relevant to this overlay.\n *\n * @see Table#constructor\n * @param {...*} args Parameters that will be forwarded to the `Table` constructor.\n * @returns {TopInlineStartCornerOverlayTable}\n */\n createTable() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new TopInlineStartCornerOverlayTable(...args);\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return this.wtSettings.getSetting('shouldRenderTopOverlay') && this.wtSettings.getSetting('shouldRenderInlineStartOverlay');\n }\n\n /**\n * Updates the corner overlay position.\n *\n * @returns {boolean}\n */\n resetFixedPosition() {\n this.updateTrimmingContainer();\n if (!this.wot.wtTable.holder.parentNode) {\n // removed from DOM\n return false;\n }\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n if (this.trimmingContainer === this.domBindings.rootWindow) {\n const left = this.inlineStartOverlay.getOverlayOffset() * (this.isRtl() ? -1 : 1);\n const top = this.topOverlay.getOverlayOffset();\n setOverlayPosition(overlayRoot, `${left}px`, `${top}px`);\n } else {\n resetCssTransform(overlayRoot);\n }\n let tableHeight = outerHeight(this.clone.wtTable.TABLE);\n const tableWidth = outerWidth(this.clone.wtTable.TABLE);\n if (!this.wot.wtTable.hasDefinedSize()) {\n tableHeight = 0;\n }\n overlayRoot.style.height = `${tableHeight}px`;\n overlayRoot.style.width = `${tableWidth}px`;\n return false;\n }\n}","import { defineGetter } from \"../../../../../helpers/object.mjs\";\nconst MIXIN_NAME = 'stickyRowsTop';\n\n/**\n * Mixin for the subclasses of `Table` with implementations of\n * helper methods that are related to rows.\n * This mixin is meant to be applied in the subclasses of `Table`\n * that use sticky rendering of the top rows in the vertical axis.\n *\n * @type {object}\n */\nconst stickyRowsTop = {\n /**\n * Get the source index of the first rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getFirstRenderedRow() {\n const totalRows = this.wtSettings.getSetting('totalRows');\n if (totalRows === 0) {\n return -1;\n }\n return 0;\n },\n /**\n * Get the source index of the first row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstVisibleRow() {\n return this.getFirstRenderedRow();\n },\n /**\n * Get the source index of the first row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getFirstPartiallyVisibleRow() {\n return this.getFirstRenderedRow();\n },\n /**\n * Get the source index of the last rendered row. If no rows are rendered, returns an error code: -1.\n *\n * @returns {number}\n * @this Table\n */\n getLastRenderedRow() {\n return this.getRenderedRowsCount() - 1;\n },\n /**\n * Get the source index of the last row fully visible in the viewport. If no rows are fully visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastVisibleRow() {\n return this.getLastRenderedRow();\n },\n /**\n * Get the source index of the last row partially visible in the viewport. If no rows are partially visible, returns an error code: -1.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getLastPartiallyVisibleRow() {\n return this.getLastRenderedRow();\n },\n /**\n * Get the number of rendered rows.\n *\n * @returns {number}\n * @this Table\n */\n getRenderedRowsCount() {\n const totalRows = this.wtSettings.getSetting('totalRows');\n return Math.min(this.wtSettings.getSetting('fixedRowsTop'), totalRows);\n },\n /**\n * Get the number of fully visible rows in the viewport.\n * Assumes that all rendered rows are fully visible.\n *\n * @returns {number}\n * @this Table\n */\n getVisibleRowsCount() {\n return this.getRenderedRowsCount();\n },\n /**\n * Get the number of rendered column headers.\n *\n * @returns {number}\n * @this Table\n */\n getColumnHeadersCount() {\n return this.dataAccessObject.columnHeaders.length;\n }\n};\ndefineGetter(stickyRowsTop, 'MIXIN_NAME', MIXIN_NAME, {\n writable: false,\n enumerable: false\n});\nexport default stickyRowsTop;","import Table from \"../table.mjs\";\nimport stickyRowsTop from \"./mixin/stickyRowsTop.mjs\";\nimport stickyColumnsStart from \"./mixin/stickyColumnsStart.mjs\";\nimport { mixin } from \"../../../../helpers/object.mjs\";\nimport { CLONE_TOP_INLINE_START_CORNER } from \"../overlay/index.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to topInlineStartCornerOverlay\n * (in RTL mode the overlay sits on the right of the screen), implemented through mixins.\n *\n * @mixes stickyRowsTop\n * @mixes stickyColumnsStart\n */\nclass TopInlineStartCornerOverlayTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, CLONE_TOP_INLINE_START_CORNER);\n }\n}\nmixin(TopInlineStartCornerOverlayTable, stickyRowsTop);\nmixin(TopInlineStartCornerOverlayTable, stickyColumnsStart);\nexport default TopInlineStartCornerOverlayTable;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { addClass, getMaximumScrollTop, getScrollbarWidth, getScrollTop, getWindowScrollLeft, hasClass, outerHeight, removeClass, setOverlayPosition, resetCssTransform } from \"../../../../helpers/dom/element.mjs\";\nimport TopOverlayTable from \"./../table/top.mjs\";\nimport { Overlay } from \"./_base.mjs\";\nimport { CORNER_DEFAULT_STYLE } from \"../selection/index.mjs\";\nimport { CLONE_TOP } from \"./constants.mjs\";\n/**\n * @class TopOverlay\n */\nexport class TopOverlay extends Overlay {\n /**\n * @param {Walkontable} wotInstance The Walkontable instance. @TODO refactoring: check if can be deleted.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {DomBindings} domBindings Dom elements bound to the current instance.\n */\n constructor(wotInstance, facadeGetter, wtSettings, domBindings) {\n super(wotInstance, facadeGetter, CLONE_TOP, wtSettings, domBindings);\n /**\n * Cached value which holds the previous value of the `fixedRowsTop` option.\n * It is used as a comparison value that can be used to detect changes in this value.\n *\n * @type {number}\n */\n _defineProperty(this, \"cachedFixedRowsTop\", -1);\n this.cachedFixedRowsTop = this.wtSettings.getSetting('fixedRowsTop');\n }\n\n /**\n * Factory method to create a subclass of `Table` that is relevant to this overlay.\n *\n * @see Table#constructor\n * @param {...*} args Parameters that will be forwarded to the `Table` constructor.\n * @returns {TopOverlayTable}\n */\n createTable() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return new TopOverlayTable(...args);\n }\n\n /**\n * Checks if overlay should be fully rendered.\n *\n * @returns {boolean}\n */\n shouldBeRendered() {\n return this.wtSettings.getSetting('shouldRenderTopOverlay');\n }\n\n /**\n * Updates the top overlay position.\n *\n * @returns {boolean}\n */\n resetFixedPosition() {\n if (!this.needFullRender || !this.shouldBeRendered() || !this.wot.wtTable.holder.parentNode) {\n // removed from DOM\n return false;\n }\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n const {\n rootWindow\n } = this.domBindings;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let overlayPosition = 0;\n let skipInnerBorderAdjusting = false;\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'vertical')) {\n const {\n wtTable\n } = this.wot;\n const hiderRect = wtTable.hider.getBoundingClientRect();\n const bottom = Math.ceil(hiderRect.bottom);\n const rootHeight = overlayRoot.offsetHeight;\n\n // This checks if the overlay is going to an infinite loop caused by added (or removed)\n // `innerBorderTop` class name. Toggling the class name shifts the viewport by 1px and\n // triggers the `scroll` event. It causes the table to render. The new render cycle takes into,\n // account the shift and toggles the class name again. This causes the next loops. This\n // happens only on Chrome (#7256).\n //\n // When we detect that the table bottom position is the same as the overlay bottom,\n // do not toggle the class name.\n //\n // This workaround will be able to be cleared after merging the SVG borders, which introduces\n // frozen lines (no more `innerBorderTop` workaround).\n skipInnerBorderAdjusting = bottom === rootHeight;\n overlayPosition = this.getOverlayOffset();\n setOverlayPosition(overlayRoot, '0px', `${overlayPosition}px`);\n } else {\n overlayPosition = this.getScrollPosition();\n resetCssTransform(overlayRoot);\n }\n const positionChanged = this.adjustHeaderBordersPosition(overlayPosition, skipInnerBorderAdjusting);\n this.adjustElementsSize();\n return positionChanged;\n }\n\n /**\n * Sets the main overlay's vertical scroll position.\n *\n * @param {number} pos The scroll position.\n * @returns {boolean}\n */\n setScrollPosition(pos) {\n const rootWindow = this.domBindings.rootWindow;\n let result = false;\n if (this.mainTableScrollableElement === rootWindow && rootWindow.scrollY !== pos) {\n rootWindow.scrollTo(getWindowScrollLeft(rootWindow), pos);\n result = true;\n } else if (this.mainTableScrollableElement.scrollTop !== pos) {\n this.mainTableScrollableElement.scrollTop = pos;\n result = true;\n }\n return result;\n }\n\n /**\n * Triggers onScroll hook callback.\n */\n onScroll() {\n this.wtSettings.getSetting('onScrollHorizontally');\n }\n\n /**\n * Calculates total sum cells height.\n *\n * @param {number} from Row index which calculates started from.\n * @param {number} to Row index where calculation is finished.\n * @returns {number} Height sum.\n */\n sumCellSizes(from, to) {\n const defaultRowHeight = this.wtSettings.getSetting('defaultRowHeight');\n let row = from;\n let sum = 0;\n while (row < to) {\n const height = this.wot.wtTable.getRowHeight(row);\n sum += height === undefined ? defaultRowHeight : height;\n row += 1;\n }\n return sum;\n }\n\n /**\n * Adjust overlay root element, children and master table element sizes (width, height).\n */\n adjustElementsSize() {\n this.updateTrimmingContainer();\n if (this.needFullRender) {\n this.adjustRootElementSize();\n this.adjustRootChildrenSize();\n }\n }\n\n /**\n * Adjust overlay root element size (width and height).\n */\n adjustRootElementSize() {\n const {\n wtTable\n } = this.wot;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const scrollbarWidth = getScrollbarWidth(rootDocument);\n const overlayRoot = this.clone.wtTable.holder.parentNode;\n const overlayRootStyle = overlayRoot.style;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (this.trimmingContainer !== rootWindow || preventOverflow === 'horizontal') {\n let width = this.wot.wtViewport.getWorkspaceWidth();\n if (this.wot.wtOverlays.hasScrollbarRight) {\n width -= scrollbarWidth;\n }\n width = Math.min(width, wtTable.wtRootElement.scrollWidth);\n overlayRootStyle.width = `${width}px`;\n } else {\n overlayRootStyle.width = '';\n }\n this.clone.wtTable.holder.style.width = overlayRootStyle.width;\n let tableHeight = outerHeight(this.clone.wtTable.TABLE);\n if (!this.wot.wtTable.hasDefinedSize()) {\n tableHeight = 0;\n }\n overlayRootStyle.height = `${tableHeight}px`;\n }\n\n /**\n * Adjust overlay root childs size.\n */\n adjustRootChildrenSize() {\n const {\n holder\n } = this.clone.wtTable;\n const selectionCornerOffset = this.wot.selectionManager.getFocusSelection() ? parseInt(CORNER_DEFAULT_STYLE.height, 10) / 2 : 0;\n this.clone.wtTable.hider.style.width = this.hider.style.width;\n holder.style.width = holder.parentNode.style.width;\n // Add selection corner protruding part to the holder total height to make sure that\n // borders' corner won't be cut after vertical scroll (#6937).\n holder.style.height = `${parseInt(holder.parentNode.style.height, 10) + selectionCornerOffset}px`;\n }\n\n /**\n * Adjust the overlay dimensions and position.\n */\n applyToDOM() {\n const total = this.wtSettings.getSetting('totalRows');\n if (typeof this.wot.wtViewport.rowsRenderCalculator.startPosition === 'number') {\n this.spreader.style.top = `${this.wot.wtViewport.rowsRenderCalculator.startPosition}px`;\n } else if (total === 0) {\n // can happen if there are 0 rows\n this.spreader.style.top = '0';\n } else {\n throw new Error('Incorrect value of the rowsRenderCalculator');\n }\n this.spreader.style.bottom = '';\n if (this.needFullRender) {\n this.syncOverlayOffset();\n }\n }\n\n /**\n * Synchronize calculated left position to an element.\n */\n syncOverlayOffset() {\n const styleProperty = this.isRtl() ? 'right' : 'left';\n const {\n spreader\n } = this.clone.wtTable;\n if (typeof this.wot.wtViewport.columnsRenderCalculator.startPosition === 'number') {\n spreader.style[styleProperty] = `${this.wot.wtViewport.columnsRenderCalculator.startPosition}px`;\n } else {\n spreader.style[styleProperty] = '';\n }\n }\n\n /**\n * Scrolls vertically to a row.\n *\n * @param {number} sourceRow Row index which you want to scroll to.\n * @param {boolean} [bottomEdge] If `true`, scrolls according to the bottom edge (top edge is by default).\n * @returns {boolean}\n */\n scrollTo(sourceRow, bottomEdge) {\n const {\n wot,\n wtSettings\n } = this;\n const sourceInstance = wot.cloneSource ? wot.cloneSource : wot;\n const mainHolder = sourceInstance.wtTable.holder;\n const columnHeaders = wtSettings.getSetting('columnHeaders');\n const fixedRowsTop = wtSettings.getSetting('fixedRowsTop');\n const columnHeaderBorderCompensation = fixedRowsTop === 0 && columnHeaders.length > 0 && !hasClass(mainHolder.parentNode, 'innerBorderTop') ? 1 : 0;\n let newY = this.getTableParentOffset();\n let scrollbarCompensation = 0;\n if (bottomEdge) {\n const rowHeight = this.wot.wtTable.getRowHeight(sourceRow);\n const viewportHeight = this.wot.wtViewport.getViewportHeight();\n if (rowHeight > viewportHeight) {\n bottomEdge = false;\n }\n }\n if (bottomEdge && mainHolder.offsetHeight !== mainHolder.clientHeight) {\n scrollbarCompensation = getScrollbarWidth(this.domBindings.rootDocument);\n }\n if (bottomEdge) {\n const fixedRowsBottom = wtSettings.getSetting('fixedRowsBottom');\n const totalRows = wtSettings.getSetting('totalRows');\n newY += this.sumCellSizes(0, sourceRow + 1);\n newY -= wot.wtViewport.getViewportHeight() - this.sumCellSizes(totalRows - fixedRowsBottom, totalRows);\n // Fix 1 pixel offset when cell is selected\n newY += 1;\n // Compensate for the bottom header border if scrolled from the absolute top.\n newY += columnHeaderBorderCompensation;\n } else {\n newY += this.sumCellSizes(wtSettings.getSetting('fixedRowsTop'), sourceRow);\n }\n newY += scrollbarCompensation;\n\n // If the table is scrolled all the way up when starting the scroll and going to be scrolled to the bottom,\n // we need to compensate for the potential header bottom border height.\n if (getMaximumScrollTop(this.mainTableScrollableElement) === newY - columnHeaderBorderCompensation && columnHeaderBorderCompensation > 0) {\n this.wot.wtOverlays.expandHiderVerticallyBy(columnHeaderBorderCompensation);\n }\n return this.setScrollPosition(newY);\n }\n\n /**\n * Gets table parent top position.\n *\n * @returns {number}\n */\n getTableParentOffset() {\n if (this.mainTableScrollableElement === this.domBindings.rootWindow) {\n return this.wot.wtTable.holderOffset.top;\n }\n return 0;\n }\n\n /**\n * Gets the main overlay's vertical scroll position.\n *\n * @returns {number} Main table's vertical scroll position.\n */\n getScrollPosition() {\n return getScrollTop(this.mainTableScrollableElement, this.domBindings.rootWindow);\n }\n\n /**\n * Gets the main overlay's vertical overlay offset.\n *\n * @returns {number} Main table's vertical overlay offset.\n */\n getOverlayOffset() {\n const {\n rootWindow\n } = this.domBindings;\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n let overlayOffset = 0;\n if (this.trimmingContainer === rootWindow && (!preventOverflow || preventOverflow !== 'vertical')) {\n const rootHeight = this.wot.wtTable.getTotalHeight();\n const overlayRootHeight = this.clone.wtTable.getTotalHeight();\n const maxOffset = rootHeight - overlayRootHeight;\n overlayOffset = Math.max(this.getScrollPosition() - this.getTableParentOffset(), 0);\n if (overlayOffset > maxOffset) {\n overlayOffset = 0;\n }\n }\n return overlayOffset;\n }\n\n /**\n * Adds css classes to hide the header border's header (cell-selection border hiding issue).\n *\n * @param {number} position Header Y position if trimming container is window or scroll top if not.\n * @param {boolean} [skipInnerBorderAdjusting=false] If `true` the inner border adjusting will be skipped.\n * @returns {boolean}\n */\n adjustHeaderBordersPosition(position) {\n let skipInnerBorderAdjusting = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n const {\n wtSettings\n } = this;\n const masterParent = this.wot.wtTable.holder.parentNode;\n const totalColumns = wtSettings.getSetting('totalColumns');\n const preventHorizontalOverflow = wtSettings.getSetting('preventOverflow') === 'horizontal';\n if (totalColumns) {\n removeClass(masterParent, 'emptyColumns');\n } else {\n addClass(masterParent, 'emptyColumns');\n }\n let positionChanged = false;\n if (!skipInnerBorderAdjusting && !preventHorizontalOverflow) {\n const fixedRowsTop = wtSettings.getSetting('fixedRowsTop');\n const areFixedRowsTopChanged = this.cachedFixedRowsTop !== fixedRowsTop;\n const columnHeaders = wtSettings.getSetting('columnHeaders');\n if ((areFixedRowsTopChanged || fixedRowsTop === 0) && columnHeaders.length > 0) {\n const previousState = hasClass(masterParent, 'innerBorderTop');\n this.cachedFixedRowsTop = wtSettings.getSetting('fixedRowsTop');\n if (position || wtSettings.getSetting('totalRows') === 0) {\n addClass(masterParent, 'innerBorderTop');\n positionChanged = !previousState;\n } else {\n removeClass(masterParent, 'innerBorderTop');\n positionChanged = previousState;\n }\n }\n }\n return positionChanged;\n }\n}","import Table from \"../table.mjs\";\nimport stickyRowsTop from \"./mixin/stickyRowsTop.mjs\";\nimport calculatedColumns from \"./mixin/calculatedColumns.mjs\";\nimport { mixin } from \"../../../../helpers/object.mjs\";\nimport { CLONE_TOP } from \"../overlay/index.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to TopOverlay, implemented through mixins.\n *\n * @mixes stickyRowsTop\n * @mixes calculatedColumns\n */\nclass TopOverlayTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, CLONE_TOP);\n }\n}\nmixin(TopOverlayTable, stickyRowsTop);\nmixin(TopOverlayTable, calculatedColumns);\nexport default TopOverlayTable;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { fastInnerText } from \"../../../helpers/dom/element.mjs\";\nimport { objectEach } from \"../../../helpers/object.mjs\";\n/**\n * @todo Describe options.\n * @typedef SettingsPure\n *\n * @property {Option} facade @todo desc.\n * @property {Option} ariaTags Option `ariaTags`.\n * @property {Option} cellRenderer Option `cellRenderer`.\n * @property {Option} columnHeaders Option `columnHeaders`.\n * @property {Option} columnWidth Option `columnWidth`.\n * @property {Option} currentRowClassName Option `currentRowClassName`.\n * @property {Option} data Option `data`.\n * @property {Option} defaultColumnWidth Option `defaultColumnWidth`.\n * @property {Option} defaultRowHeight Option `defaultRowHeight`.\n * @property {Option} externalRowCalculator Option `externalRowCalculator`.\n * @property {Option} fixedColumnsStart Option `fixedColumnsStart`.\n * @property {Option} fixedRowsBottom Option `fixedRowsBottom`.\n * @property {Option} fixedRowsTop Option `fixedRowsTop`.\n * @property {Option} freezeOverlays Option `freezeOverlays`.\n * @property {Option} groups Option `groups`.\n * @property {Option} hideBorderOnMouseDownOver Option `hideBorderOnMouseDownOver`.\n * @property {Option} isRtl Option `isRtl`.\n * @property {Option} isDataViewInstance Option `isDataViewInstance`.\n * @property {Option} minSpareRows Option `minSpareRows`.\n * @property {Option} onBeforeHighlightingColumnHeader Option `onBeforeHighlightingColumnHeader`.\n * @property {Option} onBeforeHighlightingRowHeader Option `onBeforeHighlightingRowHeader`.\n * @property {Option} onBeforeRemoveCellClassNames Option `onBeforeRemoveCellClassNames`.\n * @property {Option} onBeforeStretchingColumnWidth Option `onBeforeStretchingColumnWidth`.\n * @property {Option} preventOverflow Option `preventOverflow`.\n * @property {Option} preventWheel Option `preventWheel`.\n * @property {Option} renderAllColumns Option `renderAllColumns`.\n * @property {Option} renderAllRows Option `renderAllRows`.\n * @property {Option} rowHeaders Option `rowHeaders`.\n * @property {Option} rowHeightOption `rowHeight`.\n * @property {Option} rowHeightByOverlayName Option `rowHeightByOverlayName`.\n * @property {Option} shouldRenderBottomOverlay Option `shouldRenderBottomOverlay`.\n * @property {Option} shouldRenderInlineStartOverlay Option `shouldRenderInlineStartOverlay`.\n * @property {Option} shouldRenderTopOverlay Option `shouldRenderTopOverlay`.\n * @property {Option} stretchH Option `stretchH`.\n * @property {Option} table Option `table`.\n * @property {Option} totalColumns Option `totalColumns`.\n * @property {Option} totalRows Option `totalRows`.\n * @property {?Option} beforeDraw Option `beforeDraw`.\n * @property {?Option} columnHeaderHeight Option `columnHeaderHeight`.\n * @property {?Option} currentColumnClassName Option `currentColumnClassName`.\n * @property {?Option} headerClassName Option `headerClassName`.\n * @property {?Option} onAfterDrawSelection Option `onAfterDrawSelection`.\n * @property {?Option} onAfterMomentumScroll Option `onAfterMomentumScroll`.\n * @property {?Option} onBeforeDrawBorders Option `onBeforeDrawBorders`.\n * @property {?Option} onBeforeTouchScroll Option `onBeforeTouchScroll`.\n * @property {?Option} onCellContextMenu Option `onCellContextMenu`.\n * @property {?Option} onCellCornerDblClick Option `onCellCornerDblClick`.\n * @property {?Option} onCellCornerMouseDown Option `onCellCornerMouseDown`.\n * @property {?Option} onCellDblClick Option `onCellDblClick`.\n * @property {?Option} onCellMouseDown Option `onCellMouseDown`.\n * @property {?Option} onCellMouseOut Option `onCellMouseOut`.\n * @property {?Option} onCellMouseOver Option `onCellMouseOver`.\n * @property {?Option} onCellMouseUp Option `onCellMouseUp`.\n * @property {?Option} onDraw Option `onDraw`.\n * @property {?Option} onModifyGetCellCoords Option `onModifyGetCellCoords`.\n * @property {?Option} onModifyRowHeaderWidth Option `onModifyRowHeaderWidth`.\n * @property {?Option} onBeforeViewportScrollHorizontally Option `onBeforeViewportScrollHorizontally`.\n * @property {?Option} onBeforeViewportScrollVertically Option `onBeforeViewportScrollVertically`.\n * @property {?Option} onScrollHorizontally Option `onScrollHorizontally`.\n * @property {?Option} onScrollVertically Option `onScrollVertically`.\n * @property {?Option} onWindowResize Option `onWindowResize`.\n * @property {?Option} rowHeaderWidth Option `rowHeaderWidth`.\n * @property {?Option} selections Option `selections`.\n * @property {?Option} viewportColumnCalculatorOverride Option `viewportColumnCalculatorOverride`.\n * @property {?Option} viewportRowCalculatorOverride Option `viewportRowCalculatorOverride`.\n */\n/**\n * @template TValue.\n * @typedef { TValue | Array. | (function(...*): TValue) } Option\n */\n/**\n * @class Settings\n */\nexport default class Settings {\n /**\n * @param {SettingsPure} settings The user defined settings.\n */\n constructor(settings) {\n /**\n * Reference to settings.\n *\n * @protected\n * @type {SettingsPure}\n */\n _defineProperty(this, \"settings\", {});\n /**\n * The defaults values of settings.\n * Void 0 means it is required, null means it can be empty.\n *\n * @public\n * @type {Readonly}\n */\n _defineProperty(this, \"defaults\", Object.freeze(this.getDefaults()));\n objectEach(this.defaults, (value, key) => {\n if (settings[key] !== undefined) {\n this.settings[key] = settings[key];\n } else if (value === undefined) {\n throw new Error(`A required setting \"${key}\" was not provided`);\n } else {\n this.settings[key] = value;\n }\n });\n }\n\n /**\n * Generate defaults for a settings.\n * Void 0 means it is required, null means it can be empty.\n *\n * @private\n * @returns {SettingsPure}\n */\n getDefaults() {\n return {\n facade: undefined,\n table: undefined,\n // Determines whether the Walkontable instance is used as dataset viewer. When its instance is used as\n // a context menu, autocomplete list, etc, the returned value is `false`.\n isDataViewInstance: true,\n // presentation mode\n externalRowCalculator: false,\n stretchH: 'none',\n // values: all, last, none\n currentRowClassName: null,\n currentColumnClassName: null,\n preventOverflow() {\n return false;\n },\n preventWheel: false,\n // data source\n data: undefined,\n freezeOverlays: false,\n // Number of renderable columns for the left overlay.\n fixedColumnsStart: 0,\n // Number of renderable rows for the top overlay.\n fixedRowsTop: 0,\n // Number of renderable rows for the bottom overlay.\n fixedRowsBottom: 0,\n // Enable the inline start overlay when conditions are met (left for LTR and right for RTL document mode).\n shouldRenderInlineStartOverlay: () => {\n return this.getSetting('fixedColumnsStart') > 0 || this.getSetting('rowHeaders').length > 0;\n },\n // Enable the top overlay when conditions are met.\n shouldRenderTopOverlay: () => {\n return this.getSetting('fixedRowsTop') > 0 || this.getSetting('columnHeaders').length > 0;\n },\n // Enable the bottom overlay when conditions are met.\n shouldRenderBottomOverlay: () => {\n return this.getSetting('fixedRowsBottom') > 0;\n },\n minSpareRows: 0,\n // this must be array of functions: [function (row, TH) {}]\n rowHeaders() {\n return [];\n },\n // this must be array of functions: [function (column, TH) {}]\n columnHeaders() {\n return [];\n },\n totalRows: undefined,\n totalColumns: undefined,\n cellRenderer: (row, column, TD) => {\n const cellData = this.getSetting('data', row, column);\n fastInnerText(TD, cellData === undefined || cellData === null ? '' : cellData);\n },\n // columnWidth: 50,\n columnWidth() {\n // return undefined means use default size for the rendered cell content\n },\n rowHeight() {\n // return undefined means use default size for the rendered cell content\n },\n rowHeightByOverlayName() {\n // return undefined means use default size for the rendered cell content\n },\n defaultRowHeight: 23,\n defaultColumnWidth: 50,\n selections: null,\n hideBorderOnMouseDownOver: false,\n viewportRowCalculatorOverride: null,\n viewportColumnCalculatorOverride: null,\n // callbacks\n onCellMouseDown: null,\n onCellContextMenu: null,\n onCellMouseOver: null,\n onCellMouseOut: null,\n onCellMouseUp: null,\n // onCellMouseOut: null,\n onCellDblClick: null,\n onCellCornerMouseDown: null,\n onCellCornerDblClick: null,\n beforeDraw: null,\n onDraw: null,\n onBeforeRemoveCellClassNames: null,\n onAfterDrawSelection: null,\n onBeforeDrawBorders: null,\n // viewport scroll hooks\n onBeforeViewportScrollHorizontally: column => column,\n onBeforeViewportScrollVertically: row => row,\n // native scroll hooks\n onScrollHorizontally: null,\n onScrollVertically: null,\n //\n onBeforeTouchScroll: null,\n onAfterMomentumScroll: null,\n onBeforeStretchingColumnWidth: width => width,\n onModifyRowHeaderWidth: null,\n onModifyGetCellCoords: null,\n onBeforeHighlightingRowHeader: sourceRow => sourceRow,\n onBeforeHighlightingColumnHeader: sourceCol => sourceCol,\n onWindowResize: null,\n onContainerElementResize: null,\n renderAllColumns: false,\n renderAllRows: false,\n groups: false,\n rowHeaderWidth: null,\n columnHeaderHeight: null,\n headerClassName: null,\n rtlMode: false,\n ariaTags: true\n };\n }\n\n /**\n * Update settings.\n *\n * @param {object|string} settings The singular settings to update or if passed as object to merge with.\n * @param {*} value The value to set if the first argument is passed as string.\n * @returns {Settings}\n */\n update(settings, value) {\n if (value === undefined) {\n // settings is object\n objectEach(settings, (settingValue, key) => {\n this.settings[key] = settingValue;\n });\n } else {\n // if value is defined then settings is the key\n this.settings[settings] = value;\n }\n return this;\n }\n\n /**\n * Get setting by name.\n *\n * @param {$Keys} key The settings key to retrieve.\n * @param {*} [param1] Additional parameter passed to the options defined as function.\n * @param {*} [param2] Additional parameter passed to the options defined as function.\n * @param {*} [param3] Additional parameter passed to the options defined as function.\n * @param {*} [param4] Additional parameter passed to the options defined as function.\n * @returns {*}\n */\n getSetting(key, param1, param2, param3, param4) {\n if (typeof this.settings[key] === 'function') {\n return this.settings[key](param1, param2, param3, param4);\n } else if (param1 !== undefined && Array.isArray(this.settings[key])) {\n return this.settings[key][param1];\n }\n return this.settings[key];\n }\n\n /**\n * Get a setting value without any evaluation.\n *\n * @param {string} key The settings key to retrieve.\n * @returns {*}\n */\n getSettingPure(key) {\n return this.settings[key];\n }\n\n /**\n * Checks if setting exists.\n *\n * @param {boolean} key The settings key to check.\n * @returns {boolean}\n */\n has(key) {\n return !!this.settings[key];\n }\n}","import { getStyle, getComputedStyle, getTrimmingContainer, isVisible } from \"./../../../../helpers/dom/element.mjs\";\nimport Table from \"../table.mjs\";\nimport calculatedRows from \"./mixin/calculatedRows.mjs\";\nimport calculatedColumns from \"./mixin/calculatedColumns.mjs\";\nimport { mixin } from \"./../../../../helpers/object.mjs\";\n/**\n * Subclass of `Table` that provides the helper methods relevant to the master table (not overlays), implemented through mixins.\n *\n * @mixes calculatedRows\n * @mixes calculatedColumns\n */\nclass MasterTable extends Table {\n /**\n * @param {TableDao} dataAccessObject The data access object.\n * @param {FacadeGetter} facadeGetter Function which return proper facade.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n */\n constructor(dataAccessObject, facadeGetter, domBindings, wtSettings) {\n super(dataAccessObject, facadeGetter, domBindings, wtSettings, 'master');\n }\n alignOverlaysWithTrimmingContainer() {\n const trimmingElement = getTrimmingContainer(this.wtRootElement);\n const {\n rootWindow\n } = this.domBindings;\n if (trimmingElement === rootWindow) {\n const preventOverflow = this.wtSettings.getSetting('preventOverflow');\n if (!preventOverflow) {\n this.holder.style.overflow = 'visible';\n this.wtRootElement.style.overflow = 'visible';\n }\n } else {\n const trimmingElementParent = trimmingElement.parentElement;\n const trimmingHeight = getStyle(trimmingElement, 'height', rootWindow);\n const trimmingOverflow = getStyle(trimmingElement, 'overflow', rootWindow);\n const holderStyle = this.holder.style;\n const {\n scrollWidth,\n scrollHeight\n } = trimmingElement;\n let width = trimmingElement.offsetWidth;\n let height = trimmingElement.offsetHeight;\n const overflow = ['auto', 'hidden', 'scroll'];\n if (trimmingElementParent && overflow.includes(trimmingOverflow)) {\n const cloneNode = trimmingElement.cloneNode(false);\n\n // Before calculating the height of the trimming element, set overflow: auto to hide scrollbars.\n // An issue occurred on Firefox, where an empty element with overflow: scroll returns an element height higher than 0px\n // despite an empty content within.\n cloneNode.style.overflow = 'auto';\n // Issue #9545 shows problem with calculating height for HOT on Firefox while placing instance in some\n // flex containers and setting overflow for some `div` section.\n cloneNode.style.position = 'absolute';\n if (trimmingElement.nextElementSibling) {\n trimmingElementParent.insertBefore(cloneNode, trimmingElement.nextElementSibling);\n } else {\n trimmingElementParent.appendChild(cloneNode);\n }\n const cloneHeight = parseInt(getComputedStyle(cloneNode, rootWindow).height, 10);\n trimmingElementParent.removeChild(cloneNode);\n if (cloneHeight === 0) {\n height = 0;\n }\n }\n height = Math.min(height, scrollHeight);\n holderStyle.height = trimmingHeight === 'auto' ? 'auto' : `${height}px`;\n width = Math.min(width, scrollWidth);\n holderStyle.width = `${width}px`;\n holderStyle.overflow = '';\n this.hasTableHeight = holderStyle.height === 'auto' ? true : height > 0;\n this.hasTableWidth = width > 0;\n }\n this.isTableVisible = isVisible(this.TABLE);\n }\n markOversizedColumnHeaders() {\n const {\n wtSettings\n } = this;\n const {\n wtViewport\n } = this.dataAccessObject;\n const overlayName = 'master';\n const columnHeaders = wtSettings.getSetting('columnHeaders');\n const columnHeadersCount = columnHeaders.length;\n if (columnHeadersCount && !wtViewport.hasOversizedColumnHeadersMarked[overlayName]) {\n const rowHeaders = wtSettings.getSetting('rowHeaders');\n const rowHeaderCount = rowHeaders.length;\n const columnCount = this.getRenderedColumnsCount();\n for (let i = 0; i < columnHeadersCount; i++) {\n for (let renderedColumnIndex = -1 * rowHeaderCount; renderedColumnIndex < columnCount; renderedColumnIndex++) {\n // eslint-disable-line max-len\n this.markIfOversizedColumnHeader(renderedColumnIndex);\n }\n }\n wtViewport.hasOversizedColumnHeadersMarked[overlayName] = true;\n }\n }\n}\nmixin(MasterTable, calculatedRows);\nmixin(MasterTable, calculatedColumns);\nexport default MasterTable;","import { getScrollbarWidth, getStyle, offset, outerHeight, outerWidth } from \"../../../helpers/dom/element.mjs\";\nimport { objectEach } from \"../../../helpers/object.mjs\";\nimport { FullyVisibleColumnsCalculationType, FullyVisibleRowsCalculationType, PartiallyVisibleColumnsCalculationType, PartiallyVisibleRowsCalculationType, RenderedAllColumnsCalculationType, RenderedAllRowsCalculationType, RenderedColumnsCalculationType, RenderedRowsCalculationType, ViewportColumnsCalculator, ViewportRowsCalculator } from \"./calculator/index.mjs\";\n/**\n * @class Viewport\n */\nclass Viewport {\n /**\n * @param {ViewportDao} dataAccessObject The Walkontable instance.\n * @param {DomBindings} domBindings Bindings into DOM.\n * @param {Settings} wtSettings The Walkontable settings.\n * @param {EventManager} eventManager The instance event manager.\n * @param {Table} wtTable The table.\n */\n constructor(dataAccessObject, domBindings, wtSettings, eventManager, wtTable) {\n this.dataAccessObject = dataAccessObject;\n // legacy support\n this.wot = dataAccessObject.wot;\n this.instance = this.wot;\n this.domBindings = domBindings;\n this.wtSettings = wtSettings;\n this.wtTable = wtTable;\n this.oversizedRows = [];\n this.oversizedColumnHeaders = [];\n this.hasOversizedColumnHeadersMarked = {};\n this.clientHeight = 0;\n this.containerWidth = NaN;\n this.rowHeaderWidth = NaN;\n this.rowsVisibleCalculator = null;\n this.columnsVisibleCalculator = null;\n this.rowsCalculatorTypes = new Map([['rendered', () => this.wtSettings.getSetting('renderAllRows') ? new RenderedAllRowsCalculationType() : new RenderedRowsCalculationType()], ['fullyVisible', () => new FullyVisibleRowsCalculationType()], ['partiallyVisible', () => new PartiallyVisibleRowsCalculationType()]]);\n this.columnsCalculatorTypes = new Map([['rendered', () => this.wtSettings.getSetting('renderAllColumns') ? new RenderedAllColumnsCalculationType() : new RenderedColumnsCalculationType()], ['fullyVisible', () => new FullyVisibleColumnsCalculationType()], ['partiallyVisible', () => new PartiallyVisibleColumnsCalculationType()]]);\n this.eventManager = eventManager;\n this.eventManager.addEventListener(this.domBindings.rootWindow, 'resize', () => {\n this.clientHeight = this.getWorkspaceHeight();\n });\n }\n\n /**\n * @returns {number}\n */\n getWorkspaceHeight() {\n const currentDocument = this.domBindings.rootDocument;\n const trimmingContainer = this.dataAccessObject.topOverlayTrimmingContainer;\n let height = 0;\n if (trimmingContainer === this.domBindings.rootWindow) {\n height = currentDocument.documentElement.clientHeight;\n } else {\n const elemHeight = outerHeight(trimmingContainer);\n\n // returns height without DIV scrollbar\n height = elemHeight > 0 && trimmingContainer.clientHeight > 0 ? trimmingContainer.clientHeight : Infinity;\n }\n return height;\n }\n getWorkspaceWidth() {\n const {\n wtSettings\n } = this;\n const {\n rootDocument,\n rootWindow\n } = this.domBindings;\n const trimmingContainer = this.dataAccessObject.inlineStartOverlayTrimmingContainer;\n const docOffsetWidth = rootDocument.documentElement.offsetWidth;\n const totalColumns = wtSettings.getSetting('totalColumns');\n const preventOverflow = wtSettings.getSetting('preventOverflow');\n const isRtl = wtSettings.getSetting('rtlMode');\n const tableRect = this.wtTable.TABLE.getBoundingClientRect();\n const inlineStart = isRtl ? tableRect.right - docOffsetWidth : tableRect.left;\n const tableOffset = docOffsetWidth - inlineStart;\n let width;\n let overflow;\n if (preventOverflow) {\n return outerWidth(this.wtTable.wtRootElement);\n }\n if (wtSettings.getSetting('freezeOverlays')) {\n width = Math.min(tableOffset, docOffsetWidth);\n } else {\n width = Math.min(this.getContainerFillWidth(), tableOffset, docOffsetWidth);\n }\n if (trimmingContainer === rootWindow && totalColumns > 0 && this.sumColumnWidths(0, totalColumns - 1) > width) {\n // in case sum of column widths is higher than available stylesheet width, let's assume using the whole window\n // otherwise continue below, which will allow stretching\n // this is used in `scroll_window.html`\n // TODO test me\n return rootDocument.documentElement.clientWidth;\n }\n if (trimmingContainer !== rootWindow) {\n overflow = getStyle(this.dataAccessObject.inlineStartOverlayTrimmingContainer, 'overflow', rootWindow);\n if (overflow === 'scroll' || overflow === 'hidden' || overflow === 'auto') {\n // this is used in `scroll.html`\n // TODO test me\n return Math.max(width, trimmingContainer.clientWidth);\n }\n }\n const stretchSetting = wtSettings.getSetting('stretchH');\n if (stretchSetting === 'none' || !stretchSetting) {\n // if no stretching is used, return the maximum used workspace width\n return Math.max(width, outerWidth(this.wtTable.TABLE));\n }\n\n // if stretching is used, return the actual container width, so the columns can fit inside it\n return width;\n }\n\n /**\n * Checks if viewport has vertical scroll.\n *\n * @returns {boolean}\n */\n hasVerticalScroll() {\n return this.wtTable.hider.offsetHeight > this.getWorkspaceHeight();\n }\n\n /**\n * Checks if viewport has horizontal scroll.\n *\n * @returns {boolean}\n */\n hasHorizontalScroll() {\n return this.wtTable.hider.offsetWidth > this.getWorkspaceWidth();\n }\n\n /**\n * @param {number} from The visual column index from the width sum is start calculated.\n * @param {number} length The length of the column to traverse.\n * @returns {number}\n */\n sumColumnWidths(from, length) {\n let sum = 0;\n let column = from;\n while (column < length) {\n sum += this.wtTable.getColumnWidth(column);\n column += 1;\n }\n return sum;\n }\n\n /**\n * @returns {number}\n */\n getContainerFillWidth() {\n if (this.containerWidth) {\n return this.containerWidth;\n }\n const mainContainer = this.wtTable.holder;\n const dummyElement = this.domBindings.rootDocument.createElement('div');\n dummyElement.style.width = '100%';\n dummyElement.style.height = '1px';\n mainContainer.appendChild(dummyElement);\n const fillWidth = dummyElement.offsetWidth;\n this.containerWidth = fillWidth;\n mainContainer.removeChild(dummyElement);\n return fillWidth;\n }\n\n /**\n * @returns {number}\n */\n getWorkspaceOffset() {\n return offset(this.wtTable.TABLE);\n }\n\n /**\n * @returns {number}\n */\n getColumnHeaderHeight() {\n const columnHeaders = this.wtSettings.getSetting('columnHeaders');\n if (!columnHeaders.length) {\n this.columnHeaderHeight = 0;\n } else if (isNaN(this.columnHeaderHeight)) {\n this.columnHeaderHeight = outerHeight(this.wtTable.THEAD);\n }\n return this.columnHeaderHeight;\n }\n\n /**\n * @returns {number}\n */\n getViewportHeight() {\n let containerHeight = this.getWorkspaceHeight();\n if (containerHeight === Infinity) {\n return containerHeight;\n }\n const columnHeaderHeight = this.getColumnHeaderHeight();\n if (columnHeaderHeight > 0) {\n containerHeight -= columnHeaderHeight;\n }\n return containerHeight;\n }\n\n /**\n * @returns {number}\n */\n getRowHeaderWidth() {\n const rowHeadersWidthSetting = this.wtSettings.getSetting('rowHeaderWidth');\n const rowHeaders = this.wtSettings.getSetting('rowHeaders');\n if (rowHeadersWidthSetting) {\n this.rowHeaderWidth = 0;\n for (let i = 0, len = rowHeaders.length; i < len; i++) {\n this.rowHeaderWidth += rowHeadersWidthSetting[i] || rowHeadersWidthSetting;\n }\n }\n if (isNaN(this.rowHeaderWidth)) {\n if (rowHeaders.length) {\n let TH = this.wtTable.TABLE.querySelector('TH');\n this.rowHeaderWidth = 0;\n for (let i = 0, len = rowHeaders.length; i < len; i++) {\n if (TH) {\n this.rowHeaderWidth += outerWidth(TH);\n TH = TH.nextSibling;\n } else {\n // yes this is a cheat but it worked like that before, just taking assumption from CSS instead of measuring.\n // TODO: proper fix\n this.rowHeaderWidth += 50;\n }\n }\n } else {\n this.rowHeaderWidth = 0;\n }\n }\n this.rowHeaderWidth = this.wtSettings.getSetting('onModifyRowHeaderWidth', this.rowHeaderWidth) || this.rowHeaderWidth;\n return this.rowHeaderWidth;\n }\n\n /**\n * @returns {number}\n */\n getViewportWidth() {\n const containerWidth = this.getWorkspaceWidth();\n if (containerWidth === Infinity) {\n return containerWidth;\n }\n const rowHeaderWidth = this.getRowHeaderWidth();\n if (rowHeaderWidth > 0) {\n return containerWidth - rowHeaderWidth;\n }\n return containerWidth;\n }\n\n /**\n * Creates rows calculators. The type of the calculations can be chosen from the list:\n * - 'rendered' Calculates rows that should be rendered within the current table's viewport;\n * - 'fullyVisible' Calculates rows that are fully visible (used mostly for scrolling purposes);\n * - 'partiallyVisible' Calculates rows that are partially visible (used mostly for scrolling purposes).\n *\n * @param {'rendered' | 'fullyVisible' | 'partiallyVisible'} calculatorTypes The list of the calculation types.\n * @returns {ViewportRowsCalculator}\n */\n createRowsCalculator() {\n let calculatorTypes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['rendered', 'fullyVisible', 'partiallyVisible'];\n const {\n wtSettings,\n wtTable\n } = this;\n let height = this.getViewportHeight();\n let scrollbarHeight;\n let fixedRowsHeight;\n this.rowHeaderWidth = NaN;\n let pos = this.dataAccessObject.topScrollPosition - this.dataAccessObject.topParentOffset;\n const fixedRowsTop = wtSettings.getSetting('fixedRowsTop');\n const fixedRowsBottom = wtSettings.getSetting('fixedRowsBottom');\n const totalRows = wtSettings.getSetting('totalRows');\n if (fixedRowsTop && pos >= 0) {\n fixedRowsHeight = this.dataAccessObject.topOverlay.sumCellSizes(0, fixedRowsTop);\n pos += fixedRowsHeight;\n height -= fixedRowsHeight;\n }\n if (fixedRowsBottom && this.dataAccessObject.bottomOverlay.clone) {\n fixedRowsHeight = this.dataAccessObject.bottomOverlay.sumCellSizes(totalRows - fixedRowsBottom, totalRows);\n height -= fixedRowsHeight;\n }\n if (wtTable.holder.clientHeight === wtTable.holder.offsetHeight) {\n scrollbarHeight = 0;\n } else {\n scrollbarHeight = getScrollbarWidth(this.domBindings.rootDocument);\n }\n return new ViewportRowsCalculator({\n calculationTypes: calculatorTypes.map(type => [type, this.rowsCalculatorTypes.get(type)()]),\n viewportHeight: height,\n scrollOffset: pos,\n totalRows: wtSettings.getSetting('totalRows'),\n rowHeightFn: sourceRow => wtTable.getRowHeight(sourceRow),\n overrideFn: wtSettings.getSettingPure('viewportRowCalculatorOverride'),\n horizontalScrollbarHeight: scrollbarHeight\n });\n }\n\n /**\n * Creates columns calculators. The type of the calculations can be chosen from the list:\n * - 'rendered' Calculates columns that should be rendered within the current table's viewport;\n * - 'fullyVisible' Calculates columns that are fully visible (used mostly for scrolling purposes);\n * - 'partiallyVisible' Calculates columns that are partially visible (used mostly for scrolling purposes).\n *\n * @param {'rendered' | 'fullyVisible' | 'partiallyVisible'} calculatorTypes The list of the calculation types.\n * @returns {ViewportColumnsCalculator}\n */\n createColumnsCalculator() {\n let calculatorTypes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['rendered', 'fullyVisible', 'partiallyVisible'];\n const {\n wtSettings,\n wtTable\n } = this;\n let width = this.getViewportWidth();\n let pos = Math.abs(this.dataAccessObject.inlineStartScrollPosition) - this.dataAccessObject.inlineStartParentOffset;\n this.columnHeaderHeight = NaN;\n const fixedColumnsStart = wtSettings.getSetting('fixedColumnsStart');\n if (fixedColumnsStart && pos >= 0) {\n const fixedColumnsWidth = this.dataAccessObject.inlineStartOverlay.sumCellSizes(0, fixedColumnsStart);\n pos += fixedColumnsWidth;\n width -= fixedColumnsWidth;\n }\n if (wtTable.holder.clientWidth !== wtTable.holder.offsetWidth) {\n width -= getScrollbarWidth(this.domBindings.rootDocument);\n }\n return new ViewportColumnsCalculator({\n calculationTypes: calculatorTypes.map(type => [type, this.columnsCalculatorTypes.get(type)()]),\n viewportWidth: width,\n scrollOffset: pos,\n totalColumns: wtSettings.getSetting('totalColumns'),\n columnWidthFn: sourceCol => wtTable.getColumnWidth(sourceCol),\n overrideFn: wtSettings.getSettingPure('viewportColumnCalculatorOverride'),\n inlineStartOffset: this.dataAccessObject.inlineStartParentOffset\n });\n }\n\n /**\n * Creates rowsRenderCalculator and columnsRenderCalculator (before draw, to determine what rows and\n * cols should be rendered).\n *\n * @param {boolean} fastDraw If `true`, will try to avoid full redraw and only update the border positions.\n * If `false` or `undefined`, will perform a full redraw.\n * @returns {boolean} The fastDraw value, possibly modified.\n */\n createCalculators() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const {\n wtSettings\n } = this;\n const rowsCalculator = this.createRowsCalculator();\n const columnsCalculator = this.createColumnsCalculator();\n if (fastDraw && !wtSettings.getSetting('renderAllRows')) {\n const proposedRowsVisibleCalculator = rowsCalculator.getResultsFor('fullyVisible');\n fastDraw = this.areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator);\n }\n if (fastDraw && !wtSettings.getSetting('renderAllColumns')) {\n const proposedColumnsVisibleCalculator = columnsCalculator.getResultsFor('fullyVisible');\n fastDraw = this.areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator);\n }\n if (!fastDraw) {\n this.rowsRenderCalculator = rowsCalculator.getResultsFor('rendered');\n this.columnsRenderCalculator = columnsCalculator.getResultsFor('rendered');\n }\n this.rowsVisibleCalculator = rowsCalculator.getResultsFor('fullyVisible');\n this.columnsVisibleCalculator = columnsCalculator.getResultsFor('fullyVisible');\n this.rowsPartiallyVisibleCalculator = rowsCalculator.getResultsFor('partiallyVisible');\n this.columnsPartiallyVisibleCalculator = columnsCalculator.getResultsFor('partiallyVisible');\n return fastDraw;\n }\n\n /**\n * Creates rows and columns calculators (after draw, to determine what are\n * the actually fully visible and partially visible rows and columns).\n */\n createVisibleCalculators() {\n const rowsCalculator = this.createRowsCalculator(['fullyVisible', 'partiallyVisible']);\n const columnsCalculator = this.createColumnsCalculator(['fullyVisible', 'partiallyVisible']);\n this.rowsVisibleCalculator = rowsCalculator.getResultsFor('fullyVisible');\n this.columnsVisibleCalculator = columnsCalculator.getResultsFor('fullyVisible');\n this.rowsPartiallyVisibleCalculator = rowsCalculator.getResultsFor('partiallyVisible');\n this.columnsPartiallyVisibleCalculator = columnsCalculator.getResultsFor('partiallyVisible');\n }\n\n /**\n * Returns information whether proposedRowsVisibleCalculator viewport\n * is contained inside rows rendered in previous draw (cached in rowsRenderCalculator).\n *\n * @param {ViewportRowsCalculator} proposedRowsVisibleCalculator The instance of the viewport calculator to compare with.\n * @returns {boolean} Returns `true` if all proposed visible rows are already rendered (meaning: redraw is not needed).\n * Returns `false` if at least one proposed visible row is not already rendered (meaning: redraw is needed).\n */\n areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator) {\n if (!this.rowsVisibleCalculator) {\n return false;\n }\n let {\n startRow,\n endRow\n } = proposedRowsVisibleCalculator;\n\n // if there are no fully visible rows at all...\n if (startRow === null && endRow === null) {\n if (!proposedRowsVisibleCalculator.isVisibleInTrimmingContainer) {\n return true;\n }\n // ...use partially visible rows calculator to determine what render type is needed\n startRow = this.rowsPartiallyVisibleCalculator.startRow;\n endRow = this.rowsPartiallyVisibleCalculator.endRow;\n }\n const {\n startRow: renderedStartRow,\n endRow: renderedEndRow\n } = this.rowsRenderCalculator;\n if (startRow < renderedStartRow || startRow === renderedStartRow && startRow > 0) {\n return false;\n } else if (endRow > renderedEndRow || endRow === renderedEndRow && endRow < this.wtSettings.getSetting('totalRows') - 1) {\n return false;\n }\n return true;\n }\n\n /**\n * Returns information whether proposedColumnsVisibleCalculator viewport\n * is contained inside column rendered in previous draw (cached in columnsRenderCalculator).\n *\n * @param {ViewportRowsCalculator} proposedColumnsVisibleCalculator The instance of the viewport calculator to compare with.\n * @returns {boolean} Returns `true` if all proposed visible columns are already rendered (meaning: redraw is not needed).\n * Returns `false` if at least one proposed visible column is not already rendered (meaning: redraw is needed).\n */\n areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator) {\n if (!this.columnsVisibleCalculator) {\n return false;\n }\n let {\n startColumn,\n endColumn\n } = proposedColumnsVisibleCalculator;\n\n // if there are no fully visible columns at all...\n if (startColumn === null && endColumn === null) {\n if (!proposedColumnsVisibleCalculator.isVisibleInTrimmingContainer) {\n return true;\n }\n // ...use partially visible columns calculator to determine what render type is needed\n startColumn = this.columnsPartiallyVisibleCalculator.startColumn;\n endColumn = this.columnsPartiallyVisibleCalculator.endColumn;\n }\n const {\n startColumn: renderedStartColumn,\n endColumn: renderedEndColumn\n } = this.columnsRenderCalculator;\n if (startColumn < renderedStartColumn || startColumn === renderedStartColumn && startColumn > 0) {\n return false;\n } else if (endColumn > renderedEndColumn || endColumn === renderedEndColumn && endColumn < this.wtSettings.getSetting('totalColumns') - 1) {\n return false;\n }\n return true;\n }\n\n /**\n * Resets values in keys of the hasOversizedColumnHeadersMarked object after updateSettings.\n */\n resetHasOversizedColumnHeadersMarked() {\n objectEach(this.hasOversizedColumnHeadersMarked, (value, key, object) => {\n object[key] = undefined;\n });\n }\n}\nexport default Viewport;","import Walkontable from \"../core/core.mjs\";\nimport CoreAbstract from \"../core/_base.mjs\";\n/**\n * This layer cares about backward compatibility.\n *\n * @class WalkontableFacade\n * @augments Walkontable\n * @inheritDoc\n */\nexport default class WalkontableFacade {\n /**\n * @param {SettingsPure|Walkontable} settingsOrInstance The Walkontable settings.\n */\n constructor(settingsOrInstance) {\n if (settingsOrInstance instanceof CoreAbstract) {\n this._wot = settingsOrInstance;\n } else {\n this._initFromSettings(settingsOrInstance);\n }\n }\n _initFromSettings(settings) {\n settings.facade = instance => {\n const facade = new WalkontableFacade(instance);\n return () => facade;\n };\n this._wot = new Walkontable(settings.table, settings);\n }\n get guid() {\n return this._wot.guid;\n }\n get rootDocument() {\n return this._wot.domBindings.rootDocument;\n }\n get rootWindow() {\n return this._wot.domBindings.rootWindow;\n }\n get wtSettings() {\n return this._wot.wtSettings; // todo create facade\n }\n get cloneSource() {\n return this._wot.cloneSource; // todo create facade\n }\n get cloneOverlay() {\n return this._wot.cloneOverlay; // todo create facade\n }\n get selectionManager() {\n return this._wot.selectionManager; // todo create facade\n }\n get wtViewport() {\n return this._wot.wtViewport; // todo create facade\n }\n get wtOverlays() {\n return this._wot.wtOverlays; // todo create facade\n }\n get wtTable() {\n return this._wot.wtTable; // todo create facade\n }\n get wtEvent() {\n return this._wot.wtEvent; // todo create facade\n }\n get wtScroll() {\n return this._wot.wtScroll; // todo create facade\n }\n get drawn() {\n return this._wot.drawn;\n }\n set drawn(value) {\n this._wot.drawn = value;\n }\n get drawInterrupted() {\n return this._wot.drawInterrupted;\n }\n set drawInterrupted(value) {\n this._wot.drawInterrupted = value;\n }\n get lastMouseOver() {\n return this._wot.lastMouseOver;\n }\n set lastMouseOver(value) {\n this._wot.lastMouseOver = value;\n }\n get momentumScrolling() {\n return this._wot.momentumScrolling;\n }\n set momentumScrolling(value) {\n this._wot.momentumScrolling = value;\n }\n get touchApplied() {\n return this._wot.touchApplied;\n }\n set touchApplied(value) {\n this._wot.touchApplied = value;\n }\n get domBindings() {\n return this._wot.domBindings;\n }\n get eventListeners() {\n return this._wot.eventListeners;\n }\n set eventListeners(value) {\n this._wot.eventListeners = value;\n }\n get eventManager() {\n return this._wot.eventManager;\n }\n createCellCoords(row, column) {\n return this._wot.createCellCoords(row, column);\n }\n createCellRange(highlight, from, to) {\n return this._wot.createCellRange(highlight, from, to);\n }\n draw() {\n let fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n this._wot.draw(fastDraw);\n return this;\n }\n getCell(coords) {\n let topmost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n return this._wot.getCell(coords, topmost);\n }\n scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft) {\n return this._wot.scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft);\n }\n scrollViewportHorizontally(column, snapToRight, snapToLeft) {\n return this._wot.scrollViewportHorizontally(column, snapToRight, snapToLeft);\n }\n scrollViewportVertically(row, snapToTop, snapToBottom) {\n return this._wot.scrollViewportVertically(row, snapToTop, snapToBottom);\n }\n getViewport() {\n return this._wot.getViewport();\n }\n getOverlayName() {\n return this._wot.cloneOverlay ? this._wot.cloneOverlay.type : 'master';\n }\n getOverlayByName(overlayName) {\n return this._wot.getOverlayByName(overlayName);\n }\n exportSettingsAsClassNames() {\n return this._wot.exportSettingsAsClassNames();\n }\n update(settings, value) {\n this._wot.wtSettings.update(settings, value);\n return this;\n }\n getSetting(key, param1, param2, param3, param4) {\n return this._wot.wtSettings.getSetting(key, param1, param2, param3, param4);\n }\n hasSetting(key) {\n return this._wot.wtSettings.hasSetting(key);\n }\n destroy() {\n this._wot.destroy();\n }\n}","import { isRightClick as isRightClickEvent, isLeftClick as isLeftClickEvent } from \"./../helpers/dom/event.mjs\";\n/**\n * MouseDown handler.\n *\n * @param {object} options The handler options.\n * @param {boolean} options.isShiftKey The flag which indicates if the shift key is pressed.\n * @param {boolean} options.isLeftClick The flag which indicates if the left mouse button is pressed.\n * @param {boolean} options.isRightClick The flag which indicates if the right mouse button is pressed.\n * @param {CellRange} options.coords The CellCoords object with defined visual coordinates.\n * @param {Selection} options.selection The Selection class instance.\n * @param {object} options.controller An object with keys `row`, `column`, `cell` which indicate what\n * operation will be performed in later selection stages.\n * @param {Function} options.cellCoordsFactory The function factory for CellCoords objects.\n */\nexport function mouseDown(_ref) {\n let {\n isShiftKey,\n isLeftClick,\n isRightClick,\n coords,\n selection,\n controller,\n cellCoordsFactory\n } = _ref;\n const currentSelection = selection.isSelected() ? selection.getSelectedRange().current() : null;\n const selectedCorner = selection.isSelectedByCorner();\n const selectedRow = selection.isSelectedByRowHeader();\n selection.markSource('mouse');\n if (isShiftKey && currentSelection) {\n if (coords.row >= 0 && coords.col >= 0 && !controller.cell) {\n selection.setRangeEnd(coords);\n } else if ((selectedCorner || selectedRow) && coords.row >= 0 && coords.col >= 0 && !controller.cell) {\n selection.setRangeEnd(cellCoordsFactory(coords.row, coords.col));\n } else if (selectedCorner && coords.row < 0 && !controller.column) {\n selection.setRangeEnd(cellCoordsFactory(currentSelection.to.row, coords.col));\n } else if (selectedRow && coords.col < 0 && !controller.row) {\n selection.setRangeEnd(cellCoordsFactory(coords.row, currentSelection.to.col));\n } else if ((!selectedCorner && !selectedRow && coords.col < 0 || selectedCorner && coords.col < 0) && !controller.row) {\n selection.selectRows(Math.max(currentSelection.from.row, 0), coords.row, coords.col);\n } else if ((!selectedCorner && !selectedRow && coords.row < 0 || selectedRow && coords.row < 0) && !controller.column) {\n selection.selectColumns(Math.max(currentSelection.from.col, 0), coords.col, coords.row);\n }\n } else {\n const allowRightClickSelection = !selection.inInSelection(coords);\n const performSelection = isLeftClick || isRightClick && allowRightClickSelection;\n\n // clicked row header and when some column was selected\n if (coords.row < 0 && coords.col >= 0 && !controller.column) {\n if (performSelection) {\n selection.selectColumns(coords.col, coords.col, coords.row);\n }\n\n // clicked column header and when some row was selected\n } else if (coords.col < 0 && coords.row >= 0 && !controller.row) {\n if (performSelection) {\n selection.selectRows(coords.row, coords.row, coords.col);\n }\n } else if (coords.col >= 0 && coords.row >= 0 && !controller.cell) {\n if (performSelection) {\n selection.setRangeStart(coords);\n }\n } else if (coords.col < 0 && coords.row < 0) {\n selection.selectAll(true, true, {\n disableHeadersHighlight: true,\n focusPosition: {\n row: 0,\n col: 0\n }\n });\n }\n }\n selection.markEndSource();\n}\n\n/**\n * MouseOver handler.\n *\n * @param {object} options The handler options.\n * @param {boolean} options.isLeftClick Indicates that event was fired using the left mouse button.\n * @param {CellRange} options.coords The CellCoords object with defined visual coordinates.\n * @param {Selection} options.selection The Selection class instance.\n * @param {object} options.controller An object with keys `row`, `column`, `cell` which indicate what\n * operation will be performed in later selection stages.\n * @param {Function} options.cellCoordsFactory The function factory for CellCoords objects.\n */\nexport function mouseOver(_ref2) {\n let {\n isLeftClick,\n coords,\n selection,\n controller,\n cellCoordsFactory\n } = _ref2;\n if (!isLeftClick) {\n return;\n }\n const selectedRow = selection.isSelectedByRowHeader();\n const selectedColumn = selection.isSelectedByColumnHeader();\n const countCols = selection.tableProps.countCols();\n const countRows = selection.tableProps.countRows();\n selection.markSource('mouse');\n if (selectedColumn && !controller.column) {\n selection.setRangeEnd(cellCoordsFactory(countRows - 1, coords.col));\n } else if (selectedRow && !controller.row) {\n selection.setRangeEnd(cellCoordsFactory(coords.row, countCols - 1));\n } else if (!controller.cell) {\n selection.setRangeEnd(coords);\n }\n selection.markEndSource();\n}\nconst handlers = new Map([['mousedown', mouseDown], ['mouseover', mouseOver], ['touchstart', mouseDown]]);\n\n/**\n * Mouse handler for selection functionality.\n *\n * @param {Event} event An native event to handle.\n * @param {object} options The handler options.\n * @param {CellRange} options.coords The CellCoords object with defined visual coordinates.\n * @param {Selection} options.selection The Selection class instance.\n * @param {object} options.controller An object with keys `row`, `column`, `cell` which indicate what\n * operation will be performed in later selection stages.\n * @param {Function} options.cellCoordsFactory The function factory for CellCoords objects.\n */\nexport function handleMouseEvent(event, _ref3) {\n let {\n coords,\n selection,\n controller,\n cellCoordsFactory\n } = _ref3;\n handlers.get(event.type)({\n coords,\n selection,\n controller,\n cellCoordsFactory,\n isShiftKey: event.shiftKey,\n isLeftClick: isLeftClickEvent(event) || event.type === 'touchstart',\n isRightClick: isRightClickEvent(event)\n });\n}","export const holder = new WeakMap();\nexport const rootInstanceSymbol = Symbol('rootInstance');\n\n/**\n * Register an object as a root instance.\n *\n * @param {object} object An object to associate with root instance flag.\n */\nexport function registerAsRootInstance(object) {\n holder.set(object, true);\n}\n\n/**\n * Check if the source of the root indication call is valid.\n *\n * @param {symbol} rootSymbol A symbol as a source of truth.\n * @returns {boolean}\n */\nexport function hasValidParameter(rootSymbol) {\n return rootSymbol === rootInstanceSymbol;\n}\n\n/**\n * Check if passed an object was flagged as a root instance.\n *\n * @param {object} object An object to check.\n * @returns {boolean}\n */\nexport function isRootInstance(object) {\n return holder.has(object);\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { createObjectPropListener, getProperty, isObject, objectEach, setProperty } from \"../helpers/object.mjs\";\nimport { countFirstRowKeys } from \"../helpers/data.mjs\";\nimport { arrayEach } from \"../helpers/array.mjs\";\nimport { rangeEach } from \"../helpers/number.mjs\";\nimport { isFunction } from \"../helpers/function.mjs\";\n/**\n * @class DataSource\n * @private\n */\nclass DataSource {\n constructor(hotInstance) {\n let dataSource = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];\n /**\n * Instance of Handsontable.\n *\n * @type {Handsontable}\n */\n _defineProperty(this, \"hot\", void 0);\n /**\n * Data source.\n *\n * @type {Array}\n */\n _defineProperty(this, \"data\", void 0);\n /**\n * Type of data source.\n *\n * @type {string}\n * @default 'array'\n */\n _defineProperty(this, \"dataType\", 'array');\n _defineProperty(this, \"colToProp\", () => {});\n _defineProperty(this, \"propToCol\", () => {});\n this.hot = hotInstance;\n this.data = dataSource;\n }\n\n /**\n * Run the `modifyRowData` hook and return either the modified or the source data for the provided row.\n *\n * @private\n * @param {number} rowIndex Row index.\n * @returns {Array|object} Source or modified row of data.\n */\n modifyRowData(rowIndex) {\n let modifyRowData;\n if (this.hot.hasHook('modifyRowData')) {\n modifyRowData = this.hot.runHooks('modifyRowData', rowIndex);\n }\n return modifyRowData !== undefined && !Number.isInteger(modifyRowData) ? modifyRowData : this.data[rowIndex];\n }\n\n /**\n * Get all data.\n *\n * @param {boolean} [toArray=false] If `true` return source data as an array of arrays even when source data was provided\n * in another format.\n * @returns {Array}\n */\n getData() {\n let toArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n if (!this.data || this.data.length === 0) {\n return this.data;\n }\n return this.getByRange(null, null, toArray);\n }\n\n /**\n * Set new data source.\n *\n * @param {Array} data The new data.\n */\n setData(data) {\n this.data = data;\n }\n\n /**\n * Returns array of column values from the data source. `column` is the index of the row in the data source.\n *\n * @param {number} column Visual column index.\n * @returns {Array}\n */\n getAtColumn(column) {\n const result = [];\n arrayEach(this.data, (row, rowIndex) => {\n const value = this.getAtCell(rowIndex, column);\n result.push(value);\n });\n return result;\n }\n\n /**\n * Returns a single row of the data or a subset of its columns. If a column range or `toArray` arguments are provided, it\n * operates only on the columns declared by the `columns` setting or the data schema.\n *\n * @param {number} row Physical row index.\n * @param {number} [startColumn] Starting index for the column range (optional).\n * @param {number} [endColumn] Ending index for the column range (optional).\n * @param {boolean} [toArray=false] `true` if the returned value should be forced to be presented as an array.\n * @returns {Array|object}\n */\n getAtRow(row, startColumn, endColumn) {\n let toArray = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n const getAllProps = startColumn === undefined && endColumn === undefined;\n const {\n dataDotNotation\n } = this.hot.getSettings();\n let dataRow = null;\n let newDataRow = null;\n dataRow = this.modifyRowData(row);\n if (Array.isArray(dataRow)) {\n newDataRow = [];\n if (getAllProps) {\n dataRow.forEach((cell, column) => {\n newDataRow[column] = this.getAtPhysicalCell(row, column, dataRow);\n });\n } else {\n // Only the columns from the provided range\n rangeEach(startColumn, endColumn, column => {\n newDataRow[column - startColumn] = this.getAtPhysicalCell(row, column, dataRow);\n });\n }\n } else if (isObject(dataRow) || isFunction(dataRow)) {\n if (toArray) {\n newDataRow = [];\n } else {\n newDataRow = {};\n }\n if (!getAllProps || toArray) {\n const rangeStart = 0;\n const rangeEnd = this.countFirstRowKeys() - 1;\n rangeEach(rangeStart, rangeEnd, column => {\n const prop = this.colToProp(column);\n if (column >= (startColumn || rangeStart) && column <= (endColumn || rangeEnd) && !Number.isInteger(prop)) {\n const cellValue = this.getAtPhysicalCell(row, prop, dataRow);\n if (toArray) {\n newDataRow.push(cellValue);\n } else if (dataDotNotation) {\n setProperty(newDataRow, prop, cellValue);\n } else {\n newDataRow[prop] = cellValue;\n }\n }\n });\n } else {\n objectEach(dataRow, (value, prop) => {\n const cellValue = this.getAtPhysicalCell(row, prop, dataRow);\n if (dataDotNotation) {\n setProperty(newDataRow, prop, cellValue);\n } else {\n newDataRow[prop] = cellValue;\n }\n });\n }\n }\n return newDataRow;\n }\n\n /**\n * Set the provided value in the source data set at the provided coordinates.\n *\n * @param {number} row Physical row index.\n * @param {number|string} column Property name / physical column index.\n * @param {*} value The value to be set at the provided coordinates.\n */\n setAtCell(row, column, value) {\n if (row >= this.countRows() || column >= this.countFirstRowKeys()) {\n // Not enough rows and/or columns.\n return;\n }\n if (this.hot.hasHook('modifySourceData')) {\n const valueHolder = createObjectPropListener(value);\n this.hot.runHooks('modifySourceData', row, column, valueHolder, 'set');\n if (valueHolder.isTouched()) {\n value = valueHolder.value;\n }\n }\n if (!Number.isInteger(column)) {\n // column argument is the prop name\n setProperty(this.data[row], column, value);\n } else {\n this.data[row][column] = value;\n }\n }\n\n /**\n * Get data from the source data set using the physical indexes.\n *\n * @private\n * @param {number} row Physical row index.\n * @param {string|number|Function} column Physical column index / property / function.\n * @param {Array|object} dataRow A representation of a data row.\n * @returns {*} Value at the provided coordinates.\n */\n getAtPhysicalCell(row, column, dataRow) {\n let result = null;\n if (dataRow) {\n if (typeof column === 'string') {\n const {\n dataDotNotation\n } = this.hot.getSettings();\n result = dataDotNotation ? getProperty(dataRow, column) : dataRow[column];\n } else if (typeof column === 'function') {\n result = column(dataRow);\n } else {\n result = dataRow[column];\n }\n }\n if (this.hot.hasHook('modifySourceData')) {\n const valueHolder = createObjectPropListener(result);\n this.hot.runHooks('modifySourceData', row, column, valueHolder, 'get');\n if (valueHolder.isTouched()) {\n result = valueHolder.value;\n }\n }\n return result;\n }\n\n /**\n * Returns a single value from the data.\n *\n * @param {number} row Physical row index.\n * @param {number} columnOrProp Visual column index or property.\n * @returns {*}\n */\n getAtCell(row, columnOrProp) {\n const dataRow = this.modifyRowData(row);\n return this.getAtPhysicalCell(row, this.colToProp(columnOrProp), dataRow);\n }\n\n /**\n * Returns source data by passed range.\n *\n * @param {object} [start] Object with physical `row` and `col` keys (or visual column index, if data type is an array of objects).\n * @param {object} [end] Object with physical `row` and `col` keys (or visual column index, if data type is an array of objects).\n * @param {boolean} [toArray=false] If `true` return source data as an array of arrays even when source data was provided\n * in another format.\n * @returns {Array}\n */\n getByRange() {\n let start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let end = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n let toArray = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let getAllProps = false;\n let startRow = null;\n let startCol = null;\n let endRow = null;\n let endCol = null;\n if (start === null || end === null) {\n getAllProps = true;\n startRow = 0;\n endRow = this.countRows() - 1;\n } else {\n startRow = Math.min(start.row, end.row);\n startCol = Math.min(start.col, end.col);\n endRow = Math.max(start.row, end.row);\n endCol = Math.max(start.col, end.col);\n }\n const result = [];\n rangeEach(startRow, endRow, currentRow => {\n result.push(getAllProps ? this.getAtRow(currentRow, undefined, undefined, toArray) : this.getAtRow(currentRow, startCol, endCol, toArray));\n });\n return result;\n }\n\n /**\n * Count number of rows.\n *\n * @returns {number}\n */\n countRows() {\n if (this.hot.hasHook('modifySourceLength')) {\n const modifiedSourceLength = this.hot.runHooks('modifySourceLength');\n if (Number.isInteger(modifiedSourceLength)) {\n return modifiedSourceLength;\n }\n }\n return this.data.length;\n }\n\n /**\n * Count number of columns.\n *\n * @returns {number}\n */\n countFirstRowKeys() {\n return countFirstRowKeys(this.data);\n }\n\n /**\n * Destroy instance.\n */\n destroy() {\n this.data = null;\n this.hot = null;\n }\n}\nexport default DataSource;","import \"core-js/modules/es.array.push.js\";\nimport { deepObjectSize, isObject } from \"./object.mjs\";\nconst COLUMN_LABEL_BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst COLUMN_LABEL_BASE_LENGTH = COLUMN_LABEL_BASE.length;\n\n/**\n * Generates spreadsheet-like column names: A, B, C, ..., Z, AA, AB, etc.\n *\n * @param {number} index Column index.\n * @returns {string}\n */\nexport function spreadsheetColumnLabel(index) {\n let dividend = index + 1;\n let columnLabel = '';\n let modulo;\n while (dividend > 0) {\n modulo = (dividend - 1) % COLUMN_LABEL_BASE_LENGTH;\n columnLabel = String.fromCharCode(65 + modulo) + columnLabel;\n dividend = parseInt((dividend - modulo) / COLUMN_LABEL_BASE_LENGTH, 10);\n }\n return columnLabel;\n}\n\n/**\n * Generates spreadsheet-like column index from theirs labels: A, B, C ...., Z, AA, AB, etc.\n *\n * @param {string} label Column label.\n * @returns {number}\n */\nexport function spreadsheetColumnIndex(label) {\n let result = 0;\n if (label) {\n for (let i = 0, j = label.length - 1; i < label.length; i += 1, j -= 1) {\n result += COLUMN_LABEL_BASE_LENGTH ** j * (COLUMN_LABEL_BASE.indexOf(label[i]) + 1);\n }\n }\n result -= 1;\n return result;\n}\n\n/**\n * Creates 2D array of Excel-like values \"A1\", \"A2\", ...\n *\n * @param {number} rows Number of rows to generate.\n * @param {number} columns Number of columns to generate.\n * @returns {Array}\n */\nexport function createSpreadsheetData() {\n let rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;\n let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;\n const _rows = [];\n let i;\n let j;\n for (i = 0; i < rows; i++) {\n const row = [];\n for (j = 0; j < columns; j++) {\n row.push(spreadsheetColumnLabel(j) + (i + 1));\n }\n _rows.push(row);\n }\n return _rows;\n}\n\n/**\n * Creates 2D array of Excel-like values \"A1\", \"A2\", as an array of objects.\n *\n * @param {number} rows Number of rows to generate.\n * @param {number} colCount Number of columns to generate.\n * @returns {Array}\n */\nexport function createSpreadsheetObjectData() {\n let rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;\n let colCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;\n const _rows = [];\n let i;\n let j;\n for (i = 0; i < rows; i++) {\n const row = {};\n for (j = 0; j < colCount; j++) {\n row[`prop${j}`] = spreadsheetColumnLabel(j) + (i + 1);\n }\n _rows.push(row);\n }\n return _rows;\n}\n\n/**\n * Generates an empty data object.\n *\n * @param {number} rows Number of rows to generate.\n * @param {number} columns Number of columns to generate.\n * @returns {Array}\n */\nexport function createEmptySpreadsheetData(rows, columns) {\n const data = [];\n let row;\n for (let i = 0; i < rows; i++) {\n row = [];\n for (let j = 0; j < columns; j++) {\n row.push('');\n }\n data.push(row);\n }\n return data;\n}\n\n/**\n * Transform a data row (either an array or an object) or an array of data rows to array of changes in a form of `[row,\n * prop/col, value]`. Convenient to use with `setDataAtRowProp` and `setSourceDataAtCell` methods.\n *\n * @param {Array|object} dataRow Object of row data, array of row data or an array of either.\n * @param {number} rowOffset Row offset to be passed to the resulting change list. Defaults to `0`.\n * @returns {Array} Array of changes (in a form of an array).\n */\nexport function dataRowToChangesArray(dataRow) {\n let rowOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n let dataRows = dataRow;\n const changesArray = [];\n if (!Array.isArray(dataRow) || !Array.isArray(dataRow[0])) {\n dataRows = [dataRow];\n }\n dataRows.forEach((row, rowIndex) => {\n if (Array.isArray(row)) {\n row.forEach((value, column) => {\n changesArray.push([rowIndex + rowOffset, column, value]);\n });\n } else {\n Object.keys(row).forEach(propName => {\n changesArray.push([rowIndex + rowOffset, propName, row[propName]]);\n });\n }\n });\n return changesArray;\n}\n\n/**\n * Count the number of keys (or, basically, columns when the data is an array or arrays) in the first row of the\n * provided dataset.\n *\n * @param {Array} data The dataset.\n * @returns {number} Number of keys in the first row of the dataset.\n */\nexport function countFirstRowKeys(data) {\n let result = 0;\n if (Array.isArray(data)) {\n if (data[0] && Array.isArray(data[0])) {\n result = data[0].length;\n } else if (data[0] && isObject(data[0])) {\n result = deepObjectSize(data[0]);\n }\n }\n return result;\n}\n\n/**\n * Check whether the provided dataset is a *non-empty* array of arrays.\n *\n * @param {Array} data Dataset to be checked.\n * @returns {boolean} `true` if data is an array of arrays, `false` otherwise.\n */\nexport function isArrayOfArrays(data) {\n return !!(Array.isArray(data) && data.length && data.every(el => Array.isArray(el)));\n}\n\n/**\n * Check whether the provided dataset is a *non-empty* array of objects.\n *\n * @param {Array} data Dataset to be checked.\n * @returns {boolean} `true` if data is an array of objects, `false` otherwise.\n */\nexport function isArrayOfObjects(data) {\n return !!(Array.isArray(data) && data.length && data.every(el => typeof el === 'object' && !Array.isArray(el) && el !== null));\n}","function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nimport { arrayMap } from \"../helpers/array.mjs\";\nimport { createIndexMap, getListWithInsertedItems, getListWithRemovedItems, HidingMap, IndexesSequence, TrimmingMap } from \"./maps/index.mjs\";\nimport { AggregatedCollection, MapCollection } from \"./mapCollections/index.mjs\";\nimport localHooks from \"../mixins/localHooks.mjs\";\nimport { mixin } from \"../helpers/object.mjs\";\nimport { isDefined } from \"../helpers/mixed.mjs\";\nimport { ChangesObservable } from \"./changesObservable/observable.mjs\";\n/**\n * A set of deprecated feature names.\n *\n * @type {Set}\n */\n// eslint-disable-next-line no-unused-vars\nconst deprecationWarns = new Set();\n\n/**\n * @class IndexMapper\n * @description\n *\n * Index mapper stores, registers and manages the indexes on the basis of calculations collected from the subsidiary maps.\n * It should be seen as a single source of truth (regarding row and column indexes, for example, their sequence, information if they are skipped in the process of rendering (hidden or trimmed), values linked to them)\n * for any operation that considers CRUD actions such as **insertion**, **movement**, **removal** etc, and is used to properly calculate physical and visual indexes translations in both ways.\n * It has a built-in cache that is updated only when the data or structure changes.\n *\n * **Physical index** is a type of an index from the sequence of indexes assigned to the data source rows or columns\n * (from 0 to n, where n is number of the cells on the axis of data set).\n * **Visual index** is a type of an index from the sequence of indexes assigned to rows or columns existing in {@link DataMap} (from 0 to n, where n is number of the cells on the axis of data set).\n * **Renderable index** is a type of an index from the sequence of indexes assigned to rows or columns whose may be rendered (when they are in a viewport; from 0 to n, where n is number of the cells renderable on the axis).\n *\n * There are different kinds of index maps which may be registered in the collections and can be used by a reference.\n * They also expose public API and trigger two local hooks such as `init` (on initialization) and `change` (on change).\n *\n * These are: {@link IndexesSequence}, {@link PhysicalIndexToValueMap}, {@link LinkedPhysicalIndexToValueMap}, {@link HidingMap}, and {@link TrimmingMap}.\n */\nexport class IndexMapper {\n constructor() {\n /**\n * Map for storing the sequence of indexes.\n *\n * It is registered by default and may be used from API methods.\n *\n * @private\n * @type {IndexesSequence}\n */\n _defineProperty(this, \"indexesSequence\", new IndexesSequence());\n /**\n * Collection for different trimming maps. Indexes marked as trimmed in any map WILL NOT be included in\n * the {@link DataMap} and won't be rendered.\n *\n * @private\n * @type {MapCollection}\n */\n _defineProperty(this, \"trimmingMapsCollection\", new AggregatedCollection(valuesForIndex => valuesForIndex.some(value => value === true), false));\n /**\n * Collection for different hiding maps. Indexes marked as hidden in any map WILL be included in the {@link DataMap},\n * but won't be rendered.\n *\n * @private\n * @type {MapCollection}\n */\n _defineProperty(this, \"hidingMapsCollection\", new AggregatedCollection(valuesForIndex => valuesForIndex.some(value => value === true), false));\n /**\n * Collection for another kind of maps. There are stored mappings from indexes (visual or physical) to values.\n *\n * @private\n * @type {MapCollection}\n */\n _defineProperty(this, \"variousMapsCollection\", new MapCollection());\n /**\n * The class instance collects row and column index changes that happen while the Handsontable\n * is running. The object allows creating observers that you can subscribe. Each event represents\n * the index change (e.g., insert, removing, change index value), which can be consumed by a\n * developer to update its logic.\n *\n * @private\n * @type {ChangesObservable}\n */\n _defineProperty(this, \"hidingChangesObservable\", new ChangesObservable({\n initialIndexValue: false\n }));\n /**\n * Cache for list of not trimmed indexes, respecting the indexes sequence (physical indexes).\n *\n * Note: Please keep in mind that trimmed index can be also hidden.\n *\n * @private\n * @type {Array}\n */\n _defineProperty(this, \"notTrimmedIndexesCache\", []);\n /**\n * Cache for list of not hidden indexes, respecting the indexes sequence (physical indexes).\n *\n * Note: Please keep in mind that hidden index can be also trimmed.\n *\n * @private\n * @type {Array}\n */\n _defineProperty(this, \"notHiddenIndexesCache\", []);\n /**\n * Flag determining whether actions performed on index mapper have been batched. It's used for cache management.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"isBatched\", false);\n /**\n * Flag determining whether any action on indexes sequence has been performed. It's used for cache management.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"indexesSequenceChanged\", false);\n /**\n * Flag informing about source of the change.\n *\n * @type {undefined|string}\n */\n _defineProperty(this, \"indexesChangeSource\", undefined);\n /**\n * Flag determining whether any action on trimmed indexes has been performed. It's used for cache management.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"trimmedIndexesChanged\", false);\n /**\n * Flag determining whether any action on hidden indexes has been performed. It's used for cache management.\n *\n * @private\n * @type {boolean}\n */\n _defineProperty(this, \"hiddenIndexesChanged\", false);\n /**\n * Physical indexes (respecting the sequence of indexes) which may be rendered (when they are in a viewport).\n *\n * @private\n * @type {Array}\n */\n _defineProperty(this, \"renderablePhysicalIndexesCache\", []);\n /**\n * Visual indexes (native map's value) corresponding to physical indexes (native map's index).\n *\n * @private\n * @type {Map}\n */\n _defineProperty(this, \"fromPhysicalToVisualIndexesCache\", new Map());\n /**\n * Visual indexes (native map's value) corresponding to physical indexes (native map's index).\n *\n * @private\n * @type {Map}\n */\n _defineProperty(this, \"fromVisualToRenderableIndexesCache\", new Map());\n this.indexesSequence.addLocalHook('change', () => {\n this.indexesSequenceChanged = true;\n\n // Sequence of stored indexes might change.\n this.updateCache();\n this.runLocalHooks('indexesSequenceChange', this.indexesChangeSource);\n this.runLocalHooks('change', this.indexesSequence, null);\n });\n this.trimmingMapsCollection.addLocalHook('change', changedMap => {\n this.trimmedIndexesChanged = true;\n\n // Number of trimmed indexes might change.\n this.updateCache();\n this.runLocalHooks('change', changedMap, this.trimmingMapsCollection);\n });\n this.hidingMapsCollection.addLocalHook('change', changedMap => {\n this.hiddenIndexesChanged = true;\n\n // Number of hidden indexes might change.\n this.updateCache();\n this.runLocalHooks('change', changedMap, this.hidingMapsCollection);\n });\n this.variousMapsCollection.addLocalHook('change', changedMap => {\n this.runLocalHooks('change', changedMap, this.variousMapsCollection);\n });\n }\n\n /**\n * Suspends the cache update for this map. The method is helpful to group multiple\n * operations, which affects the cache. In this case, the cache will be updated once after\n * calling the `resumeOperations` method.\n */\n suspendOperations() {\n this.isBatched = true;\n }\n\n /**\n * Resumes the cache update for this map. It recalculates the cache and restores the\n * default behavior where each map modification updates the cache.\n */\n resumeOperations() {\n this.isBatched = false;\n this.updateCache();\n }\n\n /**\n * It creates and returns the new instance of the ChangesObserver object. The object\n * allows listening to the index changes that happen while the Handsontable is running.\n *\n * @param {string} indexMapType The index map type which we want to observe.\n * Currently, only the 'hiding' index map types are observable.\n * @returns {ChangesObserver}\n */\n createChangesObserver(indexMapType) {\n if (indexMapType !== 'hiding') {\n throw new Error(`Unsupported index map type \"${indexMapType}\".`);\n }\n return this.hidingChangesObservable.createObserver();\n }\n\n /**\n * Creates and registers a new `IndexMap` for a specified `IndexMapper` instance.\n *\n * @param {string} indexName A unique index name.\n * @param {string} mapType The index map type (e.g., \"hiding\", \"trimming\", \"physicalIndexToValue\").\n * @param {*} [initValueOrFn] The initial value for the index map.\n * @returns {IndexMap}\n */\n createAndRegisterIndexMap(indexName, mapType, initValueOrFn) {\n return this.registerMap(indexName, createIndexMap(mapType, initValueOrFn));\n }\n\n /**\n * Register map which provide some index mappings. Type of map determining to which collection it will be added.\n *\n * @param {string} uniqueName Name of the index map. It should be unique.\n * @param {IndexMap} indexMap Registered index map updated on items removal and insertion.\n * @returns {IndexMap}\n */\n registerMap(uniqueName, indexMap) {\n if (this.trimmingMapsCollection.get(uniqueName) || this.hidingMapsCollection.get(uniqueName) || this.variousMapsCollection.get(uniqueName)) {\n throw Error(`Map with name \"${uniqueName}\" has been already registered.`);\n }\n if (indexMap instanceof TrimmingMap) {\n this.trimmingMapsCollection.register(uniqueName, indexMap);\n } else if (indexMap instanceof HidingMap) {\n this.hidingMapsCollection.register(uniqueName, indexMap);\n } else {\n this.variousMapsCollection.register(uniqueName, indexMap);\n }\n const numberOfIndexes = this.getNumberOfIndexes();\n\n /*\n We initialize map ony when we have full information about number of indexes and the dataset is not empty.\n Otherwise it's unnecessary. Initialization of empty array would not give any positive changes. After initializing\n it with number of indexes equal to 0 the map would be still empty. What's more there would be triggered\n not needed hook (no real change have occurred). Number of indexes is known after loading data (the `loadData`\n function from the `Core`).\n */\n if (numberOfIndexes > 0) {\n indexMap.init(numberOfIndexes);\n }\n return indexMap;\n }\n\n /**\n * Unregister a map with given name.\n *\n * @param {string} name Name of the index map.\n */\n unregisterMap(name) {\n this.trimmingMapsCollection.unregister(name);\n this.hidingMapsCollection.unregister(name);\n this.variousMapsCollection.unregister(name);\n }\n\n /**\n * Unregisters all collected index map instances from all map collection types.\n */\n unregisterAll() {\n this.trimmingMapsCollection.unregisterAll();\n this.hidingMapsCollection.unregisterAll();\n this.variousMapsCollection.unregisterAll();\n }\n\n /**\n * Get a physical index corresponding to the given visual index.\n *\n * @param {number} visualIndex Visual index.\n * @returns {number|null} Returns translated index mapped by passed visual index.\n */\n getPhysicalFromVisualIndex(visualIndex) {\n // Index in the table boundaries provided by the `DataMap`.\n const physicalIndex = this.notTrimmedIndexesCache[visualIndex];\n if (isDefined(physicalIndex)) {\n return physicalIndex;\n }\n return null;\n }\n\n /**\n * Get a physical index corresponding to the given renderable index.\n *\n * @param {number} renderableIndex Renderable index.\n * @returns {null|number}\n */\n getPhysicalFromRenderableIndex(renderableIndex) {\n const physicalIndex = this.renderablePhysicalIndexesCache[renderableIndex];\n\n // Index in the renderable table boundaries.\n if (isDefined(physicalIndex)) {\n return physicalIndex;\n }\n return null;\n }\n\n /**\n * Get a visual index corresponding to the given physical index.\n *\n * @param {number} physicalIndex Physical index to search.\n * @returns {number|null} Returns a visual index of the index mapper.\n */\n getVisualFromPhysicalIndex(physicalIndex) {\n const visualIndex = this.fromPhysicalToVisualIndexesCache.get(physicalIndex);\n\n // Index in the table boundaries provided by the `DataMap`.\n if (isDefined(visualIndex)) {\n return visualIndex;\n }\n return null;\n }\n\n /**\n * Get a visual index corresponding to the given renderable index.\n *\n * @param {number} renderableIndex Renderable index.\n * @returns {null|number}\n */\n getVisualFromRenderableIndex(renderableIndex) {\n return this.getVisualFromPhysicalIndex(this.getPhysicalFromRenderableIndex(renderableIndex));\n }\n\n /**\n * Get a renderable index corresponding to the given visual index.\n *\n * @param {number} visualIndex Visual index.\n * @returns {null|number}\n */\n getRenderableFromVisualIndex(visualIndex) {\n const renderableIndex = this.fromVisualToRenderableIndexesCache.get(visualIndex);\n\n // Index in the renderable table boundaries.\n if (isDefined(renderableIndex)) {\n return renderableIndex;\n }\n return null;\n }\n\n /**\n * Search for the nearest not-hidden row or column.\n *\n * @param {number} fromVisualIndex The visual index of the row or column from which the search starts.
\n * If the row or column from which the search starts is not hidden, the method simply returns the `fromVisualIndex` number.\n * @param {number} searchDirection The search direction.
`1`: search from `fromVisualIndex` to the end of the dataset.
\n * `-1`: search from `fromVisualIndex` to the beginning of the dataset (i.e., to the row or column at visual index `0`).\n * @param {boolean} searchAlsoOtherWayAround `true`: if a search in a first direction failed, try the opposite direction.
\n * `false`: search in one direction only.\n *\n * @returns {number|null} A visual index of a row or column, or `null`.\n */\n getNearestNotHiddenIndex(fromVisualIndex, searchDirection) {\n let searchAlsoOtherWayAround = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n const physicalIndex = this.getPhysicalFromVisualIndex(fromVisualIndex);\n if (physicalIndex === null) {\n return null;\n }\n if (this.fromVisualToRenderableIndexesCache.has(fromVisualIndex)) {\n return fromVisualIndex;\n }\n const visibleIndexes = Array.from(this.fromVisualToRenderableIndexesCache.keys());\n let index = -1;\n if (searchDirection > 0) {\n index = visibleIndexes.findIndex(visualIndex => visualIndex > fromVisualIndex);\n } else {\n index = visibleIndexes.reverse().findIndex(visualIndex => visualIndex < fromVisualIndex);\n }\n if (index === -1) {\n if (searchAlsoOtherWayAround) {\n return this.getNearestNotHiddenIndex(fromVisualIndex, -searchDirection, false);\n }\n return null;\n }\n return visibleIndexes[index];\n }\n\n /**\n * Set default values for all indexes in registered index maps.\n *\n * @param {number} [length] Destination length for all stored index maps.\n */\n initToLength() {\n let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getNumberOfIndexes();\n this.notTrimmedIndexesCache = [...new Array(length).keys()];\n this.notHiddenIndexesCache = [...new Array(length).keys()];\n this.suspendOperations();\n this.indexesChangeSource = 'init';\n this.indexesSequence.init(length);\n this.indexesChangeSource = undefined;\n this.trimmingMapsCollection.initEvery(length);\n this.resumeOperations();\n\n // We move initialization of hidden collection to next batch for purpose of working on sequence of already trimmed indexes.\n this.suspendOperations();\n this.hidingMapsCollection.initEvery(length);\n\n // It shouldn't reset the cache.\n this.variousMapsCollection.initEvery(length);\n this.resumeOperations();\n this.runLocalHooks('init');\n }\n\n /**\n * Trim/extend the mappers to fit the desired length.\n *\n * @param {number} length New mapper length.\n */\n fitToLength(length) {\n const currentIndexCount = this.getNumberOfIndexes();\n if (length < currentIndexCount) {\n const indexesToBeRemoved = [...Array(this.getNumberOfIndexes() - length).keys()].map(i => i + length);\n this.removeIndexes(indexesToBeRemoved);\n } else {\n this.insertIndexes(currentIndexCount, length - currentIndexCount);\n }\n }\n\n /**\n * Get sequence of indexes.\n *\n * @returns {Array} Physical indexes.\n */\n getIndexesSequence() {\n return this.indexesSequence.getValues();\n }\n\n /**\n * Set completely new indexes sequence.\n *\n * @param {Array} indexes Physical indexes.\n */\n setIndexesSequence(indexes) {\n if (this.indexesChangeSource === undefined) {\n this.indexesChangeSource = 'update';\n }\n this.indexesSequence.setValues(indexes);\n if (this.indexesChangeSource === 'update') {\n this.indexesChangeSource = undefined;\n }\n }\n\n /**\n * Get all NOT trimmed indexes.\n *\n * Note: Indexes marked as trimmed aren't included in a {@link DataMap} and aren't rendered.\n *\n * @param {boolean} [readFromCache=true] Determine if read indexes from cache.\n * @returns {Array} List of physical indexes. Index of this native array is a \"visual index\",\n * value of this native array is a \"physical index\".\n */\n getNotTrimmedIndexes() {\n let readFromCache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n if (readFromCache === true) {\n return this.notTrimmedIndexesCache;\n }\n const indexesSequence = this.getIndexesSequence();\n return indexesSequence.filter(physicalIndex => this.isTrimmed(physicalIndex) === false);\n }\n\n /**\n * Get length of all NOT trimmed indexes.\n *\n * Note: Indexes marked as trimmed aren't included in a {@link DataMap} and aren't rendered.\n *\n * @returns {number}\n */\n getNotTrimmedIndexesLength() {\n return this.getNotTrimmedIndexes().length;\n }\n\n /**\n * Get all NOT hidden indexes.\n *\n * Note: Indexes marked as hidden are included in a {@link DataMap}, but aren't rendered.\n *\n * @param {boolean} [readFromCache=true] Determine if read indexes from cache.\n * @returns {Array} List of physical indexes. Please keep in mind that index of this native array IS NOT a \"visual index\".\n */\n getNotHiddenIndexes() {\n let readFromCache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n if (readFromCache === true) {\n return this.notHiddenIndexesCache;\n }\n const indexesSequence = this.getIndexesSequence();\n return indexesSequence.filter(physicalIndex => this.isHidden(physicalIndex) === false);\n }\n\n /**\n * Get length of all NOT hidden indexes.\n *\n * Note: Indexes marked as hidden are included in a {@link DataMap}, but aren't rendered.\n *\n * @returns {number}\n */\n getNotHiddenIndexesLength() {\n return this.getNotHiddenIndexes().length;\n }\n\n /**\n * Get list of physical indexes (respecting the sequence of indexes) which may be rendered (when they are in a viewport).\n *\n * @param {boolean} [readFromCache=true] Determine if read indexes from cache.\n * @returns {Array} List of physical indexes. Index of this native array is a \"renderable index\",\n * value of this native array is a \"physical index\".\n */\n getRenderableIndexes() {\n let readFromCache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n if (readFromCache === true) {\n return this.renderablePhysicalIndexesCache;\n }\n const notTrimmedIndexes = this.getNotTrimmedIndexes();\n return notTrimmedIndexes.filter(physicalIndex => this.isHidden(physicalIndex) === false);\n }\n\n /**\n * Get length of all NOT trimmed and NOT hidden indexes.\n *\n * @returns {number}\n */\n getRenderableIndexesLength() {\n return this.getRenderableIndexes().length;\n }\n\n /**\n * Get number of all indexes.\n *\n * @returns {number}\n */\n getNumberOfIndexes() {\n return this.getIndexesSequence().length;\n }\n\n /**\n * Move indexes in the index mapper.\n *\n * @param {number|Array} movedIndexes Visual index(es) to move.\n * @param {number} finalIndex Visual index being a start index for the moved elements.\n */\n moveIndexes(movedIndexes, finalIndex) {\n if (typeof movedIndexes === 'number') {\n movedIndexes = [movedIndexes];\n }\n const physicalMovedIndexes = arrayMap(movedIndexes, visualIndex => this.getPhysicalFromVisualIndex(visualIndex));\n const notTrimmedIndexesLength = this.getNotTrimmedIndexesLength();\n const movedIndexesLength = movedIndexes.length;\n\n // Removing moved indexes without re-indexing.\n const notMovedIndexes = getListWithRemovedItems(this.getIndexesSequence(), physicalMovedIndexes);\n const notTrimmedNotMovedItems = notMovedIndexes.filter(index => this.isTrimmed(index) === false);\n\n // When item(s) are moved after the last visible item we assign the last possible index.\n let destinationPosition = notMovedIndexes.indexOf(notTrimmedNotMovedItems[notTrimmedNotMovedItems.length - 1]) + 1;\n\n // Otherwise, we find proper index for inserted item(s).\n if (finalIndex + movedIndexesLength < notTrimmedIndexesLength) {\n // Physical index at final index position.\n const physicalIndex = notTrimmedNotMovedItems[finalIndex];\n destinationPosition = notMovedIndexes.indexOf(physicalIndex);\n }\n this.indexesChangeSource = 'move';\n\n // Adding indexes without re-indexing.\n this.setIndexesSequence(getListWithInsertedItems(notMovedIndexes, destinationPosition, physicalMovedIndexes));\n this.indexesChangeSource = undefined;\n }\n\n /**\n * Get whether index is trimmed. Index marked as trimmed isn't included in a {@link DataMap} and isn't rendered.\n *\n * @param {number} physicalIndex Physical index.\n * @returns {boolean}\n */\n isTrimmed(physicalIndex) {\n return this.trimmingMapsCollection.getMergedValueAtIndex(physicalIndex);\n }\n\n /**\n * Get whether index is hidden. Index marked as hidden is included in a {@link DataMap}, but isn't rendered.\n *\n * @param {number} physicalIndex Physical index.\n * @returns {boolean}\n */\n isHidden(physicalIndex) {\n return this.hidingMapsCollection.getMergedValueAtIndex(physicalIndex);\n }\n\n /**\n * Insert new indexes and corresponding mapping and update values of the others, for all stored index maps.\n *\n * @private\n * @param {number} firstInsertedVisualIndex First inserted visual index.\n * @param {number} amountOfIndexes Amount of inserted indexes.\n */\n insertIndexes(firstInsertedVisualIndex, amountOfIndexes) {\n const nthVisibleIndex = this.getNotTrimmedIndexes()[firstInsertedVisualIndex];\n const firstInsertedPhysicalIndex = isDefined(nthVisibleIndex) ? nthVisibleIndex : this.getNumberOfIndexes();\n const insertionIndex = this.getIndexesSequence().includes(nthVisibleIndex) ? this.getIndexesSequence().indexOf(nthVisibleIndex) : this.getNumberOfIndexes();\n const insertedIndexes = arrayMap(new Array(amountOfIndexes).fill(firstInsertedPhysicalIndex), (nextIndex, stepsFromStart) => nextIndex + stepsFromStart);\n this.suspendOperations();\n this.indexesChangeSource = 'insert';\n this.indexesSequence.insert(insertionIndex, insertedIndexes);\n this.indexesChangeSource = undefined;\n this.trimmingMapsCollection.insertToEvery(insertionIndex, insertedIndexes);\n this.hidingMapsCollection.insertToEvery(insertionIndex, insertedIndexes);\n this.variousMapsCollection.insertToEvery(insertionIndex, insertedIndexes);\n this.resumeOperations();\n }\n\n /**\n * Remove some indexes and corresponding mappings and update values of the others, for all stored index maps.\n *\n * @private\n * @param {Array} removedIndexes List of removed indexes.\n */\n removeIndexes(removedIndexes) {\n this.suspendOperations();\n this.indexesChangeSource = 'remove';\n this.indexesSequence.remove(removedIndexes);\n this.indexesChangeSource = undefined;\n this.trimmingMapsCollection.removeFromEvery(removedIndexes);\n this.hidingMapsCollection.removeFromEvery(removedIndexes);\n this.variousMapsCollection.removeFromEvery(removedIndexes);\n this.resumeOperations();\n }\n\n /**\n * Rebuild cache for some indexes. Every action on indexes sequence or indexes skipped in the process of rendering\n * by default reset cache, thus batching some index maps actions is recommended.\n *\n * @private\n * @param {boolean} [force=false] Determine if force cache update.\n */\n updateCache() {\n let force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n const anyCachedIndexChanged = this.indexesSequenceChanged || this.trimmedIndexesChanged || this.hiddenIndexesChanged;\n if (force === true || this.isBatched === false && anyCachedIndexChanged === true) {\n this.trimmingMapsCollection.updateCache();\n this.hidingMapsCollection.updateCache();\n this.notTrimmedIndexesCache = this.getNotTrimmedIndexes(false);\n this.notHiddenIndexesCache = this.getNotHiddenIndexes(false);\n this.renderablePhysicalIndexesCache = this.getRenderableIndexes(false);\n this.cacheFromPhysicalToVisualIndexes();\n this.cacheFromVisualToRenderableIndexes();\n\n // Currently there's support only for the \"hiding\" map type.\n if (this.hiddenIndexesChanged) {\n this.hidingChangesObservable.emit(this.hidingMapsCollection.getMergedValues());\n }\n this.runLocalHooks('cacheUpdated', {\n indexesSequenceChanged: this.indexesSequenceChanged,\n trimmedIndexesChanged: this.trimmedIndexesChanged,\n hiddenIndexesChanged: this.hiddenIndexesChanged\n });\n this.indexesSequenceChanged = false;\n this.trimmedIndexesChanged = false;\n this.hiddenIndexesChanged = false;\n }\n }\n\n /**\n * Update cache for translations from physical to visual indexes.\n *\n * @private\n */\n cacheFromPhysicalToVisualIndexes() {\n const nrOfNotTrimmedIndexes = this.getNotTrimmedIndexesLength();\n this.fromPhysicalToVisualIndexesCache.clear();\n for (let visualIndex = 0; visualIndex < nrOfNotTrimmedIndexes; visualIndex += 1) {\n const physicalIndex = this.getPhysicalFromVisualIndex(visualIndex);\n\n // Every visual index have corresponding physical index, but some physical indexes may don't have\n // corresponding visual indexes (physical indexes may represent trimmed indexes, beyond the table boundaries)\n this.fromPhysicalToVisualIndexesCache.set(physicalIndex, visualIndex);\n }\n }\n\n /**\n * Update cache for translations from visual to renderable indexes.\n *\n * @private\n */\n cacheFromVisualToRenderableIndexes() {\n const nrOfRenderableIndexes = this.getRenderableIndexesLength();\n this.fromVisualToRenderableIndexesCache.clear();\n for (let renderableIndex = 0; renderableIndex < nrOfRenderableIndexes; renderableIndex += 1) {\n // Can't use getRenderableFromVisualIndex here because we're building the cache here\n const physicalIndex = this.getPhysicalFromRenderableIndex(renderableIndex);\n const visualIndex = this.getVisualFromPhysicalIndex(physicalIndex);\n this.fromVisualToRenderableIndexesCache.set(visualIndex, renderableIndex);\n }\n }\n}\nmixin(IndexMapper, localHooks);","import \"core-js/modules/es.error.cause.js\";\nimport { HidingMap } from \"./hidingMap.mjs\";\nimport { IndexMap } from \"./indexMap.mjs\";\nimport { LinkedPhysicalIndexToValueMap } from \"./linkedPhysicalIndexToValueMap.mjs\";\nimport { PhysicalIndexToValueMap } from \"./physicalIndexToValueMap.mjs\";\nimport { TrimmingMap } from \"./trimmingMap.mjs\";\nexport * from \"./indexesSequence.mjs\";\nexport * from \"./utils/indexesSequence.mjs\";\nexport { HidingMap, IndexMap, LinkedPhysicalIndexToValueMap, PhysicalIndexToValueMap, TrimmingMap };\nconst availableIndexMapTypes = new Map([['hiding', HidingMap], ['index', IndexMap], ['linkedPhysicalIndexToValue', LinkedPhysicalIndexToValueMap], ['physicalIndexToValue', PhysicalIndexToValueMap], ['trimming', TrimmingMap]]);\n\n/**\n * Creates and returns new IndexMap instance.\n *\n * @param {string} mapType The type of the map.\n * @param {*} [initValueOrFn=null] Initial value or function for index map.\n * @returns {IndexMap}\n */\nexport function createIndexMap(mapType) {\n let initValueOrFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n if (!availableIndexMapTypes.has(mapType)) {\n throw new Error(`The provided map type (\"${mapType}\") does not exist.`);\n }\n return new (availableIndexMapTypes.get(mapType))(initValueOrFn);\n}","import \"core-js/modules/es.array.push.js\";\nimport { PhysicalIndexToValueMap } from \"./physicalIndexToValueMap.mjs\";\nimport { arrayReduce } from \"../../helpers/array.mjs\";\n/**\n * Map for storing mappings from an physical index to a boolean value. It stores information whether physical index is\n * included in a dataset, but skipped in the process of rendering.\n *\n * @class HidingMap\n */\nexport class HidingMap extends PhysicalIndexToValueMap {\n constructor() {\n let initValueOrFn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n super(initValueOrFn);\n }\n\n /**\n * Get physical indexes which are hidden.\n *\n * Note: Indexes marked as hidden are included in a {@link DataMap}, but aren't rendered.\n *\n * @returns {Array}\n */\n getHiddenIndexes() {\n return arrayReduce(this.getValues(), (indexesList, isHidden, physicalIndex) => {\n if (isHidden) {\n indexesList.push(physicalIndex);\n }\n return indexesList;\n }, []);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { rangeEach } from \"../../helpers/number.mjs\";\nimport { mixin } from \"../../helpers/object.mjs\";\nimport { isFunction } from \"../../helpers/function.mjs\";\nimport localHooks from \"../../mixins/localHooks.mjs\";\n/**\n * Map for storing mappings from an index to a value.\n *\n * @class IndexMap\n */\nexport class IndexMap {\n constructor() {\n let initValueOrFn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n /**\n * List of values for particular indexes.\n *\n * @private\n * @type {Array}\n */\n _defineProperty(this, \"indexedValues\", []);\n /**\n * Initial value or function for each existing index.\n *\n * @private\n * @type {*}\n */\n _defineProperty(this, \"initValueOrFn\", void 0);\n this.initValueOrFn = initValueOrFn;\n }\n\n /**\n * Get full list of values for particular indexes.\n *\n * @returns {Array}\n */\n getValues() {\n return this.indexedValues;\n }\n\n /**\n * Get value for the particular index.\n *\n * @param {number} index Index for which value is got.\n * @returns {*}\n */\n getValueAtIndex(index) {\n const values = this.indexedValues;\n if (index < values.length) {\n return values[index];\n }\n }\n\n /**\n * Set new values for particular indexes.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @param {Array} values List of set values.\n */\n setValues(values) {\n this.indexedValues = values.slice();\n this.runLocalHooks('change');\n }\n\n /**\n * Set new value for the particular index.\n *\n * @param {number} index The index.\n * @param {*} value The value to save.\n *\n * Note: Please keep in mind that it is not possible to set value beyond the map (not respecting already set\n * map's size). Please use the `setValues` method when you would like to extend the map.\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @returns {boolean}\n */\n setValueAtIndex(index, value) {\n if (index < this.indexedValues.length) {\n this.indexedValues[index] = value;\n this.runLocalHooks('change');\n return true;\n }\n return false;\n }\n\n /**\n * Clear all values to the defaults.\n */\n clear() {\n this.setDefaultValues();\n }\n\n /**\n * Get length of the index map.\n *\n * @returns {number}\n */\n getLength() {\n return this.getValues().length;\n }\n\n /**\n * Set default values for elements from `0` to `n`, where `n` is equal to the handled variable.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @private\n * @param {number} [length] Length of list.\n */\n setDefaultValues() {\n let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.indexedValues.length;\n this.indexedValues.length = 0;\n if (isFunction(this.initValueOrFn)) {\n rangeEach(length - 1, index => this.indexedValues.push(this.initValueOrFn(index)));\n } else {\n rangeEach(length - 1, () => this.indexedValues.push(this.initValueOrFn));\n }\n this.runLocalHooks('change');\n }\n\n /**\n * Initialize list with default values for particular indexes.\n *\n * @private\n * @param {number} length New length of indexed list.\n * @returns {IndexMap}\n */\n init(length) {\n this.setDefaultValues(length);\n this.runLocalHooks('init');\n return this;\n }\n\n /**\n * Add values to the list.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @private\n */\n insert() {\n this.runLocalHooks('change');\n }\n\n /**\n * Remove values from the list.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @private\n */\n remove() {\n this.runLocalHooks('change');\n }\n\n /**\n * Destroys the Map instance.\n */\n destroy() {\n this.clearLocalHooks();\n this.indexedValues = null;\n this.initValueOrFn = null;\n }\n}\nmixin(IndexMap, localHooks);","import { isFunction } from \"../../../helpers/function.mjs\";\nimport { arrayFilter } from \"../../../helpers/array.mjs\";\n/**\n * Insert new items to the list.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {number} insertionIndex Position inside the actual list.\n * @param {Array} insertedIndexes List of inserted indexes.\n * @param {*} insertedValuesMapping Mapping which may provide value or function returning value for the specific parameters.\n * @returns {Array} List with new mappings.\n */\nexport function getListWithInsertedItems(indexedValues, insertionIndex, insertedIndexes, insertedValuesMapping) {\n const firstInsertedIndex = insertedIndexes.length ? insertedIndexes[0] : undefined;\n return [...indexedValues.slice(0, firstInsertedIndex), ...insertedIndexes.map((insertedIndex, ordinalNumber) => {\n if (isFunction(insertedValuesMapping)) {\n return insertedValuesMapping(insertedIndex, ordinalNumber);\n }\n return insertedValuesMapping;\n }), ...(firstInsertedIndex === undefined ? [] : indexedValues.slice(firstInsertedIndex))];\n}\n\n/**\n * Filter items from the list.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {Array} removedIndexes List of removed indexes.\n * @returns {Array} Reduced list of mappings.\n */\nexport function getListWithRemovedItems(indexedValues, removedIndexes) {\n return arrayFilter(indexedValues, (_, index) => removedIndexes.includes(index) === false);\n}","import { IndexMap } from \"./indexMap.mjs\";\nimport { getListWithRemovedItems, getListWithInsertedItems } from \"./utils/physicallyIndexed.mjs\";\n/**\n * Map for storing mappings from an physical index to a value.\n *\n * Does not update stored values on remove/add row or column action.\n *\n * @class PhysicalIndexToValueMap\n */\nexport class PhysicalIndexToValueMap extends IndexMap {\n /**\n * Add values to list and reorganize.\n *\n * @private\n * @param {number} insertionIndex Position inside the list.\n * @param {Array} insertedIndexes List of inserted indexes.\n */\n insert(insertionIndex, insertedIndexes) {\n this.indexedValues = getListWithInsertedItems(this.indexedValues, insertionIndex, insertedIndexes, this.initValueOrFn);\n super.insert(insertionIndex, insertedIndexes);\n }\n\n /**\n * Remove values from the list and reorganize.\n *\n * @private\n * @param {Array} removedIndexes List of removed indexes.\n */\n remove(removedIndexes) {\n this.indexedValues = getListWithRemovedItems(this.indexedValues, removedIndexes);\n super.remove(removedIndexes);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { IndexMap } from \"./indexMap.mjs\";\nimport { getListWithRemovedItems, getListWithInsertedItems } from \"./utils/physicallyIndexed.mjs\";\nimport { getListWithRemovedItems as getListWithoutIndexes } from \"./utils/indexesSequence.mjs\";\nimport { getDecreasedIndexes, getIncreasedIndexes } from \"./utils/actionsOnIndexes.mjs\";\nimport { isFunction } from \"../../helpers/function.mjs\";\n/**\n * Map for storing mappings from an physical index to a value. Those entries are linked and stored in a certain order.\n *\n * It does not update stored values on remove/add row or column action. Otherwise, order of entries is updated after\n * such changes.\n *\n * @class LinkedPhysicalIndexToValueMap\n */\nexport class LinkedPhysicalIndexToValueMap extends IndexMap {\n constructor() {\n super(...arguments);\n /**\n * Indexes and values corresponding to them (entries) are stored in a certain order.\n *\n * @private\n * @type {Array}\n */\n _defineProperty(this, \"orderOfIndexes\", []);\n }\n /**\n * Get full list of ordered values for particular indexes.\n *\n * @returns {Array}\n */\n getValues() {\n return this.orderOfIndexes.map(physicalIndex => this.indexedValues[physicalIndex]);\n }\n\n /**\n * Set new values for particular indexes. Entries are linked and stored in a certain order.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @param {Array} values List of set values.\n */\n setValues(values) {\n this.orderOfIndexes = [...Array(values.length).keys()];\n super.setValues(values);\n }\n\n /**\n * Set value at index and add it to the linked list of entries. Entries are stored in a certain order.\n *\n * Note: Value will be added at the end of the queue.\n *\n * @param {number} index The index.\n * @param {*} value The value to save.\n * @param {number} position Position to which entry will be added.\n *\n * @returns {boolean}\n */\n setValueAtIndex(index, value) {\n let position = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.orderOfIndexes.length;\n if (index < this.indexedValues.length) {\n this.indexedValues[index] = value;\n if (this.orderOfIndexes.includes(index) === false) {\n this.orderOfIndexes.splice(position, 0, index);\n }\n this.runLocalHooks('change');\n return true;\n }\n return false;\n }\n\n /**\n * Clear value for particular index.\n *\n * @param {number} physicalIndex Physical index.\n */\n clearValue(physicalIndex) {\n this.orderOfIndexes = getListWithoutIndexes(this.orderOfIndexes, [physicalIndex]);\n if (isFunction(this.initValueOrFn)) {\n super.setValueAtIndex(physicalIndex, this.initValueOrFn(physicalIndex));\n } else {\n super.setValueAtIndex(physicalIndex, this.initValueOrFn);\n }\n }\n\n /**\n * Get length of the index map.\n *\n * @returns {number}\n */\n getLength() {\n return this.orderOfIndexes.length;\n }\n\n /**\n * Set default values for elements from `0` to `n`, where `n` is equal to the handled variable.\n *\n * Note: Please keep in mind that `change` hook triggered by the method may not update cache of a collection immediately.\n *\n * @private\n * @param {number} [length] Length of list.\n */\n setDefaultValues() {\n let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.indexedValues.length;\n this.orderOfIndexes.length = 0;\n super.setDefaultValues(length);\n }\n\n /**\n * Add values to list and reorganize. It updates list of indexes related to ordered values.\n *\n * @private\n * @param {number} insertionIndex Position inside the list.\n * @param {Array} insertedIndexes List of inserted indexes.\n */\n insert(insertionIndex, insertedIndexes) {\n this.indexedValues = getListWithInsertedItems(this.indexedValues, insertionIndex, insertedIndexes, this.initValueOrFn);\n this.orderOfIndexes = getIncreasedIndexes(this.orderOfIndexes, insertedIndexes);\n super.insert(insertionIndex, insertedIndexes);\n }\n\n /**\n * Remove values from the list and reorganize. It updates list of indexes related to ordered values.\n *\n * @private\n * @param {Array} removedIndexes List of removed indexes.\n */\n remove(removedIndexes) {\n this.indexedValues = getListWithRemovedItems(this.indexedValues, removedIndexes);\n this.orderOfIndexes = getListWithoutIndexes(this.orderOfIndexes, removedIndexes);\n this.orderOfIndexes = getDecreasedIndexes(this.orderOfIndexes, removedIndexes);\n super.remove(removedIndexes);\n }\n\n /**\n * Get every entry containing index and value, respecting order of indexes.\n *\n * @returns {Array}\n */\n getEntries() {\n return this.orderOfIndexes.map(physicalIndex => [physicalIndex, this.getValueAtIndex(physicalIndex)]);\n }\n}","import { arrayFilter } from \"../../../helpers/array.mjs\";\n/**\n * Insert new items to the list.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {number} insertionIndex Position inside the actual list.\n * @param {Array} insertedIndexes List of inserted indexes.\n * @returns {Array} List with new mappings.\n */\nexport function getListWithInsertedItems(indexedValues, insertionIndex, insertedIndexes) {\n return [...indexedValues.slice(0, insertionIndex), ...insertedIndexes, ...indexedValues.slice(insertionIndex)];\n}\n\n/**\n * Filter items from the list.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {Array} removedIndexes List of removed indexes.\n * @returns {Array} Reduced list of mappings.\n */\nexport function getListWithRemovedItems(indexedValues, removedIndexes) {\n return arrayFilter(indexedValues, index => {\n return removedIndexes.includes(index) === false;\n });\n}","import { arrayMap } from \"../../../helpers/array.mjs\";\n/**\n * Transform mappings after removal.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {Array} removedIndexes List of removed indexes.\n * @returns {Array} List with decreased indexes.\n */\nexport function getDecreasedIndexes(indexedValues, removedIndexes) {\n return arrayMap(indexedValues, index => index - removedIndexes.filter(removedIndex => removedIndex < index).length);\n}\n\n/**\n * Transform mappings after insertion.\n *\n * @private\n * @param {Array} indexedValues List of values for particular indexes.\n * @param {Array} insertedIndexes List of inserted indexes.\n * @returns {Array} List with increased indexes.\n */\nexport function getIncreasedIndexes(indexedValues, insertedIndexes) {\n const firstInsertedIndex = insertedIndexes[0];\n const amountOfIndexes = insertedIndexes.length;\n return arrayMap(indexedValues, index => {\n if (index >= firstInsertedIndex) {\n return index + amountOfIndexes;\n }\n return index;\n });\n}","import \"core-js/modules/es.array.push.js\";\nimport { PhysicalIndexToValueMap } from \"./physicalIndexToValueMap.mjs\";\nimport { arrayReduce } from \"../../helpers/array.mjs\";\n/**\n * Map for storing mappings from an physical index to a boolean value. It stores information whether physical index is\n * NOT included in a dataset and skipped in the process of rendering.\n *\n * @class TrimmingMap\n */\nexport class TrimmingMap extends PhysicalIndexToValueMap {\n constructor() {\n let initValueOrFn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n super(initValueOrFn);\n }\n\n /**\n * Get physical indexes which are trimmed.\n *\n * Note: Indexes marked as trimmed aren't included in a {@link DataMap} and aren't rendered.\n *\n * @returns {Array}\n */\n getTrimmedIndexes() {\n return arrayReduce(this.getValues(), (indexesList, isTrimmed, physicalIndex) => {\n if (isTrimmed) {\n indexesList.push(physicalIndex);\n }\n return indexesList;\n }, []);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport { getDecreasedIndexes, getIncreasedIndexes } from \"./actionsOnIndexes.mjs\";\nimport { getListWithInsertedItems as sequenceStrategyInsert, getListWithRemovedItems as sequenceStrategyRemove } from \"./indexesSequence.mjs\";\nimport { getListWithInsertedItems as physicalStrategyInsert, getListWithRemovedItems as physicalStrategyRemove } from \"./physicallyIndexed.mjs\";\nconst alterStrategies = new Map([['indexesSequence', {\n getListWithInsertedItems: sequenceStrategyInsert,\n getListWithRemovedItems: sequenceStrategyRemove\n}], ['physicallyIndexed', {\n getListWithInsertedItems: physicalStrategyInsert,\n getListWithRemovedItems: physicalStrategyRemove\n}]]);\nconst alterUtilsFactory = indexationStrategy => {\n if (alterStrategies.has(indexationStrategy) === false) {\n throw new Error(`Alter strategy with ID '${indexationStrategy}' does not exist.`);\n }\n return alterStrategies.get(indexationStrategy);\n};\nexport { getDecreasedIndexes, getIncreasedIndexes, alterUtilsFactory };","import { IndexMap } from \"./indexMap.mjs\";\nimport { getListWithRemovedItems, getListWithInsertedItems } from \"./utils/indexesSequence.mjs\";\nimport { getDecreasedIndexes, getIncreasedIndexes } from \"./utils/index.mjs\";\n/**\n * Map for storing mappings from an index to a physical index.\n *\n * It also updates the physical indexes (remaining in the map) on remove/add row or column action.\n *\n * @class IndexesSequence\n */\nexport class IndexesSequence extends IndexMap {\n constructor() {\n // Not handling custom init function or init value.\n super(index => index);\n }\n\n /**\n * Add values to list and reorganize.\n *\n * @private\n * @param {number} insertionIndex Position inside the list.\n * @param {Array} insertedIndexes List of inserted indexes.\n */\n insert(insertionIndex, insertedIndexes) {\n const listAfterUpdate = getIncreasedIndexes(this.indexedValues, insertedIndexes);\n this.indexedValues = getListWithInsertedItems(listAfterUpdate, insertionIndex, insertedIndexes);\n super.insert(insertionIndex, insertedIndexes);\n }\n\n /**\n * Remove values from the list and reorganize.\n *\n * @private\n * @param {Array} removedIndexes List of removed indexes.\n */\n remove(removedIndexes) {\n const listAfterUpdate = getListWithRemovedItems(this.indexedValues, removedIndexes);\n this.indexedValues = getDecreasedIndexes(listAfterUpdate, removedIndexes);\n super.remove(removedIndexes);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { MapCollection } from \"./mapCollection.mjs\";\nimport { arrayMap } from \"../../helpers/array.mjs\";\nimport { isDefined } from \"../../helpers/mixed.mjs\";\n/**\n * Collection of maps. This collection aggregate maps with the same type of values. Values from the registered maps\n * can be used to calculate a single result for particular index.\n */\nexport class AggregatedCollection extends MapCollection {\n constructor(aggregationFunction, fallbackValue) {\n super();\n /**\n * List of merged values. Value for each index is calculated using values inside registered maps.\n *\n * @type {Array}\n */\n _defineProperty(this, \"mergedValuesCache\", []);\n /**\n * Function which do aggregation on the values for particular index.\n */\n _defineProperty(this, \"aggregationFunction\", void 0);\n /**\n * Fallback value when there is no calculated value for particular index.\n */\n _defineProperty(this, \"fallbackValue\", void 0);\n this.aggregationFunction = aggregationFunction;\n this.fallbackValue = fallbackValue;\n }\n\n /**\n * Get merged values for all indexes.\n *\n * @param {boolean} [readFromCache=true] Determine if read results from the cache.\n * @returns {Array}\n */\n getMergedValues() {\n let readFromCache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n if (readFromCache === true) {\n return this.mergedValuesCache;\n }\n if (this.getLength() === 0) {\n return [];\n }\n\n // Below variable stores values for every particular map. Example describing situation when we have 2 registered maps,\n // with length equal to 5.\n //\n // +---------+---------------------------------------------+\n // | | indexes |\n // +---------+---------------------------------------------+\n // | maps | 0 | 1 | 2 | 3 | 4 |\n // +---------+----------+-------+-------+-------+----------+\n // | 0 | [[ value, value, value, value, value ], |\n // | 1 | [ value, value, value, value, value ]] |\n // +---------+----------+-------+-------+-------+----------+\n const mapsValuesMatrix = arrayMap(this.get(), map => map.getValues());\n // Below variable stores values for every particular index. Example describing situation when we have 2 registered maps,\n // with length equal to 5.\n //\n // +---------+---------------------+\n // | | maps |\n // +---------+---------------------+\n // | indexes | 0 | 1 |\n // +---------+----------+----------+\n // | 0 | [[ value, value ], |\n // | 1 | [ value, value ], |\n // | 2 | [ value, value ], |\n // | 3 | [ value, value ], |\n // | 4 | [ value, value ]] |\n // +---------+----------+----------+\n const indexesValuesMatrix = [];\n const mapsLength = isDefined(mapsValuesMatrix[0]) && mapsValuesMatrix[0].length || 0;\n for (let index = 0; index < mapsLength; index += 1) {\n const valuesForIndex = [];\n for (let mapIndex = 0; mapIndex < this.getLength(); mapIndex += 1) {\n valuesForIndex.push(mapsValuesMatrix[mapIndex][index]);\n }\n indexesValuesMatrix.push(valuesForIndex);\n }\n return arrayMap(indexesValuesMatrix, this.aggregationFunction);\n }\n\n /**\n * Get merged value for particular index.\n *\n * @param {number} index Index for which we calculate single result.\n * @param {boolean} [readFromCache=true] Determine if read results from the cache.\n * @returns {*}\n */\n getMergedValueAtIndex(index, readFromCache) {\n const valueAtIndex = this.getMergedValues(readFromCache)[index];\n return isDefined(valueAtIndex) ? valueAtIndex : this.fallbackValue;\n }\n\n /**\n * Rebuild cache for the collection.\n */\n updateCache() {\n this.mergedValuesCache = this.getMergedValues(false);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { isUndefined, isDefined } from \"../../helpers/mixed.mjs\";\nimport { mixin } from \"../../helpers/object.mjs\";\nimport localHooks from \"../../mixins/localHooks.mjs\"; // Counter for checking if there is a memory leak.\nlet registeredMaps = 0;\n\n/**\n * Collection of index maps having unique names. It allow us to perform bulk operations such as init, remove, insert on all index maps that have been registered in the collection.\n */\nexport class MapCollection {\n constructor() {\n /**\n * Collection of index maps.\n *\n * @type {Map}\n */\n _defineProperty(this, \"collection\", new Map());\n }\n /**\n * Register custom index map.\n *\n * @param {string} uniqueName Unique name of the index map.\n * @param {IndexMap} indexMap Index map containing miscellaneous (i.e. Meta data, indexes sequence), updated after remove and insert data actions.\n */\n register(uniqueName, indexMap) {\n if (this.collection.has(uniqueName) === false) {\n this.collection.set(uniqueName, indexMap);\n indexMap.addLocalHook('change', () => this.runLocalHooks('change', indexMap));\n registeredMaps += 1;\n }\n }\n\n /**\n * Unregister custom index map.\n *\n * @param {string} name Name of the index map.\n */\n unregister(name) {\n const indexMap = this.collection.get(name);\n if (isDefined(indexMap)) {\n indexMap.destroy();\n this.collection.delete(name);\n this.runLocalHooks('change', indexMap);\n registeredMaps -= 1;\n }\n }\n\n /**\n * Unregisters and destroys all collected index map instances.\n */\n unregisterAll() {\n this.collection.forEach((indexMap, name) => this.unregister(name));\n this.collection.clear();\n }\n\n /**\n * Get index map for the provided name.\n *\n * @param {string} [name] Name of the index map.\n * @returns {Array|IndexMap}\n */\n get(name) {\n if (isUndefined(name)) {\n return Array.from(this.collection.values());\n }\n return this.collection.get(name);\n }\n\n /**\n * Get collection size.\n *\n * @returns {number}\n */\n getLength() {\n return this.collection.size;\n }\n\n /**\n * Remove some indexes and corresponding mappings and update values of the others within all collection's index maps.\n *\n * @private\n * @param {Array} removedIndexes List of removed indexes.\n */\n removeFromEvery(removedIndexes) {\n this.collection.forEach(indexMap => {\n indexMap.remove(removedIndexes);\n });\n }\n\n /**\n * Insert new indexes and corresponding mapping and update values of the others all collection's index maps.\n *\n * @private\n * @param {number} insertionIndex Position inside the actual list.\n * @param {Array} insertedIndexes List of inserted indexes.\n */\n insertToEvery(insertionIndex, insertedIndexes) {\n this.collection.forEach(indexMap => {\n indexMap.insert(insertionIndex, insertedIndexes);\n });\n }\n\n /**\n * Set default values to index maps within collection.\n *\n * @param {number} length Destination length for all stored maps.\n */\n initEvery(length) {\n this.collection.forEach(indexMap => {\n indexMap.init(length);\n });\n }\n}\nmixin(MapCollection, localHooks);\n\n/**\n * @returns {number}\n */\nexport function getRegisteredMapsCounter() {\n return registeredMaps;\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { ChangesObserver } from \"./observer.mjs\";\nimport { arrayDiff } from \"./utils.mjs\";\n/**\n * The ChangesObservable module is an object that represents a resource that provides\n * the ability to observe the changes that happened in the index map indexes during\n * the code running.\n *\n * @private\n * @class ChangesObservable\n */\nvar _observers = /*#__PURE__*/new WeakMap();\nvar _indexMatrix = /*#__PURE__*/new WeakMap();\nvar _currentIndexState = /*#__PURE__*/new WeakMap();\nvar _isMatrixIndexesInitialized = /*#__PURE__*/new WeakMap();\nvar _initialIndexValue = /*#__PURE__*/new WeakMap();\nexport class ChangesObservable {\n constructor() {\n let {\n initialIndexValue\n } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n /**\n * The list of registered ChangesObserver instances.\n *\n * @type {ChangesObserver[]}\n */\n _classPrivateFieldInitSpec(this, _observers, new Set());\n /**\n * An array with default values that act as a base array that will be compared with\n * the last saved index state. The changes are generated and immediately send through\n * the newly created ChangesObserver object. Thanks to that, the observer initially has\n * all information about what indexes are currently changed.\n *\n * @type {Array}\n */\n _classPrivateFieldInitSpec(this, _indexMatrix, []);\n /**\n * An array that holds the indexes state that is currently valid. The value is changed on every\n * index mapper cache update.\n *\n * @type {Array}\n */\n _classPrivateFieldInitSpec(this, _currentIndexState, []);\n /**\n * The flag determines if the observable is initialized or not. Not initialized object creates\n * index matrix once while emitting new changes.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _isMatrixIndexesInitialized, false);\n /**\n * The initial index value allows control from what value the index matrix array will be created.\n * Changing that value changes how the array diff generates the changes for the initial data\n * sent to the subscribers. For example, the changes can be triggered by detecting the changes\n * from `false` to `true` value or vice versa. Generally, it depends on which index map type\n * the Observable will work with. For \"hiding\" or \"trimming\" index types, it will be boolean\n * values. For various index maps, it can be anything, but I suspect that the most appropriate\n * initial value will be \"undefined\" in that case.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _initialIndexValue, false);\n _classPrivateFieldSet(_initialIndexValue, this, initialIndexValue !== null && initialIndexValue !== void 0 ? initialIndexValue : false);\n }\n\n /* eslint-disable jsdoc/require-description-complete-sentence */\n /**\n * Creates and returns a new instance of the ChangesObserver object. The resource\n * allows subscribing to the index changes that during the code running may change.\n * Changes are emitted as an array of the index change. Each change is represented\n * separately as an object with `op`, `index`, `oldValue`, and `newValue` props.\n *\n * For example:\n * ```\n * [\n * { op: 'replace', index: 1, oldValue: false, newValue: true },\n * { op: 'replace', index: 3, oldValue: false, newValue: true },\n * { op: 'insert', index: 4, oldValue: false, newValue: true },\n * ]\n * // or when the new index map changes have less indexes\n * [\n * { op: 'replace', index: 1, oldValue: false, newValue: true },\n * { op: 'remove', index: 4, oldValue: false, newValue: true },\n * ]\n * ```\n *\n * @returns {ChangesObserver}\n */\n /* eslint-enable jsdoc/require-description-complete-sentence */\n createObserver() {\n const observer = new ChangesObserver();\n _classPrivateFieldGet(_observers, this).add(observer);\n observer.addLocalHook('unsubscribe', () => {\n _classPrivateFieldGet(_observers, this).delete(observer);\n });\n observer._writeInitialChanges(arrayDiff(_classPrivateFieldGet(_indexMatrix, this), _classPrivateFieldGet(_currentIndexState, this)));\n return observer;\n }\n\n /**\n * The method is an entry point for triggering new index map changes. Emitting the\n * changes triggers comparing algorithm which compares last saved state with a new\n * state. When there are some differences, the changes are sent to all subscribers.\n *\n * @param {Array} indexesState An array with index map state.\n */\n emit(indexesState) {\n let currentIndexState = _classPrivateFieldGet(_currentIndexState, this);\n if (!_classPrivateFieldGet(_isMatrixIndexesInitialized, this) || _classPrivateFieldGet(_indexMatrix, this).length !== indexesState.length) {\n if (indexesState.length === 0) {\n indexesState = new Array(currentIndexState.length).fill(_classPrivateFieldGet(_initialIndexValue, this));\n } else {\n _classPrivateFieldSet(_indexMatrix, this, new Array(indexesState.length).fill(_classPrivateFieldGet(_initialIndexValue, this)));\n }\n if (!_classPrivateFieldGet(_isMatrixIndexesInitialized, this)) {\n _classPrivateFieldSet(_isMatrixIndexesInitialized, this, true);\n currentIndexState = _classPrivateFieldGet(_indexMatrix, this);\n }\n }\n const changes = arrayDiff(currentIndexState, indexesState);\n _classPrivateFieldGet(_observers, this).forEach(observer => observer._write(changes));\n _classPrivateFieldSet(_currentIndexState, this, indexesState);\n }\n}","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { mixin } from \"../../helpers/object.mjs\";\nimport localHooks from \"../../mixins/localHooks.mjs\";\n/**\n * The ChangesObserver module is an object that represents a disposable resource\n * provided by the ChangesObservable module.\n *\n * @class ChangesObserver\n */\nvar _currentInitialChanges = /*#__PURE__*/new WeakMap();\nexport class ChangesObserver {\n constructor() {\n /**\n * The field holds initial changes that will be used to notify the callbacks added using\n * subscribe method. Regardless of the moment of listening for changes, the subscriber\n * will be notified once with all changes made before subscribing.\n *\n * @type {Array}\n */\n _classPrivateFieldInitSpec(this, _currentInitialChanges, []);\n }\n /**\n * Subscribes to the observer.\n *\n * @param {Function} callback A function that will be called when the new changes will appear.\n * @returns {ChangesObserver}\n */\n subscribe(callback) {\n this.addLocalHook('change', callback);\n this._write(_classPrivateFieldGet(_currentInitialChanges, this));\n return this;\n }\n\n /**\n * Unsubscribes all subscriptions. After the method call, the observer would not produce\n * any new events.\n *\n * @returns {ChangesObserver}\n */\n unsubscribe() {\n this.runLocalHooks('unsubscribe');\n this.clearLocalHooks();\n return this;\n }\n\n /**\n * The write method is executed by the ChangesObservable module. The module produces all\n * changes events that are distributed further by the observer.\n *\n * @private\n * @param {object} changes The chunk of changes produced by the ChangesObservable module.\n * @returns {ChangesObserver}\n */\n _write(changes) {\n if (changes.length > 0) {\n this.runLocalHooks('change', changes);\n }\n return this;\n }\n\n /**\n * The write method is executed by the ChangesObservable module. The module produces initial\n * changes that will be used to notify new subscribers.\n *\n * @private\n * @param {object} initialChanges The chunk of changes produced by the ChangesObservable module.\n */\n _writeInitialChanges(initialChanges) {\n _classPrivateFieldSet(_currentInitialChanges, this, initialChanges);\n }\n}\nmixin(ChangesObserver, localHooks);","import \"core-js/modules/es.array.push.js\";\n/**\n * An array diff implementation. The function iterates through the arrays and depends\n * on the diff results, collect the changes as a list of the objects.\n *\n * Each object contains information about the differences in the indexes of the arrays.\n * The changes also contain data about the new and previous array values.\n *\n * @private\n * @param {Array} baseArray The base array to diff from.\n * @param {Array} newArray The new array to compare with.\n * @returns {Array}\n */\nexport function arrayDiff(baseArray, newArray) {\n const changes = [];\n let i = 0;\n let j = 0;\n\n /* eslint-disable no-plusplus */\n for (; i < baseArray.length && j < newArray.length; i++, j++) {\n if (baseArray[i] !== newArray[j]) {\n changes.push({\n op: 'replace',\n index: j,\n oldValue: baseArray[i],\n newValue: newArray[j]\n });\n }\n }\n for (; i < newArray.length; i++) {\n changes.push({\n op: 'insert',\n index: i,\n oldValue: undefined,\n newValue: newArray[i]\n });\n }\n for (; j < baseArray.length; j++) {\n changes.push({\n op: 'remove',\n index: j,\n oldValue: baseArray[j],\n newValue: undefined\n });\n }\n return changes;\n}","import { isUndefined, isDefined } from \"./../helpers/mixed.mjs\";\nimport { objectEach } from \"./../helpers/object.mjs\";\nimport { error } from \"./../helpers/console.mjs\";\nimport { toSingleLine } from \"./../helpers/templateLiteralTag.mjs\";\n/**\n * Perform shallow extend of a target object with only this extension's properties which doesn't exist in the target.\n *\n * TODO: Maybe it should be moved to global helpers? It's changed `extend` function.\n *\n * @param {object} target An object that will receive the new properties.\n * @param {object} extension An object containing additional properties to merge into the target.\n * @returns {object}\n */\nexport function extendNotExistingKeys(target, extension) {\n objectEach(extension, (value, key) => {\n if (isUndefined(target[key])) {\n target[key] = value;\n }\n });\n return target;\n}\n\n/**\n * Create range of values basing on cell indexes. For example, it will create below ranges for specified function arguments:\n *\n * createCellHeadersRange(2, 7) => `2-7`\n * createCellHeadersRange(7, 2) => `2-7`\n * createCellHeadersRange(0, 4, 'A', 'D') => `A-D`\n * createCellHeadersRange(4, 0, 'D', 'A') => `A-D`.\n *\n * @param {number} firstRowIndex Index of \"first\" cell.\n * @param {number} nextRowIndex Index of \"next\" cell.\n * @param {*} fromValue Value which will represent \"first\" cell.\n * @param {*} toValue Value which will represent \"next\" cell.\n * @returns {string} Value representing range i.e. A-Z, 11-15.\n */\nexport function createCellHeadersRange(firstRowIndex, nextRowIndex) {\n let fromValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : firstRowIndex;\n let toValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : nextRowIndex;\n // Will swap `fromValue` with `toValue` if it's necessary.\n let [from, to] = [fromValue, toValue];\n if (firstRowIndex > nextRowIndex) {\n [from, to] = [to, from];\n }\n return `${from}-${to}`;\n}\n\n/**\n * Normalize language code. It takes handled languageCode proposition and change it to proper languageCode.\n * For example, when it takes `eN-us` as parameter it return `en-US`.\n *\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n * @returns {string}\n */\nexport function normalizeLanguageCode(languageCode) {\n const languageCodePattern = /^([a-zA-Z]{2})-([a-zA-Z]{2})$/;\n const partsOfLanguageCode = languageCodePattern.exec(languageCode);\n if (partsOfLanguageCode) {\n return `${partsOfLanguageCode[1].toLowerCase()}-${partsOfLanguageCode[2].toUpperCase()}`;\n }\n return languageCode;\n}\n\n/**\n *\n * Warn user if there is no registered language.\n *\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n */\nexport function warnUserAboutLanguageRegistration(languageCode) {\n if (isDefined(languageCode)) {\n error(toSingleLine`Language with code \"${languageCode}\" was not found. You should register particular language\\x20\n before using it. Read more about this issue at: https://docs.handsontable.com/i18n/missing-language-code.`);\n }\n}","/**\n * Try to choose plural form from available phrase propositions.\n *\n * @param {Array} phrasePropositions List of phrases propositions.\n * @param {number} pluralForm Number determining which phrase form should be used.\n *\n * @returns {string|Array} One particular phrase if it's possible, list of unchanged phrase propositions otherwise.\n */\nexport default function pluralize(phrasePropositions, pluralForm) {\n const isPluralizable = Array.isArray(phrasePropositions) && Number.isInteger(pluralForm);\n if (isPluralizable) {\n return phrasePropositions[pluralForm];\n }\n return phrasePropositions;\n}","import staticRegister from \"./../../utils/staticRegister.mjs\";\nimport pluralizeFn from \"./pluralize.mjs\";\nconst {\n register: registerGloballyPhraseFormatter,\n getValues: getGlobalPhraseFormatters\n} = staticRegister('phraseFormatters');\n\n/**\n * Register phrase formatter.\n *\n * @param {string} name Name of formatter.\n * @param {Function} formatterFn Function which will be applied on phrase propositions. It will transform them if it's possible.\n */\nexport function register(name, formatterFn) {\n registerGloballyPhraseFormatter(name, formatterFn);\n}\n\n/**\n * Get all registered previously formatters.\n *\n * @returns {Array}\n */\nexport function getAll() {\n return getGlobalPhraseFormatters();\n}\nexport { register as registerPhraseFormatter, getAll as getPhraseFormatters };\nregister('pluralize', pluralizeFn);","/**\n * Constants for parts of translation.\n */\n\nexport const CONTEXT_MENU_ITEMS_NAMESPACE = 'ContextMenu:items';\nconst CM_ALIAS = CONTEXT_MENU_ITEMS_NAMESPACE;\nexport const CONTEXTMENU_ITEMS_NO_ITEMS = `${CM_ALIAS}.noItems`;\nexport const CONTEXTMENU_ITEMS_ROW_ABOVE = `${CM_ALIAS}.insertRowAbove`;\nexport const CONTEXTMENU_ITEMS_ROW_BELOW = `${CM_ALIAS}.insertRowBelow`;\nexport const CONTEXTMENU_ITEMS_INSERT_LEFT = `${CM_ALIAS}.insertColumnOnTheLeft`;\nexport const CONTEXTMENU_ITEMS_INSERT_RIGHT = `${CM_ALIAS}.insertColumnOnTheRight`;\nexport const CONTEXTMENU_ITEMS_REMOVE_ROW = `${CM_ALIAS}.removeRow`;\nexport const CONTEXTMENU_ITEMS_REMOVE_COLUMN = `${CM_ALIAS}.removeColumn`;\nexport const CONTEXTMENU_ITEMS_UNDO = `${CM_ALIAS}.undo`;\nexport const CONTEXTMENU_ITEMS_REDO = `${CM_ALIAS}.redo`;\nexport const CONTEXTMENU_ITEMS_READ_ONLY = `${CM_ALIAS}.readOnly`;\nexport const CONTEXTMENU_ITEMS_CLEAR_COLUMN = `${CM_ALIAS}.clearColumn`;\nexport const CONTEXTMENU_ITEMS_COPY = `${CM_ALIAS}.copy`;\nexport const CONTEXTMENU_ITEMS_COPY_WITH_COLUMN_HEADERS = `${CM_ALIAS}.copyWithHeaders`;\nexport const CONTEXTMENU_ITEMS_COPY_WITH_COLUMN_GROUP_HEADERS = `${CM_ALIAS}.copyWithGroupHeaders`;\nexport const CONTEXTMENU_ITEMS_COPY_COLUMN_HEADERS_ONLY = `${CM_ALIAS}.copyHeadersOnly`;\nexport const CONTEXTMENU_ITEMS_CUT = `${CM_ALIAS}.cut`;\nexport const CONTEXTMENU_ITEMS_FREEZE_COLUMN = `${CM_ALIAS}.freezeColumn`;\nexport const CONTEXTMENU_ITEMS_UNFREEZE_COLUMN = `${CM_ALIAS}.unfreezeColumn`;\nexport const CONTEXTMENU_ITEMS_MERGE_CELLS = `${CM_ALIAS}.mergeCells`;\nexport const CONTEXTMENU_ITEMS_UNMERGE_CELLS = `${CM_ALIAS}.unmergeCells`;\nexport const CONTEXTMENU_ITEMS_ADD_COMMENT = `${CM_ALIAS}.addComment`;\nexport const CONTEXTMENU_ITEMS_EDIT_COMMENT = `${CM_ALIAS}.editComment`;\nexport const CONTEXTMENU_ITEMS_REMOVE_COMMENT = `${CM_ALIAS}.removeComment`;\nexport const CONTEXTMENU_ITEMS_READ_ONLY_COMMENT = `${CM_ALIAS}.readOnlyComment`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT = `${CM_ALIAS}.align`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_LEFT = `${CM_ALIAS}.align.left`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_CENTER = `${CM_ALIAS}.align.center`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT = `${CM_ALIAS}.align.right`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY = `${CM_ALIAS}.align.justify`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_TOP = `${CM_ALIAS}.align.top`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE = `${CM_ALIAS}.align.middle`;\nexport const CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM = `${CM_ALIAS}.align.bottom`;\nexport const CONTEXTMENU_ITEMS_BORDERS = `${CM_ALIAS}.borders`;\nexport const CONTEXTMENU_ITEMS_BORDERS_TOP = `${CM_ALIAS}.borders.top`;\nexport const CONTEXTMENU_ITEMS_BORDERS_RIGHT = `${CM_ALIAS}.borders.right`;\nexport const CONTEXTMENU_ITEMS_BORDERS_BOTTOM = `${CM_ALIAS}.borders.bottom`;\nexport const CONTEXTMENU_ITEMS_BORDERS_LEFT = `${CM_ALIAS}.borders.left`;\nexport const CONTEXTMENU_ITEMS_REMOVE_BORDERS = `${CM_ALIAS}.borders.remove`;\nexport const CONTEXTMENU_ITEMS_NESTED_ROWS_INSERT_CHILD = `${CM_ALIAS}.nestedHeaders.insertChildRow`; // eslint-disable-line max-len\nexport const CONTEXTMENU_ITEMS_NESTED_ROWS_DETACH_CHILD = `${CM_ALIAS}.nestedHeaders.detachFromParent`; // eslint-disable-line max-len\n\nexport const CONTEXTMENU_ITEMS_HIDE_COLUMN = `${CM_ALIAS}.hideColumn`;\nexport const CONTEXTMENU_ITEMS_SHOW_COLUMN = `${CM_ALIAS}.showColumn`;\nexport const CONTEXTMENU_ITEMS_HIDE_ROW = `${CM_ALIAS}.hideRow`;\nexport const CONTEXTMENU_ITEMS_SHOW_ROW = `${CM_ALIAS}.showRow`;\nexport const FILTERS_NAMESPACE = 'Filters:';\nexport const FILTERS_CONDITIONS_NAMESPACE = `${FILTERS_NAMESPACE}conditions`;\nexport const FILTERS_CONDITIONS_NONE = `${FILTERS_CONDITIONS_NAMESPACE}.none`;\nexport const FILTERS_CONDITIONS_EMPTY = `${FILTERS_CONDITIONS_NAMESPACE}.isEmpty`;\nexport const FILTERS_CONDITIONS_NOT_EMPTY = `${FILTERS_CONDITIONS_NAMESPACE}.isNotEmpty`;\nexport const FILTERS_CONDITIONS_EQUAL = `${FILTERS_CONDITIONS_NAMESPACE}.isEqualTo`;\nexport const FILTERS_CONDITIONS_NOT_EQUAL = `${FILTERS_CONDITIONS_NAMESPACE}.isNotEqualTo`;\nexport const FILTERS_CONDITIONS_BEGINS_WITH = `${FILTERS_CONDITIONS_NAMESPACE}.beginsWith`;\nexport const FILTERS_CONDITIONS_ENDS_WITH = `${FILTERS_CONDITIONS_NAMESPACE}.endsWith`;\nexport const FILTERS_CONDITIONS_CONTAINS = `${FILTERS_CONDITIONS_NAMESPACE}.contains`;\nexport const FILTERS_CONDITIONS_NOT_CONTAIN = `${FILTERS_CONDITIONS_NAMESPACE}.doesNotContain`;\nexport const FILTERS_CONDITIONS_BY_VALUE = `${FILTERS_CONDITIONS_NAMESPACE}.byValue`;\nexport const FILTERS_CONDITIONS_GREATER_THAN = `${FILTERS_CONDITIONS_NAMESPACE}.greaterThan`;\nexport const FILTERS_CONDITIONS_GREATER_THAN_OR_EQUAL = `${FILTERS_CONDITIONS_NAMESPACE}.greaterThanOrEqualTo`;\nexport const FILTERS_CONDITIONS_LESS_THAN = `${FILTERS_CONDITIONS_NAMESPACE}.lessThan`;\nexport const FILTERS_CONDITIONS_LESS_THAN_OR_EQUAL = `${FILTERS_CONDITIONS_NAMESPACE}.lessThanOrEqualTo`;\nexport const FILTERS_CONDITIONS_BETWEEN = `${FILTERS_CONDITIONS_NAMESPACE}.isBetween`;\nexport const FILTERS_CONDITIONS_NOT_BETWEEN = `${FILTERS_CONDITIONS_NAMESPACE}.isNotBetween`;\nexport const FILTERS_CONDITIONS_AFTER = `${FILTERS_CONDITIONS_NAMESPACE}.after`;\nexport const FILTERS_CONDITIONS_BEFORE = `${FILTERS_CONDITIONS_NAMESPACE}.before`;\nexport const FILTERS_CONDITIONS_TODAY = `${FILTERS_CONDITIONS_NAMESPACE}.today`;\nexport const FILTERS_CONDITIONS_TOMORROW = `${FILTERS_CONDITIONS_NAMESPACE}.tomorrow`;\nexport const FILTERS_CONDITIONS_YESTERDAY = `${FILTERS_CONDITIONS_NAMESPACE}.yesterday`;\nexport const FILTERS_DIVS_FILTER_BY_CONDITION = `${FILTERS_NAMESPACE}labels.filterByCondition`;\nexport const FILTERS_DIVS_FILTER_BY_VALUE = `${FILTERS_NAMESPACE}labels.filterByValue`;\nexport const FILTERS_LABELS_CONJUNCTION = `${FILTERS_NAMESPACE}labels.conjunction`;\nexport const FILTERS_LABELS_DISJUNCTION = `${FILTERS_NAMESPACE}labels.disjunction`;\nexport const FILTERS_VALUES_BLANK_CELLS = `${FILTERS_NAMESPACE}values.blankCells`;\nexport const FILTERS_BUTTONS_SELECT_ALL = `${FILTERS_NAMESPACE}buttons.selectAll`;\nexport const FILTERS_BUTTONS_CLEAR = `${FILTERS_NAMESPACE}buttons.clear`;\nexport const FILTERS_BUTTONS_OK = `${FILTERS_NAMESPACE}buttons.ok`;\nexport const FILTERS_BUTTONS_CANCEL = `${FILTERS_NAMESPACE}buttons.cancel`;\nexport const FILTERS_BUTTONS_PLACEHOLDER_SEARCH = `${FILTERS_NAMESPACE}buttons.placeholder.search`;\nexport const FILTERS_BUTTONS_PLACEHOLDER_VALUE = `${FILTERS_NAMESPACE}buttons.placeholder.value`;\nexport const FILTERS_BUTTONS_PLACEHOLDER_SECOND_VALUE = `${FILTERS_NAMESPACE}buttons.placeholder.secondValue`;\nexport const CHECKBOX_RENDERER_NAMESPACE = 'CheckboxRenderer:';\nexport const CHECKBOX_CHECKED = `${CHECKBOX_RENDERER_NAMESPACE}checked`;\nexport const CHECKBOX_UNCHECKED = `${CHECKBOX_RENDERER_NAMESPACE}unchecked`;","/**\n * @preserve\n * Authors: Handsoncode\n * Last updated: Nov 15, 2017\n *\n * Description: Definition file for English - United States language-country.\n */\nimport * as C from \"../constants.mjs\";\nconst dictionary = {\n languageCode: 'en-US',\n [C.CONTEXTMENU_ITEMS_NO_ITEMS]: 'No available options',\n [C.CONTEXTMENU_ITEMS_ROW_ABOVE]: 'Insert row above',\n [C.CONTEXTMENU_ITEMS_ROW_BELOW]: 'Insert row below',\n [C.CONTEXTMENU_ITEMS_INSERT_LEFT]: 'Insert column left',\n [C.CONTEXTMENU_ITEMS_INSERT_RIGHT]: 'Insert column right',\n [C.CONTEXTMENU_ITEMS_REMOVE_ROW]: ['Remove row', 'Remove rows'],\n [C.CONTEXTMENU_ITEMS_REMOVE_COLUMN]: ['Remove column', 'Remove columns'],\n [C.CONTEXTMENU_ITEMS_UNDO]: 'Undo',\n [C.CONTEXTMENU_ITEMS_REDO]: 'Redo',\n [C.CONTEXTMENU_ITEMS_READ_ONLY]: 'Read only',\n [C.CONTEXTMENU_ITEMS_CLEAR_COLUMN]: 'Clear column',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT]: 'Alignment',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT]: 'Left',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER]: 'Center',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT]: 'Right',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY]: 'Justify',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP]: 'Top',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE]: 'Middle',\n [C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM]: 'Bottom',\n [C.CONTEXTMENU_ITEMS_FREEZE_COLUMN]: 'Freeze column',\n [C.CONTEXTMENU_ITEMS_UNFREEZE_COLUMN]: 'Unfreeze column',\n [C.CONTEXTMENU_ITEMS_BORDERS]: 'Borders',\n [C.CONTEXTMENU_ITEMS_BORDERS_TOP]: 'Top',\n [C.CONTEXTMENU_ITEMS_BORDERS_RIGHT]: 'Right',\n [C.CONTEXTMENU_ITEMS_BORDERS_BOTTOM]: 'Bottom',\n [C.CONTEXTMENU_ITEMS_BORDERS_LEFT]: 'Left',\n [C.CONTEXTMENU_ITEMS_REMOVE_BORDERS]: 'Remove border(s)',\n [C.CONTEXTMENU_ITEMS_ADD_COMMENT]: 'Add comment',\n [C.CONTEXTMENU_ITEMS_EDIT_COMMENT]: 'Edit comment',\n [C.CONTEXTMENU_ITEMS_REMOVE_COMMENT]: 'Delete comment',\n [C.CONTEXTMENU_ITEMS_READ_ONLY_COMMENT]: 'Read-only comment',\n [C.CONTEXTMENU_ITEMS_MERGE_CELLS]: 'Merge cells',\n [C.CONTEXTMENU_ITEMS_UNMERGE_CELLS]: 'Unmerge cells',\n [C.CONTEXTMENU_ITEMS_COPY]: 'Copy',\n [C.CONTEXTMENU_ITEMS_COPY_WITH_COLUMN_HEADERS]: ['Copy with header', 'Copy with headers'],\n [C.CONTEXTMENU_ITEMS_COPY_WITH_COLUMN_GROUP_HEADERS]: ['Copy with group header', 'Copy with group headers'],\n [C.CONTEXTMENU_ITEMS_COPY_COLUMN_HEADERS_ONLY]: ['Copy header only', 'Copy headers only'],\n [C.CONTEXTMENU_ITEMS_CUT]: 'Cut',\n [C.CONTEXTMENU_ITEMS_NESTED_ROWS_INSERT_CHILD]: 'Insert child row',\n [C.CONTEXTMENU_ITEMS_NESTED_ROWS_DETACH_CHILD]: 'Detach from parent',\n [C.CONTEXTMENU_ITEMS_HIDE_COLUMN]: ['Hide column', 'Hide columns'],\n [C.CONTEXTMENU_ITEMS_SHOW_COLUMN]: ['Show column', 'Show columns'],\n [C.CONTEXTMENU_ITEMS_HIDE_ROW]: ['Hide row', 'Hide rows'],\n [C.CONTEXTMENU_ITEMS_SHOW_ROW]: ['Show row', 'Show rows'],\n [C.FILTERS_CONDITIONS_NONE]: 'None',\n [C.FILTERS_CONDITIONS_EMPTY]: 'Is empty',\n [C.FILTERS_CONDITIONS_NOT_EMPTY]: 'Is not empty',\n [C.FILTERS_CONDITIONS_EQUAL]: 'Is equal to',\n [C.FILTERS_CONDITIONS_NOT_EQUAL]: 'Is not equal to',\n [C.FILTERS_CONDITIONS_BEGINS_WITH]: 'Begins with',\n [C.FILTERS_CONDITIONS_ENDS_WITH]: 'Ends with',\n [C.FILTERS_CONDITIONS_CONTAINS]: 'Contains',\n [C.FILTERS_CONDITIONS_NOT_CONTAIN]: 'Does not contain',\n [C.FILTERS_CONDITIONS_GREATER_THAN]: 'Greater than',\n [C.FILTERS_CONDITIONS_GREATER_THAN_OR_EQUAL]: 'Greater than or equal to',\n [C.FILTERS_CONDITIONS_LESS_THAN]: 'Less than',\n [C.FILTERS_CONDITIONS_LESS_THAN_OR_EQUAL]: 'Less than or equal to',\n [C.FILTERS_CONDITIONS_BETWEEN]: 'Is between',\n [C.FILTERS_CONDITIONS_NOT_BETWEEN]: 'Is not between',\n [C.FILTERS_CONDITIONS_AFTER]: 'After',\n [C.FILTERS_CONDITIONS_BEFORE]: 'Before',\n [C.FILTERS_CONDITIONS_TODAY]: 'Today',\n [C.FILTERS_CONDITIONS_TOMORROW]: 'Tomorrow',\n [C.FILTERS_CONDITIONS_YESTERDAY]: 'Yesterday',\n [C.FILTERS_VALUES_BLANK_CELLS]: 'Blank cells',\n [C.FILTERS_DIVS_FILTER_BY_CONDITION]: 'Filter by condition',\n [C.FILTERS_DIVS_FILTER_BY_VALUE]: 'Filter by value',\n [C.FILTERS_LABELS_CONJUNCTION]: 'And',\n [C.FILTERS_LABELS_DISJUNCTION]: 'Or',\n [C.FILTERS_BUTTONS_SELECT_ALL]: 'Select all',\n [C.FILTERS_BUTTONS_CLEAR]: 'Clear',\n [C.FILTERS_BUTTONS_OK]: 'OK',\n [C.FILTERS_BUTTONS_CANCEL]: 'Cancel',\n [C.FILTERS_BUTTONS_PLACEHOLDER_SEARCH]: 'Search',\n [C.FILTERS_BUTTONS_PLACEHOLDER_VALUE]: 'Value',\n [C.FILTERS_BUTTONS_PLACEHOLDER_SECOND_VALUE]: 'Second value',\n [C.CHECKBOX_CHECKED]: 'Checked',\n [C.CHECKBOX_UNCHECKED]: 'Unchecked'\n};\nexport default dictionary;","import { isObject, deepClone } from \"../helpers/object.mjs\";\nimport { arrayEach } from \"./../helpers/array.mjs\";\nimport { isUndefined } from \"../helpers/mixed.mjs\";\nimport { extendNotExistingKeys, normalizeLanguageCode, warnUserAboutLanguageRegistration } from \"./utils.mjs\";\nimport staticRegister from \"../utils/staticRegister.mjs\";\nimport { getPhraseFormatters } from \"./phraseFormatters/index.mjs\";\nimport DEFAULT_DICTIONARY from \"./languages/en-US.mjs\";\nimport * as _dictionaryKeys from \"./constants.mjs\";\nexport const dictionaryKeys = _dictionaryKeys;\nexport const DEFAULT_LANGUAGE_CODE = DEFAULT_DICTIONARY.languageCode;\nconst {\n register: registerGloballyLanguageDictionary,\n getItem: getGlobalLanguageDictionary,\n hasItem: hasGlobalLanguageDictionary,\n getValues: getGlobalLanguagesDictionaries\n} = staticRegister('languagesDictionaries');\n\n/**\n * Register automatically the default language dictionary.\n */\nregisterLanguageDictionary(DEFAULT_DICTIONARY);\n\n/**\n * Register language dictionary for specific language code.\n *\n * @param {string|object} languageCodeOrDictionary Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE' or object representing dictionary.\n * @param {object} dictionary Dictionary for specific language (optional if first parameter has already dictionary).\n * @returns {object}\n */\nexport function registerLanguageDictionary(languageCodeOrDictionary, dictionary) {\n let languageCode = languageCodeOrDictionary;\n let dictionaryObject = dictionary;\n\n // Dictionary passed as first argument.\n if (isObject(languageCodeOrDictionary)) {\n dictionaryObject = languageCodeOrDictionary;\n languageCode = dictionaryObject.languageCode;\n }\n extendLanguageDictionary(languageCode, dictionaryObject);\n registerGloballyLanguageDictionary(languageCode, deepClone(dictionaryObject));\n\n // We do not allow user to work with dictionary by reference, it can cause lot of bugs.\n return deepClone(dictionaryObject);\n}\n\n/**\n * Extend handled dictionary by default language dictionary. As result, if any dictionary key isn't defined for specific language, it will be filled with default language value (\"dictionary gaps\" are supplemented).\n *\n * @private\n * @param {string} languageCode Language code.\n * @param {object} dictionary Dictionary which is extended.\n */\nfunction extendLanguageDictionary(languageCode, dictionary) {\n if (languageCode !== DEFAULT_LANGUAGE_CODE) {\n extendNotExistingKeys(dictionary, getGlobalLanguageDictionary(DEFAULT_LANGUAGE_CODE));\n }\n}\n\n/**\n * Get language dictionary for specific language code.\n *\n * @param {string} languageCode Language code.\n * @returns {object} Object with constants representing identifiers for translation (as keys) and corresponding translation phrases (as values).\n */\nexport function getLanguageDictionary(languageCode) {\n if (!hasLanguageDictionary(languageCode)) {\n return null;\n }\n return deepClone(getGlobalLanguageDictionary(languageCode));\n}\n\n/**\n *\n * Get if language with specified language code was registered.\n *\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n * @returns {boolean}\n */\nexport function hasLanguageDictionary(languageCode) {\n return hasGlobalLanguageDictionary(languageCode);\n}\n\n/**\n * Get default language dictionary.\n *\n * @returns {object} Object with constants representing identifiers for translation (as keys) and corresponding translation phrases (as values).\n */\nexport function getDefaultLanguageDictionary() {\n return DEFAULT_DICTIONARY;\n}\n\n/**\n * Get registered language dictionaries.\n *\n * @returns {Array}\n */\nexport function getLanguagesDictionaries() {\n return getGlobalLanguagesDictionaries();\n}\n\n/**\n * Get phrase for specified dictionary key.\n *\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n * @param {string} dictionaryKey Constant which is dictionary key.\n * @param {*} argumentsForFormatters Arguments which will be handled by formatters.\n *\n * @returns {string}\n */\nexport function getTranslatedPhrase(languageCode, dictionaryKey, argumentsForFormatters) {\n const languageDictionary = getLanguageDictionary(languageCode);\n if (languageDictionary === null) {\n return null;\n }\n const phrasePropositions = languageDictionary[dictionaryKey];\n if (isUndefined(phrasePropositions)) {\n return null;\n }\n const formattedPhrase = getFormattedPhrase(phrasePropositions, argumentsForFormatters);\n if (Array.isArray(formattedPhrase)) {\n return formattedPhrase[0];\n }\n return formattedPhrase;\n}\n\n/**\n * Get formatted phrase from phrases propositions for specified dictionary key.\n *\n * @private\n * @param {Array|string} phrasePropositions List of phrase propositions.\n * @param {*} argumentsForFormatters Arguments which will be handled by formatters.\n *\n * @returns {Array|string}\n */\nfunction getFormattedPhrase(phrasePropositions, argumentsForFormatters) {\n let formattedPhrasePropositions = phrasePropositions;\n arrayEach(getPhraseFormatters(), formatter => {\n formattedPhrasePropositions = formatter(phrasePropositions, argumentsForFormatters);\n });\n return formattedPhrasePropositions;\n}\n\n/**\n * Returns valid language code. If the passed language code doesn't exist default one will be used.\n *\n * @param {string} languageCode Language code for specific language i.e. 'en-US', 'pt-BR', 'de-DE'.\n * @returns {string}\n */\nexport function getValidLanguageCode(languageCode) {\n let normalizedLanguageCode = normalizeLanguageCode(languageCode);\n if (!hasLanguageDictionary(normalizedLanguageCode)) {\n normalizedLanguageCode = DEFAULT_LANGUAGE_CODE;\n warnUserAboutLanguageRegistration(languageCode);\n }\n return normalizedLanguageCode;\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport Highlight, { AREA_TYPE, HEADER_TYPE, FOCUS_TYPE } from \"./highlight/highlight.mjs\";\nimport SelectionRange from \"./range.mjs\";\nimport { createObjectPropListener, mixin } from \"./../helpers/object.mjs\";\nimport { isUndefined } from \"./../helpers/mixed.mjs\";\nimport { clamp } from \"./../helpers/number.mjs\";\nimport { arrayEach } from \"./../helpers/array.mjs\";\nimport localHooks from \"./../mixins/localHooks.mjs\";\nimport Transformation from \"./transformation.mjs\";\nimport { detectSelectionType, normalizeSelectionFactory, SELECTION_TYPE_EMPTY, SELECTION_TYPE_UNRECOGNIZED } from \"./utils.mjs\";\nimport { toSingleLine } from \"./../helpers/templateLiteralTag.mjs\";\nimport { A11Y_SELECTED } from \"../helpers/a11y.mjs\";\n/**\n * @class Selection\n * @util\n */\nvar _transformation = /*#__PURE__*/new WeakMap();\nvar _focusTransformation = /*#__PURE__*/new WeakMap();\nvar _isFocusSelectionChanged = /*#__PURE__*/new WeakMap();\nvar _disableHeadersHighlight = /*#__PURE__*/new WeakMap();\nvar _selectionSource = /*#__PURE__*/new WeakMap();\nvar _expectedLayersCount = /*#__PURE__*/new WeakMap();\nclass Selection {\n constructor(settings, tableProps) {\n var _this = this;\n /**\n * Handsontable settings instance.\n *\n * @type {GridSettings}\n */\n _defineProperty(this, \"settings\", void 0);\n /**\n * An additional object with dynamically defined properties which describes table state.\n *\n * @type {object}\n */\n _defineProperty(this, \"tableProps\", void 0);\n /**\n * The flag which determines if the selection is in progress.\n *\n * @type {boolean}\n */\n _defineProperty(this, \"inProgress\", false);\n /**\n * Selection data layer (handle visual coordinates).\n *\n * @type {SelectionRange}\n */\n _defineProperty(this, \"selectedRange\", new SelectionRange((highlight, from, to) => {\n return this.tableProps.createCellRange(highlight, from, to);\n }));\n /**\n * Visualization layer.\n *\n * @type {Highlight}\n */\n _defineProperty(this, \"highlight\", void 0);\n /**\n * The module for modifying coordinates of the start and end selection.\n *\n * @type {Transformation}\n */\n _classPrivateFieldInitSpec(this, _transformation, void 0);\n /**\n * The module for modifying coordinates of the focus selection.\n *\n * @type {Transformation}\n */\n _classPrivateFieldInitSpec(this, _focusTransformation, void 0);\n /**\n * The collection of the selection layer levels where the whole row was selected using the row header or\n * the corner header.\n *\n * @type {Set}\n */\n _defineProperty(this, \"selectedByRowHeader\", new Set());\n /**\n * The collection of the selection layer levels where the whole column was selected using the column header or\n * the corner header.\n *\n * @type {Set}\n */\n _defineProperty(this, \"selectedByColumnHeader\", new Set());\n /**\n * The flag which determines if the focus selection was changed.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _isFocusSelectionChanged, false);\n /**\n * When sets disable highlighting the headers even when the logical coordinates points on them.\n *\n * @type {boolean}\n */\n _classPrivateFieldInitSpec(this, _disableHeadersHighlight, false);\n /**\n * The source of the selection. It can be one of the following values: `mouse`, `unknown` or any other string.\n *\n * @type {'mouse' | 'unknown' | string}\n */\n _classPrivateFieldInitSpec(this, _selectionSource, 'unknown');\n /**\n * The number of expected layers. It is used mostly to track when the last selection layer of non-contiguous\n * selection is applied, thus the viewport scroll is triggered.\n *\n * @param {number}\n */\n _classPrivateFieldInitSpec(this, _expectedLayersCount, -1);\n this.settings = settings;\n this.tableProps = tableProps;\n this.highlight = new Highlight({\n headerClassName: settings.currentHeaderClassName,\n activeHeaderClassName: settings.activeHeaderClassName,\n rowClassName: settings.currentRowClassName,\n columnClassName: settings.currentColClassName,\n cellAttributes: [A11Y_SELECTED()],\n rowIndexMapper: this.tableProps.rowIndexMapper,\n columnIndexMapper: this.tableProps.columnIndexMapper,\n disabledCellSelection: (row, column) => this.tableProps.isDisabledCellSelection(row, column),\n cellCornerVisible: function () {\n return _this.isCellCornerVisible(...arguments);\n },\n areaCornerVisible: function () {\n return _this.isAreaCornerVisible(...arguments);\n },\n visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),\n renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),\n createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),\n createCellRange: (highlight, from, to) => this.tableProps.createCellRange(highlight, from, to)\n });\n _classPrivateFieldSet(_transformation, this, new Transformation(this.selectedRange, {\n rowIndexMapper: this.tableProps.rowIndexMapper,\n columnIndexMapper: this.tableProps.columnIndexMapper,\n countRenderableRows: () => this.tableProps.countRenderableRows(),\n countRenderableColumns: () => this.tableProps.countRenderableColumns(),\n visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),\n renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),\n findFirstNonHiddenRenderableRow: function () {\n return _this.tableProps.findFirstNonHiddenRenderableRow(...arguments);\n },\n findFirstNonHiddenRenderableColumn: function () {\n return _this.tableProps.findFirstNonHiddenRenderableColumn(...arguments);\n },\n createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),\n fixedRowsBottom: () => settings.fixedRowsBottom,\n minSpareRows: () => settings.minSpareRows,\n minSpareCols: () => settings.minSpareCols,\n autoWrapRow: () => settings.autoWrapRow,\n autoWrapCol: () => settings.autoWrapCol\n }));\n _classPrivateFieldSet(_focusTransformation, this, new Transformation(this.selectedRange, {\n rowIndexMapper: this.tableProps.rowIndexMapper,\n columnIndexMapper: this.tableProps.columnIndexMapper,\n countRenderableRows: () => {\n const range = this.selectedRange.current();\n return this.tableProps.countRenderableRowsInRange(0, range.getOuterBottomEndCorner().row);\n },\n countRenderableColumns: () => {\n const range = this.selectedRange.current();\n return this.tableProps.countRenderableColumnsInRange(0, range.getOuterBottomEndCorner().col);\n },\n visualToRenderableCoords: coords => this.tableProps.visualToRenderableCoords(coords),\n renderableToVisualCoords: coords => this.tableProps.renderableToVisualCoords(coords),\n findFirstNonHiddenRenderableRow: function () {\n return _this.tableProps.findFirstNonHiddenRenderableRow(...arguments);\n },\n findFirstNonHiddenRenderableColumn: function () {\n return _this.tableProps.findFirstNonHiddenRenderableColumn(...arguments);\n },\n createCellCoords: (row, column) => this.tableProps.createCellCoords(row, column),\n fixedRowsBottom: () => 0,\n minSpareRows: () => 0,\n minSpareCols: () => 0,\n autoWrapRow: () => true,\n autoWrapCol: () => true\n }));\n _classPrivateFieldGet(_transformation, this).addLocalHook('beforeTransformStart', function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return _this.runLocalHooks('beforeModifyTransformStart', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('afterTransformStart', function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return _this.runLocalHooks('afterModifyTransformStart', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('beforeTransformEnd', function () {\n for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n return _this.runLocalHooks('beforeModifyTransformEnd', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('afterTransformEnd', function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return _this.runLocalHooks('afterModifyTransformEnd', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('insertRowRequire', function () {\n for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {\n args[_key5] = arguments[_key5];\n }\n return _this.runLocalHooks('insertRowRequire', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('insertColRequire', function () {\n for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n return _this.runLocalHooks('insertColRequire', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('beforeRowWrap', function () {\n for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {\n args[_key7] = arguments[_key7];\n }\n return _this.runLocalHooks('beforeRowWrap', ...args);\n });\n _classPrivateFieldGet(_transformation, this).addLocalHook('beforeColumnWrap', function () {\n for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {\n args[_key8] = arguments[_key8];\n }\n return _this.runLocalHooks('beforeColumnWrap', ...args);\n });\n _classPrivateFieldGet(_focusTransformation, this).addLocalHook('beforeTransformStart', function () {\n for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {\n args[_key9] = arguments[_key9];\n }\n return _this.runLocalHooks('beforeModifyTransformFocus', ...args);\n });\n _classPrivateFieldGet(_focusTransformation, this).addLocalHook('afterTransformStart', function () {\n for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {\n args[_key10] = arguments[_key10];\n }\n return _this.runLocalHooks('afterModifyTransformFocus', ...args);\n });\n }\n\n /**\n * Get data layer for current selection.\n *\n * @returns {SelectionRange}\n */\n getSelectedRange() {\n return this.selectedRange;\n }\n\n /**\n * Marks the source of the selection. It can be one of the following values: `mouse`, or any other string.\n *\n * @param {'mouse' | 'unknown' | string} sourceName The source name.\n */\n markSource(sourceName) {\n _classPrivateFieldSet(_selectionSource, this, sourceName);\n }\n\n /**\n * Marks end of the selection source. It restores the selection source to default value which is 'unknown'.\n */\n markEndSource() {\n _classPrivateFieldSet(_selectionSource, this, 'unknown');\n }\n\n /**\n * Returns the source of the selection.\n *\n * @returns {'mouse' | 'unknown' | string}\n */\n getSelectionSource() {\n return _classPrivateFieldGet(_selectionSource, this);\n }\n\n /**\n * Set the number of expected layers. The method is not obligatory to call. It is used mostly internally\n * to determine when the last selection layer of non-contiguous is applied, thus the viewport scroll is triggered.\n *\n * @param {number} layersCount The number of expected layers.\n */\n setExpectedLayers(layersCount) {\n _classPrivateFieldSet(_expectedLayersCount, this, layersCount);\n }\n\n /**\n * Indicate that selection process began. It sets internally `.inProgress` property to `true`.\n */\n begin() {\n this.inProgress = true;\n }\n\n /**\n * Indicate that selection process finished. It sets internally `.inProgress` property to `false`.\n */\n finish() {\n this.runLocalHooks('afterSelectionFinished', Array.from(this.selectedRange));\n this.inProgress = false;\n _classPrivateFieldSet(_expectedLayersCount, this, -1);\n }\n\n /**\n * Check if the process of selecting the cell/cells is in progress.\n *\n * @returns {boolean}\n */\n isInProgress() {\n return this.inProgress;\n }\n\n /**\n * Starts selection range on given coordinate object.\n *\n * @param {CellCoords} coords Visual coords.\n * @param {boolean} [multipleSelection] If `true`, selection will be worked in 'multiple' mode. This option works\n * only when 'selectionMode' is set as 'multiple'. If the argument is not defined\n * the default trigger will be used.\n * @param {boolean} [fragment=false] If `true`, the selection will be treated as a partial selection where the\n * `setRangeEnd` method won't be called on every `setRangeStart` call.\n * @param {CellCoords} [highlightCoords] If set, allows changing the coordinates of the highlight/focus cell.\n */\n setRangeStart(coords, multipleSelection) {\n let fragment = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let highlightCoords = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : coords;\n const isMultipleMode = this.settings.selectionMode === 'multiple';\n const isMultipleSelection = isUndefined(multipleSelection) ? this.tableProps.getShortcutManager().isCtrlPressed() : multipleSelection;\n // We are creating copy. We would like to modify just the start of the selection by below hook. Then original coords\n // should be handled by next methods.\n const coordsClone = coords.clone();\n _classPrivateFieldSet(_isFocusSelectionChanged, this, false);\n this.runLocalHooks(`beforeSetRangeStart${fragment ? 'Only' : ''}`, coordsClone);\n if (!isMultipleMode || isMultipleMode && !isMultipleSelection && isUndefined(multipleSelection)) {\n this.selectedRange.clear();\n }\n this.selectedRange.add(coordsClone).current().setHighlight(highlightCoords.clone());\n if (this.getLayerLevel() === 0) {\n this.selectedByRowHeader.clear();\n this.selectedByColumnHeader.clear();\n }\n if (!fragment) {\n this.setRangeEnd(coords);\n }\n }\n\n /**\n * Starts selection range on given coordinate object.\n *\n * @param {CellCoords} coords Visual coords.\n * @param {boolean} [multipleSelection] If `true`, selection will be worked in 'multiple' mode. This option works\n * only when 'selectionMode' is set as 'multiple'. If the argument is not defined\n * the default trigger will be used.\n * @param {CellCoords} [highlightCoords] If set, allows changing the coordinates of the highlight/focus cell.\n */\n setRangeStartOnly(coords, multipleSelection) {\n let highlightCoords = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : coords;\n this.setRangeStart(coords, multipleSelection, true, highlightCoords);\n }\n\n /**\n * Ends selection range on given coordinate object.\n *\n * @param {CellCoords} coords Visual coords.\n */\n setRangeEnd(coords) {\n if (this.selectedRange.isEmpty()) {\n return;\n }\n const coordsClone = coords.clone();\n const countRows = this.tableProps.countRows();\n const countCols = this.tableProps.countCols();\n const isSingle = this.selectedRange.current().clone().setTo(coords).isSingleHeader();\n\n // Ignore processing the end range when the header selection starts overlapping the corner and\n // the selection is not a single header highlight.\n if ((countRows > 0 || countCols > 0) && (countRows === 0 && coordsClone.col < 0 && !isSingle || countCols === 0 && coordsClone.row < 0 && !isSingle)) {\n return;\n }\n this.runLocalHooks('beforeSetRangeEnd', coordsClone);\n this.begin();\n const cellRange = this.selectedRange.current();\n if (!this.settings.navigableHeaders) {\n cellRange.highlight.normalize();\n }\n if (this.settings.selectionMode === 'single') {\n cellRange.setFrom(cellRange.highlight);\n cellRange.setTo(cellRange.highlight);\n } else {\n const horizontalDir = cellRange.getHorizontalDirection();\n const verticalDir = cellRange.getVerticalDirection();\n const isMultiple = this.isMultiple();\n cellRange.setTo(coordsClone);\n if (isMultiple && (horizontalDir !== cellRange.getHorizontalDirection() || cellRange.getWidth() === 1 && !cellRange.includes(cellRange.highlight))) {\n cellRange.from.assign({\n col: cellRange.highlight.col\n });\n }\n if (isMultiple && (verticalDir !== cellRange.getVerticalDirection() || cellRange.getHeight() === 1 && !cellRange.includes(cellRange.highlight))) {\n cellRange.from.assign({\n row: cellRange.highlight.row\n });\n }\n }\n\n // Prevent creating \"area\" selection that overlaps headers.\n if (countRows > 0 && countCols > 0) {\n if (!this.settings.navigableHeaders || this.settings.navigableHeaders && !cellRange.isSingleHeader()) {\n cellRange.to.normalize();\n }\n }\n this.runLocalHooks('beforeHighlightSet');\n this.setRangeFocus(this.selectedRange.current().highlight);\n this.applyAndCommit();\n const isLastLayer = _classPrivateFieldGet(_expectedLayersCount, this) === -1 || this.selectedRange.size() === _classPrivateFieldGet(_expectedLayersCount, this);\n this.runLocalHooks('afterSetRangeEnd', coords, isLastLayer);\n }\n\n /**\n * Applies and commits the selection to all layers (using the Walkontable Selection API) based on the selection (CellRanges)\n * collected in the `selectedRange` module.\n *\n * @param {CellRange} [cellRange] The cell range to apply. If not provided, the current selection is used.\n * @param {number} [layerLevel] The layer level to apply. If not provided, the current layer level is used.\n */\n applyAndCommit() {\n let cellRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.selectedRange.current();\n let layerLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.getLayerLevel();\n const countRows = this.tableProps.countRows();\n const countCols = this.tableProps.countCols();\n\n // If the next layer level is lower than previous then clear all area and header highlights. This is the\n // indication that the new selection is performing.\n if (layerLevel < this.highlight.layerLevel) {\n arrayEach(this.highlight.getAreas(), highlight => void highlight.clear());\n arrayEach(this.highlight.getLayeredAreas(), highlight => void highlight.clear());\n arrayEach(this.highlight.getRowHeaders(), highlight => void highlight.clear());\n arrayEach(this.highlight.getColumnHeaders(), highlight => void highlight.clear());\n arrayEach(this.highlight.getActiveRowHeaders(), highlight => void highlight.clear());\n arrayEach(this.highlight.getActiveColumnHeaders(), highlight => void highlight.clear());\n arrayEach(this.highlight.getActiveCornerHeaders(), highlight => void highlight.clear());\n arrayEach(this.highlight.getRowHighlights(), highlight => void highlight.clear());\n arrayEach(this.highlight.getColumnHighlights(), highlight => void highlight.clear());\n }\n this.highlight.useLayerLevel(layerLevel);\n const areaHighlight = this.highlight.createArea();\n const layeredAreaHighlight = this.highlight.createLayeredArea();\n const rowHeaderHighlight = this.highlight.createRowHeader();\n const columnHeaderHighlight = this.highlight.createColumnHeader();\n const activeRowHeaderHighlight = this.highlight.createActiveRowHeader();\n const activeColumnHeaderHighlight = this.highlight.createActiveColumnHeader();\n const activeCornerHeaderHighlight = this.highlight.createActiveCornerHeader();\n const rowHighlight = this.highlight.createRowHighlight();\n const columnHighlight = this.highlight.createColumnHighlight();\n areaHighlight.clear();\n layeredAreaHighlight.clear();\n rowHeaderHighlight.clear();\n columnHeaderHighlight.clear();\n activeRowHeaderHighlight.clear();\n activeColumnHeaderHighlight.clear();\n activeCornerHeaderHighlight.clear();\n rowHighlight.clear();\n columnHighlight.clear();\n if (this.highlight.isEnabledFor(AREA_TYPE, cellRange.highlight) && (this.isMultiple() || layerLevel >= 1)) {\n areaHighlight.add(cellRange.from).add(cellRange.to).commit();\n layeredAreaHighlight.add(cellRange.from).add(cellRange.to).commit();\n if (layerLevel === 1) {\n // For single cell selection in the same layer, we do not create area selection to prevent blue background.\n // When non-consecutive selection is performed we have to add that missing area selection to the previous layer\n // based on previous coordinates. It only occurs when the previous selection wasn't select multiple cells.\n const previousRange = this.selectedRange.previous();\n this.highlight.useLayerLevel(layerLevel - 1);\n this.highlight.createArea().add(previousRange.from).commit()\n // Range may start with hidden indexes. Commit would not found start point (as we add just the `from` coords).\n .syncWith(previousRange);\n this.highlight.createLayeredArea().add(previousRange.from).commit()\n // Range may start with hidden indexes. Commit would not found start point (as we add just the `from` coords).\n .syncWith(previousRange);\n this.highlight.useLayerLevel(layerLevel);\n }\n }\n if (this.highlight.isEnabledFor(HEADER_TYPE, cellRange.highlight)) {\n if (!cellRange.isSingleHeader()) {\n const rowCoordsFrom = this.tableProps.createCellCoords(Math.max(cellRange.from.row, 0), -1);\n const rowCoordsTo = this.tableProps.createCellCoords(cellRange.to.row, -1);\n const columnCoordsFrom = this.tableProps.createCellCoords(-1, Math.max(cellRange.from.col, 0));\n const columnCoordsTo = this.tableProps.createCellCoords(-1, cellRange.to.col);\n if (this.settings.selectionMode === 'single') {\n rowHeaderHighlight.add(rowCoordsFrom).commit();\n columnHeaderHighlight.add(columnCoordsFrom).commit();\n rowHighlight.add(rowCoordsFrom).commit();\n columnHighlight.add(columnCoordsFrom).commit();\n } else {\n rowHeaderHighlight.add(rowCoordsFrom).add(rowCoordsTo).commit();\n columnHeaderHighlight.add(columnCoordsFrom).add(columnCoordsTo).commit();\n rowHighlight.add(rowCoordsFrom).add(rowCoordsTo).commit();\n columnHighlight.add(columnCoordsFrom).add(columnCoordsTo).commit();\n }\n }\n const highlightRowHeaders = !_classPrivateFieldGet(_disableHeadersHighlight, this) && this.isEntireRowSelected() && (countCols > 0 && countCols === cellRange.getWidth() || countCols === 0 && this.isSelectedByRowHeader());\n const highlightColumnHeaders = !_classPrivateFieldGet(_disableHeadersHighlight, this) && this.isEntireColumnSelected() && (countRows > 0 && countRows === cellRange.getHeight() || countRows === 0 && this.isSelectedByColumnHeader());\n if (highlightRowHeaders) {\n activeRowHeaderHighlight.add(this.tableProps.createCellCoords(Math.max(cellRange.from.row, 0), Math.min(-this.tableProps.countRowHeaders(), -1))).add(this.tableProps.createCellCoords(Math.max(cellRange.to.row, 0), -1)).commit();\n }\n if (highlightColumnHeaders) {\n activeColumnHeaderHighlight.add(this.tableProps.createCellCoords(Math.min(-this.tableProps.countColHeaders(), -1), Math.max(cellRange.from.col, 0))).add(this.tableProps.createCellCoords(-1, Math.max(cellRange.to.col, 0))).commit();\n }\n if (highlightRowHeaders && highlightColumnHeaders) {\n activeCornerHeaderHighlight.add(this.tableProps.createCellCoords(-this.tableProps.countColHeaders(), -this.tableProps.countRowHeaders())).add(this.tableProps.createCellCoords(-1, -1)).commit();\n }\n }\n }\n\n /**\n * Sets the selection focus position at the specified coordinates.\n *\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n */\n setRangeFocus(coords) {\n if (this.selectedRange.isEmpty()) {\n return;\n }\n const cellRange = this.selectedRange.current();\n if (!this.inProgress) {\n this.runLocalHooks('beforeSetFocus', coords);\n }\n const focusHighlight = this.highlight.getFocus();\n focusHighlight.clear();\n cellRange.setHighlight(coords);\n if (!this.inProgress) {\n this.runLocalHooks('beforeHighlightSet');\n }\n if (this.highlight.isEnabledFor(FOCUS_TYPE, cellRange.highlight)) {\n focusHighlight.add(cellRange.highlight).commit().syncWith(cellRange);\n }\n if (!this.inProgress) {\n _classPrivateFieldSet(_isFocusSelectionChanged, this, true);\n this.runLocalHooks('afterSetFocus', cellRange.highlight);\n }\n }\n\n /**\n * Selects cell relative to the current cell (if possible).\n *\n * @param {number} rowDelta Rows number to move, value can be passed as negative number.\n * @param {number} colDelta Columns number to move, value can be passed as negative number.\n * @param {boolean} [createMissingRecords=false] If `true` the new rows/columns will be created if necessary.\n * Otherwise, row/column will be created according to `minSpareRows/minSpareCols` settings of Handsontable.\n */\n transformStart(rowDelta, colDelta) {\n let createMissingRecords = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n if (this.settings.navigableHeaders) {\n _classPrivateFieldGet(_transformation, this).setOffsetSize({\n x: this.tableProps.countRowHeaders(),\n y: this.tableProps.countColHeaders()\n });\n } else {\n _classPrivateFieldGet(_transformation, this).resetOffsetSize();\n }\n this.setRangeStart(_classPrivateFieldGet(_transformation, this).transformStart(rowDelta, colDelta, createMissingRecords));\n }\n\n /**\n * Sets selection end cell relative to the current selection end cell (if possible).\n *\n * @param {number} rowDelta Rows number to move, value can be passed as negative number.\n * @param {number} colDelta Columns number to move, value can be passed as negative number.\n */\n transformEnd(rowDelta, colDelta) {\n if (this.settings.navigableHeaders) {\n _classPrivateFieldGet(_transformation, this).setOffsetSize({\n x: this.tableProps.countRowHeaders(),\n y: this.tableProps.countColHeaders()\n });\n } else {\n _classPrivateFieldGet(_transformation, this).resetOffsetSize();\n }\n this.setRangeEnd(_classPrivateFieldGet(_transformation, this).transformEnd(rowDelta, colDelta));\n }\n\n /**\n * Transforms the focus cell selection relative to the current focus position.\n *\n * @param {number} rowDelta Rows number to move, value can be passed as negative number.\n * @param {number} colDelta Columns number to move, value can be passed as negative number.\n */\n transformFocus(rowDelta, colDelta) {\n const range = this.selectedRange.current();\n const {\n row,\n col\n } = range.getOuterTopStartCorner();\n const columnsInRange = this.tableProps.countRenderableColumnsInRange(0, col - 1);\n const rowsInRange = this.tableProps.countRenderableRowsInRange(0, row - 1);\n if (range.highlight.isHeader()) {\n // for header focus selection calculate the new coords based on the selection including headers\n _classPrivateFieldGet(_focusTransformation, this).setOffsetSize({\n x: col < 0 ? Math.abs(col) : -columnsInRange,\n y: row < 0 ? Math.abs(row) : -rowsInRange\n });\n } else {\n // for focus selection in cells calculate the new coords only based on the selected cells\n _classPrivateFieldGet(_focusTransformation, this).setOffsetSize({\n x: col < 0 ? 0 : -columnsInRange,\n y: row < 0 ? 0 : -rowsInRange\n });\n }\n const focusCoords = _classPrivateFieldGet(_focusTransformation, this).transformStart(rowDelta, colDelta);\n this.setRangeFocus(focusCoords.normalize());\n }\n\n /**\n * Transforms the last selection layer down or up by the index count.\n *\n * @param {number} visualRowIndex Visual row index from which the selection will be shifted.\n * @param {number} amount The number of rows to shift the selection.\n */\n shiftRows(visualRowIndex, amount) {\n if (!this.isSelected()) {\n return;\n }\n const range = this.selectedRange.current();\n if (this.isSelectedByCorner()) {\n this.selectAll(true, true, {\n disableHeadersHighlight: true\n });\n } else if (this.isSelectedByColumnHeader() || range.getOuterTopStartCorner().row >= visualRowIndex) {\n const {\n from,\n to,\n highlight\n } = range;\n const countRows = this.tableProps.countRows();\n const isSelectedByRowHeader = this.isSelectedByRowHeader();\n const isSelectedByColumnHeader = this.isSelectedByColumnHeader();\n const minRow = isSelectedByColumnHeader ? -1 : 0;\n const coordsStartAmount = isSelectedByColumnHeader ? 0 : amount;\n\n // Remove from the stack the last added selection as that selection below will be\n // replaced by new transformed selection.\n this.getSelectedRange().pop();\n const coordsStart = this.tableProps.createCellCoords(clamp(from.row + coordsStartAmount, minRow, countRows - 1), from.col);\n const coordsEnd = this.tableProps.createCellCoords(clamp(to.row + amount, minRow, countRows - 1), to.col);\n this.markSource('shift');\n if (highlight.row >= visualRowIndex) {\n this.setRangeStartOnly(coordsStart, true, this.tableProps.createCellCoords(clamp(highlight.row + amount, 0, countRows - 1), highlight.col));\n } else {\n this.setRangeStartOnly(coordsStart, true);\n }\n if (isSelectedByRowHeader) {\n this.selectedByRowHeader.add(this.getLayerLevel());\n }\n if (isSelectedByColumnHeader) {\n this.selectedByColumnHeader.add(this.getLayerLevel());\n }\n this.setRangeEnd(coordsEnd);\n this.markEndSource();\n }\n }\n\n /**\n * Transforms the last selection layer left or right by the index count.\n *\n * @param {number} visualColumnIndex Visual column index from which the selection will be shifted.\n * @param {number} amount The number of columns to shift the selection.\n */\n shiftColumns(visualColumnIndex, amount) {\n if (!this.isSelected()) {\n return;\n }\n const range = this.selectedRange.current();\n if (this.isSelectedByCorner()) {\n this.selectAll(true, true, {\n disableHeadersHighlight: true\n });\n } else if (this.isSelectedByRowHeader() || range.getOuterTopStartCorner().col >= visualColumnIndex) {\n const {\n from,\n to,\n highlight\n } = range;\n const countCols = this.tableProps.countCols();\n const isSelectedByRowHeader = this.isSelectedByRowHeader();\n const isSelectedByColumnHeader = this.isSelectedByColumnHeader();\n const minColumn = isSelectedByRowHeader ? -1 : 0;\n const coordsStartAmount = isSelectedByRowHeader ? 0 : amount;\n\n // Remove from the stack the last added selection as that selection below will be\n // replaced by new transformed selection.\n this.getSelectedRange().pop();\n const coordsStart = this.tableProps.createCellCoords(from.row, clamp(from.col + coordsStartAmount, minColumn, countCols - 1));\n const coordsEnd = this.tableProps.createCellCoords(to.row, clamp(to.col + amount, minColumn, countCols - 1));\n this.markSource('shift');\n if (highlight.col >= visualColumnIndex) {\n this.setRangeStartOnly(coordsStart, true, this.tableProps.createCellCoords(highlight.row, clamp(highlight.col + amount, 0, countCols - 1)));\n } else {\n this.setRangeStartOnly(coordsStart, true);\n }\n if (isSelectedByRowHeader) {\n this.selectedByRowHeader.add(this.getLayerLevel());\n }\n if (isSelectedByColumnHeader) {\n this.selectedByColumnHeader.add(this.getLayerLevel());\n }\n this.setRangeEnd(coordsEnd);\n this.markEndSource();\n }\n }\n\n /**\n * Returns currently used layer level.\n *\n * @returns {number} Returns layer level starting from 0. If no selection was added to the table -1 is returned.\n */\n getLayerLevel() {\n return this.selectedRange.size() - 1;\n }\n\n /**\n * Returns `true` if currently there is a selection on the screen, `false` otherwise.\n *\n * @returns {boolean}\n */\n isSelected() {\n return !this.selectedRange.isEmpty();\n }\n\n /**\n * Returns information if we have a multi-selection. This method check multi-selection only on the latest layer of\n * the selection.\n *\n * @returns {boolean}\n */\n isMultiple() {\n if (!this.isSelected()) {\n return false;\n }\n const isMultipleListener = createObjectPropListener(!this.selectedRange.current().isSingle());\n this.runLocalHooks('afterIsMultipleSelection', isMultipleListener);\n return isMultipleListener.value;\n }\n\n /**\n * Checks if the last selection involves changing the focus cell position only.\n *\n * @returns {boolean}\n */\n isFocusSelectionChanged() {\n return this.isSelected() && _classPrivateFieldGet(_isFocusSelectionChanged, this);\n }\n\n /**\n * Returns `true` if the selection was applied by clicking to the row header. If the `layerLevel`\n * argument is passed then only that layer will be checked. Otherwise, it checks if any row header\n * was clicked on any selection layer level.\n *\n * @param {number} [layerLevel=this.getLayerLevel()] Selection layer level to check.\n * @returns {boolean}\n */\n isSelectedByRowHeader() {\n let layerLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getLayerLevel();\n return !this.isSelectedByCorner(layerLevel) && (layerLevel === -1 ? this.selectedByRowHeader.size > 0 : this.selectedByRowHeader.has(layerLevel));\n }\n\n /**\n * Returns `true` if the selection consists of entire rows (including their headers). If the `layerLevel`\n * argument is passed then only that layer will be checked. Otherwise, it checks the selection for all layers.\n *\n * @param {number} [layerLevel=this.getLayerLevel()] Selection layer level to check.\n * @returns {boolean}\n */\n isEntireRowSelected() {\n let layerLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getLayerLevel();\n const tester = range => {\n const {\n col\n } = range.getOuterTopStartCorner();\n const rowHeaders = this.tableProps.countRowHeaders();\n const countCols = this.tableProps.countCols();\n return (rowHeaders > 0 && col < 0 || rowHeaders === 0) && range.getWidth() === countCols;\n };\n if (layerLevel === -1) {\n return Array.from(this.selectedRange).some(range => tester(range));\n }\n const range = this.selectedRange.peekByIndex(layerLevel);\n return range ? tester(range) : false;\n }\n\n /**\n * Returns `true` if the selection was applied by clicking to the column header. If the `layerLevel`\n * argument is passed then only that layer will be checked. Otherwise, it checks if any column header\n * was clicked on any selection layer level.\n *\n * @param {number} [layerLevel=this.getLayerLevel()] Selection layer level to check.\n * @returns {boolean}\n */\n isSelectedByColumnHeader() {\n let layerLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getLayerLevel();\n return !this.isSelectedByCorner() && (layerLevel === -1 ? this.selectedByColumnHeader.size > 0 : this.selectedByColumnHeader.has(layerLevel));\n }\n\n /**\n * Returns `true` if the selection consists of entire columns (including their headers). If the `layerLevel`\n * argument is passed then only that layer will be checked. Otherwise, it checks the selection for all layers.\n *\n * @param {number} [layerLevel=this.getLayerLevel()] Selection layer level to check.\n * @returns {boolean}\n */\n isEntireColumnSelected() {\n let layerLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getLayerLevel();\n const tester = range => {\n const {\n row\n } = range.getOuterTopStartCorner();\n const colHeaders = this.tableProps.countColHeaders();\n const countRows = this.tableProps.countRows();\n return (colHeaders > 0 && row < 0 || colHeaders === 0) && range.getHeight() === countRows;\n };\n if (layerLevel === -1) {\n return Array.from(this.selectedRange).some(range => tester(range));\n }\n const range = this.selectedRange.peekByIndex(layerLevel);\n return range ? tester(range) : false;\n }\n\n /**\n * Returns `true` if the selection was applied by clicking on the row or column header on any layer level.\n *\n * @returns {boolean}\n */\n isSelectedByAnyHeader() {\n return this.isSelectedByRowHeader(-1) || this.isSelectedByColumnHeader(-1) || this.isSelectedByCorner();\n }\n\n /**\n * Returns `true` if the selection was applied by clicking on the left-top corner overlay.\n *\n * @returns {boolean}\n */\n isSelectedByCorner() {\n return this.selectedByColumnHeader.has(this.getLayerLevel()) && this.selectedByRowHeader.has(this.getLayerLevel());\n }\n\n /**\n * Returns `true` if coords is within selection coords. This method iterates through all selection layers to check if\n * the coords object is within selection range.\n *\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n * @returns {boolean}\n */\n inInSelection(coords) {\n return this.selectedRange.includes(coords);\n }\n\n /**\n * Returns `true` if the cell corner should be visible.\n *\n * @private\n * @returns {boolean} `true` if the corner element has to be visible, `false` otherwise.\n */\n isCellCornerVisible() {\n return this.settings.fillHandle && !this.tableProps.isEditorOpened() && !this.isMultiple();\n }\n\n /**\n * Returns `true` if the cell coordinates are visible (renderable).\n *\n * @private\n * @param {CellCoords} coords The cell coordinates to check.\n * @returns {boolean}\n */\n isCellVisible(coords) {\n const renderableCoords = this.tableProps.visualToRenderableCoords(coords);\n return renderableCoords.row !== null && renderableCoords.col !== null;\n }\n\n /**\n * Returns `true` if the area corner should be visible.\n *\n * @param {number} layerLevel The layer level.\n * @returns {boolean} `true` if the corner element has to be visible, `false` otherwise.\n */\n isAreaCornerVisible(layerLevel) {\n if (Number.isInteger(layerLevel) && layerLevel !== this.getLayerLevel()) {\n return false;\n }\n return this.settings.fillHandle && !this.tableProps.isEditorOpened() && this.isMultiple();\n }\n\n /**\n * Clear the selection by resetting the collected ranges and highlights.\n */\n clear() {\n // TODO: collections selectedByColumnHeader and selectedByRowHeader should be clear too.\n this.selectedRange.clear();\n this.highlight.clear();\n }\n\n /**\n * Deselects all selected cells.\n */\n deselect() {\n if (!this.isSelected()) {\n return;\n }\n this.inProgress = false;\n this.clear();\n this.runLocalHooks('afterDeselect');\n }\n\n /**\n * Selects all cells and headers.\n *\n * @param {boolean} [includeRowHeaders=false] `true` If the selection should include the row headers,\n * `false` otherwise.\n * @param {boolean} [includeColumnHeaders=false] `true` If the selection should include the column\n * headers, `false` otherwise.\n * @param {object} [options] Additional object with options.\n * @param {{row: number, col: number} | boolean} [options.focusPosition] The argument allows changing the cell/header\n * focus position. The value takes an object with a `row` and `col` properties from -N to N, where\n * negative values point to the headers and positive values point to the cell range. If `false`, the focus\n * position won't be changed.\n * @param {boolean} [options.disableHeadersHighlight] If `true`, disables highlighting the headers even when\n * the logical coordinates points on them.\n */\n selectAll() {\n var _this$getSelectedRang;\n let includeRowHeaders = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n let includeColumnHeaders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {\n focusPosition: false,\n disableHeadersHighlight: false\n };\n const nrOfRows = this.tableProps.countRows();\n const nrOfColumns = this.tableProps.countCols();\n const countRowHeaders = this.tableProps.countRowHeaders();\n const countColHeaders = this.tableProps.countColHeaders();\n const rowFrom = includeColumnHeaders ? -countColHeaders : 0;\n const columnFrom = includeRowHeaders ? -countRowHeaders : 0;\n\n // We can't select cells when there is no data.\n if (rowFrom === 0 && columnFrom === 0 && (nrOfRows === 0 || nrOfColumns === 0)) {\n return;\n }\n let highlight = (_this$getSelectedRang = this.getSelectedRange().current()) === null || _this$getSelectedRang === void 0 ? void 0 : _this$getSelectedRang.highlight;\n const {\n focusPosition,\n disableHeadersHighlight\n } = options;\n _classPrivateFieldSet(_disableHeadersHighlight, this, disableHeadersHighlight);\n if (focusPosition && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {\n highlight = this.tableProps.createCellCoords(clamp(focusPosition.row, rowFrom, nrOfRows - 1), clamp(focusPosition.col, columnFrom, nrOfColumns - 1));\n }\n const startCoords = this.tableProps.createCellCoords(rowFrom, columnFrom);\n const endCoords = this.tableProps.createCellCoords(nrOfRows - 1, nrOfColumns - 1);\n this.clear();\n this.setRangeStartOnly(startCoords, undefined, highlight);\n if (columnFrom < 0) {\n this.selectedByRowHeader.add(this.getLayerLevel());\n }\n if (rowFrom < 0) {\n this.selectedByColumnHeader.add(this.getLayerLevel());\n }\n this.setRangeEnd(endCoords);\n this.finish();\n _classPrivateFieldSet(_disableHeadersHighlight, this, false);\n }\n\n /**\n * Make multiple, non-contiguous selection specified by `row` and `column` values or a range of cells\n * finishing at `endRow`, `endColumn`. The method supports two input formats, first as an array of arrays such\n * as `[[rowStart, columnStart, rowEnd, columnEnd]]` and second format as an array of CellRange objects.\n * If the passed ranges have another format the exception will be thrown.\n *\n * @param {Array[]|CellRange[]} selectionRanges The coordinates which define what the cells should be selected.\n * @returns {boolean} Returns `true` if selection was successful, `false` otherwise.\n */\n selectCells(selectionRanges) {\n var _this2 = this;\n const selectionType = detectSelectionType(selectionRanges);\n if (selectionType === SELECTION_TYPE_EMPTY) {\n return false;\n } else if (selectionType === SELECTION_TYPE_UNRECOGNIZED) {\n throw new Error(toSingleLine`Unsupported format of the selection ranges was passed. To select cells pass\\x20\n the coordinates as an array of arrays ([[rowStart, columnStart/columnPropStart, rowEnd,\\x20\n columnEnd/columnPropEnd]]) or as an array of CellRange objects.`);\n }\n const selectionSchemaNormalizer = normalizeSelectionFactory(selectionType, {\n createCellCoords: function () {\n return _this2.tableProps.createCellCoords(...arguments);\n },\n createCellRange: function () {\n return _this2.tableProps.createCellRange(...arguments);\n },\n propToCol: prop => this.tableProps.propToCol(prop),\n keepDirection: true\n });\n const navigableHeaders = this.settings.navigableHeaders;\n const tableParams = {\n countRows: this.tableProps.countRows(),\n countCols: this.tableProps.countCols(),\n countRowHeaders: navigableHeaders ? this.tableProps.countRowHeaders() : 0,\n countColHeaders: navigableHeaders ? this.tableProps.countColHeaders() : 0\n };\n\n // Check if every layer of the coordinates are valid.\n const isValid = !selectionRanges.some(selection => {\n const cellRange = selectionSchemaNormalizer(selection);\n const rangeValidity = cellRange.isValid(tableParams);\n return !(rangeValidity && !cellRange.containsHeaders() || rangeValidity && cellRange.containsHeaders() && cellRange.isSingleHeader());\n });\n if (isValid) {\n this.clear();\n this.setExpectedLayers(selectionRanges.length);\n arrayEach(selectionRanges, selection => {\n const {\n from,\n to\n } = selectionSchemaNormalizer(selection);\n this.setRangeStartOnly(from.clone(), false);\n this.setRangeEnd(to.clone());\n });\n this.finish();\n }\n return isValid;\n }\n\n /**\n * Select column specified by `startColumn` visual index or column property or a range of columns finishing at\n * `endColumn`.\n *\n * @param {number|string} startColumn Visual column index or column property from which the selection starts.\n * @param {number|string} [endColumn] Visual column index or column property from to the selection finishes.\n * @param {number | { row: number, col: number }} [focusPosition=0] The argument allows changing the cell/header focus\n * position. The value can take visual row index from -N to N, where negative values point to the headers and positive\n * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus\n * position horizontally.\n * @returns {boolean} Returns `true` if selection was successful, `false` otherwise.\n */\n selectColumns(startColumn) {\n let endColumn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startColumn;\n let focusPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n const start = typeof startColumn === 'string' ? this.tableProps.propToCol(startColumn) : startColumn;\n const end = typeof endColumn === 'string' ? this.tableProps.propToCol(endColumn) : endColumn;\n const countRows = this.tableProps.countRows();\n const countCols = this.tableProps.countCols();\n const countColHeaders = this.tableProps.countColHeaders();\n const columnHeaderLastIndex = countColHeaders === 0 ? 0 : -countColHeaders;\n const fromCoords = this.tableProps.createCellCoords(columnHeaderLastIndex, start);\n const toCoords = this.tableProps.createCellCoords(countRows - 1, end);\n const isValid = this.tableProps.createCellRange(fromCoords, fromCoords, toCoords).isValid({\n countRows,\n countCols,\n countRowHeaders: 0,\n countColHeaders\n });\n if (isValid) {\n let highlightRow = 0;\n let highlightColumn = 0;\n if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {\n highlightRow = clamp(focusPosition.row, columnHeaderLastIndex, countRows - 1);\n highlightColumn = clamp(focusPosition.col, Math.min(start, end), Math.max(start, end));\n } else {\n highlightRow = clamp(focusPosition, columnHeaderLastIndex, countRows - 1);\n highlightColumn = start;\n }\n const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);\n const fromRow = countColHeaders === 0 ? 0 : clamp(highlight.row, columnHeaderLastIndex, -1);\n const toRow = countRows - 1;\n const from = this.tableProps.createCellCoords(fromRow, start);\n const to = this.tableProps.createCellCoords(toRow, end);\n this.runLocalHooks('beforeSelectColumns', from, to, highlight);\n\n // disallow modifying row axis for that hooks\n from.row = fromRow;\n to.row = toRow;\n this.setRangeStartOnly(from, undefined, highlight);\n this.selectedByColumnHeader.add(this.getLayerLevel());\n this.setRangeEnd(to);\n this.runLocalHooks('afterSelectColumns', from, to, highlight);\n this.finish();\n }\n return isValid;\n }\n\n /**\n * Select row specified by `startRow` visual index or a range of rows finishing at `endRow`.\n *\n * @param {number} startRow Visual row index from which the selection starts.\n * @param {number} [endRow] Visual row index from to the selection finishes.\n * @param {number | { row: number, col: number }} [focusPosition=0] The argument allows changing the cell/header focus\n * position. The value can take visual row index from -N to N, where negative values point to the headers and positive\n * values point to the cell range. An object with `row` and `col` properties also can be passed to change the focus\n * position horizontally.\n * @returns {boolean} Returns `true` if selection was successful, `false` otherwise.\n */\n selectRows(startRow) {\n let endRow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : startRow;\n let focusPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n const countRows = this.tableProps.countRows();\n const countCols = this.tableProps.countCols();\n const countRowHeaders = this.tableProps.countRowHeaders();\n const rowHeaderLastIndex = countRowHeaders === 0 ? 0 : -countRowHeaders;\n const fromCoords = this.tableProps.createCellCoords(startRow, rowHeaderLastIndex);\n const toCoords = this.tableProps.createCellCoords(endRow, countCols - 1);\n const isValid = this.tableProps.createCellRange(fromCoords, fromCoords, toCoords).isValid({\n countRows,\n countCols,\n countRowHeaders,\n countColHeaders: 0\n });\n if (isValid) {\n let highlightRow = 0;\n let highlightColumn = 0;\n if (Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.row) && Number.isInteger(focusPosition === null || focusPosition === void 0 ? void 0 : focusPosition.col)) {\n highlightRow = clamp(focusPosition.row, Math.min(startRow, endRow), Math.max(startRow, endRow));\n highlightColumn = clamp(focusPosition.col, rowHeaderLastIndex, countCols - 1);\n } else {\n highlightRow = startRow;\n highlightColumn = clamp(focusPosition, rowHeaderLastIndex, countCols - 1);\n }\n const highlight = this.tableProps.createCellCoords(highlightRow, highlightColumn);\n const fromColumn = countRowHeaders === 0 ? 0 : clamp(highlight.col, rowHeaderLastIndex, -1);\n const toColumn = countCols - 1;\n const from = this.tableProps.createCellCoords(startRow, fromColumn);\n const to = this.tableProps.createCellCoords(endRow, toColumn);\n this.runLocalHooks('beforeSelectRows', from, to, highlight);\n\n // disallow modifying column axis for that hooks\n from.col = fromColumn;\n to.col = toColumn;\n this.setRangeStartOnly(from, undefined, highlight);\n this.selectedByRowHeader.add(this.getLayerLevel());\n this.setRangeEnd(to);\n this.runLocalHooks('afterSelectRows', from, to, highlight);\n this.finish();\n }\n return isValid;\n }\n\n /**\n * Refreshes the whole selection by clearing, reapplying and committing the renderable selection (Walkontable Selection API)\n * by using already added visual ranges.\n */\n refresh() {\n if (!this.isSelected()) {\n return;\n }\n const countRows = this.tableProps.countRows();\n const countColumns = this.tableProps.countCols();\n if (countRows === 0 || countColumns === 0) {\n this.deselect();\n return;\n }\n const range = this.selectedRange.peekByIndex(this.selectedRange.size() - 1);\n const {\n from,\n to,\n highlight\n } = range;\n this.clear();\n highlight.assign({\n row: clamp(highlight.row, -Infinity, countRows - 1),\n col: clamp(highlight.col, -Infinity, countColumns - 1)\n });\n from.assign({\n row: clamp(from.row, -Infinity, countRows - 1),\n col: clamp(from.col, -Infinity, countColumns - 1)\n });\n to.assign({\n row: clamp(to.row, 0, countRows - 1),\n col: clamp(to.col, 0, countColumns - 1)\n });\n this.selectedRange.ranges.push(range);\n this.highlight.getFocus().add(highlight).commit().syncWith(range);\n this.applyAndCommit(range);\n }\n\n /**\n * Refreshes the whole selection by recommitting (recalculating visual indexes to renderable ones) the renderable selection\n * that was already added.\n */\n commit() {\n const customSelections = this.highlight.getCustomSelections();\n customSelections.forEach(customSelection => {\n customSelection.commit();\n });\n if (!this.isSelected()) {\n return;\n }\n const focusHighlight = this.highlight.getFocus();\n const currentLayer = this.getLayerLevel();\n focusHighlight.commit().syncWith(this.selectedRange.current());\n\n // Rewriting rendered ranges going through all layers.\n for (let layerLevel = 0; layerLevel < this.selectedRange.size(); layerLevel += 1) {\n this.highlight.useLayerLevel(layerLevel);\n const areaHighlight = this.highlight.createArea();\n const areaLayeredHighlight = this.highlight.createLayeredArea();\n const rowHeaderHighlight = this.highlight.createRowHeader();\n const columnHeaderHighlight = this.highlight.createColumnHeader();\n const activeRowHeaderHighlight = this.highlight.createActiveRowHeader();\n const activeColumnHeaderHighlight = this.highlight.createActiveColumnHeader();\n const activeCornerHeaderHighlight = this.highlight.createActiveCornerHeader();\n const rowHighlight = this.highlight.createRowHighlight();\n const columnHighlight = this.highlight.createColumnHighlight();\n areaHighlight.commit();\n areaLayeredHighlight.commit();\n rowHeaderHighlight.commit();\n columnHeaderHighlight.commit();\n activeRowHeaderHighlight.commit();\n activeColumnHeaderHighlight.commit();\n activeCornerHeaderHighlight.commit();\n rowHighlight.commit();\n columnHighlight.commit();\n }\n\n // Reverting starting layer for the Highlight.\n this.highlight.useLayerLevel(currentLayer);\n }\n}\nmixin(Selection, localHooks);\nexport default Selection;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { createHighlight as createActiveHighlight } from \"./types/activeHeader.mjs\";\nimport { createHighlight as createAreaLayeredHighlight } from \"./types/areaLayered.mjs\";\nimport { createHighlight as createAreaHighlight } from \"./types/area.mjs\";\nimport { createHighlight as createColumnHighlight } from \"./types/column.mjs\";\nimport { createHighlight as createFocusHighlight } from \"./types/focus.mjs\";\nimport { createHighlight as createCustomHighlight } from \"./types/customSelection.mjs\";\nimport { createHighlight as createFillHighlight } from \"./types/fill.mjs\";\nimport { createHighlight as createHeaderHighlight } from \"./types/header.mjs\";\nimport { createHighlight as createRowHighlight } from \"./types/row.mjs\";\nimport { HIGHLIGHT_ACTIVE_HEADER_TYPE, HIGHLIGHT_AREA_TYPE, HIGHLIGHT_FOCUS_TYPE, HIGHLIGHT_CUSTOM_SELECTION_TYPE, HIGHLIGHT_FILL_TYPE, HIGHLIGHT_HEADER_TYPE, HIGHLIGHT_ROW_TYPE, HIGHLIGHT_COLUMN_TYPE } from \"../../3rdparty/walkontable/src/index.mjs\";\nimport { arrayEach } from \"./../../helpers/array.mjs\";\nexport { HIGHLIGHT_ACTIVE_HEADER_TYPE as ACTIVE_HEADER_TYPE, HIGHLIGHT_AREA_TYPE as AREA_TYPE, HIGHLIGHT_FOCUS_TYPE as FOCUS_TYPE, HIGHLIGHT_CUSTOM_SELECTION_TYPE as CUSTOM_SELECTION_TYPE, HIGHLIGHT_FILL_TYPE as FILL_TYPE, HIGHLIGHT_HEADER_TYPE as HEADER_TYPE, HIGHLIGHT_ROW_TYPE as ROW_TYPE, HIGHLIGHT_COLUMN_TYPE as COLUMN_TYPE };\n\n/**\n * Highlight class responsible for managing Walkontable Selection classes.\n *\n * With Highlight object you can manipulate four different highlight types:\n * - `cell` can be added only to a single cell at a time and it defines currently selected cell;\n * - `fill` can occur only once and its highlight defines selection of autofill functionality (managed by the plugin with the same name);\n * - `areas` can be added to multiple cells at a time. This type highlights selected cell or multiple cells.\n * The multiple cells have to be defined as an uninterrupted order (regular shape). Otherwise, the new layer of\n * that type should be created to manage not-consecutive selection;\n * - `header` can occur multiple times. This type is designed to highlight only headers. Like `area` type it\n * can appear with multiple highlights (accessed under different level layers).\n *\n * @class Highlight\n * @util\n */\nvar _Highlight_brand = /*#__PURE__*/new WeakSet();\nclass Highlight {\n constructor(options) {\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance.\n *\n * @param {Map} cacheMap The map where the instance will be cached.\n * @param {Function} highlightFactory The function factory.\n * @returns {VisualSelection}\n */\n _classPrivateMethodInitSpec(this, _Highlight_brand);\n /**\n * Options consumed by Highlight class and Walkontable Selection classes.\n *\n * @type {object}\n */\n _defineProperty(this, \"options\", void 0);\n /**\n * The property which describes which layer level of the visual selection will be modified.\n * This option is valid only for `area` and `header` highlight types which occurs multiple times on\n * the table (as a non-consecutive selection).\n *\n * An order of the layers is the same as the order of added new non-consecutive selections.\n *\n * @type {number}\n * @default 0\n */\n _defineProperty(this, \"layerLevel\", 0);\n /**\n * `cell` highlight object which describes attributes for the currently selected cell.\n * It can only occur only once on the table.\n *\n * @type {Selection}\n */\n _defineProperty(this, \"focus\", void 0);\n /**\n * `fill` highlight object which describes attributes for the borders for autofill functionality.\n * It can only occur only once on the table.\n *\n * @type {Selection}\n */\n _defineProperty(this, \"fill\", void 0);\n /**\n * Collection of the `area` highlights. That objects describes attributes for the borders and selection of\n * the multiple selected cells. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"layeredAreas\", new Map());\n /**\n * Collection of the `highlight` highlights. That objects describes attributes for the borders and selection of\n * the multiple selected cells. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"areas\", new Map());\n /**\n * Collection of the `header` highlights. That objects describes attributes for the selection of\n * the multiple selected rows in the table header. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"rowHeaders\", new Map());\n /**\n * Collection of the `header` highlights. That objects describes attributes for the selection of\n * the multiple selected columns in the table header. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"columnHeaders\", new Map());\n /**\n * Collection of the `active-header` highlights. That objects describes attributes for the selection of\n * the multiple selected rows in the table header. The table headers which have selected all items in\n * a row will be marked as `active-header`.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"activeRowHeaders\", new Map());\n /**\n * Collection of the `active-header` highlights. That objects describes attributes for the selection of\n * the multiple selected columns in the table header. The table headers which have selected all items in\n * a row will be marked as `active-header`.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"activeColumnHeaders\", new Map());\n /**\n * Collection of the `active-header` highlights. That objects describes attributes for the selection of\n * the selected corner in the table header. The table headers which have selected all items in\n * a row will be marked as `active-header`.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"activeCornerHeaders\", new Map());\n /**\n * Collection of the `rows` highlights. That objects describes attributes for the selection of\n * the multiple selected cells in a row. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"rowHighlights\", new Map());\n /**\n * Collection of the `columns` highlights. That objects describes attributes for the selection of\n * the multiple selected cells in a column. It can occur multiple times on the table.\n *\n * @type {Map.}\n */\n _defineProperty(this, \"columnHighlights\", new Map());\n /**\n * Collection of the `custom-selection`, holder for example borders added through CustomBorders plugin.\n *\n * @type {Selection[]}\n */\n _defineProperty(this, \"customSelections\", []);\n this.options = options;\n this.focus = createFocusHighlight(options);\n this.fill = createFillHighlight(options);\n }\n\n /**\n * Check if highlight cell rendering is disabled for specified highlight type.\n *\n * @param {string} highlightType Highlight type. Possible values are: `cell`, `area`, `fill` or `header`.\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n * @returns {boolean}\n */\n isEnabledFor(highlightType, coords) {\n let type = highlightType;\n\n // Legacy compatibility.\n if (highlightType === HIGHLIGHT_FOCUS_TYPE) {\n type = 'current'; // One from settings for `disableVisualSelection` up to Handsontable 0.36/Handsontable Pro 1.16.0.\n }\n let disableHighlight = this.options.disabledCellSelection(coords.row, coords.col);\n if (typeof disableHighlight === 'string') {\n disableHighlight = [disableHighlight];\n }\n return disableHighlight === false || Array.isArray(disableHighlight) && !disableHighlight.includes(type);\n }\n\n /**\n * Set a new layer level to make access to the desire `area` and `header` highlights.\n *\n * @param {number} [level=0] Layer level to use.\n * @returns {Highlight}\n */\n useLayerLevel() {\n let level = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;\n this.layerLevel = level;\n return this;\n }\n\n /**\n * Get Walkontable Selection instance created for controlling highlight of the currently\n * focused cell (or header).\n *\n * @returns {Selection}\n */\n getFocus() {\n return this.focus;\n }\n\n /**\n * Get Walkontable Selection instance created for controlling highlight of the autofill functionality.\n *\n * @returns {Selection}\n */\n getFill() {\n return this.fill;\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * `area` highlights.\n *\n * @returns {Selection}\n */\n createLayeredArea() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.layeredAreas, createAreaLayeredHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the cells.\n *\n * @returns {Selection[]}\n */\n getLayeredAreas() {\n return [...this.layeredAreas.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * `highlight` highlights.\n *\n * @returns {Selection}\n */\n createArea() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.areas, createAreaHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the cells.\n *\n * @returns {Selection[]}\n */\n getAreas() {\n return [...this.areas.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * header highlight for rows.\n *\n * @returns {Selection}\n */\n createRowHeader() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.rowHeaders, createHeaderHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the headers.\n *\n * @returns {Selection[]}\n */\n getRowHeaders() {\n return [...this.rowHeaders.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * header highlight for columns.\n *\n * @returns {Selection}\n */\n createColumnHeader() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.columnHeaders, createHeaderHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the headers.\n *\n * @returns {Selection[]}\n */\n getColumnHeaders() {\n return [...this.columnHeaders.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * highlight for active row headers.\n *\n * @returns {Selection}\n */\n createActiveRowHeader() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.activeRowHeaders, createActiveHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the active headers.\n *\n * @returns {Selection[]}\n */\n getActiveRowHeaders() {\n return [...this.activeRowHeaders.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * highlight for active column headers.\n *\n * @returns {Selection}\n */\n createActiveColumnHeader() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.activeColumnHeaders, createActiveHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the active headers.\n *\n * @returns {Selection[]}\n */\n getActiveColumnHeaders() {\n return [...this.activeColumnHeaders.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * highlight for the headers corner.\n *\n * @returns {Selection}\n */\n createActiveCornerHeader() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.activeCornerHeaders, createActiveHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the visual highlight of the headers corner.\n *\n * @returns {Selection[]}\n */\n getActiveCornerHeaders() {\n return [...this.activeCornerHeaders.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * highlight cells in a row.\n *\n * @returns {Selection}\n */\n createRowHighlight() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.rowHighlights, createRowHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the rows highlighting.\n *\n * @returns {Selection[]}\n */\n getRowHighlights() {\n return [...this.rowHighlights.values()];\n }\n\n /**\n * Creates (if not exist in the cache) Walkontable Selection instance created for controlling\n * highlight cells in a column.\n *\n * @returns {Selection}\n */\n createColumnHighlight() {\n return _assertClassBrand(_Highlight_brand, this, _createHighlight).call(this, this.columnHighlights, createColumnHighlight);\n }\n\n /**\n * Get all Walkontable Selection instances which describes the state of the columns highlighting.\n *\n * @returns {Selection[]}\n */\n getColumnHighlights() {\n return [...this.columnHighlights.values()];\n }\n\n /**\n * Get Walkontable Selection instance created for controlling highlight of the custom selection functionality.\n *\n * @returns {Selection}\n */\n getCustomSelections() {\n return [...this.customSelections.values()];\n }\n\n /**\n * Add selection to the custom selection instance. The new selection are added to the end of the selection collection.\n *\n * @param {object} selectionInstance The selection instance.\n */\n addCustomSelection(selectionInstance) {\n this.customSelections.push(createCustomHighlight({\n ...this.options,\n ...selectionInstance\n }));\n }\n\n /**\n * Perform cleaning visual highlights for the whole table.\n */\n clear() {\n this.focus.clear();\n this.fill.clear();\n arrayEach(this.areas.values(), highlight => void highlight.clear());\n arrayEach(this.layeredAreas.values(), highlight => void highlight.clear());\n arrayEach(this.rowHeaders.values(), highlight => void highlight.clear());\n arrayEach(this.columnHeaders.values(), highlight => void highlight.clear());\n arrayEach(this.activeRowHeaders.values(), highlight => void highlight.clear());\n arrayEach(this.activeColumnHeaders.values(), highlight => void highlight.clear());\n arrayEach(this.activeCornerHeaders.values(), highlight => void highlight.clear());\n arrayEach(this.rowHighlights.values(), highlight => void highlight.clear());\n arrayEach(this.columnHighlights.values(), highlight => void highlight.clear());\n }\n /**\n * This object can be iterate over using `for of` syntax or using internal `arrayEach` helper.\n *\n * @returns {Selection[]}\n */\n [Symbol.iterator]() {\n return [this.focus, this.fill, ...this.areas.values(), ...this.layeredAreas.values(), ...this.rowHeaders.values(), ...this.columnHeaders.values(), ...this.activeRowHeaders.values(), ...this.activeColumnHeaders.values(), ...this.activeCornerHeaders.values(), ...this.rowHighlights.values(), ...this.columnHighlights.values(), ...this.customSelections][Symbol.iterator]();\n }\n}\nfunction _createHighlight(cacheMap, highlightFactory) {\n const layerLevel = this.layerLevel;\n if (cacheMap.has(layerLevel)) {\n return cacheMap.get(layerLevel);\n }\n const highlight = highlightFactory({\n layerLevel,\n ...this.options\n });\n cacheMap.set(layerLevel, highlight);\n return highlight;\n}\nexport default Highlight;","import \"core-js/modules/es.error.cause.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { Selection } from \"./../../3rdparty/walkontable/src/index.mjs\";\nclass VisualSelection extends Selection {\n constructor(settings, visualCellRange) {\n super(settings, null);\n /**\n * Range of selection visually. Visual representation may have representation in a rendered selection.\n *\n * @type {null|CellRange}\n */\n _defineProperty(this, \"visualCellRange\", null);\n this.visualCellRange = visualCellRange || null;\n this.commit();\n }\n /**\n * Adds a cell coords to the selection.\n *\n * @param {CellCoords} coords Visual coordinates of a cell.\n * @returns {VisualSelection}\n */\n add(coords) {\n if (this.visualCellRange === null) {\n this.visualCellRange = this.settings.createCellRange(coords);\n } else {\n this.visualCellRange.expand(coords);\n }\n return this;\n }\n\n /**\n * Clears visual and renderable selection.\n *\n * @returns {VisualSelection}\n */\n clear() {\n this.visualCellRange = null;\n return super.clear();\n }\n\n /**\n * Trims the passed cell range object by removing all coordinates that points to the hidden rows\n * or columns. The result is a new cell range object that points only to the visible indexes or `null`.\n *\n * @private\n * @param {CellRange} cellRange Cells range object to be trimmed.\n * @returns {CellRange} Visual non-hidden cells range coordinates.\n */\n trimToVisibleCellsRangeOnly(_ref) {\n let {\n from,\n to\n } = _ref;\n let visibleFromCoords = this.getNearestNotHiddenCoords(from, 1);\n let visibleToCoords = this.getNearestNotHiddenCoords(to, -1);\n if (visibleFromCoords === null || visibleToCoords === null) {\n return null;\n }\n if (visibleFromCoords.row > visibleToCoords.row || visibleFromCoords.col > visibleToCoords.col) {\n visibleFromCoords = from;\n visibleToCoords = to;\n }\n return this.settings.createCellRange(visibleFromCoords, visibleFromCoords, visibleToCoords);\n }\n\n /**\n * Gets nearest coordinates that points to the visible row and column indexes. If there are no visible\n * rows and/or columns the `null` value is returned.\n *\n * @private\n * @param {CellCoords} coords The coords object as starting point for finding the nearest visible coordinates.\n * @param {1|-1} rowSearchDirection The search direction. For value 1, it means searching from top to bottom for\n * rows and from left to right for columns. For -1, it is the other way around.\n * @param {1|-1} columnSearchDirection The same as above but for rows.\n * @returns {CellCoords|null} Visual cell coordinates.\n */\n getNearestNotHiddenCoords(coords, rowSearchDirection) {\n let columnSearchDirection = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : rowSearchDirection;\n const nextVisibleRow = this.getNearestNotHiddenIndex(this.settings.rowIndexMapper, coords.row, rowSearchDirection);\n\n // There are no more visual rows in the range.\n if (nextVisibleRow === null) {\n return null;\n }\n const nextVisibleColumn = this.getNearestNotHiddenIndex(this.settings.columnIndexMapper, coords.col, columnSearchDirection);\n\n // There are no more visual columns in the range.\n if (nextVisibleColumn === null) {\n return null;\n }\n return this.settings.createCellCoords(nextVisibleRow, nextVisibleColumn);\n }\n\n /**\n * Gets nearest visual index. If there are no visible rows or columns the `null` value is returned.\n *\n * @private\n * @param {IndexMapper} indexMapper The IndexMapper instance for specific axis.\n * @param {number} visualIndex The index as starting point for finding the nearest visible index.\n * @param {1|-1} searchDirection The search direction. For value 1, it means searching from top to bottom for\n * rows and from left to right for columns. For -1, it is the other way around.\n * @returns {number|null} Visual row/column index.\n */\n getNearestNotHiddenIndex(indexMapper, visualIndex, searchDirection) {\n if (visualIndex < 0) {\n return visualIndex;\n }\n return indexMapper.getNearestNotHiddenIndex(visualIndex, searchDirection);\n }\n\n /**\n * Override internally stored visual indexes added by the Selection's `add` function. It should be executed\n * at the end of process of adding visual selection coordinates.\n *\n * @returns {VisualSelection}\n */\n commit() {\n // There is no information about visual ranges, thus no selection may be displayed.\n if (this.visualCellRange === null) {\n return this;\n }\n const trimmedCellRange = this.trimToVisibleCellsRangeOnly(this.visualCellRange);\n\n // There is no visual start point (and also visual end point) in the range.\n if (trimmedCellRange === null) {\n this.cellRange = null;\n } else {\n this.cellRange = this.createRenderableCellRange(trimmedCellRange.from, trimmedCellRange.to);\n }\n return this;\n }\n\n /**\n * Some selection may be a part of broader cell range. This function sync coordinates of current selection\n * and the broader cell range when needed (current selection can't be presented visually).\n *\n * @param {CellRange} broaderCellRange Visual range. Actual cell range may be contained in the broader cell range.\n * When there is no way to represent some cell range visually we try to find range containing just the first visible cell.\n *\n * Warn: Please keep in mind that this function may change coordinates of the handled broader range.\n *\n * @returns {VisualSelection}\n */\n syncWith(broaderCellRange) {\n const coordsFrom = broaderCellRange.from.clone().normalize();\n const rowDirection = broaderCellRange.getVerticalDirection() === 'N-S' ? 1 : -1;\n const columnDirection = broaderCellRange.getHorizontalDirection() === 'W-E' ? 1 : -1;\n const renderableHighlight = this.settings.visualToRenderableCoords(this.visualCellRange.highlight);\n let cellCoordsVisual = null;\n if (renderableHighlight === null || renderableHighlight.col === null || renderableHighlight.row === null) {\n cellCoordsVisual = this.getNearestNotHiddenCoords(coordsFrom, rowDirection, columnDirection);\n }\n if (cellCoordsVisual !== null && broaderCellRange.overlaps(cellCoordsVisual)) {\n const currentHighlight = broaderCellRange.highlight.clone();\n if (currentHighlight.row >= 0) {\n currentHighlight.row = cellCoordsVisual.row;\n }\n if (currentHighlight.col >= 0) {\n currentHighlight.col = cellCoordsVisual.col;\n }\n\n // We can't show selection visually now, but we found first visible range in the broader cell range.\n if (this.cellRange === null) {\n const cellCoordsRenderable = this.settings.visualToRenderableCoords(currentHighlight);\n this.cellRange = this.settings.createCellRange(cellCoordsRenderable);\n }\n\n // TODO\n // We set new highlight as it might change (for example, when showing/hiding some cells from the broader selection range)\n // TODO: It is also handled by the `MergeCells` plugin while adjusting already modified coordinates. Should it?\n broaderCellRange.setHighlight(currentHighlight);\n }\n\n // TODO\n // Sync the highlight coords from the visual selection layer with logical coords.\n if (this.settings.selectionType === 'focus' && renderableHighlight !== null && cellCoordsVisual === null) {\n broaderCellRange.setHighlight(this.visualCellRange.highlight);\n }\n return this;\n }\n\n /**\n * Returns the top left (TL) and bottom right (BR) selection coordinates (renderable indexes).\n * The method overwrites the original method to support header selection for hidden cells.\n * To make the header selection working, the CellCoords and CellRange have to support not\n * complete coordinates (`null` values for example, `row: null`, `col: 2`).\n *\n * @returns {Array} Returns array of coordinates for example `[1, 1, 5, 5]`.\n */\n getCorners() {\n const {\n from,\n to\n } = this.cellRange;\n return [Math.min(from.row, to.row), Math.min(from.col, to.col), Math.max(from.row, to.row), Math.max(from.col, to.col)];\n }\n\n /**\n * Returns the top left (or top right in RTL) and bottom right (or bottom left in RTL) selection\n * coordinates (visual indexes).\n *\n * @returns {Array} Returns array of coordinates for example `[1, 1, 5, 5]`.\n */\n getVisualCorners() {\n const topStart = this.settings.renderableToVisualCoords(this.cellRange.getTopStartCorner());\n const bottomEnd = this.settings.renderableToVisualCoords(this.cellRange.getBottomEndCorner());\n return [topStart.row, topStart.col, bottomEnd.row, bottomEnd.col];\n }\n\n /**\n * Creates a new CellRange object based on visual coordinates which before object creation are\n * translated to renderable indexes.\n *\n * @param {CellCoords} visualFromCoords The CellCoords object which contains coordinates that\n * points to the beginning of the selection.\n * @param {CellCoords} visualToCoords The CellCoords object which contains coordinates that\n * points to the end of the selection.\n * @returns {CellRange|null}\n */\n createRenderableCellRange(visualFromCoords, visualToCoords) {\n const renderableFromCoords = this.settings.visualToRenderableCoords(visualFromCoords);\n const renderableToCoords = this.settings.visualToRenderableCoords(visualToCoords);\n if (renderableFromCoords.row === null || renderableFromCoords.col === null || renderableToCoords.row === null || renderableToCoords.col === null) {\n return null;\n }\n return this.settings.createCellRange(renderableFromCoords, renderableFromCoords, renderableToCoords);\n }\n}\nexport default VisualSelection;","import { HIGHLIGHT_ACTIVE_HEADER_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection, responsible for highlighting column or row headers\n * only when the whole column or row is selected.\n * This type of selection can occur multiple times.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {string} highlightParams.activeHeaderClassName Highlighted headers' class name.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n activeHeaderClassName,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: activeHeaderClassName,\n ...restOptions,\n selectionType: HIGHLIGHT_ACTIVE_HEADER_TYPE\n });\n}","import { HIGHLIGHT_AREA_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection responsible for highlighting area of the selected multiple cells.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {object} highlightParams.areaCornerVisible Function to determine if area's corner should be visible.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n areaCornerVisible,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: 'area',\n createLayers: true,\n border: {\n width: 1,\n color: '#4b89ff',\n cornerVisible: areaCornerVisible\n },\n ...restOptions,\n selectionType: HIGHLIGHT_AREA_TYPE\n });\n}","import { HIGHLIGHT_AREA_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection responsible for highlighting area of the selected multiple cells.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {object} highlightParams.areaCornerVisible Function to determine if area's corner should be visible.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: 'highlight',\n ...restOptions,\n selectionType: HIGHLIGHT_AREA_TYPE\n });\n}","import { HIGHLIGHT_COLUMN_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection, responsible for highlighting cells in a columns and\n * column headers.\n * This type of selection can occur multiple times.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {string} highlightParams.columnClassName Highlighted column' class name.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n columnClassName,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: columnClassName,\n ...restOptions,\n selectionType: HIGHLIGHT_COLUMN_TYPE\n });\n}","import { HIGHLIGHT_FOCUS_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\nimport { A11Y_SELECTED } from \"../../../helpers/a11y.mjs\";\n/**\n * Creates the new instance of Selection responsible for highlighting currently selected cell. This type of selection\n * can present on the table only one at the time.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {Function} highlightParams.cellCornerVisible Function to determine if cell's corner should be visible.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n cellCornerVisible,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: 'current',\n headerAttributes: [A11Y_SELECTED()],\n border: {\n width: 2,\n color: '#4b89ff',\n cornerVisible: cellCornerVisible\n },\n ...restOptions,\n selectionType: HIGHLIGHT_FOCUS_TYPE\n });\n}","import { HIGHLIGHT_CUSTOM_SELECTION_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection responsible for highlighting currently selected cell.\n * This type of selection can present on the table only one at the time.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {object} highlightParams.border Border configuration.\n * @param {object} highlightParams.visualCellRange Function to translate visual to renderable coords.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n border,\n visualCellRange,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n ...border,\n ...restOptions,\n selectionType: HIGHLIGHT_CUSTOM_SELECTION_TYPE\n }, visualCellRange);\n}","import { HIGHLIGHT_FILL_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection, responsible for highlighting cells which are covered by fill handle\n * functionality. This type of selection can present on the table only one at the time.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: 'fill',\n border: {\n width: 1,\n color: '#ff0000'\n },\n ...restOptions,\n selectionType: HIGHLIGHT_FILL_TYPE\n });\n}","import { HIGHLIGHT_HEADER_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection, responsible for highlighting column or row headers when\n * any cell is selected.\n * This type of selection can occur multiple times.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {string} highlightParams.headerClassName Highlighted headers' class name.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n headerClassName,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: headerClassName,\n ...restOptions,\n selectionType: HIGHLIGHT_HEADER_TYPE\n });\n}","import { HIGHLIGHT_ROW_TYPE } from \"../../../3rdparty/walkontable/src/index.mjs\";\nimport VisualSelection from \"../visualSelection.mjs\";\n/**\n * Creates the new instance of Selection, responsible for highlighting cells in a rows and\n * row headers.\n * This type of selection can occur multiple times.\n *\n * @param {object} highlightParams A configuration object to create a highlight.\n * @param {string} highlightParams.rowClassName Highlighted row' class name.\n * @returns {Selection}\n */\nexport function createHighlight(_ref) {\n let {\n rowClassName,\n ...restOptions\n } = _ref;\n return new VisualSelection({\n className: rowClassName,\n ...restOptions,\n selectionType: HIGHLIGHT_ROW_TYPE\n });\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * The SelectionRange class is a simple CellRanges collection designed for easy manipulation of the multiple\n * consecutive and non-consecutive selections.\n *\n * @class SelectionRange\n * @util\n */\nclass SelectionRange {\n constructor(createCellRange) {\n /**\n * List of all CellRanges added to the class instance.\n *\n * @type {CellRange[]}\n */\n _defineProperty(this, \"ranges\", []);\n /**\n * @type {function(CellCoords): CellRange}\n */\n _defineProperty(this, \"createCellRange\", void 0);\n this.createCellRange = createCellRange;\n }\n\n /**\n * Check if selected range is empty.\n *\n * @returns {boolean}\n */\n isEmpty() {\n return this.size() === 0;\n }\n\n /**\n * Set coordinates to the class instance. It clears all previously added coordinates and push `coords`\n * to the collection.\n *\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n * @returns {SelectionRange}\n */\n set(coords) {\n this.clear();\n this.ranges.push(this.createCellRange(coords));\n return this;\n }\n\n /**\n * Add coordinates to the class instance. The new coordinates are added to the end of the range collection.\n *\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n * @returns {SelectionRange}\n */\n add(coords) {\n this.ranges.push(this.createCellRange(coords));\n return this;\n }\n\n /**\n * Removes from the stack the last added coordinates.\n *\n * @returns {SelectionRange}\n */\n pop() {\n this.ranges.pop();\n return this;\n }\n\n /**\n * Get last added coordinates from ranges, it returns a CellRange instance.\n *\n * @returns {CellRange|undefined}\n */\n current() {\n return this.peekByIndex(this.size() - 1);\n }\n\n /**\n * Get previously added coordinates from ranges, it returns a CellRange instance.\n *\n * @returns {CellRange|undefined}\n */\n previous() {\n return this.peekByIndex(this.size() - 2);\n }\n\n /**\n * Returns `true` if coords is within selection coords. This method iterates through all selection layers to check if\n * the coords object is within selection range.\n *\n * @param {CellCoords} coords The CellCoords instance with defined visual coordinates.\n * @returns {boolean}\n */\n includes(coords) {\n return this.ranges.some(cellRange => cellRange.includes(coords));\n }\n\n /**\n * Clear collection.\n *\n * @returns {SelectionRange}\n */\n clear() {\n this.ranges.length = 0;\n return this;\n }\n\n /**\n * Get count of added all coordinates added to the selection.\n *\n * @returns {number}\n */\n size() {\n return this.ranges.length;\n }\n\n /**\n * Peek the coordinates based on the index where that coordinate resides in the collection.\n *\n * @param {number} [index=0] An index where the coordinate will be retrieved from. The index '0' gets the\n * latest range.\n * @returns {CellRange|undefined}\n */\n peekByIndex() {\n let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;\n let cellRange;\n if (index >= 0 && index < this.size()) {\n cellRange = this.ranges[index];\n }\n return cellRange;\n }\n [Symbol.iterator]() {\n return this.ranges[Symbol.iterator]();\n }\n}\nexport default SelectionRange;","import \"core-js/modules/es.error.cause.js\";\nfunction _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }\nfunction _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }\nfunction _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError(\"Cannot initialize the same private elements twice on an object\"); }\nfunction _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }\nfunction _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }\nfunction _assertClassBrand(e, t, n) { if (\"function\" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError(\"Private element is not present on this object\"); }\nimport { mixin, createObjectPropListener } from \"../helpers/object.mjs\";\nimport localHooks from \"./../mixins/localHooks.mjs\";\n/**\n * The Transformation class implements algorithms for transforming coordinates based on current settings\n * passed to the Handsontable. The class performs the calculations based on the renderable indexes.\n *\n * Transformation is always applied relative to the current selection.\n *\n * The class operates on a table size defined by the renderable indexes. If the `navigableHeaders`\n * option is enabled, the table size is increased by the number of row and/or column headers.\n * Because the headers are treated as cells as part of the table size (indexes always go from 0 to N),\n * the algorithm can be written as simply as possible (without new if's that distinguish the headers\n * logic).\n *\n * @class Transformation\n * @util\n */\nvar _range = /*#__PURE__*/new WeakMap();\nvar _options = /*#__PURE__*/new WeakMap();\nvar _offset = /*#__PURE__*/new WeakMap();\nvar _Transformation_brand = /*#__PURE__*/new WeakSet();\nclass Transformation {\n constructor(range, options) {\n /**\n * Clamps the coords to make sure they points to the cell (or header) in the table range.\n *\n * @param {CellCoords} zeroBasedCoords The coords object to clamp.\n * @returns {{rowDir: 1|0|-1, colDir: 1|0|-1}}\n */\n _classPrivateMethodInitSpec(this, _Transformation_brand);\n /**\n * Instance of the SelectionRange, holder for visual coordinates applied to the table.\n *\n * @type {SelectionRange}\n */\n _classPrivateFieldInitSpec(this, _range, void 0);\n /**\n * Additional options which define the state of the settings which can infer transformation and\n * give the possibility to translate indexes.\n *\n * @type {object}\n */\n _classPrivateFieldInitSpec(this, _options, void 0);\n /**\n * Increases the table size by applying the offsets. The option is used by the `navigableHeaders`\n * option.\n *\n * @type {{ x: number, y: number }}\n */\n _classPrivateFieldInitSpec(this, _offset, {\n x: 0,\n y: 0\n });\n _classPrivateFieldSet(_range, this, range);\n _classPrivateFieldSet(_options, this, options);\n }\n\n /**\n * Selects cell relative to the current cell (if possible).\n *\n * @param {number} rowDelta Rows number to move, value can be passed as negative number.\n * @param {number} colDelta Columns number to move, value can be passed as negative number.\n * @param {boolean} [createMissingRecords=false] If `true` the new rows/columns will be created if necessary. Otherwise, row/column will\n * be created according to `minSpareRows/minSpareCols` settings of Handsontable.\n * @returns {CellCoords} Visual coordinates after transformation.\n */\n transformStart(rowDelta, colDelta) {\n let createMissingRecords = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n const delta = _classPrivateFieldGet(_options, this).createCellCoords(rowDelta, colDelta);\n let visualCoords = _classPrivateFieldGet(_range, this).current().highlight;\n const highlightRenderableCoords = _classPrivateFieldGet(_options, this).visualToRenderableCoords(visualCoords);\n let rowTransformDir = 0;\n let colTransformDir = 0;\n this.runLocalHooks('beforeTransformStart', delta);\n if (highlightRenderableCoords.row !== null && highlightRenderableCoords.col !== null) {\n const {\n width,\n height\n } = _assertClassBrand(_Transformation_brand, this, _getTableSize).call(this);\n const {\n row,\n col\n } = _assertClassBrand(_Transformation_brand, this, _visualToZeroBasedCoords).call(this, visualCoords);\n const fixedRowsBottom = _classPrivateFieldGet(_options, this).fixedRowsBottom();\n const minSpareRows = _classPrivateFieldGet(_options, this).minSpareRows();\n const minSpareCols = _classPrivateFieldGet(_options, this).minSpareCols();\n const autoWrapRow = _classPrivateFieldGet(_options, this).autoWrapRow();\n const autoWrapCol = _classPrivateFieldGet(_options, this).autoWrapCol();\n const zeroBasedCoords = _classPrivateFieldGet(_options, this).createCellCoords(row + delta.row, col + delta.col);\n if (zeroBasedCoords.row >= height) {\n const isActionInterrupted = createObjectPropListener(createMissingRecords && minSpareRows > 0 && fixedRowsBottom === 0);\n const nextColumn = zeroBasedCoords.col + 1;\n const newCoords = _classPrivateFieldGet(_options, this).createCellCoords(zeroBasedCoords.row - height, nextColumn >= width ? nextColumn - width : nextColumn);\n this.runLocalHooks('beforeColumnWrap', isActionInterrupted, _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, newCoords), nextColumn >= width);\n if (isActionInterrupted.value) {\n this.runLocalHooks('insertRowRequire', _classPrivateFieldGet(_options, this).countRenderableRows());\n } else if (autoWrapCol) {\n zeroBasedCoords.assign(newCoords);\n }\n } else if (zeroBasedCoords.row < 0) {\n const isActionInterrupted = createObjectPropListener(autoWrapCol);\n const previousColumn = zeroBasedCoords.col - 1;\n const newCoords = _classPrivateFieldGet(_options, this).createCellCoords(height + zeroBasedCoords.row, previousColumn < 0 ? width + previousColumn : previousColumn);\n this.runLocalHooks('beforeColumnWrap', isActionInterrupted, _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, newCoords), previousColumn < 0);\n if (autoWrapCol) {\n zeroBasedCoords.assign(newCoords);\n }\n }\n if (zeroBasedCoords.col >= width) {\n const isActionInterrupted = createObjectPropListener(createMissingRecords && minSpareCols > 0);\n const nextRow = zeroBasedCoords.row + 1;\n const newCoords = _classPrivateFieldGet(_options, this).createCellCoords(nextRow >= height ? nextRow - height : nextRow, zeroBasedCoords.col - width);\n this.runLocalHooks('beforeRowWrap', isActionInterrupted, _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, newCoords), nextRow >= height);\n if (isActionInterrupted.value) {\n this.runLocalHooks('insertColRequire', _classPrivateFieldGet(_options, this).countRenderableColumns());\n } else if (autoWrapRow) {\n zeroBasedCoords.assign(newCoords);\n }\n } else if (zeroBasedCoords.col < 0) {\n const isActionInterrupted = createObjectPropListener(autoWrapRow);\n const previousRow = zeroBasedCoords.row - 1;\n const newCoords = _classPrivateFieldGet(_options, this).createCellCoords(previousRow < 0 ? height + previousRow : previousRow, width + zeroBasedCoords.col);\n this.runLocalHooks('beforeRowWrap', isActionInterrupted, _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, newCoords), previousRow < 0);\n if (autoWrapRow) {\n zeroBasedCoords.assign(newCoords);\n }\n }\n const {\n rowDir,\n colDir\n } = _assertClassBrand(_Transformation_brand, this, _clampCoords).call(this, zeroBasedCoords);\n rowTransformDir = rowDir;\n colTransformDir = colDir;\n visualCoords = _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, zeroBasedCoords);\n }\n this.runLocalHooks('afterTransformStart', visualCoords, rowTransformDir, colTransformDir);\n return visualCoords;\n }\n\n /**\n * Sets selection end cell relative to the current selection end cell (if possible).\n *\n * @param {number} rowDelta Rows number to move, value can be passed as negative number.\n * @param {number} colDelta Columns number to move, value can be passed as negative number.\n * @returns {CellCoords} Visual coordinates after transformation.\n */\n transformEnd(rowDelta, colDelta) {\n const delta = _classPrivateFieldGet(_options, this).createCellCoords(rowDelta, colDelta);\n const cellRange = _classPrivateFieldGet(_range, this).current();\n const highlightRenderableCoords = _classPrivateFieldGet(_options, this).visualToRenderableCoords(cellRange.highlight);\n const toRow = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedRow).call(this, cellRange.to.row, cellRange.from.row);\n const toColumn = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedColumn).call(this, cellRange.to.col, cellRange.from.col);\n const visualCoords = cellRange.to.clone();\n let rowTransformDir = 0;\n let colTransformDir = 0;\n this.runLocalHooks('beforeTransformEnd', delta);\n if (highlightRenderableCoords.row !== null && highlightRenderableCoords.col !== null && toRow !== null && toColumn !== null) {\n const {\n row: highlightRow,\n col: highlightColumn\n } = _assertClassBrand(_Transformation_brand, this, _visualToZeroBasedCoords).call(this, cellRange.highlight);\n const coords = _classPrivateFieldGet(_options, this).createCellCoords(toRow + delta.row, toColumn + delta.col);\n const topStartCorner = cellRange.getTopStartCorner();\n const topEndCorner = cellRange.getTopEndCorner();\n const bottomEndCorner = cellRange.getBottomEndCorner();\n if (delta.col < 0 && toColumn >= highlightColumn && coords.col < highlightColumn) {\n const columnRestDelta = coords.col - highlightColumn;\n coords.col = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedColumn).call(this, topStartCorner.col, topEndCorner.col) + columnRestDelta;\n } else if (delta.col > 0 && toColumn <= highlightColumn && coords.col > highlightColumn) {\n const endColumnIndex = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedColumn).call(this, topEndCorner.col, topStartCorner.col);\n const columnRestDelta = Math.max(coords.col - endColumnIndex, 1);\n coords.col = endColumnIndex + columnRestDelta;\n }\n if (delta.row < 0 && toRow >= highlightRow && coords.row < highlightRow) {\n const rowRestDelta = coords.row - highlightRow;\n coords.row = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedRow).call(this, topStartCorner.row, bottomEndCorner.row) + rowRestDelta;\n } else if (delta.row > 0 && toRow <= highlightRow && coords.row > highlightRow) {\n const bottomRowIndex = _assertClassBrand(_Transformation_brand, this, _findFirstNonHiddenZeroBasedRow).call(this, bottomEndCorner.row, topStartCorner.row);\n const rowRestDelta = Math.max(coords.row - bottomRowIndex, 1);\n coords.row = bottomRowIndex + rowRestDelta;\n }\n const {\n rowDir,\n colDir\n } = _assertClassBrand(_Transformation_brand, this, _clampCoords).call(this, coords);\n rowTransformDir = rowDir;\n colTransformDir = colDir;\n const newVisualCoords = _assertClassBrand(_Transformation_brand, this, _zeroBasedToVisualCoords).call(this, coords);\n if (delta.row === 0 && delta.col !== 0) {\n visualCoords.col = newVisualCoords.col;\n } else if (delta.row !== 0 && delta.col === 0) {\n visualCoords.row = newVisualCoords.row;\n } else {\n visualCoords.row = newVisualCoords.row;\n visualCoords.col = newVisualCoords.col;\n }\n }\n this.runLocalHooks('afterTransformEnd', visualCoords, rowTransformDir, colTransformDir);\n return visualCoords;\n }\n\n /**\n * Sets the additional offset in table size that may occur when the `navigableHeaders` option\n * is enabled.\n *\n * @param {{x: number, y: number}} offset Offset as x and y properties.\n */\n setOffsetSize(_ref) {\n let {\n x,\n y\n } = _ref;\n _classPrivateFieldSet(_offset, this, {\n x,\n y\n });\n }\n\n /**\n * Resets the offset size to the default values.\n */\n resetOffsetSize() {\n _classPrivateFieldSet(_offset, this, {\n x: 0,\n y: 0\n });\n }\n}\nfunction _clampCoords(zeroBasedCoords) {\n const {\n width,\n height\n } = _assertClassBrand(_Transformation_brand, this, _getTableSize).call(this);\n let rowDir = 0;\n let colDir = 0;\n if (zeroBasedCoords.row < 0) {\n rowDir = -1;\n zeroBasedCoords.row = 0;\n } else if (zeroBasedCoords.row > 0 && zeroBasedCoords.row >= height) {\n rowDir = 1;\n zeroBasedCoords.row = height - 1;\n }\n if (zeroBasedCoords.col < 0) {\n colDir = -1;\n zeroBasedCoords.col = 0;\n } else if (zeroBasedCoords.col > 0 && zeroBasedCoords.col >= width) {\n colDir = 1;\n zeroBasedCoords.col = width - 1;\n }\n return {\n rowDir,\n colDir\n };\n}\n/**\n * Gets the table size in number of rows with headers as \"height\" and number of columns with\n * headers as \"width\".\n *\n * @returns {{width: number, height: number}}\n */\nfunction _getTableSize() {\n return {\n width: _classPrivateFieldGet(_offset, this).x + _classPrivateFieldGet(_options, this).countRenderableColumns(),\n height: _classPrivateFieldGet(_offset, this).y + _classPrivateFieldGet(_options, this).countRenderableRows()\n };\n}\n/**\n * Finds the first non-hidden zero-based row in the table range.\n *\n * @param {number} visualRowFrom The visual row from which the search should start.\n * @param {number} visualRowTo The visual row to which the search should end.\n * @returns {number | null}\n */\nfunction _findFirstNonHiddenZeroBasedRow(visualRowFrom, visualRowTo) {\n const row = _classPrivateFieldGet(_options, this).findFirstNonHiddenRenderableRow(visualRowFrom, visualRowTo);\n if (row === null) {\n return null;\n }\n return _classPrivateFieldGet(_offset, this).y + row;\n}\n/**\n * Finds the first non-hidden zero-based column in the table range.\n *\n * @param {number} visualColumnFrom The visual column from which the search should start.\n * @param {number} visualColumnTo The visual column to which the search should end.\n * @returns {number | null}\n */\nfunction _findFirstNonHiddenZeroBasedColumn(visualColumnFrom, visualColumnTo) {\n const column = _classPrivateFieldGet(_options, this).findFirstNonHiddenRenderableColumn(visualColumnFrom, visualColumnTo);\n if (column === null) {\n return null;\n }\n return _classPrivateFieldGet(_offset, this).x + column;\n}\n/**\n * Translates the visual coordinates to zero-based ones.\n *\n * @param {CellCoords} visualCoords The visual coords to process.\n * @returns {CellCoords}\n */\nfunction _visualToZeroBasedCoords(visualCoords) {\n const {\n row,\n col\n } = _classPrivateFieldGet(_options, this).visualToRenderableCoords(visualCoords);\n if (row === null || col === null) {\n throw new Error('Renderable coords are not visible.');\n }\n return _classPrivateFieldGet(_options, this).createCellCoords(_classPrivateFieldGet(_offset, this).y + row, _classPrivateFieldGet(_offset, this).x + col);\n}\n/**\n * Translates the zero-based coordinates to visual ones.\n *\n * @param {CellCoords} zeroBasedCoords The coordinates to process.\n * @returns {CellCoords}\n */\nfunction _zeroBasedToVisualCoords(zeroBasedCoords) {\n const coords = zeroBasedCoords.clone();\n coords.col = zeroBasedCoords.col - _classPrivateFieldGet(_offset, this).x;\n coords.row = zeroBasedCoords.row - _classPrivateFieldGet(_offset, this).y;\n return _classPrivateFieldGet(_options, this).renderableToVisualCoords(coords);\n}\nmixin(Transformation, localHooks);\nexport default Transformation;","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nimport \"core-js/modules/esnext.set.difference.v2.js\";\nimport \"core-js/modules/esnext.set.intersection.v2.js\";\nimport \"core-js/modules/esnext.set.is-disjoint-from.v2.js\";\nimport \"core-js/modules/esnext.set.is-subset-of.v2.js\";\nimport \"core-js/modules/esnext.set.is-superset-of.v2.js\";\nimport \"core-js/modules/esnext.set.symmetric-difference.v2.js\";\nimport \"core-js/modules/esnext.set.union.v2.js\";\nimport { CellRange } from \"./../3rdparty/walkontable/src/index.mjs\";\nimport { arrayEach, arrayReduce } from \"./../helpers/array.mjs\";\nimport { isUndefined } from \"./../helpers/mixed.mjs\";\nexport const SELECTION_TYPE_UNRECOGNIZED = 0;\nexport const SELECTION_TYPE_EMPTY = 1;\nexport const SELECTION_TYPE_ARRAY = 2;\nexport const SELECTION_TYPE_OBJECT = 3;\nexport const SELECTION_TYPES = [SELECTION_TYPE_OBJECT, SELECTION_TYPE_ARRAY];\nconst ARRAY_TYPE_PATTERN = [['number'], ['number', 'string'], ['number', 'undefined'], ['number', 'string', 'undefined']];\nconst rootCall = Symbol('root');\nconst childCall = Symbol('child');\n\n/**\n * Detect selection schema structure.\n *\n * @param {*} selectionRanges The selected range or and array of selected ranges. This type of data is produced by\n * `hot.getSelected()`, `hot.getSelectedLast()`, `hot.getSelectedRange()`\n * and `hot.getSelectedRangeLast()` methods.\n * @param {symbol} _callSymbol The symbol object which indicates source of the helper invocation.\n * @returns {number} Returns a number that specifies the type of detected selection schema. If selection schema type\n * is unrecognized than it returns `0`.\n */\nexport function detectSelectionType(selectionRanges) {\n let _callSymbol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : rootCall;\n if (_callSymbol !== rootCall && _callSymbol !== childCall) {\n throw new Error('The second argument is used internally only and cannot be overwritten.');\n }\n const isArray = Array.isArray(selectionRanges);\n const isRootCall = _callSymbol === rootCall;\n let result = SELECTION_TYPE_UNRECOGNIZED;\n if (isArray) {\n const firstItem = selectionRanges[0];\n if (selectionRanges.length === 0) {\n result = SELECTION_TYPE_EMPTY;\n } else if (isRootCall && firstItem instanceof CellRange) {\n result = SELECTION_TYPE_OBJECT;\n } else if (isRootCall && Array.isArray(firstItem)) {\n result = detectSelectionType(firstItem, childCall);\n } else if (selectionRanges.length >= 2 && selectionRanges.length <= 4) {\n const isArrayType = !selectionRanges.some((value, index) => !ARRAY_TYPE_PATTERN[index].includes(typeof value));\n if (isArrayType) {\n result = SELECTION_TYPE_ARRAY;\n }\n }\n }\n return result;\n}\n\n/**\n * Factory function designed for normalization data schema from different data structures of the selection ranges.\n *\n * @param {number} type Selection type which will be processed.\n * @param {object} options The normalization options.\n * @param {function(number, number): CellCoords} options.createCellCoords The factory function that returns an instance of the `CellCoords` class.\n * @param {function(CellCoords, CellCoords, CellCoords): CellRange} options.createCellRange The factory function that returns an instance of the `CellRange` class.\n * @param {boolean} [options.keepDirection=false] If `true`, the coordinates which contain the direction of the\n * selected cells won't be changed. Otherwise, the selection will be\n * normalized to values starting from top-left to bottom-right.\n * @param {Function} [options.propToCol] Pass the converting function (usually `datamap.propToCol`) if the column\n * defined as props should be normalized to the numeric values.\n * @returns {number[]} Returns normalized data about selected range as an array (`[rowStart, columnStart, rowEnd, columnEnd]`).\n */\nexport function normalizeSelectionFactory(type) {\n let {\n createCellCoords,\n createCellRange,\n keepDirection = false,\n propToCol\n } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n if (!SELECTION_TYPES.includes(type)) {\n throw new Error('Unsupported selection ranges schema type was provided.');\n }\n return function (selection) {\n const isObjectType = type === SELECTION_TYPE_OBJECT;\n let rowStart = isObjectType ? selection.from.row : selection[0];\n let columnStart = isObjectType ? selection.from.col : selection[1];\n let rowEnd = isObjectType ? selection.to.row : selection[2];\n let columnEnd = isObjectType ? selection.to.col : selection[3];\n if (typeof propToCol === 'function') {\n if (typeof columnStart === 'string') {\n columnStart = propToCol(columnStart);\n }\n if (typeof columnEnd === 'string') {\n columnEnd = propToCol(columnEnd);\n }\n }\n if (isUndefined(rowEnd)) {\n rowEnd = rowStart;\n }\n if (isUndefined(columnEnd)) {\n columnEnd = columnStart;\n }\n if (!keepDirection) {\n const origRowStart = rowStart;\n const origColumnStart = columnStart;\n const origRowEnd = rowEnd;\n const origColumnEnd = columnEnd;\n rowStart = Math.min(origRowStart, origRowEnd);\n columnStart = Math.min(origColumnStart, origColumnEnd);\n rowEnd = Math.max(origRowStart, origRowEnd);\n columnEnd = Math.max(origColumnStart, origColumnEnd);\n }\n const from = createCellCoords(rowStart, columnStart);\n const to = createCellCoords(rowEnd, columnEnd);\n return createCellRange(from, from, to);\n };\n}\n\n/**\n * Function transform selection ranges (produced by `hot.getSelected()` and `hot.getSelectedRange()`) to normalized\n * data structure. It merges repeated ranges into consecutive coordinates. The returned structure\n * contains an array of arrays. The single item contains at index 0 visual column index from the selection was\n * started and at index 1 distance as a count of selected columns.\n *\n * @param {Core} hotInstance The Handsontable instance.\n * @returns {Array[]} Returns an array of arrays with ranges defines in that schema:\n * `[[visualColumnStart, distance], [visualColumnStart, distance], ...]`.\n * The column distances are always created starting from the left (zero index) to the\n * right (the latest column index).\n */\nexport function transformSelectionToColumnDistance(hotInstance) {\n const selectionType = detectSelectionType(hotInstance.getSelected());\n if (selectionType === SELECTION_TYPE_UNRECOGNIZED || selectionType === SELECTION_TYPE_EMPTY) {\n return [];\n }\n const selectionSchemaNormalizer = normalizeSelectionFactory(selectionType, {\n createCellCoords: hotInstance._createCellCoords.bind(hotInstance),\n createCellRange: hotInstance._createCellRange.bind(hotInstance)\n });\n const unorderedIndexes = new Set();\n\n // Iterate through all ranges and collect all column indexes which are not saved yet.\n arrayEach(hotInstance.getSelected(), selection => {\n const {\n from,\n to\n } = selectionSchemaNormalizer(selection);\n const columnNonHeaderStart = Math.max(from.col, 0);\n const amount = to.col - columnNonHeaderStart + 1;\n arrayEach(Array.from(new Array(amount), (_, i) => columnNonHeaderStart + i), index => {\n if (!unorderedIndexes.has(index)) {\n unorderedIndexes.add(index);\n }\n });\n });\n\n // Sort indexes in ascending order to easily detecting non-consecutive columns.\n const orderedIndexes = Array.from(unorderedIndexes).sort((a, b) => a - b);\n const normalizedColumnRanges = arrayReduce(orderedIndexes, (acc, visualColumnIndex, index, array) => {\n if (index !== 0 && visualColumnIndex === array[index - 1] + 1) {\n acc[acc.length - 1][1] += 1;\n } else {\n acc.push([visualColumnIndex, 1]);\n }\n return acc;\n }, []);\n return normalizedColumnRanges;\n}\n\n/**\n * Function transform selection ranges (produced by `hot.getSelected()` and `hot.getSelectedRange()`) to normalized\n * data structure. It merges repeated ranges into consecutive coordinates. The returned structure\n * contains an array of arrays. The single item contains at index 0 visual column index from the selection was\n * started and at index 1 distance as a count of selected columns.\n *\n * @param {Core} hotInstance The Handsontable instance.\n * @returns {Array[]} Returns an array of arrays with ranges defines in that schema:\n * `[[visualColumnStart, distance], [visualColumnStart, distance], ...]`.\n * The column distances are always created starting from the left (zero index) to the\n * right (the latest column index).\n */\nexport function transformSelectionToRowDistance(hotInstance) {\n const selectionType = detectSelectionType(hotInstance.getSelected());\n if (selectionType === SELECTION_TYPE_UNRECOGNIZED || selectionType === SELECTION_TYPE_EMPTY) {\n return [];\n }\n const selectionSchemaNormalizer = normalizeSelectionFactory(selectionType, {\n createCellCoords: hotInstance._createCellCoords.bind(hotInstance),\n createCellRange: hotInstance._createCellRange.bind(hotInstance)\n });\n const unorderedIndexes = new Set();\n\n // Iterate through all ranges and collect all column indexes which are not saved yet.\n arrayEach(hotInstance.getSelected(), selection => {\n const {\n from,\n to\n } = selectionSchemaNormalizer(selection);\n const rowNonHeaderStart = Math.max(from.row, 0);\n const amount = to.row - rowNonHeaderStart + 1;\n arrayEach(Array.from(new Array(amount), (_, i) => rowNonHeaderStart + i), index => {\n if (!unorderedIndexes.has(index)) {\n unorderedIndexes.add(index);\n }\n });\n });\n\n // Sort indexes in ascending order to easily detecting non-consecutive columns.\n const orderedIndexes = Array.from(unorderedIndexes).sort((a, b) => a - b);\n const normalizedRowRanges = arrayReduce(orderedIndexes, (acc, rowIndex, index, array) => {\n if (index !== 0 && rowIndex === array[index - 1] + 1) {\n acc[acc.length - 1][1] += 1;\n } else {\n acc.push([rowIndex, 1]);\n }\n return acc;\n }, []);\n return normalizedRowRanges;\n}","import \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.array.push.js\";\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == typeof i ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != typeof i) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nimport { stringify } from \"../3rdparty/SheetClip/index.mjs\";\nimport { countFirstRowKeys } from \"../helpers/data.mjs\";\nimport { createObjectPropListener, deepClone, deepExtend, deepObjectSize, duckSchema, hasOwnProperty, isObject, objectEach } from \"../helpers/object.mjs\";\nimport { extendArray, to2dArray } from \"../helpers/array.mjs\";\nimport { rangeEach } from \"../helpers/number.mjs\";\nimport { isDefined } from \"../helpers/mixed.mjs\";\n/*\nThis class contains open-source contributions covered by the MIT license.\n\n1) In the `createRow` method: Row creation using functional `dataSchema` value\n2) In the `set` method: Data setting using functional `prop` value\n3) in the `get` method: Data getting using functional `prop` value\n\nThe remaining part of this code comment contains the full license text of these contributions.\n\n======\n\nThe MIT License\n\nCopyright 2013 Nicholas Bollweg\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/**\n * Utility class that gets and saves data from/to the data source using mapping of columns numbers to object property names.\n *\n * @todo Refactor arguments of methods getRange, getText to be numbers (not objects).\n * @todo Remove priv, GridSettings from object constructor.\n *\n * @class DataMap\n * @private\n */\nclass DataMap {\n /**\n * @type {number}\n */\n static get DESTINATION_RENDERER() {\n return 1;\n }\n\n /**\n * @type {number}\n */\n static get DESTINATION_CLIPBOARD_GENERATOR() {\n return 2;\n }\n\n /**\n * Instance of {@link Handsontable}.\n *\n * @private\n * @type {Handsontable}\n */\n\n /**\n * @param {object} hotInstance Instance of Handsontable.\n * @param {Array} data Array of arrays or array of objects containing data.\n * @param {MetaManager} metaManager The meta manager instance.\n */\n constructor(hotInstance, data, metaManager) {\n _defineProperty(this, \"hot\", void 0);\n /**\n * Instance of {@link MetaManager}.\n *\n * @private\n * @type {MetaManager}\n */\n _defineProperty(this, \"metaManager\", void 0);\n /**\n * Instance of {@link TableMeta}.\n *\n * @private\n * @type {TableMeta}\n */\n _defineProperty(this, \"tableMeta\", void 0);\n /**\n * Reference to the original dataset.\n *\n * @type {*}\n */\n _defineProperty(this, \"dataSource\", void 0);\n /**\n * Generated schema based on the first row from the source data.\n *\n * @type {object}\n */\n _defineProperty(this, \"duckSchema\", void 0);\n /**\n * Cached array of properties to columns.\n *\n * @type {Array}\n */\n _defineProperty(this, \"colToPropCache\", void 0);\n /**\n * Cached map of properties to columns.\n *\n * @type {Map}\n */\n _defineProperty(this, \"propToColCache\", void 0);\n this.hot = hotInstance;\n this.metaManager = metaManager;\n this.tableMeta = metaManager.getTableMeta();\n this.dataSource = data;\n this.duckSchema = this.createDuckSchema();\n this.createMap();\n }\n\n /**\n * Generates cache for property to and from column addressation.\n */\n createMap() {\n const schema = this.getSchema();\n if (typeof schema === 'undefined') {\n throw new Error('trying to create `columns` definition but you didn\\'t provide `schema` nor `data`');\n }\n const columns = this.tableMeta.columns;\n let i;\n this.colToPropCache = [];\n this.propToColCache = new Map();\n if (columns) {\n let columnsLen = 0;\n let filteredIndex = 0;\n let columnsAsFunc = false;\n if (typeof columns === 'function') {\n const schemaLen = deepObjectSize(schema);\n columnsLen = schemaLen > 0 ? schemaLen : this.countFirstRowKeys();\n columnsAsFunc = true;\n } else {\n const maxCols = this.tableMeta.maxCols;\n columnsLen = Math.min(maxCols, columns.length);\n }\n for (i = 0; i < columnsLen; i++) {\n const column = columnsAsFunc ? columns(i) : columns[i];\n if (isObject(column)) {\n if (typeof column.data !== 'undefined') {\n const index = columnsAsFunc ? filteredIndex : i;\n this.colToPropCache[index] = column.data;\n this.propToColCache.set(column.data, index);\n }\n filteredIndex += 1;\n }\n }\n } else {\n this.recursiveDuckColumns(schema);\n }\n }\n\n /**\n * Get the amount of physical columns in the first data row.\n *\n * @returns {number} Amount of physical columns in the first data row.\n */\n countFirstRowKeys() {\n return countFirstRowKeys(this.dataSource);\n }\n\n /**\n * Generates columns' translation cache.\n *\n * @param {object} schema An object to generate schema from.\n * @param {number} lastCol The column index.\n * @param {number} parent The property cache for recursive calls.\n * @returns {number}\n */\n recursiveDuckColumns(schema, lastCol, parent) {\n let lastColumn = lastCol;\n let propertyParent = parent;\n let prop;\n if (typeof lastColumn === 'undefined') {\n lastColumn = 0;\n propertyParent = '';\n }\n if (typeof schema === 'object' && !Array.isArray(schema)) {\n objectEach(schema, (value, key) => {\n if (value === null) {\n prop = propertyParent + key;\n this.colToPropCache.push(prop);\n this.propToColCache.set(prop, lastColumn);\n lastColumn += 1;\n } else {\n lastColumn = this.recursiveDuckColumns(value, lastColumn, `${key}.`);\n }\n });\n }\n return lastColumn;\n }\n\n /**\n * Returns property name that corresponds with the given column index.\n *\n * @param {string|number} column Visual column index or another passed argument.\n * @returns {string|number} Column property, physical column index or passed argument.\n */\n colToProp(column) {\n // TODO: Should it work? Please, look at the test:\n // \"it should return the provided property name, when the user passes a property name as a column number\".\n if (Number.isInteger(column) === false) {\n return column;\n }\n const physicalColumn = this.hot.toPhysicalColumn(column);\n\n // Out of range, not visible column index.\n if (physicalColumn === null) {\n return column;\n }\n\n // Cached property.\n if (this.colToPropCache && isDefined(this.colToPropCache[physicalColumn])) {\n return this.colToPropCache[physicalColumn];\n }\n return physicalColumn;\n }\n\n /**\n * Translates property into visual column index.\n *\n * @param {string|number} prop Column property which may be also a physical column index.\n * @returns {string|number} Visual column index or passed argument.\n */\n propToCol(prop) {\n const cachedPhysicalIndex = this.propToColCache.get(prop);\n if (isDefined(cachedPhysicalIndex)) {\n return this.hot.toVisualColumn(cachedPhysicalIndex);\n }\n\n // Property may be a physical column index.\n const visualColumn = this.hot.toVisualColumn(prop);\n if (visualColumn === null) {\n return prop;\n }\n return visualColumn;\n }\n\n /**\n * Returns data's schema.\n *\n * @returns {object}\n */\n getSchema() {\n const schema = this.tableMeta.dataSchema;\n if (schema) {\n if (typeof schema === 'function') {\n return schema();\n }\n return schema;\n }\n return this.duckSchema;\n }\n\n /**\n * Creates the duck schema based on the current dataset.\n *\n * @returns {Array|object}\n */\n createDuckSchema() {\n return this.dataSource && this.dataSource[0] ? duckSchema(this.dataSource[0]) : {};\n }\n\n /**\n * Refresh the data schema.\n */\n refreshDuckSchema() {\n this.duckSchema = this.createDuckSchema();\n }\n\n /**\n * Creates row at the bottom of the data array.\n *\n * @param {number} [index] Physical index of the row before which the new row will be inserted.\n * @param {number} [amount=1] An amount of rows to add.\n * @param {object} [options] Additional options for created rows.\n * @param {string} [options.source] Source of method call.\n * @param {'above'|'below'} [options.mode] Sets where the row is inserted: above or below the passed index.\n * @fires Hooks#afterCreateRow\n * @returns {number} Returns number of created rows.\n */\n createRow(index) {\n let amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n let {\n source,\n mode = 'above'\n } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n const sourceRowsCount = this.hot.countSourceRows();\n let physicalRowIndex = sourceRowsCount;\n let numberOfCreatedRows = 0;\n let rowIndex = index;\n if (typeof rowIndex !== 'number' || rowIndex >= sourceRowsCount) {\n rowIndex = sourceRowsCount;\n }\n if (rowIndex < this.hot.countRows()) {\n physicalRowIndex = this.hot.toPhysicalRow(rowIndex);\n }\n const continueProcess = this.hot.runHooks('beforeCreateRow', rowIndex, amount, source);\n if (continueProcess === false || physicalRowIndex === null) {\n return {\n delta: 0\n };\n }\n const maxRows = this.tableMeta.maxRows;\n const columnCount = this.getSchema().length;\n const rowsToAdd = [];\n while (numberOfCreatedRows < amount && sourceRowsCount + numberOfCreatedRows < maxRows) {\n let row = null;\n if (this.hot.dataType === 'array') {\n if (this.tableMeta.dataSchema) {\n // Clone template array\n row = deepClone(this.getSchema());\n } else {\n row = [];\n /* eslint-disable no-loop-func */\n rangeEach(columnCount - 1, () => row.push(null));\n }\n } else if (this.hot.dataType === 'function') {\n row = this.tableMeta.dataSchema(rowIndex + numberOfCreatedRows);\n } else {\n row = {};\n deepExtend(row, this.getSchema());\n }\n rowsToAdd.push(row);\n numberOfCreatedRows += 1;\n }\n this.hot.rowIndexMapper.insertIndexes(rowIndex, numberOfCreatedRows);\n if (mode === 'below') {\n physicalRowIndex = Math.min(physicalRowIndex + 1, sourceRowsCount);\n }\n this.spliceData(physicalRowIndex, 0, rowsToAdd);\n const newVisualRowIndex = this.hot.toVisualRow(physicalRowIndex);\n\n // In case the created rows are the only ones in the table, the column index mappers need to be rebuilt based on\n // the number of columns created in the row or the schema.\n if (this.hot.countSourceRows() === rowsToAdd.length) {\n this.hot.columnIndexMapper.initToLength(this.hot.getInitialColumnCount());\n }\n if (numberOfCreatedRows > 0) {\n if (index === undefined || index === null) {\n // Creates the meta rows at the end of the rows collection without shifting the cells\n // that were defined out of the range of the dataset.\n this.metaManager.createRow(null, numberOfCreatedRows);\n } else if (source !== 'auto') {\n this.metaManager.createRow(physicalRowIndex, amount);\n }\n }\n this.hot.runHooks('afterCreateRow', newVisualRowIndex, numberOfCreatedRows, source);\n this.hot.forceFullRender = true; // used when data was changed\n\n return {\n delta: numberOfCreatedRows,\n startPhysicalIndex: physicalRowIndex\n };\n }\n\n /**\n * Creates column at the right of the data array.\n *\n * @param {number} [index] Visual index of the column before which the new column will be inserted.\n * @param {number} [amount=1] An amount of columns to add.\n * @param {object} [options] Additional options for created columns.\n * @param {string} [options.source] Source of method call.\n * @param {'start'|'end'} [options.mode] Sets where the column is inserted: at the start (left in [LTR](@/api/options.md#layoutdirection), right in [RTL](@/api/options.md#layoutdirection)) or at the end (right in LTR, left in LTR)\n * the passed index.\n * @fires Hooks#afterCreateCol\n * @returns {number} Returns number of created columns.\n */\n createCol(index) {\n let amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n let {\n source,\n mode = 'start'\n } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n if (!this.hot.isColumnModificationAllowed()) {\n throw new Error('Cannot create new column. When data source in an object, ' + 'you can only have as much columns as defined in first data row, data schema or in the \\'columns\\' setting.' + 'If you want to be able to add new columns, you have to use array datasource.');\n }\n const dataSource = this.dataSource;\n const maxCols = this.tableMeta.maxCols;\n const countSourceCols = this.hot.countSourceCols();\n let columnIndex = index;\n if (typeof columnIndex !== 'number' || columnIndex >= countSourceCols) {\n columnIndex = countSourceCols;\n }\n const continueProcess = this.hot.runHooks('beforeCreateCol', columnIndex, amount, source);\n if (continueProcess === false) {\n return {\n delta: 0\n };\n }\n let physicalColumnIndex = countSourceCols;\n if (columnIndex < this.hot.countCols()) {\n physicalColumnIndex = this.hot.toPhysicalColumn(columnIndex);\n }\n const numberOfSourceRows = this.hot.countSourceRows();\n let nrOfColumns = this.hot.countCols();\n let numberOfCreatedCols = 0;\n let currentIndex = physicalColumnIndex;\n if (mode === 'end') {\n currentIndex = Math.min(currentIndex + 1, countSourceCols);\n }\n const startPhysicalIndex = currentIndex;\n while (numberOfCreatedCols < amount && nrOfColumns < maxCols) {\n if (typeof columnIndex !== 'number' || columnIndex >= nrOfColumns) {\n if (numberOfSourceRows > 0) {\n for (let row = 0; row < numberOfSourceRows; row += 1) {\n if (typeof dataSource[row] === 'undefined') {\n dataSource[row] = [];\n }\n dataSource[row].push(null);\n }\n } else {\n dataSource.push([null]);\n }\n } else {\n for (let row = 0; row < numberOfSourceRows; row++) {\n dataSource[row].splice(currentIndex, 0, null);\n }\n }\n numberOfCreatedCols += 1;\n currentIndex += 1;\n nrOfColumns += 1;\n }\n this.hot.columnIndexMapper.insertIndexes(columnIndex, numberOfCreatedCols);\n if (numberOfCreatedCols > 0) {\n if (index === undefined || index === null) {\n // Creates the meta columns at the end of the columns collection without shifting the cells\n // that were defined out of the range of the dataset.\n this.metaManager.createColumn(null, numberOfCreatedCols);\n } else if (source !== 'auto') {\n this.metaManager.createColumn(startPhysicalIndex, amount);\n }\n }\n const newVisualColumnIndex = this.hot.toVisualColumn(startPhysicalIndex);\n this.hot.runHooks('afterCreateCol', newVisualColumnIndex, numberOfCreatedCols, source);\n this.hot.forceFullRender = true; // used when data was changed\n\n this.refreshDuckSchema();\n return {\n delta: numberOfCreatedCols,\n startPhysicalIndex\n };\n }\n\n /**\n * Removes row from the data array.\n *\n * @fires Hooks#beforeRemoveRow\n * @fires Hooks#afterRemoveRow\n * @param {number} [index] Visual index of the row to be removed. If not provided, the last row will be removed.\n * @param {number} [amount=1] Amount of the rows to be removed. If not provided, one row will be removed.\n * @param {string} [source] Source of method call.\n * @returns {boolean} Returns `false` when action was cancelled, otherwise `true`.\n */\n removeRow(index) {\n let amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n let source = arguments.length > 2 ? arguments[2] : undefined;\n let rowIndex = Number.isInteger(index) ? index : -amount; // -amount = taking indexes from the end.\n const removedPhysicalIndexes = this.visualRowsToPhysical(rowIndex, amount);\n const sourceRowsLength = this.hot.countSourceRows();\n rowIndex = (sourceRowsLength + rowIndex) % sourceRowsLength;\n\n // It handle also callback from the `NestedRows` plugin. Removing parent node has effect in removing children nodes.\n const actionWasNotCancelled = this.hot.runHooks('beforeRemoveRow', rowIndex, removedPhysicalIndexes.length, removedPhysicalIndexes, source);\n if (actionWasNotCancelled === false) {\n return false;\n }\n\n // List of removed indexes might be changed in the `beforeRemoveRow` hook. There may be new values.\n const numberOfRemovedIndexes = removedPhysicalIndexes.length;\n this.filterData(rowIndex, numberOfRemovedIndexes, removedPhysicalIndexes);\n\n // TODO: Function `removeRow` should validate fully, probably above.\n if (rowIndex < this.hot.countRows()) {\n this.hot.rowIndexMapper.removeIndexes(removedPhysicalIndexes);\n const customDefinedColumns = isDefined(this.tableMeta.columns) || isDefined(this.tableMeta.dataSchema);\n\n // All rows have been removed. There shouldn't be any columns.\n if (this.hot.rowIndexMapper.getNotTrimmedIndexesLength() === 0 && customDefinedColumns === false) {\n this.hot.columnIndexMapper.setIndexesSequence([]);\n }\n }\n const descendingPhysicalRows = removedPhysicalIndexes.slice(0).sort((a, b) => b - a);\n descendingPhysicalRows.forEach(rowPhysicalIndex => {\n this.metaManager.removeRow(rowPhysicalIndex, 1);\n });\n this.hot.runHooks('afterRemoveRow', rowIndex, numberOfRemovedIndexes, removedPhysicalIndexes, source);\n this.hot.forceFullRender = true; // used when data was changed\n\n return true;\n }\n\n /**\n * Removes column from the data array.\n *\n * @fires Hooks#beforeRemoveCol\n * @fires Hooks#afterRemoveCol\n * @param {number} [index] Visual index of the column to be removed. If not provided, the last column will be removed.\n * @param {number} [amount=1] Amount of the columns to be removed. If not provided, one column will be removed.\n * @param {string} [source] Source of method call.\n * @returns {boolean} Returns `false` when action was cancelled, otherwise `true`.\n */\n removeCol(index) {\n let amount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n let source = arguments.length > 2 ? arguments[2] : undefined;\n if (this.hot.dataType === 'object' || this.tableMeta.columns) {\n throw new Error('cannot remove column with object data source or columns option specified');\n }\n let columnIndex = typeof index !== 'number' ? -amount : index;\n columnIndex = (this.hot.countCols() + columnIndex) % this.hot.countCols();\n const removedPhysicalIndexes = this.visualColumnsToPhysical(columnIndex, amount);\n const descendingPhysicalColumns = removedPhysicalIndexes.slice(0).sort((a, b) => b - a);\n const actionWasNotCancelled = this.hot.runHooks('beforeRemoveCol', columnIndex, amount, removedPhysicalIndexes, source);\n if (actionWasNotCancelled === false) {\n return false;\n }\n let isTableUniform = true;\n const removedColumnsCount = descendingPhysicalColumns.length;\n const data = this.dataSource;\n for (let c = 0; c < removedColumnsCount; c++) {\n if (isTableUniform && removedPhysicalIndexes[0] !== removedPhysicalIndexes[c] - c) {\n isTableUniform = false;\n }\n }\n if (isTableUniform) {\n for (let r = 0, rlen = this.hot.countSourceRows(); r < rlen; r++) {\n data[r].splice(removedPhysicalIndexes[0], amount);\n if (r === 0) {\n this.metaManager.removeColumn(removedPhysicalIndexes[0], amount);\n }\n }\n } else {\n for (let r = 0, rlen = this.hot.countSourceRows(); r < rlen; r++) {\n for (let c = 0; c < removedColumnsCount; c++) {\n data[r].splice(descendingPhysicalColumns[c], 1);\n if (r === 0) {\n this.metaManager.removeColumn(descendingPhysicalColumns[c], 1);\n }\n }\n }\n }\n\n // TODO: Function `removeCol` should validate fully, probably above.\n if (columnIndex < this.hot.countCols()) {\n this.hot.columnIndexMapper.removeIndexes(removedPhysicalIndexes);\n\n // All columns have been removed. There shouldn't be any rows.\n if (this.hot.columnIndexMapper.getNotTrimmedIndexesLength() === 0) {\n this.hot.rowIndexMapper.setIndexesSequence([]);\n }\n }\n this.hot.runHooks('afterRemoveCol', columnIndex, amount, removedPhysicalIndexes, source);\n this.hot.forceFullRender = true; // used when data was changed\n this.refreshDuckSchema();\n return true;\n }\n\n /**\n * Add/Removes data from the column.\n *\n * @param {number} col Physical index of column in which do you want to do splice.\n * @param {number} index Index at which to start changing the array. If negative, will begin that many elements from the end.\n * @param {number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.\n * @param {Array} [elements] The new columns to add.\n * @returns {Array} Returns removed portion of columns.\n */\n spliceCol(col, index, amount) {\n const colData = this.hot.getDataAtCol(col);\n const removed = colData.slice(index, index + amount);\n const after = colData.slice(index + amount);\n for (var _len = arguments.length, elements = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {\n elements[_key - 3] = arguments[_key];\n }\n extendArray(elements, after);\n let i = 0;\n while (i < amount) {\n elements.push(null); // add null in place of removed elements\n i += 1;\n }\n to2dArray(elements);\n this.hot.populateFromArray(index, col, elements, null, null, 'spliceCol');\n return removed;\n }\n\n /**\n * Add/Removes data from the row.\n *\n * @param {number} row Physical index of row in which do you want to do splice.\n * @param {number} index Index at which to start changing the array. If negative, will begin that many elements from the end.\n * @param {number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed.\n * @param {Array} [elements] The new rows to add.\n * @returns {Array} Returns removed portion of rows.\n */\n spliceRow(row, index, amount) {\n const rowData = this.hot.getSourceDataAtRow(row);\n const removed = rowData.slice(index, index + amount);\n const after = rowData.slice(index + amount);\n for (var _len2 = arguments.length, elements = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {\n elements[_key2 - 3] = arguments[_key2];\n }\n extendArray(elements, after);\n let i = 0;\n while (i < amount) {\n elements.push(null); // add null in place of removed elements\n i += 1;\n }\n this.hot.populateFromArray(row, index, [elements], null, null, 'spliceRow');\n return removed;\n }\n\n /**\n * Add/remove row(s) to/from the data source.\n *\n * @param {number} index Physical index of the element to add/remove.\n * @param {number} deleteCount Number of rows to remove.\n * @param {Array