@revolist/revogrid 4.17.2 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/cjs/{cell-renderer-DHSqT1hc.js → cell-renderer-ChTDsUI9.js} +3 -3
  2. package/dist/cjs/{cell-renderer-DHSqT1hc.js.map → cell-renderer-ChTDsUI9.js.map} +1 -1
  3. package/dist/cjs/{column.drag.plugin-Bz_MVClL.js → column.drag.plugin-C79X0yTw.js} +84 -4
  4. package/dist/cjs/column.drag.plugin-C79X0yTw.js.map +1 -0
  5. package/dist/cjs/{column.service-Cq2d9W4R.js → column.service-D9RDDMpb.js} +2 -391
  6. package/dist/cjs/column.service-D9RDDMpb.js.map +1 -0
  7. package/dist/cjs/{header-cell-renderer-BbmGu-fy.js → header-cell-renderer-CbdtxSW8.js} +3 -3
  8. package/dist/cjs/{header-cell-renderer-BbmGu-fy.js.map → header-cell-renderer-CbdtxSW8.js.map} +1 -1
  9. package/dist/cjs/index.cjs.js +5 -6
  10. package/dist/cjs/index.cjs.js.map +1 -1
  11. package/dist/cjs/revo-grid.cjs.entry.js +286 -20
  12. package/dist/cjs/revo-grid.cjs.entry.js.map +1 -1
  13. package/dist/cjs/revo-grid.entry.cjs.js.map +1 -1
  14. package/dist/cjs/revogr-attribution_7.cjs.entry.js +2 -2
  15. package/dist/cjs/revogr-data.revogr-header.revogr-viewport-scroll.vnode-html.entry.cjs.js.map +1 -1
  16. package/dist/cjs/revogr-data_4.cjs.entry.js +5 -5
  17. package/dist/cjs/revogr-data_4.cjs.entry.js.map +1 -1
  18. package/dist/cjs/{viewport.helpers-DWmWzj7C.js → viewport.helpers-BAovztDd.js} +5 -3
  19. package/dist/cjs/viewport.helpers-BAovztDd.js.map +1 -0
  20. package/dist/collection/components/header/revogr-header-style.css +15 -17
  21. package/dist/collection/components/revoGrid/viewport.helpers.js +3 -1
  22. package/dist/collection/components/revoGrid/viewport.helpers.js.map +1 -1
  23. package/dist/collection/components/revoGrid/viewport.service.js +11 -16
  24. package/dist/collection/components/revoGrid/viewport.service.js.map +1 -1
  25. package/dist/collection/services/selection.store.connector.js +13 -46
  26. package/dist/collection/services/selection.store.connector.js.map +1 -1
  27. package/dist/collection/store/selection/selection.helpers.js +0 -4
  28. package/dist/collection/store/selection/selection.helpers.js.map +1 -1
  29. package/dist/collection/types/selection.js.map +1 -1
  30. package/dist/esm/{cell-renderer-BjdtMiBM.js → cell-renderer-ePazz-Zt.js} +3 -3
  31. package/dist/esm/{cell-renderer-BjdtMiBM.js.map → cell-renderer-ePazz-Zt.js.map} +1 -1
  32. package/dist/{revo-grid/column.drag.plugin-CIivVS-c.js → esm/column.drag.plugin-CS8ilBtr.js} +84 -5
  33. package/dist/esm/column.drag.plugin-CS8ilBtr.js.map +1 -0
  34. package/dist/esm/{column.service-CspjVf-q.js → column.service-DT_CqxqZ.js} +4 -389
  35. package/dist/esm/column.service-DT_CqxqZ.js.map +1 -0
  36. package/dist/esm/{header-cell-renderer-bvKLyRcy.js → header-cell-renderer-DNIoql0s.js} +3 -3
  37. package/dist/{revo-grid/header-cell-renderer-bvKLyRcy.js.map → esm/header-cell-renderer-DNIoql0s.js.map} +1 -1
  38. package/dist/esm/index.js +5 -5
  39. package/dist/esm/revo-grid.entry.js +285 -19
  40. package/dist/esm/revo-grid.entry.js.map +1 -1
  41. package/dist/esm/revogr-attribution_7.entry.js +2 -2
  42. package/dist/esm/revogr-data.revogr-header.revogr-viewport-scroll.vnode-html.entry.js.map +1 -1
  43. package/dist/esm/revogr-data_4.entry.js +5 -5
  44. package/dist/esm/revogr-data_4.entry.js.map +1 -1
  45. package/dist/esm/{viewport.helpers-B3EYGhqf.js → viewport.helpers-VXhsJZtn.js} +5 -3
  46. package/dist/esm/viewport.helpers-VXhsJZtn.js.map +1 -0
  47. package/dist/revo-grid/{cell-renderer-BjdtMiBM.js → cell-renderer-ePazz-Zt.js} +3 -3
  48. package/dist/revo-grid/{cell-renderer-BjdtMiBM.js.map → cell-renderer-ePazz-Zt.js.map} +1 -1
  49. package/dist/{esm/column.drag.plugin-CIivVS-c.js → revo-grid/column.drag.plugin-CS8ilBtr.js} +84 -5
  50. package/dist/revo-grid/column.drag.plugin-CS8ilBtr.js.map +1 -0
  51. package/dist/revo-grid/{column.service-CspjVf-q.js → column.service-DT_CqxqZ.js} +4 -389
  52. package/dist/revo-grid/column.service-DT_CqxqZ.js.map +1 -0
  53. package/dist/revo-grid/{header-cell-renderer-bvKLyRcy.js → header-cell-renderer-DNIoql0s.js} +3 -3
  54. package/dist/{esm/header-cell-renderer-bvKLyRcy.js.map → revo-grid/header-cell-renderer-DNIoql0s.js.map} +1 -1
  55. package/dist/revo-grid/index.esm.js +5 -5
  56. package/dist/revo-grid/revo-grid.entry.esm.js.map +1 -1
  57. package/dist/revo-grid/revo-grid.entry.js +285 -19
  58. package/dist/revo-grid/revo-grid.entry.js.map +1 -1
  59. package/dist/revo-grid/revogr-attribution_7.entry.js +2 -2
  60. package/dist/revo-grid/revogr-data.revogr-header.revogr-viewport-scroll.vnode-html.entry.esm.js.map +1 -1
  61. package/dist/revo-grid/revogr-data_4.entry.js +5 -5
  62. package/dist/revo-grid/revogr-data_4.entry.js.map +1 -1
  63. package/dist/revo-grid/{viewport.helpers-B3EYGhqf.js → viewport.helpers-VXhsJZtn.js} +5 -3
  64. package/dist/revo-grid/viewport.helpers-VXhsJZtn.js.map +1 -0
  65. package/dist/types/components/revoGrid/viewport.helpers.d.ts +3 -0
  66. package/dist/types/services/selection.store.connector.d.ts +0 -5
  67. package/dist/types/store/selection/selection.helpers.d.ts +0 -1
  68. package/dist/types/types/selection.d.ts +1 -0
  69. package/hydrate/index.js +638 -676
  70. package/hydrate/index.mjs +638 -676
  71. package/package.json +6 -6
  72. package/standalone/column.service.js +2 -387
  73. package/standalone/column.service.js.map +1 -1
  74. package/standalone/index.js +2 -2
  75. package/standalone/revo-grid.js +362 -17
  76. package/standalone/revo-grid.js.map +1 -1
  77. package/standalone/revogr-data2.js +1 -1
  78. package/standalone/revogr-header2.js +2 -2
  79. package/standalone/revogr-header2.js.map +1 -1
  80. package/standalone/revogr-overlay-selection2.js +1 -1
  81. package/standalone/revogr-viewport-scroll2.js +3 -1
  82. package/standalone/revogr-viewport-scroll2.js.map +1 -1
  83. package/dist/cjs/column.drag.plugin-Bz_MVClL.js.map +0 -1
  84. package/dist/cjs/column.service-Cq2d9W4R.js.map +0 -1
  85. package/dist/cjs/viewport.helpers-DWmWzj7C.js.map +0 -1
  86. package/dist/esm/column.drag.plugin-CIivVS-c.js.map +0 -1
  87. package/dist/esm/column.service-CspjVf-q.js.map +0 -1
  88. package/dist/esm/viewport.helpers-B3EYGhqf.js.map +0 -1
  89. package/dist/revo-grid/column.drag.plugin-CIivVS-c.js.map +0 -1
  90. package/dist/revo-grid/column.service-CspjVf-q.js.map +0 -1
  91. package/dist/revo-grid/viewport.helpers-B3EYGhqf.js.map +0 -1
package/hydrate/index.js CHANGED
@@ -8139,568 +8139,262 @@ class SelectionStore {
8139
8139
  }
8140
8140
  }
8141
8141
 
