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