@revolist/revogrid 4.14.7 → 4.14.8

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 (56) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/revo-grid.cjs.entry.js +3 -1
  3. package/dist/cjs/revo-grid.cjs.entry.js.map +1 -1
  4. package/dist/cjs/revo-grid.cjs.js +1 -1
  5. package/dist/cjs/revogr-attribution_7.cjs.entry.js +27 -48
  6. package/dist/cjs/revogr-attribution_7.cjs.entry.js.map +1 -1
  7. package/dist/cjs/revogr-data_4.cjs.entry.js +28 -12
  8. package/dist/cjs/revogr-data_4.cjs.entry.js.map +1 -1
  9. package/dist/cjs/{throttle-250327e5.js → throttle-c7ae5154.js} +46 -7
  10. package/dist/cjs/throttle-c7ae5154.js.map +1 -0
  11. package/dist/collection/components/revoGrid/revo-grid.js +3 -1
  12. package/dist/collection/components/revoGrid/revo-grid.js.map +1 -1
  13. package/dist/collection/components/revoGrid/viewport.resize.service.js +4 -1
  14. package/dist/collection/components/revoGrid/viewport.resize.service.js.map +1 -1
  15. package/dist/collection/components/scroll/revogr-viewport-scroll.js +23 -10
  16. package/dist/collection/components/scroll/revogr-viewport-scroll.js.map +1 -1
  17. package/dist/collection/components/scrollable/revogr-scroll-virtual.js +63 -83
  18. package/dist/collection/components/scrollable/revogr-scroll-virtual.js.map +1 -1
  19. package/dist/collection/services/local.scroll.timer.js +45 -6
  20. package/dist/collection/services/local.scroll.timer.js.map +1 -1
  21. package/dist/esm/loader.js +1 -1
  22. package/dist/esm/revo-grid.entry.js +3 -1
  23. package/dist/esm/revo-grid.entry.js.map +1 -1
  24. package/dist/esm/revo-grid.js +1 -1
  25. package/dist/esm/revogr-attribution_7.entry.js +27 -48
  26. package/dist/esm/revogr-attribution_7.entry.js.map +1 -1
  27. package/dist/esm/revogr-data_4.entry.js +28 -12
  28. package/dist/esm/revogr-data_4.entry.js.map +1 -1
  29. package/dist/{revo-grid/throttle-9dcf4e1f.js → esm/throttle-7c83ca69.js} +46 -7
  30. package/dist/esm/throttle-7c83ca69.js.map +1 -0
  31. package/dist/revo-grid/revo-grid.entry.js +3 -1
  32. package/dist/revo-grid/revo-grid.entry.js.map +1 -1
  33. package/dist/revo-grid/revo-grid.esm.js +1 -1
  34. package/dist/revo-grid/revogr-attribution_7.entry.js +27 -48
  35. package/dist/revo-grid/revogr-attribution_7.entry.js.map +1 -1
  36. package/dist/revo-grid/revogr-data_4.entry.js +28 -12
  37. package/dist/revo-grid/revogr-data_4.entry.js.map +1 -1
  38. package/dist/{esm/throttle-9dcf4e1f.js → revo-grid/throttle-7c83ca69.js} +46 -7
  39. package/dist/revo-grid/throttle-7c83ca69.js.map +1 -0
  40. package/dist/types/components/scrollable/revogr-scroll-virtual.d.ts +9 -8
  41. package/dist/types/components.d.ts +17 -9
  42. package/dist/types/services/local.scroll.timer.d.ts +7 -1
  43. package/hydrate/index.js +104 -67
  44. package/hydrate/index.mjs +104 -67
  45. package/package.json +1 -1
  46. package/standalone/local.scroll.timer.js +45 -6
  47. package/standalone/local.scroll.timer.js.map +1 -1
  48. package/standalone/revo-grid.js +3 -1
  49. package/standalone/revo-grid.js.map +1 -1
  50. package/standalone/revogr-scroll-virtual2.js +29 -49
  51. package/standalone/revogr-scroll-virtual2.js.map +1 -1
  52. package/standalone/revogr-viewport-scroll2.js +27 -11
  53. package/standalone/revogr-viewport-scroll2.js.map +1 -1
  54. package/dist/cjs/throttle-250327e5.js.map +0 -1
  55. package/dist/esm/throttle-9dcf4e1f.js.map +0 -1
  56. package/dist/revo-grid/throttle-9dcf4e1f.js.map +0 -1