8142
- const EMPTY_INDEX = -1;
8143
- class SelectionStoreConnector {
8144
- constructor() {
8145
- // dirty flag required to cleanup whole store in case visibility of panels changed
8146
- this.dirty = false;
8147
- this.stores = {};
8148
- this.columnStores = {};
8149
- this.rowStores = {};
8150
- /**
8151
- * Helpers for data conversion
8152
- */
8153
- this.storesByType = {};
8154
- this.storesXToType = {};
8155
- this.storesYToType = {};
8156
- this.sections = [];
8157
- }
8158
- get focusedStore() {
8159
- var _a;
8160
- for (let y in this.stores) {
8161
- for (let x in this.stores[y]) {
8162
- const focused = (_a = this.stores[y][x]) === null || _a === void 0 ? void 0 : _a.store.get('focus');
8163
- if (focused) {
8164
- return {
8165
- entity: this.stores[y][x],
8166
- cell: focused,
8167
- position: {
8168
- x: parseInt(x, 10),
8169
- y: parseInt(y, 10),
8170
- },
8171
- };
8172
- }
8173
- }
8174
- }
8175
- return null;
8176
- }
8177
- get edit() {
8178
- var _a;
8179
- return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('edit');
8180
- }
8181
- get focused() {
8182
- var _a;
8183
- return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('focus');
8184
- }
8185
- get selectedRange() {
8186
- var _a;
8187
- return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('range');
8188
- }
8189
- registerSection(e) {
8190
- if (!e) {
8191
- this.sections.length = 0;
8192
- // some elements removed, rebuild stores
8193
- this.dirty = true;
8194
- return;
8195
- }
8196
- if (this.sections.indexOf(e) === -1) {
8197
- this.sections.push(e);
8198
- }
8199
- }
8200
- // check if require to cleanup all stores
8201
- beforeUpdate() {
8202
- if (this.dirty) {
8203
- for (let y in this.stores) {
8204
- for (let x in this.stores[y]) {
8205
- this.stores[y][x].dispose();
8206
- }
8207
- }
8208
- this.dirty = false;
8142
+ function nextCell(cell, lastCell) {
8143
+ const nextItem = {};
8144
+ let types = ['x', 'y'];
8145
+ // previous item check
8146
+ for (let t of types) {
8147
+ if (cell[t] < 0) {
8148
+ nextItem[t] = cell[t];
8149
+ return nextItem;
8209
8150
  }
8210
8151
  }
8211
- registerColumn(x, type) {
8212
- // if hidden just create store but no operations needed
8213
- if (isHiddenStore(x)) {
8214
- return new SelectionStore();
8215
- }
8216
- if (this.columnStores[x]) {
8217
- return this.columnStores[x];
8152
+ // next item check
8153
+ for (let t of types) {
8154
+ if (cell[t] >= lastCell[t]) {
8155
+ nextItem[t] = cell[t] - lastCell[t];
8156
+ return nextItem;
8218
8157
  }
8219
- this.columnStores[x] = new SelectionStore();
8220
- // build cross-linking type to position
8221
- this.storesByType[type] = x;
8222
- this.storesXToType[x] = type;
8223
- return this.columnStores[x];
8224
8158
  }
8225
- registerRow(y, type) {
8226
- // if hidden just create store
8227
- if (isHiddenStore(y)) {
8228
- return new SelectionStore();
8159
+ return null;
8160
+ }
8161
+ function cropCellToMax(cell, lastCell) {
8162
+ const croppedCell = Object.assign({}, cell);
8163
+ const cellCoordinates = ['x', 'y'];
8164
+ for (const coordinate of cellCoordinates) {
8165
+ if (cell[coordinate] < 0) {
8166
+ croppedCell[coordinate] = 0;
8229
8167
  }
8230
- if (this.rowStores[y]) {
8231
- return this.rowStores[y];
8168
+ else if (cell[coordinate] >= lastCell[coordinate]) {
8169
+ croppedCell[coordinate] = lastCell[coordinate] - 1;
8232
8170
  }
8233
- this.rowStores[y] = new SelectionStore();
8234
- // build cross linking type to position
8235
- this.storesByType[type] = y;
8236
- this.storesYToType[y] = type;
8237
- return this.rowStores[y];
8238
8171
  }
8239
- /**
8240
- * Cross store proxy, based on multiple dimensions
8241
- */
8242
- register({ x, y }) {
8243
- var _a, _b;
8244
- // if hidden just create store
8245
- if (isHiddenStore(x) || isHiddenStore(y)) {
8246
- return new SelectionStore();
8247
- }
8248
- if (!this.stores[y]) {
8249
- this.stores[y] = {};
8172
+ return croppedCell;
8173
+ }
8174
+ function getRange(start, end) {
8175
+ return start && end
8176
+ ? {
8177
+ x: Math.min(start.x, end.x),
8178
+ y: Math.min(start.y, end.y),
8179
+ x1: Math.max(start.x, end.x),
8180
+ y1: Math.max(start.y, end.y),
8250
8181
  }
8251
- if (this.stores[y][x]) {
8252
- // Store already registered. Do not register twice
8253
- return this.stores[y][x];
8182
+ : null;
8183
+ }
8184
+ function isRangeSingleCell(a) {
8185
+ return a.x === a.x1 && a.y === a.y1;
8186
+ }
8187
+
8188
+ /**
8189
+ * Update items based on new scroll position
8190
+ * If viewport wasn't changed fully simple recombination of positions
8191
+ * Otherwise rebuild viewport items
8192
+ */
8193
+ function getUpdatedItemsByPosition(pos, // coordinate
8194
+ items, realCount, virtualSize, dimension) {
8195
+ const activeItem = getItemByPosition(dimension, pos);
8196
+ const firstItem = getFirstItem(items);
8197
+ let toUpdate;
8198
+ // do simple position recombination if items already present in viewport
8199
+ if (firstItem) {
8200
+ let changedOffsetStart = activeItem.itemIndex - (firstItem.itemIndex || 0);
8201
+ // if item changed
8202
+ if (changedOffsetStart) {
8203
+ // simple recombination
8204
+ toUpdate = recombineByOffset(Math.abs(changedOffsetStart), Object.assign(Object.assign({ positiveDirection: changedOffsetStart > -1 }, dimension), items));
8254
8205
  }
8255
- this.stores[y][x] = new SelectionStore();
8256
- // proxy update, column store trigger only range area
8257
- (_a = this.stores[y][x]) === null || _a === void 0 ? void 0 : _a.onChange('range', c => {
8258
- this.columnStores[x].setRangeArea(c);
8259
- this.rowStores[y].setRangeArea(c);
8260
- });
8261
- // clean up on remove
8262
- (_b = this.stores[y][x]) === null || _b === void 0 ? void 0 : _b.store.on('dispose', () => this.destroy(x, y));
8263
- return this.stores[y][x];
8264
8206
  }
8265
- destroy(x, y) {
8266
- var _a, _b;
8267
- (_a = this.columnStores[x]) === null || _a === void 0 ? void 0 : _a.dispose();
8268
- (_b = this.rowStores[y]) === null || _b === void 0 ? void 0 : _b.dispose();
8269
- delete this.rowStores[y];
8270
- delete this.columnStores[x];
8271
- // clear x cross-link
8272
- if (this.storesXToType[x]) {
8273
- const type = this.storesXToType[x];
8274
- delete this.storesXToType[x];
8275
- delete this.storesByType[type];
8276
- }
8277
- // clear y cross-link
8278
- if (this.storesYToType[y]) {
8279
- const type = this.storesYToType[y];
8280
- delete this.storesYToType[y];
8281
- delete this.storesByType[type];
8282
- }
8283
- if (this.stores[y]) {
8284
- delete this.stores[y][x];
8285
- }
8286
- // clear empty rows
8287
- if (!Object.keys(this.stores[y] || {}).length) {
8288
- delete this.stores[y];
8207
+ const maxSizeVirtualSize = getMaxVirtualSize(virtualSize, dimension.realSize, activeItem);
8208
+ // if partial recombination add items if revo-viewport has some space left
8209
+ if (toUpdate) {
8210
+ const extra = addMissingItems(activeItem, realCount, maxSizeVirtualSize, toUpdate, dimension);
8211
+ if (extra.length) {
8212
+ updateMissingAndRange(toUpdate.items, extra, toUpdate);
8289
8213
  }
8290
8214
  }
8291
- setEditByCell(storePos, editCell) {
8292
- this.focusByCell(storePos, editCell, editCell);
8293
- this.setEdit('');
8215
+ // new collection if no items after replacement full replacement
8216
+ if (!toUpdate) {
8217
+ const items = getItems({
8218
+ firstItemStart: activeItem.start,
8219
+ firstItemIndex: activeItem.itemIndex,
8220
+ origSize: dimension.originItemSize,
8221
+ maxSize: maxSizeVirtualSize,
8222
+ maxCount: realCount,
8223
+ sizes: dimension.sizes,
8224
+ });
8225
+ // range now comes from 0 to length - 1
8226
+ toUpdate = {
8227
+ items,
8228
+ start: 0,
8229
+ end: items.length - 1,
8230
+ };
8294
8231
  }
8295
- /**
8296
- * Sets the next focus cell before the current one.
8297
- *
8298
- * @param focus - The cell to set as the next focus.
8299
- */
8300
- beforeNextFocusCell(focus) {
8301
- var _a;
8302
- // If there is no focused store, return early.
8303
- if (!this.focusedStore) {
8304
- return;
8305
- }
8306
- // Get the next store based on the current focus and the last cell.
8307
- const lastCell = this.focusedStore.entity.store.get('lastCell');
8308
- const next = lastCell && this.getNextStore(focus, this.focusedStore.position, lastCell);
8309
- // Set the next focus cell in the store.
8310
- (_a = next === null || next === void 0 ? void 0 : next.store) === null || _a === void 0 ? void 0 : _a.setNextFocus(Object.assign(Object.assign({}, focus), next.item));
8232
+ return toUpdate;
8233
+ }
8234
+ // virtual size can differ based on scroll position if some big items are present
8235
+ // scroll can be in the middle of item and virtual size will be larger
8236
+ // so we need to exclude this part from virtual size hence it's already passed
8237
+ function getMaxVirtualSize(virtualSize, realSize, activeItem) {
8238
+ return Math.min(virtualSize + (activeItem.end - activeItem.start), realSize);
8239
+ }
8240
+ function updateMissingAndRange(items, missing, range) {
8241
+ items.splice(range.end + 1, 0, ...missing);
8242
+ // update range if start larger after recombination
8243
+ if (range.start >= range.end &&
8244
+ !(range.start === range.end && range.start === 0)) {
8245
+ range.start += missing.length;
8311
8246
  }
8312
- focusByCell(storePos, start, end) {
8313
- const store = this.stores[storePos.y][storePos.x];
8314
- this.focus(store, { focus: start, end });
8247
+ range.end += missing.length;
8248
+ }
8249
+ /**
8250
+ * If partial replacement
8251
+ * this function adds items if viewport has some space left
8252
+ */
8253
+ function addMissingItems(firstItem, realCount, virtualSize, existingCollection, dimension) {
8254
+ const lastItem = getLastItem(existingCollection);
8255
+ const items = getItems({
8256
+ sizes: dimension.sizes,
8257
+ firstItemStart: lastItem.end,
8258
+ firstItemIndex: lastItem.itemIndex + 1,
8259
+ origSize: dimension.originItemSize,
8260
+ maxSize: virtualSize - (lastItem.end - firstItem.start),
8261
+ maxCount: realCount,
8262
+ });
8263
+ return items;
8264
+ }
8265
+ /**
8266
+ * Get wiewport items parameters
8267
+ * caching position and calculating items count in viewport
8268
+ */
8269
+ function getItems(opt, currentSize = 0) {
8270
+ const items = [];
8271
+ let index = opt.firstItemIndex;
8272
+ let size = currentSize;
8273
+ // max size or max count
8274
+ while (size <= opt.maxSize && index < opt.maxCount) {
8275
+ const newSize = getItemSize(index, opt.sizes, opt.origSize);
8276
+ items.push({
8277
+ start: opt.firstItemStart + size,
8278
+ end: opt.firstItemStart + size + newSize,
8279
+ itemIndex: index,
8280
+ size: newSize,
8281
+ });
8282
+ size += newSize;
8283
+ index++;
8315
8284
  }
8316
- focus(store, { focus, end }) {
8317
- const currentStorePointer = this.getCurrentStorePointer(store);
8318
- if (!currentStorePointer) {
8319
- return null;
8320
- }
8321
- // check for the focus in nearby store/viewport
8322
- const lastCell = store.store.get('lastCell');
8323
- const next = lastCell && this.getNextStore(focus, currentStorePointer, lastCell);
8324
- // if next store present - update
8325
- if (next === null || next === void 0 ? void 0 : next.store) {
8326
- const item = Object.assign(Object.assign({}, focus), next.item);
8327
- this.focus(next.store, { focus: item, end: item });
8328
- return null;
8329
- }
8330
- if (lastCell) {
8331
- focus = cropCellToMax(focus, lastCell);
8332
- end = cropCellToMax(end, lastCell);
8333
- }
8334
- store.setFocus(focus, end);
8335
- return focus;
8285
+ return items;
8286
+ }
8287
+ function recombineByOffset(offset, data) {
8288
+ var _a, _b;
8289
+ const newItems = [...data.items];
8290
+ const itemsCount = newItems.length;
8291
+ let newRange = {
8292
+ start: data.start,
8293
+ end: data.end,
8294
+ };
8295
+ // if offset out of revo-viewport, makes sense whole redraw
8296
+ if (offset > itemsCount) {
8297
+ return undefined;
8336
8298
  }
8337
- /**
8338
- * Retrieves the current store pointer based on the active store.
8339
- * Clears focus from all stores except the active one.
8340
- */
8341
- getCurrentStorePointer(store) {
8342
- let currentStorePointer;
8343
- // Iterate through all stores
8344
- for (let y in this.stores) {
8345
- for (let x in this.stores[y]) {
8346
- const s = this.stores[y][x];
8347
- // Clear focus from stores other than the active one
8348
- if (s !== store) {
8349
- s.clearFocus();
8350
- }
8351
- else {
8352
- // Update the current store pointer with the active store coordinates
8353
- currentStorePointer = {
8354
- x: parseInt(x, 10),
8355
- y: parseInt(y, 10)
8356
- };
8357
- }
8299
+ // is direction of scroll positive
8300
+ if (data.positiveDirection) {
8301
+ // push item to the end
8302
+ let lastItem = getLastItem(data);
8303
+ let i = newRange.start;
8304
+ const length = i + offset;
8305
+ for (; i < length; i++) {
8306
+ const newIndex = lastItem.itemIndex + 1;
8307
+ const size = getItemSize(newIndex, data.sizes, data.originItemSize);
8308
+ // if item overlapped limit break a loop
8309
+ if (lastItem.end + size > data.realSize) {
8310
+ break;
8358
8311
  }
8359
- }
8360
- return currentStorePointer;
8361
- }
8362
- /**
8363
- * Retrieves the next store based on the focus cell and current store pointer.
8364
- * If the next store exists, returns an object with the next store and the item in the new store.
8365
- * If the next store does not exist, returns null.
8366
- */
8367
- getNextStore(focus, currentStorePointer, lastCell) {
8368
- // item in new store
8369
- const nextItem = nextCell(focus, lastCell);
8370
- let nextStore;
8371
- if (nextItem) {
8372
- Object.entries(nextItem).forEach(([type, nextItemCoord]) => {
8373
- let stores;
8374
- switch (type) {
8375
- case 'x':
8376
- // Get the X stores for the current Y coordinate of the current store pointer
8377
- stores = this.getXStores(currentStorePointer.y);
8378
- break;
8379
- case 'y':
8380
- // Get the Y stores for the current X coordinate of the current store pointer
8381
- stores = this.getYStores(currentStorePointer.x);
8382
- break;
8383
- }
8384
- // Get the next store based on the item in the new store
8385
- if (nextItemCoord >= 0) {
8386
- nextStore = stores[++currentStorePointer[type]];
8387
- }
8388
- else {
8389
- nextStore = stores[--currentStorePointer[type]];
8390
- const nextLastCell = nextStore === null || nextStore === void 0 ? void 0 : nextStore.store.get('lastCell');
8391
- if (nextLastCell) {
8392
- nextItem[type] = nextLastCell[type] + nextItemCoord;
8393
- }
8394
- }
8395
- });
8396
- }
8397
- return {
8398
- store: nextStore,
8399
- item: nextItem,
8400
- };
8401
- }
8402
- clearAll() {
8403
- var _a;
8404
- for (let y in this.stores) {
8405
- for (let x in this.stores[y]) {
8406
- (_a = this.stores[y][x]) === null || _a === void 0 ? void 0 : _a.clearFocus();
8312
+ // new item index to recombine
8313
+ let newEnd = i % itemsCount;
8314
+ // item should always present, we do not create new item, we recombine them
8315
+ if (!newItems[newEnd]) {
8316
+ throw new Error('incorrect index');
8407
8317
  }
8318
+ // do recombination
8319
+ newItems[newEnd] = lastItem = {
8320
+ start: lastItem.end,
8321
+ end: lastItem.end + size,
8322
+ itemIndex: newIndex,
8323
+ size: size,
8324
+ };
8325
+ // update range
8326
+ newRange.start++;
8327
+ newRange.end = newEnd;
8408
8328
  }
8329
+ // direction is negative
8409
8330
  }
8410
- setEdit(val) {
8411
- if (!this.focusedStore) {
8412
- return;
8413
- }
8414
- this.focusedStore.entity.setEdit(val);
8415
- }
8416
- /**
8417
- * Select all cells across all stores
8418
- */
8419
- selectAll() {
8420
- for (let y in this.stores) {
8421
- for (let x in this.stores[y]) {
8422
- const store = this.stores[y][x];
8423
- if (!store) {
8424
- continue;
8425
- }
8426
- const lastCell = store.store.get('lastCell');
8427
- if (lastCell) {
8428
- store.setRange({ x: 0, y: 0 }, { x: lastCell.x - 1, y: lastCell.y - 1 });
8429
- }
8331
+ else {
8332
+ // push item to the start
8333
+ let firstItem = getFirstItem(data);
8334
+ const end = newRange.end;
8335
+ for (let i = 0; i < offset; i++) {
8336
+ const newIndex = ((_a = firstItem === null || firstItem === void 0 ? void 0 : firstItem.itemIndex) !== null && _a !== void 0 ? _a : 0) - 1;
8337
+ const size = getItemSize(newIndex, data.sizes, data.originItemSize);
8338
+ // new item index to recombine
8339
+ let newStart = end - i;
8340
+ newStart = (newStart < 0 ? itemsCount + newStart : newStart) % itemsCount;
8341
+ // item should always present, we do not create new item, we recombine them
8342
+ if (!newItems[newStart]) {
8343
+ console.error('incorrect index');
8344
+ break;
8430
8345
  }
8346
+ // do recombination
8347
+ const firstItemStart = (_b = firstItem === null || firstItem === void 0 ? void 0 : firstItem.start) !== null && _b !== void 0 ? _b : 0;
8348
+ newItems[newStart] = firstItem = {
8349
+ start: firstItemStart - size,
8350
+ end: firstItemStart,
8351
+ itemIndex: newIndex,
8352
+ size: size,
8353
+ };
8354
+ // update range
8355
+ newRange.start = newStart;
8356
+ newRange.end--;
8431
8357
  }
8432
8358
  }
8433
- getXStores(y) {
8434
- return this.stores[y];
8435
- }
8436
- getYStores(x) {
8437
- const stores = {};
8438
- for (let i in this.stores) {
8439
- stores[i] = this.stores[i][x];
8440
- }
8441
- return stores;
8442
- }
8443
- }
8444
-
8445
- function isHiddenStore(pos) {
8446
- return pos === EMPTY_INDEX;
8359
+ const range = {
8360
+ start: (newRange.start < 0 ? itemsCount + newRange.start : newRange.start) %
8361
+ itemsCount,
8362
+ end: (newRange.end < 0 ? itemsCount + newRange.end : newRange.end) %
8363
+ itemsCount,
8364
+ };
8365
+ return Object.assign({ items: newItems }, range);
8447
8366
  }
8448
- function nextCell(cell, lastCell) {
8449
- const nextItem = {};
8450
- let types = ['x', 'y'];
8451
- // previous item check
8452
- for (let t of types) {
8453
- if (cell[t] < 0) {
8454
- nextItem[t] = cell[t];
8455
- return nextItem;
8456
- }
8367
+ function getItemSize(index, sizes, origSize = 0) {
8368
+ if (sizes && sizes[index]) {
8369
+ return sizes[index];
8457
8370
  }
8458
- // next item check
8459
- for (let t of types) {
8460
- if (cell[t] >= lastCell[t]) {
8461
- nextItem[t] = cell[t] - lastCell[t];
8462
- return nextItem;
8463
- }
8371
+ return origSize;
8372
+ }
8373
+ /**
8374
+ * Verify if position is in range of the PositionItem, start and end are included
8375
+ */
8376
+ function isActiveRange(pos, realSize, first, last) {
8377
+ if (!first || !last) {
8378
+ return false;
8464
8379
  }
8465
- return null;
8380
+ // if position is in range of first item
8381
+ // or position is after first item and last item is the last item in real size
8382
+ return ((pos >= first.start && pos <= first.end) ||
8383
+ (pos > first.end && last.end === realSize));
8466
8384
  }
8467
- function cropCellToMax(cell, lastCell) {
8468
- const croppedCell = Object.assign({}, cell);
8469
- const cellCoordinates = ['x', 'y'];
8470
- for (const coordinate of cellCoordinates) {
8471
- if (cell[coordinate] < 0) {
8472
- croppedCell[coordinate] = 0;
8473
- }
8474
- else if (cell[coordinate] >= lastCell[coordinate]) {
8475
- croppedCell[coordinate] = lastCell[coordinate] - 1;
8476
- }
8385
+ function isActiveRangeOutsideLastItem(pos, virtualSize, firstItem, lastItem) {
8386
+ var _a;
8387
+ // if no first item, means no items in viewport
8388
+ if (!firstItem) {
8389
+ return false;
8477
8390
  }
8478
- return croppedCell;
8391
+ return virtualSize + pos > ((_a = lastItem === null || lastItem === void 0 ? void 0 : lastItem.end) !== null && _a !== void 0 ? _a : 0);
8479
8392
  }
8480
- function getRange(start, end) {
8481
- return start && end
8482
- ? {
8483
- x: Math.min(start.x, end.x),
8484
- y: Math.min(start.y, end.y),
8485
- x1: Math.max(start.x, end.x),
8486
- y1: Math.max(start.y, end.y),
8487
- }
8488
- : null;
8393
+ function getFirstItem(s) {
8394
+ return s.items[s.start];
8489
8395
  }
8490
- function isRangeSingleCell(a) {
8491
- return a.x === a.x1 && a.y === a.y1;
8492
- }
8493
-
8494
- /**
8495
- * Update items based on new scroll position
8496
- * If viewport wasn't changed fully simple recombination of positions
8497
- * Otherwise rebuild viewport items
8498
- */
8499
- function getUpdatedItemsByPosition(pos, // coordinate
8500
- items, realCount, virtualSize, dimension) {
8501
- const activeItem = getItemByPosition(dimension, pos);
8502
- const firstItem = getFirstItem(items);
8503
- let toUpdate;
8504
- // do simple position recombination if items already present in viewport
8505
- if (firstItem) {
8506
- let changedOffsetStart = activeItem.itemIndex - (firstItem.itemIndex || 0);
8507
- // if item changed
8508
- if (changedOffsetStart) {
8509
- // simple recombination
8510
- toUpdate = recombineByOffset(Math.abs(changedOffsetStart), Object.assign(Object.assign({ positiveDirection: changedOffsetStart > -1 }, dimension), items));
8511
- }
8512
- }
8513
- const maxSizeVirtualSize = getMaxVirtualSize(virtualSize, dimension.realSize, activeItem);
8514
- // if partial recombination add items if revo-viewport has some space left
8515
- if (toUpdate) {
8516
- const extra = addMissingItems(activeItem, realCount, maxSizeVirtualSize, toUpdate, dimension);
8517
- if (extra.length) {
8518
- updateMissingAndRange(toUpdate.items, extra, toUpdate);
8519
- }
8520
- }
8521
- // new collection if no items after replacement full replacement
8522
- if (!toUpdate) {
8523
- const items = getItems({
8524
- firstItemStart: activeItem.start,
8525
- firstItemIndex: activeItem.itemIndex,
8526
- origSize: dimension.originItemSize,
8527
- maxSize: maxSizeVirtualSize,
8528
- maxCount: realCount,
8529
- sizes: dimension.sizes,
8530
- });
8531
- // range now comes from 0 to length - 1
8532
- toUpdate = {
8533
- items,
8534
- start: 0,
8535
- end: items.length - 1,
8536
- };
8537
- }
8538
- return toUpdate;
8539
- }
8540
- // virtual size can differ based on scroll position if some big items are present
8541
- // scroll can be in the middle of item and virtual size will be larger
8542
- // so we need to exclude this part from virtual size hence it's already passed
8543
- function getMaxVirtualSize(virtualSize, realSize, activeItem) {
8544
- return Math.min(virtualSize + (activeItem.end - activeItem.start), realSize);
8545
- }
8546
- function updateMissingAndRange(items, missing, range) {
8547
- items.splice(range.end + 1, 0, ...missing);
8548
- // update range if start larger after recombination
8549
- if (range.start >= range.end &&
8550
- !(range.start === range.end && range.start === 0)) {
8551
- range.start += missing.length;
8552
- }
8553
- range.end += missing.length;
8554
- }
8555
- /**
8556
- * If partial replacement
8557
- * this function adds items if viewport has some space left
8558
- */
8559
- function addMissingItems(firstItem, realCount, virtualSize, existingCollection, dimension) {
8560
- const lastItem = getLastItem(existingCollection);
8561
- const items = getItems({
8562
- sizes: dimension.sizes,
8563
- firstItemStart: lastItem.end,
8564
- firstItemIndex: lastItem.itemIndex + 1,
8565
- origSize: dimension.originItemSize,
8566
- maxSize: virtualSize - (lastItem.end - firstItem.start),
8567
- maxCount: realCount,
8568
- });
8569
- return items;
8570
- }
8571
- /**
8572
- * Get wiewport items parameters
8573
- * caching position and calculating items count in viewport
8574
- */
8575
- function getItems(opt, currentSize = 0) {
8576
- const items = [];
8577
- let index = opt.firstItemIndex;
8578
- let size = currentSize;
8579
- // max size or max count
8580
- while (size <= opt.maxSize && index < opt.maxCount) {
8581
- const newSize = getItemSize(index, opt.sizes, opt.origSize);
8582
- items.push({
8583
- start: opt.firstItemStart + size,
8584
- end: opt.firstItemStart + size + newSize,
8585
- itemIndex: index,
8586
- size: newSize,
8587
- });
8588
- size += newSize;
8589
- index++;
8590
- }
8591
- return items;
8592
- }
8593
- function recombineByOffset(offset, data) {
8594
- var _a, _b;
8595
- const newItems = [...data.items];
8596
- const itemsCount = newItems.length;
8597
- let newRange = {
8598
- start: data.start,
8599
- end: data.end,
8600
- };
8601
- // if offset out of revo-viewport, makes sense whole redraw
8602
- if (offset > itemsCount) {
8603
- return undefined;
8604
- }
8605
- // is direction of scroll positive
8606
- if (data.positiveDirection) {
8607
- // push item to the end
8608
- let lastItem = getLastItem(data);
8609
- let i = newRange.start;
8610
- const length = i + offset;
8611
- for (; i < length; i++) {
8612
- const newIndex = lastItem.itemIndex + 1;
8613
- const size = getItemSize(newIndex, data.sizes, data.originItemSize);
8614
- // if item overlapped limit break a loop
8615
- if (lastItem.end + size > data.realSize) {
8616
- break;
8617
- }
8618
- // new item index to recombine
8619
- let newEnd = i % itemsCount;
8620
- // item should always present, we do not create new item, we recombine them
8621
- if (!newItems[newEnd]) {
8622
- throw new Error('incorrect index');
8623
- }
8624
- // do recombination
8625
- newItems[newEnd] = lastItem = {
8626
- start: lastItem.end,
8627
- end: lastItem.end + size,
8628
- itemIndex: newIndex,
8629
- size: size,
8630
- };
8631
- // update range
8632
- newRange.start++;
8633
- newRange.end = newEnd;
8634
- }
8635
- // direction is negative
8636
- }
8637
- else {
8638
- // push item to the start
8639
- let firstItem = getFirstItem(data);
8640
- const end = newRange.end;
8641
- for (let i = 0; i < offset; i++) {
8642
- const newIndex = ((_a = firstItem === null || firstItem === void 0 ? void 0 : firstItem.itemIndex) !== null && _a !== void 0 ? _a : 0) - 1;
8643
- const size = getItemSize(newIndex, data.sizes, data.originItemSize);
8644
- // new item index to recombine
8645
- let newStart = end - i;
8646
- newStart = (newStart < 0 ? itemsCount + newStart : newStart) % itemsCount;
8647
- // item should always present, we do not create new item, we recombine them
8648
- if (!newItems[newStart]) {
8649
- console.error('incorrect index');
8650
- break;
8651
- }
8652
- // do recombination
8653
- const firstItemStart = (_b = firstItem === null || firstItem === void 0 ? void 0 : firstItem.start) !== null && _b !== void 0 ? _b : 0;
8654
- newItems[newStart] = firstItem = {
8655
- start: firstItemStart - size,
8656
- end: firstItemStart,
8657
- itemIndex: newIndex,
8658
- size: size,
8659
- };
8660
- // update range
8661
- newRange.start = newStart;
8662
- newRange.end--;
8663
- }
8664
- }
8665
- const range = {
8666
- start: (newRange.start < 0 ? itemsCount + newRange.start : newRange.start) %
8667
- itemsCount,
8668
- end: (newRange.end < 0 ? itemsCount + newRange.end : newRange.end) %
8669
- itemsCount,
8670
- };
8671
- return Object.assign({ items: newItems }, range);
8672
- }
8673
- function getItemSize(index, sizes, origSize = 0) {
8674
- if (sizes && sizes[index]) {
8675
- return sizes[index];
8676
- }
8677
- return origSize;
8678
- }
8679
- /**
8680
- * Verify if position is in range of the PositionItem, start and end are included
8681
- */
8682
- function isActiveRange(pos, realSize, first, last) {
8683
- if (!first || !last) {
8684
- return false;
8685
- }
8686
- // if position is in range of first item
8687
- // or position is after first item and last item is the last item in real size
8688
- return ((pos >= first.start && pos <= first.end) ||
8689
- (pos > first.end && last.end === realSize));
8690
- }
8691
- function isActiveRangeOutsideLastItem(pos, virtualSize, firstItem, lastItem) {
8692
- var _a;
8693
- // if no first item, means no items in viewport
8694
- if (!firstItem) {
8695
- return false;
8696
- }
8697
- return virtualSize + pos > ((_a = lastItem === null || lastItem === void 0 ? void 0 : lastItem.end) !== null && _a !== void 0 ? _a : 0);
8698
- }
8699
- function getFirstItem(s) {
8700
- return s.items[s.start];
8701
- }
8702
- function getLastItem(s) {
8703
- return s.items[s.end];
8396
+ function getLastItem(s) {
8397
+ return s.items[s.end];
8704
8398
  }
8705
8399
  /**
8706
8400
  * Set items sizes from start index to end
@@ -13371,7 +13065,9 @@ function viewportDataPartition(data, type, slot, fixed) {
13371
13065
  colData: data.colStore,
13372
13066
  viewportCol: data.viewports[data.colType].store,
13373
13067
  viewportRow: data.viewports[type].store,
13374
- // lastCell is the last real coordinate + 1
13068
+ /**
13069
+ * lastCell is the last real coordinate + 1, saved to selection store
13070
+ */
13375
13071
  lastCell: getLastCell(data, type),
13376
13072
  slot,
13377
13073
  type,
@@ -13419,10 +13115,9 @@ function gatherColumnData(data) {
13419
13115
  }
13420
13116
  class ViewportService {
13421
13117
  constructor(config, contentHeight) {
13422
- var _a, _b;
13423
- this.config = config;
13424
- (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.beforeUpdate();
13425
13118
  // ----------- Handle columns ----------- //
13119
+ var _a;
13120
+ this.config = config;
13426
13121
  // Transform data from stores and apply it to different components
13427
13122
  const columns = [];
13428
13123
  let x = 0; // we increase x only if column present
@@ -13463,11 +13158,10 @@ class ViewportService {
13463
13158
  // render per each column data collections vertically
13464
13159
  const dataPorts = this.dataViewPort(column).reduce((r, rgRow) => {
13465
13160
  // register selection store for Segment
13466
- const segmentSelection = this.registerSegment(rgRow.position);
13467
- segmentSelection.setLastCell(rgRow.lastCell);
13161
+ const segmentSelection = this.registerSegment(rgRow.position, rgRow.lastCell);
13468
13162
  // register selection store for Row
13469
13163
  const rowSelectionStore = this.registerRow(rgRow.position.y, rgRow.type);
13470
- const rowDef = Object.assign(Object.assign({ colType: val }, rgRow), { rowSelectionStore, selectionStore: segmentSelection.store, ref: (e) => config.selectionStoreConnector.registerSection(e), onSetrange: e => {
13164
+ const rowDef = Object.assign(Object.assign({ colType: val }, rgRow), { rowSelectionStore, selectionStore: segmentSelection.store, onSetrange: e => {
13471
13165
  segmentSelection.setRangeArea(e.detail);
13472
13166
  }, onSettemprange: e => segmentSelection.setTempArea(e.detail), onFocuscell: e => {
13473
13167
  // todo: multi focus
@@ -13483,7 +13177,7 @@ class ViewportService {
13483
13177
  });
13484
13178
  this.columns = columns;
13485
13179
  // ----------- Handle columns end ----------- //
13486
- (_b = this.config.scrollingService) === null || _b === void 0 ? void 0 : _b.unregister();
13180
+ (_a = this.config.scrollingService) === null || _a === void 0 ? void 0 : _a.unregister();
13487
13181
  }
13488
13182
  onColumnResize(type, { detail }, store) {
13489
13183
  var _a;
@@ -13501,8 +13195,10 @@ class ViewportService {
13501
13195
  this.config.resize(changedItems);
13502
13196
  }
13503
13197
  /** register selection store for Segment */
13504
- registerSegment(position) {
13505
- return this.config.selectionStoreConnector.register(position);
13198
+ registerSegment(position, lastCell) {
13199
+ const store = this.config.selectionStoreConnector.register(position);
13200
+ store.setLastCell(lastCell);
13201
+ return store;
13506
13202
  }
13507
13203
  /** register selection store for Row */
13508
13204
  registerRow(y, type) {
@@ -13522,14 +13218,10 @@ class ViewportService {
13522
13218
  // y position for selection
13523
13219
  let y = 0;
13524
13220
  return rowTypes.reduce((result, type) => {
13525
- // filter out empty sources, we still need to return source to keep slot working
13526
- const isPresent = data.viewports[type].store.get('realCount') || type === 'rgRow';
13527
- const rgCol = Object.assign(Object.assign({}, data), { position: Object.assign(Object.assign({}, data.position), { y: isPresent ? y : EMPTY_INDEX }) });
13221
+ const rgCol = Object.assign(Object.assign({}, data), { position: Object.assign(Object.assign({}, data.position), { y }) });
13528
13222
  const partition = viewportDataPartition(rgCol, type, slots[type], type !== 'rgRow');
13529
13223
  result.push(partition);
13530
- if (isPresent) {
13531
- y++;
13532
- }
13224
+ y++;
13533
13225
  return result;
13534
13226
  }, []);
13535
13227
  }
@@ -13544,162 +13236,432 @@ class ViewportService {
13544
13236
  }
13545
13237
  }
13546
13238
  }
13547
- /**
13548
- * Clear current grid focus
13549
- */
13550
- clearFocused() {
13551
- this.config.selectionStoreConnector.clearAll();
13552
- }
13553
- clearEdit() {
13554
- this.config.selectionStoreConnector.setEdit(false);
13239
+ /**
13240
+ * Clear current grid focus
13241
+ */
13242
+ clearFocused() {
13243
+ this.config.selectionStoreConnector.clearAll();
13244
+ }
13245
+ clearEdit() {
13246
+ this.config.selectionStoreConnector.setEdit(false);
13247
+ }
13248
+ /**
13249
+ * Collect focused element data
13250
+ */
13251
+ getFocused() {
13252
+ const focused = this.config.selectionStoreConnector.focusedStore;
13253
+ if (!focused) {
13254
+ return null;
13255
+ }
13256
+ // get column data
13257
+ const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x];
13258
+ const column = this.config.columnProvider.getColumn(focused.cell.x, colType);
13259
+ // get row data
13260
+ const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y];
13261
+ const model = this.config.dataProvider.getModel(focused.cell.y, rowType);
13262
+ return {
13263
+ column,
13264
+ model,
13265
+ cell: focused.cell,
13266
+ colType,
13267
+ rowType,
13268
+ };
13269
+ }
13270
+ getStoreCoordinateByType(colType, rowType) {
13271
+ const stores = this.config.selectionStoreConnector.storesByType;
13272
+ if (typeof stores[colType] === 'undefined' || typeof stores[rowType] === 'undefined') {
13273
+ return;
13274
+ }
13275
+ return {
13276
+ x: stores[colType],
13277
+ y: stores[rowType],
13278
+ };
13279
+ }
13280
+ setFocus(colType, rowType, start, end) {
13281
+ var _a;
13282
+ const coordinate = this.getStoreCoordinateByType(colType, rowType);
13283
+ if (coordinate) {
13284
+ (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.focusByCell(coordinate, start, end);
13285
+ }
13286
+ }
13287
+ getSelectedRange() {
13288
+ const focused = this.config.selectionStoreConnector.focusedStore;
13289
+ if (!focused) {
13290
+ return null;
13291
+ }
13292
+ // get column data
13293
+ const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x];
13294
+ // get row data
13295
+ const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y];
13296
+ const range = focused.entity.store.get('range');
13297
+ if (!range) {
13298
+ return null;
13299
+ }
13300
+ return Object.assign(Object.assign({}, range), { colType,
13301
+ rowType });
13302
+ }
13303
+ setEdit(rowIndex, colIndex, colType, rowType) {
13304
+ var _a;
13305
+ const coordinate = this.getStoreCoordinateByType(colType, rowType);
13306
+ if (coordinate) {
13307
+ (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.setEditByCell(coordinate, { x: colIndex, y: rowIndex });
13308
+ }
13309
+ }
13310
+ }
13311
+
13312
+ class GridScrollingService {
13313
+ constructor(setViewport) {
13314
+ this.setViewport = setViewport;
13315
+ this.elements = {};
13316
+ }
13317
+ async proxyScroll(e, key) {
13318
+ var _a;
13319
+ let newEventPromise;
13320
+ let event = e;
13321
+ for (let elKey in this.elements) {
13322
+ // skip
13323
+ if (e.dimension === 'rgCol' && elKey === 'headerRow') {
13324
+ continue;
13325
+ // pinned column only
13326
+ }
13327
+ else if (this.isPinnedColumn(key) && e.dimension === 'rgCol') {
13328
+ if (elKey === key || !e.delta) {
13329
+ continue;
13330
+ }
13331
+ for (let el of this.elements[elKey]) {
13332
+ if (el.changeScroll) {
13333
+ newEventPromise = el.changeScroll(e);
13334
+ }
13335
+ }
13336
+ }
13337
+ else {
13338
+ for (let el of this.elements[elKey]) {
13339
+ await ((_a = el.setScroll) === null || _a === void 0 ? void 0 : _a.call(el, e));
13340
+ }
13341
+ }
13342
+ }
13343
+ const newEvent = await newEventPromise;
13344
+ if (newEvent) {
13345
+ event = newEvent;
13346
+ }
13347
+ this.setViewport(event);
13348
+ }
13349
+ /**
13350
+ * Silent scroll update for mobile devices when we have negative scroll top
13351
+ */
13352
+ async scrollSilentService(e, key) {
13353
+ var _a;
13354
+ for (let elKey in this.elements) {
13355
+ // skip same element update
13356
+ if (elKey === key) {
13357
+ continue;
13358
+ }
13359
+ if (columnTypes.includes(key) &&
13360
+ (elKey === 'headerRow' ||
13361
+ columnTypes.includes(elKey))) {
13362
+ for (let el of this.elements[elKey]) {
13363
+ await ((_a = el.changeScroll) === null || _a === void 0 ? void 0 : _a.call(el, e, true));
13364
+ }
13365
+ continue;
13366
+ }
13367
+ }
13368
+ }
13369
+ isPinnedColumn(key) {
13370
+ return !!key && ['colPinStart', 'colPinEnd'].indexOf(key) > -1;
13371
+ }
13372
+ registerElements(els) {
13373
+ this.elements = els;
13374
+ }
13375
+ /**
13376
+ * Register new element for farther scroll support
13377
+ * @param el - can be null if holder removed
13378
+ * @param key - element key
13379
+ */
13380
+ registerElement(el, key) {
13381
+ if (!this.elements[key]) {
13382
+ this.elements[key] = [];
13383
+ }
13384
+ // new element added
13385
+ if (el) {
13386
+ this.elements[key].push(el);
13387
+ }
13388
+ else if (this.elements[key]) {
13389
+ // element removed
13390
+ delete this.elements[key];
13391
+ }
13392
+ }
13393
+ unregister() {
13394
+ this.elements = {};
13395
+ }
13396
+ }
13397
+
13398
+ class SelectionStoreConnector {
13399
+ constructor() {
13400
+ this.stores = {};
13401
+ this.columnStores = {};
13402
+ this.rowStores = {};
13403
+ /**
13404
+ * Helpers for data conversion
13405
+ */
13406
+ this.storesByType = {};
13407
+ this.storesXToType = {};
13408
+ this.storesYToType = {};
13409
+ }
13410
+ get focusedStore() {
13411
+ var _a;
13412
+ for (let y in this.stores) {
13413
+ for (let x in this.stores[y]) {
13414
+ const focused = (_a = this.stores[y][x]) === null || _a === void 0 ? void 0 : _a.store.get('focus');
13415
+ if (focused) {
13416
+ return {
13417
+ entity: this.stores[y][x],
13418
+ cell: focused,
13419
+ position: {
13420
+ x: parseInt(x, 10),
13421
+ y: parseInt(y, 10),
13422
+ },
13423
+ };
13424
+ }
13425
+ }
13426
+ }
13427
+ return null;
13428
+ }
13429
+ get edit() {
13430
+ var _a;
13431
+ return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('edit');
13432
+ }
13433
+ get focused() {
13434
+ var _a;
13435
+ return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('focus');
13436
+ }
13437
+ get selectedRange() {
13438
+ var _a;
13439
+ return (_a = this.focusedStore) === null || _a === void 0 ? void 0 : _a.entity.store.get('range');
13440
+ }
13441
+ registerColumn(x, type) {
13442
+ if (this.columnStores[x]) {
13443
+ return this.columnStores[x];
13444
+ }
13445
+ this.columnStores[x] = new SelectionStore();
13446
+ // build cross-linking type to position
13447
+ this.storesByType[type] = x;
13448
+ this.storesXToType[x] = type;
13449
+ return this.columnStores[x];
13450
+ }
13451
+ registerRow(y, type) {
13452
+ if (this.rowStores[y]) {
13453
+ return this.rowStores[y];
13454
+ }
13455
+ this.rowStores[y] = new SelectionStore();
13456
+ // build cross linking type to position
13457
+ this.storesByType[type] = y;
13458
+ this.storesYToType[y] = type;
13459
+ return this.rowStores[y];
13460
+ }
13461
+ /**
13462
+ * Cross store proxy, based on multiple dimensions
13463
+ */
13464
+ register({ x, y }) {
13465
+ if (!this.stores[y]) {
13466
+ this.stores[y] = {};
13467
+ }
13468
+ let store = this.stores[y][x];
13469
+ if (store) {
13470
+ // Store already registered. Do not register twice
13471
+ return store;
13472
+ }
13473
+ this.stores[y][x] = store = new SelectionStore();
13474
+ // proxy update, column store trigger only range area
13475
+ store.onChange('range', c => {
13476
+ this.columnStores[x].setRangeArea(c);
13477
+ this.rowStores[y].setRangeArea(c);
13478
+ });
13479
+ // clean up on remove
13480
+ store.store.on('dispose', () => this.destroy(x, y));
13481
+ return store;
13482
+ }
13483
+ destroy(x, y) {
13484
+ var _a, _b;
13485
+ (_a = this.columnStores[x]) === null || _a === void 0 ? void 0 : _a.dispose();
13486
+ (_b = this.rowStores[y]) === null || _b === void 0 ? void 0 : _b.dispose();
13487
+ delete this.rowStores[y];
13488
+ delete this.columnStores[x];
13489
+ // clear x cross-link
13490
+ if (this.storesXToType[x]) {
13491
+ const type = this.storesXToType[x];
13492
+ delete this.storesXToType[x];
13493
+ delete this.storesByType[type];
13494
+ }
13495
+ // clear y cross-link
13496
+ if (this.storesYToType[y]) {
13497
+ const type = this.storesYToType[y];
13498
+ delete this.storesYToType[y];
13499
+ delete this.storesByType[type];
13500
+ }
13501
+ if (this.stores[y]) {
13502
+ delete this.stores[y][x];
13503
+ }
13504
+ // clear empty rows
13505
+ if (!Object.keys(this.stores[y] || {}).length) {
13506
+ delete this.stores[y];
13507
+ }
13508
+ }
13509
+ setEditByCell(storePos, editCell) {
13510
+ this.focusByCell(storePos, editCell, editCell);
13511
+ this.setEdit('');
13555
13512
  }
13556
13513
  /**
13557
- * Collect focused element data
13514
+ * Sets the next focus cell before the current one.
13515
+ *
13516
+ * @param focus - The cell to set as the next focus.
13558
13517
  */
13559
- getFocused() {
13560
- const focused = this.config.selectionStoreConnector.focusedStore;
13561
- if (!focused) {
13562
- return null;
13563
- }
13564
- // get column data
13565
- const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x];
13566
- const column = this.config.columnProvider.getColumn(focused.cell.x, colType);
13567
- // get row data
13568
- const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y];
13569
- const model = this.config.dataProvider.getModel(focused.cell.y, rowType);
13570
- return {
13571
- column,
13572
- model,
13573
- cell: focused.cell,
13574
- colType,
13575
- rowType,
13576
- };
13577
- }
13578
- getStoreCoordinateByType(colType, rowType) {
13579
- const stores = this.config.selectionStoreConnector.storesByType;
13580
- if (typeof stores[colType] === 'undefined' || typeof stores[rowType] === 'undefined') {
13518
+ beforeNextFocusCell(focus) {
13519
+ var _a;
13520
+ // If there is no focused store, return early.
13521
+ if (!this.focusedStore) {
13581
13522
  return;
13582
13523
  }
13583
- return {
13584
- x: stores[colType],
13585
- y: stores[rowType],
13586
- };
13524
+ // Get the next store based on the current focus and the last cell.
13525
+ const lastCell = this.focusedStore.entity.store.get('lastCell');
13526
+ const next = lastCell && this.getNextStore(focus, this.focusedStore.position, lastCell);
13527
+ // Set the next focus cell in the store.
13528
+ (_a = next === null || next === void 0 ? void 0 : next.store) === null || _a === void 0 ? void 0 : _a.setNextFocus(Object.assign(Object.assign({}, focus), next.item));
13587
13529
  }
13588
- setFocus(colType, rowType, start, end) {
13589
- var _a;
13590
- const coordinate = this.getStoreCoordinateByType(colType, rowType);
13591
- if (coordinate) {
13592
- (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.focusByCell(coordinate, start, end);
13593
- }
13530
+ focusByCell(storePos, start, end) {
13531
+ const store = this.stores[storePos.y][storePos.x];
13532
+ this.focus(store, { focus: start, end });
13594
13533
  }
13595
- getSelectedRange() {
13596
- const focused = this.config.selectionStoreConnector.focusedStore;
13597
- if (!focused) {
13534
+ focus(store, { focus, end }) {
13535
+ const currentStorePointer = this.getCurrentStorePointer(store);
13536
+ if (!currentStorePointer) {
13598
13537
  return null;
13599
13538
  }
13600
- // get column data
13601
- const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x];
13602
- // get row data
13603
- const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y];
13604
- const range = focused.entity.store.get('range');
13605
- if (!range) {
13539
+ // check for the focus in nearby store/viewport
13540
+ const lastCell = store.store.get('lastCell');
13541
+ const next = lastCell && this.getNextStore(focus, currentStorePointer, lastCell);
13542
+ // if next store present - update
13543
+ if (next === null || next === void 0 ? void 0 : next.store) {
13544
+ const item = Object.assign(Object.assign({}, focus), next.item);
13545
+ this.focus(next.store, { focus: item, end: item });
13606
13546
  return null;
13607
13547
  }
13608
- return Object.assign(Object.assign({}, range), { colType,
13609
- rowType });
13610
- }
13611
- setEdit(rowIndex, colIndex, colType, rowType) {
13612
- var _a;
13613
- const coordinate = this.getStoreCoordinateByType(colType, rowType);
13614
- if (coordinate) {
13615
- (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.setEditByCell(coordinate, { x: colIndex, y: rowIndex });
13548
+ if (lastCell) {
13549
+ focus = cropCellToMax(focus, lastCell);
13550
+ end = cropCellToMax(end, lastCell);
13616
13551
  }
13552
+ store.setFocus(focus, end);
13553
+ return focus;
13617
13554
  }
13618
- }
13619
-
13620
- class GridScrollingService {
13621
- constructor(setViewport) {
13622
- this.setViewport = setViewport;
13623
- this.elements = {};
13624
- }
13625
- async proxyScroll(e, key) {
13626
- var _a;
13627
- let newEventPromise;
13628
- let event = e;
13629
- for (let elKey in this.elements) {
13630
- // skip
13631
- if (e.dimension === 'rgCol' && elKey === 'headerRow') {
13632
- continue;
13633
- // pinned column only
13634
- }
13635
- else if (this.isPinnedColumn(key) && e.dimension === 'rgCol') {
13636
- if (elKey === key || !e.delta) {
13637
- continue;
13638
- }
13639
- for (let el of this.elements[elKey]) {
13640
- if (el.changeScroll) {
13641
- newEventPromise = el.changeScroll(e);
13642
- }
13555
+ /**
13556
+ * Retrieves the current store pointer based on the active store.
13557
+ * Clears focus from all stores except the active one.
13558
+ */
13559
+ getCurrentStorePointer(store) {
13560
+ let currentStorePointer;
13561
+ // Iterate through all stores
13562
+ for (let y in this.stores) {
13563
+ for (let x in this.stores[y]) {
13564
+ const s = this.stores[y][x];
13565
+ // Clear focus from stores other than the active one
13566
+ if (s !== store) {
13567
+ s.clearFocus();
13643
13568
  }
13644
- }
13645
- else {
13646
- for (let el of this.elements[elKey]) {
13647
- await ((_a = el.setScroll) === null || _a === void 0 ? void 0 : _a.call(el, e));
13569
+ else {
13570
+ // Update the current store pointer with the active store coordinates
13571
+ currentStorePointer = {
13572
+ x: parseInt(x, 10),
13573
+ y: parseInt(y, 10)
13574
+ };
13648
13575
  }
13649
13576
  }
13650
13577
  }
13651
- const newEvent = await newEventPromise;
13652
- if (newEvent) {
13653
- event = newEvent;
13654
- }
13655
- this.setViewport(event);
13578
+ return currentStorePointer;
13656
13579
  }
13657
13580
  /**
13658
- * Silent scroll update for mobile devices when we have negative scroll top
13581
+ * Retrieves the next store based on the focus cell and current store pointer.
13582
+ * If the next store exists, returns an object with the next store and the item in the new store.
13583
+ * If the next store does not exist, returns null.
13659
13584
  */
13660
- async scrollSilentService(e, key) {
13661
- var _a;
13662
- for (let elKey in this.elements) {
13663
- // skip same element update
13664
- if (elKey === key) {
13665
- continue;
13666
- }
13667
- if (columnTypes.includes(key) &&
13668
- (elKey === 'headerRow' ||
13669
- columnTypes.includes(elKey))) {
13670
- for (let el of this.elements[elKey]) {
13671
- await ((_a = el.changeScroll) === null || _a === void 0 ? void 0 : _a.call(el, e, true));
13585
+ getNextStore(focus, currentStorePointer, lastCell) {
13586
+ // item in new store
13587
+ const nextItem = nextCell(focus, lastCell);
13588
+ let nextStore;
13589
+ if (nextItem) {
13590
+ Object.entries(nextItem).forEach(([type, nextItemCoord]) => {
13591
+ let stores;
13592
+ switch (type) {
13593
+ case 'x':
13594
+ // Get the X stores for the current Y coordinate of the current store pointer
13595
+ stores = this.getXStores(currentStorePointer.y);
13596
+ break;
13597
+ case 'y':
13598
+ // Get the Y stores for the current X coordinate of the current store pointer
13599
+ stores = this.getYStores(currentStorePointer.x);
13600
+ break;
13672
13601
  }
13673
- continue;
13674
- }
13602
+ // Get the next store based on the item in the new store
13603
+ if (nextItemCoord >= 0) {
13604
+ nextStore = stores[++currentStorePointer[type]];
13605
+ }
13606
+ else {
13607
+ nextStore = stores[--currentStorePointer[type]];
13608
+ const nextLastCell = nextStore === null || nextStore === void 0 ? void 0 : nextStore.store.get('lastCell');
13609
+ if (nextLastCell) {
13610
+ nextItem[type] = nextLastCell[type] + nextItemCoord;
13611
+ }
13612
+ }
13613
+ });
13614
+ }
13615
+ // if last cell is empty store is empty, no next store
13616
+ const lastCellNext = nextStore === null || nextStore === void 0 ? void 0 : nextStore.store.get('lastCell');
13617
+ if (!(lastCellNext === null || lastCellNext === void 0 ? void 0 : lastCellNext.x) || !(lastCellNext === null || lastCellNext === void 0 ? void 0 : lastCellNext.y)) {
13618
+ nextStore = undefined;
13675
13619
  }
13620
+ return {
13621
+ store: nextStore,
13622
+ item: nextItem,
13623
+ };
13676
13624
  }
13677
- isPinnedColumn(key) {
13678
- return !!key && ['colPinStart', 'colPinEnd'].indexOf(key) > -1;
13625
+ clearAll() {
13626
+ var _a;
13627
+ for (let y in this.stores) {
13628
+ for (let x in this.stores[y]) {
13629
+ (_a = this.stores[y][x]) === null || _a === void 0 ? void 0 : _a.clearFocus();
13630
+ }
13631
+ }
13679
13632
  }
13680
- registerElements(els) {
13681
- this.elements = els;
13633
+ setEdit(val) {
13634
+ if (!this.focusedStore) {
13635
+ return;
13636
+ }
13637
+ this.focusedStore.entity.setEdit(val);
13682
13638
  }
13683
13639
  /**
13684
- * Register new element for farther scroll support
13685
- * @param el - can be null if holder removed
13686
- * @param key - element key
13640
+ * Select all cells across all stores
13687
13641
  */
13688
- registerElement(el, key) {
13689
- if (!this.elements[key]) {
13690
- this.elements[key] = [];
13691
- }
13692
- // new element added
13693
- if (el) {
13694
- this.elements[key].push(el);
13695
- }
13696
- else if (this.elements[key]) {
13697
- // element removed
13698
- delete this.elements[key];
13642
+ selectAll() {
13643
+ for (let y in this.stores) {
13644
+ for (let x in this.stores[y]) {
13645
+ const store = this.stores[y][x];
13646
+ if (!store) {
13647
+ continue;
13648
+ }
13649
+ const lastCell = store.store.get('lastCell');
13650
+ if (lastCell) {
13651
+ store.setRange({ x: 0, y: 0 }, { x: lastCell.x - 1, y: lastCell.y - 1 });
13652
+ }
13653
+ }
13699
13654
  }
13700
13655
  }
13701
- unregister() {
13702
- this.elements = {};
13656
+ getXStores(y) {
13657
+ return this.stores[y];
13658
+ }
13659
+ getYStores(x) {
13660
+ const stores = {};
13661
+ for (let i in this.stores) {
13662
+ stores[i] = this.stores[i][x];
13663
+ }
13664
+ return stores;
13703
13665
  }
13704
13666
  }
13705
13667
 
@@ -16619,7 +16581,7 @@ const HeaderGroupRenderer = (p) => {
16619
16581
  return (hAsync(HeaderCellRenderer, { data: Object.assign(Object.assign({}, p.group), { prop: '', providers: p.providers, index: p.start }), props: groupProps, additionalData: p.additionalData }));
16620
16582
  };
16621
16583
 
16622
- const revogrHeaderStyleCss = "@charset \"UTF-8\";revogr-header{position:relative;z-index:5;display:block}revogr-header .rgHeaderCell{display:flex}revogr-header .rgHeaderCell.align-center{text-align:center}revogr-header .rgHeaderCell.align-left{text-align:left}revogr-header .rgHeaderCell.align-right{text-align:right}revogr-header .rgHeaderCell.sortable{cursor:pointer}revogr-header .rgHeaderCell i.asc:after,revogr-header .rgHeaderCell i.desc:after{font-size:13px}revogr-header .rgHeaderCell i.asc:after{content:\"↑\"}revogr-header .rgHeaderCell i.desc:after{content:\"↓\"}revogr-header .rgHeaderCell,revogr-header .grouped-cell{position:absolute;box-sizing:border-box;height:100%;z-index:1}revogr-header .header-rgRow{display:block;position:relative}revogr-header .header-rgRow.group{z-index:0}revogr-header .group-rgRow{position:relative}revogr-header .rgHeaderCell.active{z-index:10}revogr-header .rgHeaderCell.active .resizable{background-color:deepskyblue}revogr-header .rgHeaderCell .header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-grow:1}revogr-header .rgHeaderCell .resizable{display:block;position:absolute;z-index:90;touch-action:none;user-select:none}revogr-header .rgHeaderCell .resizable:hover{background-color:deepskyblue}revogr-header .rgHeaderCell>.resizable-r{cursor:ew-resize;width:6px;right:0;top:0;height:100%}revogr-header .rgHeaderCell>.resizable-rb{cursor:se-resize;width:6px;height:6px;right:0;bottom:0}revogr-header .rgHeaderCell>.resizable-b{cursor:s-resize;height:6px;bottom:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-lb{cursor:sw-resize;width:6px;height:6px;left:0;bottom:0}revogr-header .rgHeaderCell>.resizable-l{cursor:w-resize;width:6px;left:0;height:100%;top:0}revogr-header .rgHeaderCell>.resizable-lt{cursor:nw-resize;width:6px;height:6px;left:0;top:0}revogr-header .rgHeaderCell>.resizable-t{cursor:n-resize;height:6px;top:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-rt{cursor:ne-resize;width:6px;height:6px;right:0;top:0}revogr-header .rv-filter{visibility:hidden}";
16584
+ const revogrHeaderStyleCss = "@charset \"UTF-8\";revogr-header{position:relative;z-index:5;display:block}revogr-header .header-rgRow{display:block;position:relative}revogr-header .header-rgRow.group{z-index:0}revogr-header .group-rgRow{position:relative;overflow:hidden}revogr-header .rgHeaderCell{position:absolute;box-sizing:border-box;height:100%;z-index:1;display:flex}revogr-header .rgHeaderCell.align-center{text-align:center}revogr-header .rgHeaderCell.align-left{text-align:left}revogr-header .rgHeaderCell.align-right{text-align:right}revogr-header .rgHeaderCell.sortable{cursor:pointer}revogr-header .rgHeaderCell i.asc:after,revogr-header .rgHeaderCell i.desc:after{font-size:13px}revogr-header .rgHeaderCell i.asc:after{content:\"↑\"}revogr-header .rgHeaderCell i.desc:after{content:\"↓\"}revogr-header .rgHeaderCell.active{z-index:10}revogr-header .rgHeaderCell.active .resizable{background-color:deepskyblue}revogr-header .rgHeaderCell .header-content{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-grow:1}revogr-header .rgHeaderCell .resizable{display:block;position:absolute;z-index:90;touch-action:none;user-select:none}revogr-header .rgHeaderCell .resizable:hover{background-color:deepskyblue}revogr-header .rgHeaderCell>.resizable-r{cursor:ew-resize;width:6px;right:0;top:0;height:100%}revogr-header .rgHeaderCell>.resizable-rb{cursor:se-resize;width:6px;height:6px;right:0;bottom:0}revogr-header .rgHeaderCell>.resizable-b{cursor:s-resize;height:6px;bottom:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-lb{cursor:sw-resize;width:6px;height:6px;left:0;bottom:0}revogr-header .rgHeaderCell>.resizable-l{cursor:w-resize;width:6px;left:0;height:100%;top:0}revogr-header .rgHeaderCell>.resizable-lt{cursor:nw-resize;width:6px;height:6px;left:0;top:0}revogr-header .rgHeaderCell>.resizable-t{cursor:n-resize;height:6px;top:0;width:100%;left:0}revogr-header .rgHeaderCell>.resizable-rt{cursor:ne-resize;width:6px;height:6px;right:0;top:0}revogr-header .rv-filter{visibility:hidden}";
16623
16585
 
16624
16586
  class RevogrHeaderComponent {
16625
16587
  constructor(hostRef) {