package/hydrate/index.mjs CHANGED
@@ -15187,12 +15187,14 @@ class RevoGridComponent {
15187
15187
  const typeCol = 'rgCol';
15188
15188
  const viewports = this.viewportProvider.stores;
15189
15189
  const dimensions = this.dimensionProvider.stores;
15190
+ const verticalScroll = (hAsync("revogr-scroll-virtual", { class: "vertical", dimension: typeRow, clientSize: viewports[typeRow].store.get('clientSize'), virtualSize: viewports[typeRow].store.get('virtualSize'), realSize: dimensions[typeRow].store.get('realSize'), ref: el => this.scrollingService.registerElement(el, 'rowScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }));
15191
+ const horizontalScroll = (hAsync("revogr-scroll-virtual", { class: "horizontal", dimension: typeCol, clientSize: viewports[typeCol].store.get('clientSize'), virtualSize: viewports[typeCol].store.get('virtualSize'), realSize: dimensions[typeCol].store.get('realSize'), ref: el => this.scrollingService.registerElement(el, 'colScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }));
15190
15192
  return (hAsync(Host, null, this.hideAttribution ? null : (hAsync("revogr-attribution", { class: "attribution" })), hAsync("slot", { name: "header" }), hAsync("div", { class: "main-viewport", onClick: (e) => {
15191
15193
  var _a;
15192
15194
  if (e.currentTarget === e.target) {
15193
15195
  (_a = this.viewport) === null || _a === void 0 ? void 0 : _a.clearEdit();
15194
15196
  }
15195
- } }, hAsync("div", { class: "viewports" }, hAsync("slot", { name: "viewport" }), viewportSections, hAsync("revogr-scroll-virtual", { class: "vertical", dimension: typeRow, viewportStore: viewports[typeRow].store, dimensionStore: dimensions[typeRow].store, ref: el => this.scrollingService.registerElement(el, 'rowScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }), hAsync(OrderRenderer, { ref: e => (this.orderService = e) }))), hAsync("revogr-scroll-virtual", { class: "horizontal", dimension: typeCol, viewportStore: viewports[typeCol].store, dimensionStore: dimensions[typeCol].store, ref: el => this.scrollingService.registerElement(el, 'colScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }), hAsync("revogr-extra", { ref: el => (this.extraService = el), nodes: this.extraElements }), hAsync("slot", { name: "footer" })));
15197
+ } }, hAsync("div", { class: "viewports" }, hAsync("slot", { name: "viewport" }), viewportSections, verticalScroll, hAsync(OrderRenderer, { ref: e => (this.orderService = e) }))), horizontalScroll, hAsync("revogr-extra", { ref: el => (this.extraService = el), nodes: this.extraElements }), hAsync("slot", { name: "footer" })));
15196
15198
  }
15197
15199
  disconnectedCallback() {
15198
15200
  // Remove all plugins, to avoid memory leaks
@@ -16538,6 +16540,12 @@ class LocalScrollTimer {
16538
16540
  rgCol: 0,
16539
16541
  rgRow: 0,
16540
16542
  };
16543
+ /**
16544
+ * Check if scroll is ready to accept new value
16545
+ * this is an edge case for scroll events
16546
+ * when we need to apply scroll after throttling
16547
+ */
16548
+ this.lastScrollUpdateCallbacks = {};
16541
16549
  }
16542
16550
  setCoordinate(e) {
16543
16551
  this.lastKnownScrollCoordinate[e.dimension] = e.coordinate;
@@ -16548,14 +16556,47 @@ class LocalScrollTimer {
16548
16556
  latestScrollUpdate(dimension) {
16549
16557
  this.mouseWheelScrollTimestamp[dimension] = new Date().getTime();
16550
16558
  }
16551
- /**
16552
- * Check if scroll is ready to accept new value
16553
- */
16554
16559
  isReady(type, coordinate) {
16555
- const change = new Date().getTime() - this.mouseWheelScrollTimestamp[type];
16560
+ // if there is a callback, clear it
16561
+ if (this.lastScrollUpdateCallbacks[type]) {
16562
+ this.clearLastScrollUpdate(type);
16563
+ }
16556
16564
  // apply after throttling
16557
- return (change > this.scrollThrottling &&
16558
- coordinate !== this.lastKnownScrollCoordinate[type]);
16565
+ return this.verifyChange(type, coordinate);
16566
+ }
16567
+ verifyChange(type, coordinate) {
16568
+ const now = new Date().getTime();
16569
+ const change = now - this.mouseWheelScrollTimestamp[type];
16570
+ return change > this.scrollThrottling &&
16571
+ coordinate !== this.lastKnownScrollCoordinate[type];
16572
+ }
16573
+ clearLastScrollUpdate(type) {
16574
+ var _a, _b;
16575
+ clearTimeout((_b = (_a = this.lastScrollUpdateCallbacks[type]) === null || _a === void 0 ? void 0 : _a.timeout) !== null && _b !== void 0 ? _b : 0);
16576
+ delete this.lastScrollUpdateCallbacks[type];
16577
+ }
16578
+ throttleLastScrollUpdate(type, coordinate, lastScrollUpdate) {
16579
+ // if scrollThrottling is set
16580
+ // we need to throttle the last scroll event
16581
+ if (this.scrollThrottling) {
16582
+ this.clearLastScrollUpdate(type);
16583
+ // save lastScrollUpdate callback
16584
+ const callback = this.lastScrollUpdateCallbacks[type] = {
16585
+ callback: lastScrollUpdate,
16586
+ timestamp: new Date().getTime(),
16587
+ coordinate,
16588
+ timeout: 0,
16589
+ };
16590
+ callback.timeout = setTimeout(() => {
16591
+ // clear timeout
16592
+ this.clearLastScrollUpdate(type);
16593
+ // if scrollThrottling is set, and the last scroll event happened before the timeout started
16594
+ // we need to throttle the last scroll event
16595
+ if (this.mouseWheelScrollTimestamp[type] < callback.timestamp && this.verifyChange(type, callback.coordinate)) {
16596
+ callback.callback();
16597
+ }
16598
+ }, this.scrollThrottling + 50);
16599
+ }
16559
16600
  }
16560
16601
  }
16561
16602
 
@@ -16571,8 +16612,9 @@ class RevogrScrollVirtual {
16571
16612
  this.scrollVirtual = createEvent(this, "scrollvirtual", 7);
16572
16613
  this.scrollSize = 0;
16573
16614
  this.dimension = 'rgRow';
16574
- this.viewportStore = undefined;
16575
- this.dimensionStore = undefined;
16615
+ this.realSize = undefined;
16616
+ this.virtualSize = undefined;
16617
+ this.clientSize = undefined;
16576
16618
  }
16577
16619
  async setScroll(e) {
16578
16620
  var _a;
@@ -16584,8 +16626,8 @@ class RevogrScrollVirtual {
16584
16626
  if (e.coordinate) {
16585
16627
  this.autohideScrollPlugin.checkScroll({
16586
16628
  scrollSize: this.scrollSize,
16587
- contentSize: this.dimensionStore.get('realSize'),
16588
- virtualSize: this.viewportStore.get('virtualSize'),
16629
+ contentSize: this.realSize,
16630
+ virtualSize: this.virtualSize,
16589
16631
  });
16590
16632
  }
16591
16633
  }
@@ -16606,20 +16648,6 @@ class RevogrScrollVirtual {
16606
16648
  }
16607
16649
  return e;
16608
16650
  }
16609
- set size(s) {
16610
- this.autohideScrollPlugin.setScrollSize(s);
16611
- if (this.dimension === 'rgRow') {
16612
- this.element.style.minWidth = `${s}px`;
16613
- return;
16614
- }
16615
- this.element.style.minHeight = `${s}px`;
16616
- }
16617
- get size() {
16618
- if (this.dimension === 'rgRow') {
16619
- return this.element.clientHeight;
16620
- }
16621
- return this.element.clientWidth;
16622
- }
16623
16651
  connectedCallback() {
16624
16652
  this.autohideScrollPlugin = new AutohideScrollPlugin(this.element);
16625
16653
  this.localScrollTimer = new LocalScrollTimer('ontouchstart' in document.documentElement ? 0 : 10);
@@ -16640,37 +16668,23 @@ class RevogrScrollVirtual {
16640
16668
  this.scrollSize = getScrollbarSize(document);
16641
16669
  }
16642
16670
  componentDidRender() {
16643
- const type = this.dimension === 'rgRow' ? 'scrollHeight' : 'scrollWidth';
16644
- // Get scrollbar size once during component initialization
16645
- const scrollbarSize = this.scrollSize;
16646
- // Calculate if content exceeds viewport size
16647
- // Add scrollbar size to the comparison to account for other dimension's scrollbar
16648
- const hasScroll = this.element[type] > this.size + scrollbarSize;
16649
- // Set scroll size based on whether scroll is needed
16650
- this.size = hasScroll ? this.scrollSize : 0;
16651
- let additionalScrollbarSize = 0;
16671
+ let scrollSize = 0;
16652
16672
  if (this.dimension === 'rgRow') {
16653
- additionalScrollbarSize =
16654
- this.element.scrollWidth > this.element.clientWidth
16655
- ? scrollbarSize
16656
- : 0;
16673
+ scrollSize = this.element.scrollHeight > this.element.clientHeight ? this.scrollSize : 0;
16674
+ this.element.style.minWidth = `${scrollSize}px`;
16657
16675
  }
16658
16676
  else {
16659
- additionalScrollbarSize =
16660
- this.element.scrollHeight > this.element.clientHeight
16661
- ? scrollbarSize
16662
- : 0;
16677
+ scrollSize = this.element.scrollWidth > this.element.clientWidth ? this.scrollSize : 0;
16678
+ this.element.style.minHeight = `${scrollSize}px`;
16663
16679
  }
16664
- const clientSize = this.size + additionalScrollbarSize;
16680
+ this.autohideScrollPlugin.setScrollSize(scrollSize);
16665
16681
  this.localScrollService.setParams({
16666
- contentSize: this.dimensionStore.get('realSize'),
16667
- // Add scrollbar size to clientSize if other dimension has scroll
16668
- clientSize,
16669
- virtualSize: this.viewportStore.get('clientSize'),
16682
+ contentSize: this.realSize,
16683
+ clientSize: this.dimension === 'rgRow' ? this.element.clientHeight : this.element.clientWidth,
16684
+ virtualSize: this.clientSize,
16670
16685
  }, this.dimension);
16671
16686
  }
16672
16687
  onScroll(e) {
16673
- var _a;
16674
16688
  if (!(e.target instanceof Element)) {
16675
16689
  return;
16676
16690
  }
@@ -16679,16 +16693,22 @@ class RevogrScrollVirtual {
16679
16693
  if (this.dimension === 'rgRow') {
16680
16694
  type = 'scrollTop';
16681
16695
  }
16682
- // apply after throttling
16683
- if (this.localScrollTimer.isReady(this.dimension, target[type] || 0)) {
16696
+ const setScroll = () => {
16697
+ var _a;
16684
16698
  (_a = this.localScrollService) === null || _a === void 0 ? void 0 : _a.scroll(target[type] || 0, this.dimension);
16699
+ };
16700
+ // apply after throttling
16701
+ if (this.localScrollTimer.isReady(this.dimension, target[type])) {
16702
+ setScroll();
16703
+ }
16704
+ else {
16705
+ this.localScrollTimer.throttleLastScrollUpdate(this.dimension, target[type] || 0, () => setScroll());
16685
16706
  }
16686
16707
  }
16687
16708
  render() {
16688
- const sizeType = this.dimension === 'rgRow' ? 'height' : 'width';
16689
- const size = getContentSize(this.dimensionStore.get('realSize'), this.size, this.viewportStore.get('clientSize'));
16690
- return (hAsync(Host, { key: '94ccf82880ca9a3b0b1a87e94553f3c6ea6e885a', onScroll: (e) => this.onScroll(e) }, hAsync("div", { key: '3518b4db297114195e4ef9bd3555d08bae08daa9', style: {
16691
- [sizeType]: `${size}px`,
16709
+ const size = getContentSize(this.realSize, this.dimension === 'rgRow' ? this.element.clientHeight : this.element.clientWidth, this.clientSize);
16710
+ return (hAsync(Host, { key: '57f81ec9deb2395e96b283338c03b9ad44f1e929', onScroll: (e) => this.onScroll(e) }, hAsync("div", { key: '1a8c869adab53b362c351dae8d53664f33c4212c', style: {
16711
+ [this.dimension === 'rgRow' ? 'height' : 'width']: `${size}px`,
16692
16712
  } })));
16693
16713
  }
16694
16714
  get element() { return getElement(this); }
@@ -16698,8 +16718,9 @@ class RevogrScrollVirtual {
16698
16718
  "$tagName$": "revogr-scroll-virtual",
16699
16719
  "$members$": {
16700
16720
  "dimension": [1],
16701
- "viewportStore": [16],
16702
- "dimensionStore": [16],
16721
+ "realSize": [2, "real-size"],
16722
+ "virtualSize": [2, "virtual-size"],
16723
+ "clientSize": [2, "client-size"],
16703
16724
  "setScroll": [64],
16704
16725
  "changeScroll": [64]
16705
16726
  },
@@ -16735,7 +16756,10 @@ class GridResizeService {
16735
16756
  };
16736
16757
  (_a = this.resize) === null || _a === void 0 ? void 0 : _a.call(this, entry, this.previousSize);
16737
16758
  this.previousSize = entry;
16738
- }, 10);
16759
+ }, 40, {
16760
+ leading: false,
16761
+ trailing: true,
16762
+ });
16739
16763
  this.init(el);
16740
16764
  }
16741
16765
  async init(el) {
@@ -16866,30 +16890,37 @@ class RevogrViewportScroll {
16866
16890
  this.resizeService = new GridResizeService(this.horizontalScroll, (entry, previousSize) => {
16867
16891
  var _a, _b, _c, _d, _e, _f, _g, _h;
16868
16892
  const els = {};
16893
+ let calculatedHeight = 0;
16869
16894
  if (entry.height !== previousSize.height) {
16870
- let height = entry.height || 0;
16871
- if (height) {
16872
- height -=
16895
+ calculatedHeight = entry.height || 0;
16896
+ if (calculatedHeight) {
16897
+ calculatedHeight -=
16873
16898
  ((_b = (_a = this.header) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0) +
16874
16899
  ((_d = (_c = this.footer) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 0);
16875
16900
  }
16876
16901
  els.rgRow = {
16877
- size: height,
16902
+ size: calculatedHeight,
16878
16903
  contentSize: this.contentHeight,
16879
16904
  scroll: (_f = (_e = this.verticalScroll) === null || _e === void 0 ? void 0 : _e.scrollTop) !== null && _f !== void 0 ? _f : 0,
16880
16905
  noScroll: false,
16881
16906
  };
16882
16907
  }
16908
+ let calculatedWidth = 0;
16883
16909
  if (entry.width !== previousSize.width) {
16910
+ calculatedWidth = entry.width || 0;
16884
16911
  els.rgCol = {
16885
- size: entry.width || 0,
16912
+ size: calculatedWidth,
16886
16913
  contentSize: this.contentWidth,
16887
16914
  scroll: this.horizontalScroll.scrollLeft,
16888
16915
  noScroll: this.colType !== 'rgCol',
16889
16916
  };
16890
16917
  }
16891
- for (const [dim, item] of Object.entries(els)) {
16892
- const dimension = dim;
16918
+ // Process changes in order: width first, then height
16919
+ const dimensions = ['rgCol', 'rgRow'];
16920
+ for (const dimension of dimensions) {
16921
+ const item = els[dimension];
16922
+ if (!item)
16923
+ continue;
16893
16924
  this.resizeViewport.emit({
16894
16925
  dimension,
16895
16926
  size: item.size,
@@ -16954,7 +16985,7 @@ class RevogrViewportScroll {
16954
16985
  this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
16955
16986
  }
16956
16987
  render() {
16957
- return (hAsync(Host, { key: 'c8c94171231164105fad7a6f53743db615dc123a', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: 'd33774605170a5ba43e41e3d3133130eeda1a6fb', class: "inner-content-table", style: { width: `${this.contentWidth}px` } }, hAsync("div", { key: '3cf14b0fd2fce937f5f28b205fbd2402d0de3cb4', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '14ce896ee001c614553744c2e4d8d680bf4e6d15', name: HEADER_SLOT })), hAsync("div", { key: '46b937e0fc75a71f983b739e0c8179c2dc8115ac', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: 'cf775690b0eef973f205659973ea23e376bc64d6', class: "content-wrapper", style: { height: `${this.contentHeight}px` } }, hAsync("slot", { key: '63b50bb02edda40839829e7b54825953d3634906', name: CONTENT_SLOT }))), hAsync("div", { key: 'c28e2f9d0524a8d0adc86d6a7d78b1ce15831edd', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: 'bd24b24482d201ad91c279d09f3bcc0f2bc58370', name: FOOTER_SLOT })))));
16988
+ return (hAsync(Host, { key: '08e10c135ea0a9089463ae5d81a4a7dc7f9c028c', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: '2ff353b190f088a005f0fca3ad3eddf9f6728734', class: "inner-content-table", style: { width: `${this.contentWidth}px` } }, hAsync("div", { key: '17d95d8baa8cef75f2b2373d283948b62b891fb3', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: 'cd8606829aaccbb2edad9a2dbe03600284f0af86', name: HEADER_SLOT })), hAsync("div", { key: '77ffa873bb313a8940ef0032f938ce66e8e83e10', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: 'cbf25a96eb5e71eed34f68ec341a8758e0bf213c', class: "content-wrapper", style: { height: `${this.contentHeight}px` } }, hAsync("slot", { key: '5818ff4be234171f0759fcadf70e0bed6fd74f31', name: CONTENT_SLOT }))), hAsync("div", { key: '7ab569e4451fb381f48cc4e03b103866a47b35b6', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: 'ce1860fa42d6661dd78fe1609cf50ed93da0c5f7', name: FOOTER_SLOT })))));
16958
16989
  }
16959
16990
  /**
16960
16991
  * Extra layer for scroll event monitoring, where MouseWheel event is not passing
@@ -16984,10 +17015,16 @@ class RevogrViewportScroll {
16984
17015
  * Applies change on scroll event only if mousewheel event happened some time ago
16985
17016
  */
16986
17017
  applyOnScroll(type, coordinate, outside = false) {
16987
- var _a;
17018
+ const lastScrollUpdate = () => {
17019
+ var _a;
17020
+ (_a = this.localScrollService) === null || _a === void 0 ? void 0 : _a.scroll(coordinate, type, undefined, undefined, outside);
17021
+ };
16988
17022
  // apply after throttling
16989
17023
  if (this.localScrollTimer.isReady(type, coordinate)) {
16990
- (_a = this.localScrollService) === null || _a === void 0 ? void 0 : _a.scroll(coordinate, type, undefined, undefined, outside);
17024
+ lastScrollUpdate();
17025
+ }
17026
+ else {
17027
+ this.localScrollTimer.throttleLastScrollUpdate(type, coordinate, () => lastScrollUpdate());
16991
17028
  }
16992
17029
  }
16993
17030
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revolist/revogrid",
3
- "version": "4.14.7",
3
+ "version": "4.14.8",
4
4
  "type": "module",
5
5
  "description": "Virtual reactive data grid spreadsheet component - RevoGrid.",
6
6
  "license": "MIT",
@@ -141,6 +141,12 @@ class LocalScrollTimer {
141
141
  rgCol: 0,
142
142
  rgRow: 0,
143
143
  };
144
+ /**
145
+ * Check if scroll is ready to accept new value
146
+ * this is an edge case for scroll events
147
+ * when we need to apply scroll after throttling
148
+ */
149
+ this.lastScrollUpdateCallbacks = {};
144
150
  }
145
151
  setCoordinate(e) {
146
152
  this.lastKnownScrollCoordinate[e.dimension] = e.coordinate;
@@ -151,14 +157,47 @@ class LocalScrollTimer {
151
157
  latestScrollUpdate(dimension) {
152
158
  this.mouseWheelScrollTimestamp[dimension] = new Date().getTime();
153
159
  }
154
- /**
155
- * Check if scroll is ready to accept new value
156
- */
157
160
  isReady(type, coordinate) {
158
- const change = new Date().getTime() - this.mouseWheelScrollTimestamp[type];
161
+ // if there is a callback, clear it
162
+ if (this.lastScrollUpdateCallbacks[type]) {
163
+ this.clearLastScrollUpdate(type);
164
+ }
159
165
  // apply after throttling
160
- return (change > this.scrollThrottling &&
161
- coordinate !== this.lastKnownScrollCoordinate[type]);
166
+ return this.verifyChange(type, coordinate);
167
+ }
168
+ verifyChange(type, coordinate) {
169
+ const now = new Date().getTime();
170
+ const change = now - this.mouseWheelScrollTimestamp[type];
171
+ return change > this.scrollThrottling &&
172
+ coordinate !== this.lastKnownScrollCoordinate[type];
173
+ }
174
+ clearLastScrollUpdate(type) {
175
+ var _a, _b;
176
+ clearTimeout((_b = (_a = this.lastScrollUpdateCallbacks[type]) === null || _a === void 0 ? void 0 : _a.timeout) !== null && _b !== void 0 ? _b : 0);
177
+ delete this.lastScrollUpdateCallbacks[type];
178
+ }
179
+ throttleLastScrollUpdate(type, coordinate, lastScrollUpdate) {
180
+ // if scrollThrottling is set
181
+ // we need to throttle the last scroll event
182
+ if (this.scrollThrottling) {
183
+ this.clearLastScrollUpdate(type);
184
+ // save lastScrollUpdate callback
185
+ const callback = this.lastScrollUpdateCallbacks[type] = {
186
+ callback: lastScrollUpdate,
187
+ timestamp: new Date().getTime(),
188
+ coordinate,
189
+ timeout: 0,
190
+ };
191
+ callback.timeout = setTimeout(() => {
192
+ // clear timeout
193
+ this.clearLastScrollUpdate(type);
194
+ // if scrollThrottling is set, and the last scroll event happened before the timeout started
195
+ // we need to throttle the last scroll event
196
+ if (this.mouseWheelScrollTimestamp[type] < callback.timestamp && this.verifyChange(type, callback.coordinate)) {
197
+ callback.callback();
198
+ }
199
+ }, this.scrollThrottling + 50);
200
+ }
162
201
  }
163
202
  }
164
203
 
@@ -1 +1 @@
1
- {"file":"local.scroll.timer.js","mappings":"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","names":[],"sources":["src/services/local.scroll.service.ts","src/services/local.scroll.timer.ts"],"sourcesContent":["import type { DimensionType, ViewPortScrollEvent } from '@type';\nimport { scaleValue } from '../utils';\n\ninterface Config {\n skipAnimationFrame?: boolean;\n // scroll event inited and direction cached\n // scrollingService.proxyScroll get tiggered\n // setScroll event called from scrollingService\n runScroll(e: ViewPortScrollEvent): void;\n // all operation finished, apply scroll values\n applyScroll(e: ViewPortScrollEvent): void;\n}\n\ntype Params = {\n contentSize: number;\n virtualContentSize?: number;\n clientSize: number;\n virtualSize: number;\n maxSize?: number;\n};\n\nconst initialParams: Params = {\n contentSize: 0,\n clientSize: 0,\n virtualSize: 0,\n maxSize: 0,\n};\nconst NO_COORDINATE = -1;\n\n/**\n * Based on content size, client size and virtual size\n * return full size\n */\nexport function getContentSize(\n contentSize: number,\n clientSize: number,\n virtualSize = 0,\n): number {\n if (virtualSize > contentSize) {\n return 0;\n }\n return contentSize + (virtualSize ? clientSize - virtualSize : 0);\n}\n\nexport default class LocalScrollService {\n private preventArtificialScroll: Record<DimensionType, (() => void) | null> = {\n rgRow: null,\n rgCol: null,\n };\n // to check if scroll changed\n private previousScroll: Record<DimensionType, number> = {\n rgRow: NO_COORDINATE,\n rgCol: NO_COORDINATE,\n };\n private params: Record<DimensionType, Params> = {\n rgRow: { ...initialParams },\n rgCol: { ...initialParams },\n };\n\n constructor(private cfg: Config) {}\n\n setParams(params: Params, dimension: DimensionType) {\n const virtualContentSize = getContentSize(\n params.contentSize,\n params.clientSize,\n params.virtualSize,\n );\n this.params[dimension] = {\n ...params,\n maxSize: virtualContentSize - params.clientSize,\n virtualContentSize,\n };\n }\n\n // apply scroll values after scroll done\n async setScroll(e: ViewPortScrollEvent) {\n this.cancelScroll(e.dimension);\n\n // start frame animation\n const frameAnimation = new Promise<void>((resolve, reject) => {\n // for example safari desktop has issues with animation frame\n if (this.cfg.skipAnimationFrame) {\n return resolve();\n }\n const animationId = window.requestAnimationFrame(() => {\n resolve();\n });\n this.preventArtificialScroll[e.dimension] = reject.bind(\n null,\n animationId,\n );\n });\n\n try {\n await frameAnimation;\n const params = this.getParams(e.dimension);\n e.coordinate = Math.ceil(e.coordinate);\n this.previousScroll[e.dimension] = this.wrapCoordinate(\n e.coordinate,\n params,\n );\n this.preventArtificialScroll[e.dimension] = null;\n this.cfg.applyScroll({\n ...e,\n coordinate: params.virtualSize\n ? this.convert(e.coordinate, params, false)\n : e.coordinate,\n });\n } catch (id) {\n window.cancelAnimationFrame(id);\n }\n }\n\n /**\n * On scroll event started\n */\n scroll(\n coordinate: number,\n dimension: DimensionType,\n force = false,\n delta?: number,\n outside = false,\n ) {\n // cancel all previous scrolls for same dimension\n this.cancelScroll(dimension);\n\n // drop if no change\n if (!force && this.previousScroll[dimension] === coordinate) {\n this.previousScroll[dimension] = NO_COORDINATE;\n return;\n }\n\n const param = this.getParams(dimension);\n // let component know about scroll event started\n this.cfg.runScroll({\n dimension: dimension,\n coordinate: param.virtualSize\n ? this.convert(coordinate, param)\n : coordinate,\n delta,\n outside,\n });\n }\n\n private getParams(dimension: DimensionType): Params {\n return this.params[dimension];\n }\n\n // check if scroll outside of region to avoid looping\n private wrapCoordinate(c: number, param: Params): number {\n if (c < 0) {\n return NO_COORDINATE;\n }\n\n if (typeof param.maxSize === 'number' && c > param.maxSize) {\n return param.maxSize;\n }\n return c;\n }\n\n // prevent already started scroll, performance optimization\n private cancelScroll(dimension: DimensionType) {\n this.preventArtificialScroll[dimension]?.();\n this.preventArtificialScroll[dimension] = null;\n }\n\n /* convert virtual to real and back, scale range */\n private convert(pos: number, param: Params, toReal = true): number {\n const minRange = param.clientSize;\n const from: [number, number] = [0, (param.virtualContentSize ?? minRange) - minRange];\n const to: [number, number] = [0, param.contentSize - param.virtualSize];\n if (toReal) {\n return scaleValue(pos, from, to);\n }\n return scaleValue(pos, to, from);\n }\n}\n","import type { DimensionType } from '@type';\n/**\n * Apply changes only if mousewheel event happened some time ago (scrollThrottling)\n */\nexport class LocalScrollTimer {\n /**\n * Last mw event time for trigger scroll function below\n * If mousewheel function was ignored we still need to trigger render\n */\n private mouseWheelScrollTimestamp: Record<DimensionType, number> = {\n rgCol: 0,\n rgRow: 0,\n };\n private lastKnownScrollCoordinate: Record<DimensionType, number> = {\n rgCol: 0,\n rgRow: 0,\n };\n\n constructor(private scrollThrottling = 10) {}\n\n setCoordinate(e: { dimension: DimensionType; coordinate: number }) {\n this.lastKnownScrollCoordinate[e.dimension] = e.coordinate;\n }\n\n /**\n * Remember last mw event time\n */\n latestScrollUpdate(dimension: DimensionType) {\n this.mouseWheelScrollTimestamp[dimension] = new Date().getTime();\n }\n\n /**\n * Check if scroll is ready to accept new value\n */\n isReady(type: DimensionType, coordinate: number) {\n const change = new Date().getTime() - this.mouseWheelScrollTimestamp[type];\n // apply after throttling\n return (\n change > this.scrollThrottling &&\n coordinate !== this.lastKnownScrollCoordinate[type]\n );\n }\n}\n"],"version":3}
1
+ {"file":"local.scroll.timer.js","mappings":";;;;;AAqBA,MAAM,aAAa,GAAW;IAC5B,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;IACd,OAAO,EAAE,CAAC;CACX,CAAC;AACF,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC;AAEzB;;;;SAIgB,cAAc,CAC5B,WAAmB,EACnB,UAAkB,EAClB,WAAW,GAAG,CAAC;IAEf,IAAI,WAAW,GAAG,WAAW,EAAE;QAC7B,OAAO,CAAC,CAAC;KACV;IACD,OAAO,WAAW,IAAI,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC;MAEoB,kBAAkB;IAerC,YAAoB,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;QAdvB,4BAAuB,GAA+C;YAC5E,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;SACZ,CAAC;;QAEM,mBAAc,GAAkC;YACtD,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,aAAa;SACrB,CAAC;QACM,WAAM,GAAkC;YAC9C,KAAK,oBAAO,aAAa,CAAE;YAC3B,KAAK,oBAAO,aAAa,CAAE;SAC5B,CAAC;KAEiC;IAEnC,SAAS,CAAC,MAAc,EAAE,SAAwB;QAChD,MAAM,kBAAkB,GAAG,cAAc,CACvC,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,UAAU,EACjB,MAAM,CAAC,WAAW,CACnB,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,mCACjB,MAAM,KACT,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAAC,UAAU,EAC/C,kBAAkB,GACnB,CAAC;KACH;;IAGD,MAAM,SAAS,CAAC,CAAsB;QACpC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;;QAG/B,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM;;YAEvD,IAAI,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE;gBAC/B,OAAO,OAAO,EAAE,CAAC;aAClB;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,qBAAqB,CAAC;gBAC/C,OAAO,EAAE,CAAC;aACX,CAAC,CAAC;YACH,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,IAAI,CACrD,IAAI,EACJ,WAAW,CACZ,CAAC;SACH,CAAC,CAAC;QAEH,IAAI;YACF,MAAM,cAAc,CAAC;YACrB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC3C,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,cAAc,CACpD,CAAC,CAAC,UAAU,EACZ,MAAM,CACP,CAAC;YACF,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;YACjD,IAAI,CAAC,GAAG,CAAC,WAAW,iCACf,CAAC,KACJ,UAAU,EAAE,MAAM,CAAC,WAAW;sBAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC;sBACzC,CAAC,CAAC,UAAU,IAChB,CAAC;SACJ;QAAC,OAAO,EAAE,EAAE;YACX,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;SACjC;KACF;;;;IAKD,MAAM,CACJ,UAAkB,EAClB,SAAwB,EACxB,KAAK,GAAG,KAAK,EACb,KAAc,EACd,OAAO,GAAG,KAAK;;QAGf,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;;QAG7B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE;YAC3D,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC;YAC/C,OAAO;SACR;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;;QAExC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YACjB,SAAS,EAAE,SAAS;YACpB,UAAU,EAAE,KAAK,CAAC,WAAW;kBACzB,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;kBAC/B,UAAU;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAC;KACJ;IAEO,SAAS,CAAC,SAAwB;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KAC/B;;IAGO,cAAc,CAAC,CAAS,EAAE,KAAa;QAC7C,IAAI,CAAC,GAAG,CAAC,EAAE;YACT,OAAO,aAAa,CAAC;SACtB;QAED,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE;YAC1D,OAAO,KAAK,CAAC,OAAO,CAAC;SACtB;QACD,OAAO,CAAC,CAAC;KACV;;IAGO,YAAY,CAAC,SAAwB;;QAC3C,MAAA,MAAA,IAAI,CAAC,uBAAuB,EAAC,SAAS,CAAC,kDAAI,CAAC;QAC5C,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;KAChD;;IAGO,OAAO,CAAC,GAAW,EAAE,KAAa,EAAE,MAAM,GAAG,IAAI;;QACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC;QAClC,MAAM,IAAI,GAAqB,CAAC,CAAC,EAAE,CAAC,MAAA,KAAK,CAAC,kBAAkB,mCAAI,QAAQ,IAAI,QAAQ,CAAC,CAAC;QACtF,MAAM,EAAE,GAAqB,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;QACxE,IAAI,MAAM,EAAE;YACV,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;SAClC;QACD,OAAO,UAAU,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;KAClC;;;AC9KH;;;MAGa,gBAAgB;IAc3B,YAAoB,mBAAmB,EAAE;QAArB,qBAAgB,GAAhB,gBAAgB,CAAK;;;;;QATjC,8BAAyB,GAAkC;YACjE,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;SACT,CAAC;QACM,8BAAyB,GAAkC;YACjE,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;SACT,CAAC;;;;;;QAoCM,8BAAyB,GAK3B,EAAE,CAAC;KAvCoC;IAE7C,aAAa,CAAC,CAAmD;QAC/D,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;KAC5D;;;;IAKD,kBAAkB,CAAC,SAAwB;QACzC,IAAI,CAAC,yBAAyB,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;KAClE;IAED,OAAO,CAAC,IAAmB,EAAE,UAAkB;;QAE7C,IAAI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE;YACxC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;SACjC;;QAED,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;KAC5C;IAEO,YAAY,CAAC,IAAmB,EAAE,UAAkB;QAC1D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAC1D,OAAO,MAAM,GAAG,IAAI,CAAC,gBAAgB;YACrC,UAAU,KAAK,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;KACrD;IAcO,qBAAqB,CAAC,IAAmB;;QAC/C,YAAY,CAAC,MAAA,MAAA,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,0CAAE,OAAO,mCAAI,CAAC,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;KAC7C;IAED,wBAAwB,CAAC,IAAmB,EAAE,UAAkB,EAAE,gBAA4B;;;QAG5F,IAAI,IAAI,CAAC,gBAAgB,EAAE;YACzB,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;;YAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,GAAG;gBACtD,QAAQ,EAAE,gBAAgB;gBAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE;gBAC/B,UAAU;gBACV,OAAO,EAAE,CAAQ;aAClB,CAAC;YACF,QAAQ,CAAC,OAAO,GAAG,UAAU,CAAC;;gBAE5B,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;;;gBAGhC,IAAI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;oBAC7G,QAAQ,CAAC,QAAQ,EAAE,CAAC;iBACrB;aACF,EAAE,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;SAChC;KACF;;;;;","names":[],"sources":["src/services/local.scroll.service.ts","src/services/local.scroll.timer.ts"],"sourcesContent":["import type { DimensionType, ViewPortScrollEvent } from '@type';\nimport { scaleValue } from '../utils';\n\ninterface Config {\n skipAnimationFrame?: boolean;\n // scroll event inited and direction cached\n // scrollingService.proxyScroll get tiggered\n // setScroll event called from scrollingService\n runScroll(e: ViewPortScrollEvent): void;\n // all operation finished, apply scroll values\n applyScroll(e: ViewPortScrollEvent): void;\n}\n\ntype Params = {\n contentSize: number;\n virtualContentSize?: number;\n clientSize: number;\n virtualSize: number;\n maxSize?: number;\n};\n\nconst initialParams: Params = {\n contentSize: 0,\n clientSize: 0,\n virtualSize: 0,\n maxSize: 0,\n};\nconst NO_COORDINATE = -1;\n\n/**\n * Based on content size, client size and virtual size\n * return full size\n */\nexport function getContentSize(\n contentSize: number,\n clientSize: number,\n virtualSize = 0,\n): number {\n if (virtualSize > contentSize) {\n return 0;\n }\n return contentSize + (virtualSize ? clientSize - virtualSize : 0);\n}\n\nexport default class LocalScrollService {\n private preventArtificialScroll: Record<DimensionType, (() => void) | null> = {\n rgRow: null,\n rgCol: null,\n };\n // to check if scroll changed\n private previousScroll: Record<DimensionType, number> = {\n rgRow: NO_COORDINATE,\n rgCol: NO_COORDINATE,\n };\n private params: Record<DimensionType, Params> = {\n rgRow: { ...initialParams },\n rgCol: { ...initialParams },\n };\n\n constructor(private cfg: Config) {}\n\n setParams(params: Params, dimension: DimensionType) {\n const virtualContentSize = getContentSize(\n params.contentSize,\n params.clientSize,\n params.virtualSize,\n );\n this.params[dimension] = {\n ...params,\n maxSize: virtualContentSize - params.clientSize,\n virtualContentSize,\n };\n }\n\n // apply scroll values after scroll done\n async setScroll(e: ViewPortScrollEvent) {\n this.cancelScroll(e.dimension);\n\n // start frame animation\n const frameAnimation = new Promise<void>((resolve, reject) => {\n // for example safari desktop has issues with animation frame\n if (this.cfg.skipAnimationFrame) {\n return resolve();\n }\n const animationId = window.requestAnimationFrame(() => {\n resolve();\n });\n this.preventArtificialScroll[e.dimension] = reject.bind(\n null,\n animationId,\n );\n });\n\n try {\n await frameAnimation;\n const params = this.getParams(e.dimension);\n e.coordinate = Math.ceil(e.coordinate);\n this.previousScroll[e.dimension] = this.wrapCoordinate(\n e.coordinate,\n params,\n );\n this.preventArtificialScroll[e.dimension] = null;\n this.cfg.applyScroll({\n ...e,\n coordinate: params.virtualSize\n ? this.convert(e.coordinate, params, false)\n : e.coordinate,\n });\n } catch (id) {\n window.cancelAnimationFrame(id);\n }\n }\n\n /**\n * On scroll event started\n */\n scroll(\n coordinate: number,\n dimension: DimensionType,\n force = false,\n delta?: number,\n outside = false,\n ) {\n // cancel all previous scrolls for same dimension\n this.cancelScroll(dimension);\n\n // drop if no change\n if (!force && this.previousScroll[dimension] === coordinate) {\n this.previousScroll[dimension] = NO_COORDINATE;\n return;\n }\n\n const param = this.getParams(dimension);\n // let component know about scroll event started\n this.cfg.runScroll({\n dimension: dimension,\n coordinate: param.virtualSize\n ? this.convert(coordinate, param)\n : coordinate,\n delta,\n outside,\n });\n }\n\n private getParams(dimension: DimensionType): Params {\n return this.params[dimension];\n }\n\n // check if scroll outside of region to avoid looping\n private wrapCoordinate(c: number, param: Params): number {\n if (c < 0) {\n return NO_COORDINATE;\n }\n\n if (typeof param.maxSize === 'number' && c > param.maxSize) {\n return param.maxSize;\n }\n return c;\n }\n\n // prevent already started scroll, performance optimization\n private cancelScroll(dimension: DimensionType) {\n this.preventArtificialScroll[dimension]?.();\n this.preventArtificialScroll[dimension] = null;\n }\n\n /* convert virtual to real and back, scale range */\n private convert(pos: number, param: Params, toReal = true): number {\n const minRange = param.clientSize;\n const from: [number, number] = [0, (param.virtualContentSize ?? minRange) - minRange];\n const to: [number, number] = [0, param.contentSize - param.virtualSize];\n if (toReal) {\n return scaleValue(pos, from, to);\n }\n return scaleValue(pos, to, from);\n }\n}\n","import type { DimensionType } from '@type';\n/**\n * Apply changes only if mousewheel event happened some time ago (scrollThrottling)\n */\nexport class LocalScrollTimer {\n /**\n * Last mw event time for trigger scroll function below\n * If mousewheel function was ignored we still need to trigger render\n */\n private mouseWheelScrollTimestamp: Record<DimensionType, number> = {\n rgCol: 0,\n rgRow: 0,\n };\n private lastKnownScrollCoordinate: Record<DimensionType, number> = {\n rgCol: 0,\n rgRow: 0,\n };\n\n constructor(private scrollThrottling = 10) {}\n\n setCoordinate(e: { dimension: DimensionType; coordinate: number }) {\n this.lastKnownScrollCoordinate[e.dimension] = e.coordinate;\n }\n\n /**\n * Remember last mw event time\n */\n latestScrollUpdate(dimension: DimensionType) {\n this.mouseWheelScrollTimestamp[dimension] = new Date().getTime();\n }\n\n isReady(type: DimensionType, coordinate: number) {\n // if there is a callback, clear it\n if (this.lastScrollUpdateCallbacks[type]) {\n this.clearLastScrollUpdate(type)\n }\n // apply after throttling\n return this.verifyChange(type, coordinate);\n }\n\n private verifyChange(type: DimensionType, coordinate: number) {\n const now = new Date().getTime();\n const change = now - this.mouseWheelScrollTimestamp[type];\n return change > this.scrollThrottling &&\n coordinate !== this.lastKnownScrollCoordinate[type];\n }\n\n /**\n * Check if scroll is ready to accept new value\n * this is an edge case for scroll events\n * when we need to apply scroll after throttling\n */\n private lastScrollUpdateCallbacks: Partial<Record<DimensionType, {\n callback: () => void;\n timestamp: number;\n coordinate: number;\n timeout: number;\n }>> = {};\n\n private clearLastScrollUpdate(type: DimensionType) {\n clearTimeout(this.lastScrollUpdateCallbacks[type]?.timeout ?? 0);\n delete this.lastScrollUpdateCallbacks[type];\n }\n\n throttleLastScrollUpdate(type: DimensionType, coordinate: number, lastScrollUpdate: () => void) {\n // if scrollThrottling is set\n // we need to throttle the last scroll event\n if (this.scrollThrottling) {\n this.clearLastScrollUpdate(type)\n // save lastScrollUpdate callback\n const callback = this.lastScrollUpdateCallbacks[type] = {\n callback: lastScrollUpdate,\n timestamp: new Date().getTime(),\n coordinate,\n timeout: 0 as any,\n };\n callback.timeout = setTimeout(() => {\n // clear timeout\n this.clearLastScrollUpdate(type)\n // if scrollThrottling is set, and the last scroll event happened before the timeout started\n // we need to throttle the last scroll event\n if (this.mouseWheelScrollTimestamp[type] < callback.timestamp && this.verifyChange(type, callback.coordinate)) {\n callback.callback();\n }\n }, this.scrollThrottling + 50);\n }\n }\n}\n"],"version":3}
@@ -4407,12 +4407,14 @@ const RevoGridComponent = /*@__PURE__*/ proxyCustomElement(class RevoGridCompone
4407
4407
  const typeCol = 'rgCol';
4408
4408
  const viewports = this.viewportProvider.stores;
4409
4409
  const dimensions = this.dimensionProvider.stores;
4410
+ const verticalScroll = (h("revogr-scroll-virtual", { class: "vertical", dimension: typeRow, clientSize: viewports[typeRow].store.get('clientSize'), virtualSize: viewports[typeRow].store.get('virtualSize'), realSize: dimensions[typeRow].store.get('realSize'), ref: el => this.scrollingService.registerElement(el, 'rowScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }));
4411
+ const horizontalScroll = (h("revogr-scroll-virtual", { class: "horizontal", dimension: typeCol, clientSize: viewports[typeCol].store.get('clientSize'), virtualSize: viewports[typeCol].store.get('virtualSize'), realSize: dimensions[typeCol].store.get('realSize'), ref: el => this.scrollingService.registerElement(el, 'colScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }));
4410
4412
  return (h(Host, null, this.hideAttribution ? null : (h("revogr-attribution", { class: "attribution" })), h("slot", { name: "header" }), h("div", { class: "main-viewport", onClick: (e) => {
4411
4413
  var _a;
4412
4414
  if (e.currentTarget === e.target) {
4413
4415
  (_a = this.viewport) === null || _a === void 0 ? void 0 : _a.clearEdit();
4414
4416
  }
4415
- } }, h("div", { class: "viewports" }, h("slot", { name: "viewport" }), viewportSections, h("revogr-scroll-virtual", { class: "vertical", dimension: typeRow, viewportStore: viewports[typeRow].store, dimensionStore: dimensions[typeRow].store, ref: el => this.scrollingService.registerElement(el, 'rowScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }), h(OrderRenderer, { ref: e => (this.orderService = e) }))), h("revogr-scroll-virtual", { class: "horizontal", dimension: typeCol, viewportStore: viewports[typeCol].store, dimensionStore: dimensions[typeCol].store, ref: el => this.scrollingService.registerElement(el, 'colScroll'), onScrollvirtual: e => this.scrollingService.proxyScroll(e.detail) }), h("revogr-extra", { ref: el => (this.extraService = el), nodes: this.extraElements }), h("slot", { name: "footer" })));
4417
+ } }, h("div", { class: "viewports" }, h("slot", { name: "viewport" }), viewportSections, verticalScroll, h(OrderRenderer, { ref: e => (this.orderService = e) }))), horizontalScroll, h("revogr-extra", { ref: el => (this.extraService = el), nodes: this.extraElements }), h("slot", { name: "footer" })));
4416
4418
  }
4417
4419
  disconnectedCallback() {
4418
4420
  // Remove all plugins, to avoid memory leaks