@revolist/revogrid 4.23.3 → 4.23.5

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 (37) hide show
  1. package/dist/cjs/{column.drag.plugin-DJueWxN_.js → column.drag.plugin-yUSx3qoN.js} +2 -2
  2. package/dist/cjs/{header-cell-renderer-QrcXXSkF.js → header-cell-renderer-vVr4IWNV.js} +7 -18
  3. package/dist/cjs/index.cjs.js +3 -3
  4. package/dist/cjs/revo-grid.cjs.entry.js +13 -4
  5. package/dist/cjs/revogr-attribution_7.cjs.entry.js +1 -1
  6. package/dist/cjs/revogr-data_4.cjs.entry.js +27 -13
  7. package/dist/cjs/{viewport.store-BlKQ4x9H.js → viewport.store-BscUCiUk.js} +23 -0
  8. package/dist/collection/components/header/header-renderer.js +10 -7
  9. package/dist/collection/components/header/resizable.element.js +7 -18
  10. package/dist/collection/components/revoGrid/viewport.resize.service.js +1 -0
  11. package/dist/collection/components/scroll/revogr-viewport-scroll.js +15 -5
  12. package/dist/collection/services/dimension.provider.js +11 -2
  13. package/dist/collection/store/vp/viewport.helpers.js +23 -0
  14. package/dist/{revo-grid/column.drag.plugin-DCZW62Uc.js → esm/column.drag.plugin-Cg2U-91C.js} +2 -2
  15. package/dist/esm/{header-cell-renderer-BsvUQ8GS.js → header-cell-renderer-B-LX2sgu.js} +7 -18
  16. package/dist/esm/index.js +4 -4
  17. package/dist/esm/revo-grid.entry.js +13 -4
  18. package/dist/esm/revogr-attribution_7.entry.js +1 -1
  19. package/dist/esm/revogr-data_4.entry.js +27 -13
  20. package/dist/{revo-grid/viewport.store-COAfzAyu.js → esm/viewport.store-_c579YyM.js} +23 -0
  21. package/dist/{esm/column.drag.plugin-DCZW62Uc.js → revo-grid/column.drag.plugin-Cg2U-91C.js} +2 -2
  22. package/dist/revo-grid/{header-cell-renderer-BsvUQ8GS.js → header-cell-renderer-B-LX2sgu.js} +7 -18
  23. package/dist/revo-grid/index.esm.js +4 -4
  24. package/dist/revo-grid/revo-grid.entry.js +13 -4
  25. package/dist/revo-grid/revogr-attribution_7.entry.js +1 -1
  26. package/dist/revo-grid/revogr-data_4.entry.js +27 -13
  27. package/dist/{esm/viewport.store-COAfzAyu.js → revo-grid/viewport.store-_c579YyM.js} +23 -0
  28. package/dist/types/components/scroll/revogr-viewport-scroll.d.ts +1 -0
  29. package/dist/types/services/scroll.dimension.helpers.d.ts +19 -0
  30. package/dist/types/store/vp/viewport.helpers.d.ts +23 -0
  31. package/hydrate/index.js +66 -31
  32. package/hydrate/index.mjs +66 -31
  33. package/package.json +1 -1
  34. package/readme.md +127 -16
  35. package/standalone/revo-grid.js +1 -1
  36. package/standalone/revogr-header2.js +1 -1
  37. package/standalone/revogr-viewport-scroll2.js +1 -1
package/hydrate/index.js CHANGED
@@ -12051,6 +12051,29 @@ function getViewportMaxCoordinate(dimension, viewportSize, frameOffset = 1) {
12051
12051
  }
12052
12052
  return Math.max(0, dimension.realSize - viewportSize - dimension.originItemSize * frameOffset);
12053
12053
  }
12054
+ /**
12055
+ * Clamp the viewport coordinate within the valid range.
12056
+ * Given a scroll position, pick a safe starting point for rendering visible items.
12057
+ *
12058
+ * Do not use it when you need the exact scroll position for positioning math.
12059
+ *
12060
+ * It does two things:
12061
+ * 1. If the coordinate is below 0, use 0.
12062
+ * 2. If the coordinate is too close to the very end, pull it back a bit.
12063
+ *
12064
+ * Example:
12065
+ *
12066
+ * content height: 1000px
12067
+ * viewport height: 200px
12068
+ * row height: 30px
12069
+ * The real max scroll is:
12070
+ *
12071
+ * 1000 - 200 = 800
12072
+ * But clampViewportCoordinate may clamp to:
12073
+ *
12074
+ * 1000 - 200 - 30 = 770
12075
+ * Ask for 800 -> it returns 770.
12076
+ */
12054
12077
  function clampViewportCoordinate(coordinate, dimension, viewportSize, frameOffset = 1) {
12055
12078
  return Math.min(Math.max(0, coordinate), getViewportMaxCoordinate(dimension, viewportSize, frameOffset));
12056
12079
  }
@@ -14946,7 +14969,16 @@ class DimensionProvider {
14946
14969
  clientSize,
14947
14970
  virtualSize: viewportSize,
14948
14971
  });
14949
- const renderCoordinate = clampViewportCoordinate(coordinate, dimension, viewportSize);
14972
+ // Render offset must use the true logical scroll coordinate
14973
+ // It is the logical scroll position that should be used for compressed-scroll offset math.
14974
+ const renderCoordinate = Math.min(Math.max(0, coordinate), // prevents negative scroll positions
14975
+ scrollDimension.logicalScrollSize); // prevents positions past the logical end
14976
+ /**
14977
+ * If viewport sizing is initialized (clientSize and viewportSize are truthy), calculate the offset needed for compressed scroll.
14978
+ * Otherwise keep renderOffset at 0, because there is not enough measurement data yet.
14979
+ *
14980
+ * In normal scrolling, logical and physical coordinates are the same, so offset is 0.
14981
+ */
14950
14982
  const renderOffset = clientSize && viewportSize
14951
14983
  ? scrollDimension.getRenderOffset(renderCoordinate)
14952
14984
  : 0;
@@ -18408,24 +18440,13 @@ const ResizableElement = (props, children) => {
18408
18440
  }
18409
18441
  })) ||
18410
18442
  null;
18411
- if (props.active) {
18412
- if (props.canResize) {
18413
- for (let p in props.active) {
18414
- resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onDblClick: e => {
18415
- var _a;
18416
- e.preventDefault();
18417
- (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18418
- }, onMouseDown: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), onTouchStart: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), class: `resizable resizable-${props.active[p]}` }));
18419
- }
18420
- }
18421
- else {
18422
- for (let _p in props.active) {
18423
- resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onTouchStart: (e) => e.preventDefault(), onDblClick: e => {
18424
- var _a;
18425
- e.preventDefault();
18426
- (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18427
- }, class: `no-resize` }));
18428
- }
18443
+ if (props.active && props.canResize) {
18444
+ for (let p in props.active) {
18445
+ resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onDblClick: e => {
18446
+ var _a;
18447
+ e.preventDefault();
18448
+ (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18449
+ }, onMouseDown: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), onTouchStart: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), class: `resizable resizable-${props.active[p]}` }));
18429
18450
  }
18430
18451
  }
18431
18452
  return (hAsync("div", Object.assign({}, props, { ref: e => e && (directive === null || directive === void 0 ? void 0 : directive.set(e)) }), children, resizeEls));
@@ -20759,20 +20780,23 @@ class RevogrFocus {
20759
20780
  }
20760
20781
 
20761
20782
  const HeaderRenderer = (p) => {
20762
- var _a, _b, _c, _d, _e, _f, _g;
20783
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
20784
+ const hasSortingSign = !!(((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable) ||
20785
+ ((_b = p.data) === null || _b === void 0 ? void 0 : _b.order) ||
20786
+ ((_c = p.data) === null || _c === void 0 ? void 0 : _c.sortIndex));
20763
20787
  const cellClass = {
20764
20788
  [HEADER_CLASS]: true,
20765
- [HEADER_SORTABLE_CLASS]: !!((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable),
20789
+ [HEADER_SORTABLE_CLASS]: !!((_d = p.data) === null || _d === void 0 ? void 0 : _d.sortable),
20766
20790
  };
20767
- if ((_b = p.data) === null || _b === void 0 ? void 0 : _b.order) {
20791
+ if ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) {
20768
20792
  cellClass[p.data.order] = true;
20769
20793
  }
20770
20794
  const dataProps = {
20771
- key: String((_d = (_c = p.data) === null || _c === void 0 ? void 0 : _c.prop) !== null && _d !== void 0 ? _d : p.column.itemIndex),
20795
+ key: String((_g = (_f = p.data) === null || _f === void 0 ? void 0 : _f.prop) !== null && _g !== void 0 ? _g : p.column.itemIndex),
20772
20796
  [DATA_COL]: p.column.itemIndex,
20773
20797
  canResize: p.canResize,
20774
- minWidth: ((_e = p.data) === null || _e === void 0 ? void 0 : _e.minSize) || MIN_COL_SIZE,
20775
- maxWidth: (_f = p.data) === null || _f === void 0 ? void 0 : _f.maxSize,
20798
+ minWidth: ((_h = p.data) === null || _h === void 0 ? void 0 : _h.minSize) || MIN_COL_SIZE,
20799
+ maxWidth: (_j = p.data) === null || _j === void 0 ? void 0 : _j.maxSize,
20776
20800
  active: p.active || ['r'],
20777
20801
  class: cellClass,
20778
20802
  style: {
@@ -20808,7 +20832,7 @@ const HeaderRenderer = (p) => {
20808
20832
  }
20809
20833
  }
20810
20834
  }
20811
- return (hAsync(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hAsync(SortingSign, { column: p.data }), p.canFilter && ((_g = p.data) === null || _g === void 0 ? void 0 : _g.filter) !== false ? (hAsync(FilterButton, { column: p.data })) : ('')));
20835
+ return (hAsync(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hasSortingSign ? hAsync(SortingSign, { column: p.data }) : null, p.canFilter && ((_k = p.data) === null || _k === void 0 ? void 0 : _k.filter) !== false ? (hAsync(FilterButton, { column: p.data })) : ('')));
20812
20836
  };
20813
20837
 
20814
20838
  const HeaderGroupRenderer = (p) => {
@@ -21603,6 +21627,7 @@ class GridResizeService {
21603
21627
  }
21604
21628
  destroy() {
21605
21629
  var _a;
21630
+ this.apply.cancel();
21606
21631
  (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
21607
21632
  this.resizeObserver = null;
21608
21633
  }
@@ -21747,6 +21772,10 @@ class RevogrViewportScroll {
21747
21772
  scroll: this.horizontalScroll.scrollLeft,
21748
21773
  noScroll: this.colType !== 'rgCol',
21749
21774
  };
21775
+ this.setScrollParams({
21776
+ rgRow: calculatedHeight,
21777
+ rgCol: calculatedWidth,
21778
+ });
21750
21779
  // Process changes in order: width first, then height
21751
21780
  const dimensions = ['rgCol', 'rgRow'];
21752
21781
  for (const dimension of dimensions) {
@@ -21803,24 +21832,30 @@ class RevogrViewportScroll {
21803
21832
  }
21804
21833
  async componentDidRender() {
21805
21834
  var _a, _b, _c, _d;
21835
+ this.setScrollParams({
21836
+ rgRow: (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0,
21837
+ rgCol: this.horizontalScroll.clientWidth,
21838
+ });
21839
+ this.setScrollVisibility('rgRow', (_d = (_c = this.verticalScroll) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 0, this.contentHeight);
21840
+ this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
21841
+ }
21842
+ setScrollParams(clientSize) {
21806
21843
  this.localScrollService.setParams({
21807
21844
  contentSize: this.contentHeight,
21808
- clientSize: (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0,
21845
+ clientSize: clientSize.rgRow,
21809
21846
  virtualSize: 0,
21810
21847
  }, 'rgRow');
21811
21848
  this.localScrollService.setParams({
21812
21849
  contentSize: this.contentWidth,
21813
- clientSize: this.horizontalScroll.clientWidth,
21850
+ clientSize: clientSize.rgCol,
21814
21851
  virtualSize: 0,
21815
21852
  }, 'rgCol');
21816
- this.setScrollVisibility('rgRow', (_d = (_c = this.verticalScroll) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 0, this.contentHeight);
21817
- this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
21818
21853
  }
21819
21854
  render() {
21820
21855
  var _a, _b;
21821
21856
  const physicalContentHeight = getContentSize(this.contentHeight, (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0);
21822
21857
  const physicalContentWidth = getContentSize(this.contentWidth, 0);
21823
- return (hAsync(Host, { key: 'e52df53dcdcac76f02160615399c558e78fe5825', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: '6821c4472db2208c2d52da9d6d43a7e5343d15bb', class: "inner-content-table", style: { width: `${physicalContentWidth}px` } }, hAsync("div", { key: '1916ec94af312621ed4d937c905ed745a23a7d3b', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '2348a566b127f27d969a4e2ff67fab4022501ceb', name: HEADER_SLOT })), hAsync("div", { key: 'd88eebb7b0028b350f5b0feb6b3893efbd3f645c', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: '1778856706d9d6bbc52882a150cb66c9b3f11e06', class: "content-wrapper", style: { height: `${physicalContentHeight}px` } }, hAsync("slot", { key: '200bc8a9e692b6183ac2665b68961d28892f7cab', name: CONTENT_SLOT }))), hAsync("div", { key: 'dc812739b4ad829867dd1effe94a871be247979a', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: '06e3b3a4f88c477dc33268ee317856820f2650e6', name: FOOTER_SLOT })))));
21858
+ return (hAsync(Host, { key: 'ec8d907976c1d50f7aab3c263be3f0249a274df6', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: 'e35696a7993ac94261426b45c28d488cdc42b7f0', class: "inner-content-table", style: { width: `${physicalContentWidth}px` } }, hAsync("div", { key: 'a6997451e01eacda1d27d4efa1d74e1748626218', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '1d401e87d32d5b1531c2211723b552bbc894f22c', name: HEADER_SLOT })), hAsync("div", { key: 'ceab6f9e812d6ca9a0aa376afcd2562a17f505e0', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: 'a9556578a23d6efddec2e982e863aec064042154', class: "content-wrapper", style: { height: `${physicalContentHeight}px` } }, hAsync("slot", { key: '0ae01f9736b9740612e75261f6e3abebda533377', name: CONTENT_SLOT }))), hAsync("div", { key: '09c2565d4ed449a43820f92d97b6558fca3758e7', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: '1ffb08ff8138a560cc09d82e3fe22a53e502aafe', name: FOOTER_SLOT })))));
21824
21859
  }
21825
21860
  /**
21826
21861
  * Extra layer for scroll event monitoring, where MouseWheel event is not passing
package/hydrate/index.mjs CHANGED
@@ -12049,6 +12049,29 @@ function getViewportMaxCoordinate(dimension, viewportSize, frameOffset = 1) {
12049
12049
  }
12050
12050
  return Math.max(0, dimension.realSize - viewportSize - dimension.originItemSize * frameOffset);
12051
12051
  }
12052
+ /**
12053
+ * Clamp the viewport coordinate within the valid range.
12054
+ * Given a scroll position, pick a safe starting point for rendering visible items.
12055
+ *
12056
+ * Do not use it when you need the exact scroll position for positioning math.
12057
+ *
12058
+ * It does two things:
12059
+ * 1. If the coordinate is below 0, use 0.
12060
+ * 2. If the coordinate is too close to the very end, pull it back a bit.
12061
+ *
12062
+ * Example:
12063
+ *
12064
+ * content height: 1000px
12065
+ * viewport height: 200px
12066
+ * row height: 30px
12067
+ * The real max scroll is:
12068
+ *
12069
+ * 1000 - 200 = 800
12070
+ * But clampViewportCoordinate may clamp to:
12071
+ *
12072
+ * 1000 - 200 - 30 = 770
12073
+ * Ask for 800 -> it returns 770.
12074
+ */
12052
12075
  function clampViewportCoordinate(coordinate, dimension, viewportSize, frameOffset = 1) {
12053
12076
  return Math.min(Math.max(0, coordinate), getViewportMaxCoordinate(dimension, viewportSize, frameOffset));
12054
12077
  }
@@ -14944,7 +14967,16 @@ class DimensionProvider {
14944
14967
  clientSize,
14945
14968
  virtualSize: viewportSize,
14946
14969
  });
14947
- const renderCoordinate = clampViewportCoordinate(coordinate, dimension, viewportSize);
14970
+ // Render offset must use the true logical scroll coordinate
14971
+ // It is the logical scroll position that should be used for compressed-scroll offset math.
14972
+ const renderCoordinate = Math.min(Math.max(0, coordinate), // prevents negative scroll positions
14973
+ scrollDimension.logicalScrollSize); // prevents positions past the logical end
14974
+ /**
14975
+ * If viewport sizing is initialized (clientSize and viewportSize are truthy), calculate the offset needed for compressed scroll.
14976
+ * Otherwise keep renderOffset at 0, because there is not enough measurement data yet.
14977
+ *
14978
+ * In normal scrolling, logical and physical coordinates are the same, so offset is 0.
14979
+ */
14948
14980
  const renderOffset = clientSize && viewportSize
14949
14981
  ? scrollDimension.getRenderOffset(renderCoordinate)
14950
14982
  : 0;
@@ -18406,24 +18438,13 @@ const ResizableElement = (props, children) => {
18406
18438
  }
18407
18439
  })) ||
18408
18440
  null;
18409
- if (props.active) {
18410
- if (props.canResize) {
18411
- for (let p in props.active) {
18412
- resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onDblClick: e => {
18413
- var _a;
18414
- e.preventDefault();
18415
- (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18416
- }, onMouseDown: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), onTouchStart: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), class: `resizable resizable-${props.active[p]}` }));
18417
- }
18418
- }
18419
- else {
18420
- for (let _p in props.active) {
18421
- resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onTouchStart: (e) => e.preventDefault(), onDblClick: e => {
18422
- var _a;
18423
- e.preventDefault();
18424
- (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18425
- }, class: `no-resize` }));
18426
- }
18441
+ if (props.active && props.canResize) {
18442
+ for (let p in props.active) {
18443
+ resizeEls.push(hAsync("div", { onClick: e => e.preventDefault(), onDblClick: e => {
18444
+ var _a;
18445
+ e.preventDefault();
18446
+ (_a = props.onDblClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
18447
+ }, onMouseDown: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), onTouchStart: (e) => directive === null || directive === void 0 ? void 0 : directive.handleDown(e), class: `resizable resizable-${props.active[p]}` }));
18427
18448
  }
18428
18449
  }
18429
18450
  return (hAsync("div", Object.assign({}, props, { ref: e => e && (directive === null || directive === void 0 ? void 0 : directive.set(e)) }), children, resizeEls));
@@ -20757,20 +20778,23 @@ class RevogrFocus {
20757
20778
  }
20758
20779
 
20759
20780
  const HeaderRenderer = (p) => {
20760
- var _a, _b, _c, _d, _e, _f, _g;
20781
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
20782
+ const hasSortingSign = !!(((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable) ||
20783
+ ((_b = p.data) === null || _b === void 0 ? void 0 : _b.order) ||
20784
+ ((_c = p.data) === null || _c === void 0 ? void 0 : _c.sortIndex));
20761
20785
  const cellClass = {
20762
20786
  [HEADER_CLASS]: true,
20763
- [HEADER_SORTABLE_CLASS]: !!((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable),
20787
+ [HEADER_SORTABLE_CLASS]: !!((_d = p.data) === null || _d === void 0 ? void 0 : _d.sortable),
20764
20788
  };
20765
- if ((_b = p.data) === null || _b === void 0 ? void 0 : _b.order) {
20789
+ if ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) {
20766
20790
  cellClass[p.data.order] = true;
20767
20791
  }
20768
20792
  const dataProps = {
20769
- key: String((_d = (_c = p.data) === null || _c === void 0 ? void 0 : _c.prop) !== null && _d !== void 0 ? _d : p.column.itemIndex),
20793
+ key: String((_g = (_f = p.data) === null || _f === void 0 ? void 0 : _f.prop) !== null && _g !== void 0 ? _g : p.column.itemIndex),
20770
20794
  [DATA_COL]: p.column.itemIndex,
20771
20795
  canResize: p.canResize,
20772
- minWidth: ((_e = p.data) === null || _e === void 0 ? void 0 : _e.minSize) || MIN_COL_SIZE,
20773
- maxWidth: (_f = p.data) === null || _f === void 0 ? void 0 : _f.maxSize,
20796
+ minWidth: ((_h = p.data) === null || _h === void 0 ? void 0 : _h.minSize) || MIN_COL_SIZE,
20797
+ maxWidth: (_j = p.data) === null || _j === void 0 ? void 0 : _j.maxSize,
20774
20798
  active: p.active || ['r'],
20775
20799
  class: cellClass,
20776
20800
  style: {
@@ -20806,7 +20830,7 @@ const HeaderRenderer = (p) => {
20806
20830
  }
20807
20831
  }
20808
20832
  }
20809
- return (hAsync(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hAsync(SortingSign, { column: p.data }), p.canFilter && ((_g = p.data) === null || _g === void 0 ? void 0 : _g.filter) !== false ? (hAsync(FilterButton, { column: p.data })) : ('')));
20833
+ return (hAsync(HeaderCellRenderer, { data: p.data, props: dataProps, additionalData: p.additionalData }, hasSortingSign ? hAsync(SortingSign, { column: p.data }) : null, p.canFilter && ((_k = p.data) === null || _k === void 0 ? void 0 : _k.filter) !== false ? (hAsync(FilterButton, { column: p.data })) : ('')));
20810
20834
  };
20811
20835
 
20812
20836
  const HeaderGroupRenderer = (p) => {
@@ -21601,6 +21625,7 @@ class GridResizeService {
21601
21625
  }
21602
21626
  destroy() {
21603
21627
  var _a;
21628
+ this.apply.cancel();
21604
21629
  (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
21605
21630
  this.resizeObserver = null;
21606
21631
  }
@@ -21745,6 +21770,10 @@ class RevogrViewportScroll {
21745
21770
  scroll: this.horizontalScroll.scrollLeft,
21746
21771
  noScroll: this.colType !== 'rgCol',
21747
21772
  };
21773
+ this.setScrollParams({
21774
+ rgRow: calculatedHeight,
21775
+ rgCol: calculatedWidth,
21776
+ });
21748
21777
  // Process changes in order: width first, then height
21749
21778
  const dimensions = ['rgCol', 'rgRow'];
21750
21779
  for (const dimension of dimensions) {
@@ -21801,24 +21830,30 @@ class RevogrViewportScroll {
21801
21830
  }
21802
21831
  async componentDidRender() {
21803
21832
  var _a, _b, _c, _d;
21833
+ this.setScrollParams({
21834
+ rgRow: (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0,
21835
+ rgCol: this.horizontalScroll.clientWidth,
21836
+ });
21837
+ this.setScrollVisibility('rgRow', (_d = (_c = this.verticalScroll) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 0, this.contentHeight);
21838
+ this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
21839
+ }
21840
+ setScrollParams(clientSize) {
21804
21841
  this.localScrollService.setParams({
21805
21842
  contentSize: this.contentHeight,
21806
- clientSize: (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0,
21843
+ clientSize: clientSize.rgRow,
21807
21844
  virtualSize: 0,
21808
21845
  }, 'rgRow');
21809
21846
  this.localScrollService.setParams({
21810
21847
  contentSize: this.contentWidth,
21811
- clientSize: this.horizontalScroll.clientWidth,
21848
+ clientSize: clientSize.rgCol,
21812
21849
  virtualSize: 0,
21813
21850
  }, 'rgCol');
21814
- this.setScrollVisibility('rgRow', (_d = (_c = this.verticalScroll) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 0, this.contentHeight);
21815
- this.setScrollVisibility('rgCol', this.horizontalScroll.clientWidth, this.contentWidth);
21816
21851
  }
21817
21852
  render() {
21818
21853
  var _a, _b;
21819
21854
  const physicalContentHeight = getContentSize(this.contentHeight, (_b = (_a = this.verticalScroll) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0);
21820
21855
  const physicalContentWidth = getContentSize(this.contentWidth, 0);
21821
- return (hAsync(Host, { key: 'e52df53dcdcac76f02160615399c558e78fe5825', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: '6821c4472db2208c2d52da9d6d43a7e5343d15bb', class: "inner-content-table", style: { width: `${physicalContentWidth}px` } }, hAsync("div", { key: '1916ec94af312621ed4d937c905ed745a23a7d3b', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '2348a566b127f27d969a4e2ff67fab4022501ceb', name: HEADER_SLOT })), hAsync("div", { key: 'd88eebb7b0028b350f5b0feb6b3893efbd3f645c', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: '1778856706d9d6bbc52882a150cb66c9b3f11e06', class: "content-wrapper", style: { height: `${physicalContentHeight}px` } }, hAsync("slot", { key: '200bc8a9e692b6183ac2665b68961d28892f7cab', name: CONTENT_SLOT }))), hAsync("div", { key: 'dc812739b4ad829867dd1effe94a871be247979a', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: '06e3b3a4f88c477dc33268ee317856820f2650e6', name: FOOTER_SLOT })))));
21856
+ return (hAsync(Host, { key: 'ec8d907976c1d50f7aab3c263be3f0249a274df6', onWheel: this.horizontalMouseWheel, onScroll: (e) => this.applyScroll('rgCol', e) }, hAsync("div", { key: 'e35696a7993ac94261426b45c28d488cdc42b7f0', class: "inner-content-table", style: { width: `${physicalContentWidth}px` } }, hAsync("div", { key: 'a6997451e01eacda1d27d4efa1d74e1748626218', class: "header-wrapper", ref: e => (this.header = e) }, hAsync("slot", { key: '1d401e87d32d5b1531c2211723b552bbc894f22c', name: HEADER_SLOT })), hAsync("div", { key: 'ceab6f9e812d6ca9a0aa376afcd2562a17f505e0', class: "vertical-inner", ref: el => (this.verticalScroll = el), onWheel: this.verticalMouseWheel, onScroll: (e) => this.applyScroll('rgRow', e) }, hAsync("div", { key: 'a9556578a23d6efddec2e982e863aec064042154', class: "content-wrapper", style: { height: `${physicalContentHeight}px` } }, hAsync("slot", { key: '0ae01f9736b9740612e75261f6e3abebda533377', name: CONTENT_SLOT }))), hAsync("div", { key: '09c2565d4ed449a43820f92d97b6558fca3758e7', class: "footer-wrapper", ref: e => (this.footer = e) }, hAsync("slot", { key: '1ffb08ff8138a560cc09d82e3fe22a53e502aafe', name: FOOTER_SLOT })))));
21822
21857
  }
21823
21858
  /**
21824
21859
  * Extra layer for scroll event monitoring, where MouseWheel event is not passing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revolist/revogrid",
3
- "version": "4.23.3",
3
+ "version": "4.23.5",
4
4
  "type": "module",
5
5
  "description": "Virtual reactive data grid spreadsheet component - RevoGrid.",
6
6
  "license": "MIT",
package/readme.md CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  <h3 align="center">Powerful data grid component built with <a href="https://stenciljs.com" target="_blank">StencilJS</a>.</h3>
24
24
  <p align="center">
25
- Support Millions of cells and thousands of columns easy and efficiently for fast data rendering. Easy to use.
25
+ Render 1M+ rows, millions of cells, and thousands of columns efficiently with no hard row limit in the grid.
26
26
  </p>
27
27
  <p align="center">
28
28
  Used by some of the largest companies in Europe and the United States.
@@ -31,6 +31,7 @@ Used by some of the largest companies in Europe and the United States.
31
31
  <p align="center">
32
32
  <a href="https://rv-grid.com/demo/">Demo and API</a> •
33
33
  <a href="#key-features">Key Features</a> •
34
+ <a href="#revogrid-pro-features">Pro Features</a> •
34
35
  <a href="#basic-usage">How To Use</a> •
35
36
  <a href="#installation">Installation</a> •
36
37
  <a href="https://rv-grid.com/guide/">Docs</a> •
@@ -44,7 +45,7 @@ Used by some of the largest companies in Europe and the United States.
44
45
 
45
46
  ## Key Features
46
47
 
47
- - **High Performance**: Handles millions of cells in the viewport with a powerful core built by default.
48
+ - **High Performance**: Render 1M+ rows and millions of cells with no hard row limit in the grid. Virtualization keeps the DOM focused on the visible viewport.
48
49
 
49
50
  - **[Accessibility](https://rv-grid.com/guide/wcag)**: Follows WAI-ARIA best practices.
50
51
 
@@ -59,7 +60,7 @@ Used by some of the largest companies in Europe and the United States.
59
60
 
60
61
  - **[Intelligent Virtual DOM](https://rv-grid.com/guide/overview#VNode-Reactive-DOM)**: Smart row recombination to minimize redraws.
61
62
 
62
- - **[Virtual Scroll](https://rv-grid.com/guide/viewports)**: Handles large datasets with infinite scroll.
63
+ - **[Virtual Scroll](https://rv-grid.com/guide/viewports)**: Handles large datasets without rendering every row or column into the DOM.
63
64
 
64
65
  - **[Drag and Drop](https://rv-grid.com/guide/row/order)**: Drag and drop in [rows](https://rv-grid.com/guide/row/order) and [columns](https://rv-grid.com/guide/column/order).
65
66
 
@@ -112,28 +113,138 @@ Used by some of the largest companies in Europe and the United States.
112
113
 
113
114
  - **[Plugin System](https://rv-grid.com/guide/plugin/)**: Create custom plugins or extend existing ones easily.
114
115
 
115
- - **[Formula Support](https://rv-grid.com/guide/cell/formula)**: Evaluate formulas in cell data with Excel-like syntax, including basic arithmetic, statistical functions, and cell references.
116
- - **[Pivot Table](https://rv-grid.com/demo/pivot)**: Transform and analyze data dynamically with drag-and-drop field arrangement, aggregation functions, and interactive filtering capabilities.
117
-
118
- - **[Master Detail/Subtables/Forms](https://rv-grid.com/guide/row/master.pro)**: Expand rows to reveal child data.
119
- - **[Cell/Column/Row Span/Merge](https://rv-grid.com/guide/cell/merge)**: Merge cells to form groups.
120
- - **Auto Merge**: Automatically merges cells with identical values in a column.
121
- - **Form editig**: Edit forms directly within the grid, featuring all necessary fields, including custom options and markdown support for a fast and enhanced data entry experience.
122
-
123
116
  - **Customizations**:
124
117
  - [Column header template](https://rv-grid.com/guide/column/header.template).
125
118
  - [Row header template](https://rv-grid.com/guide/row/headers).
126
119
  - [Cell properties](https://rv-grid.com/guide/cell/) (define custom properties for rendered cells).
127
- - Nested grids: Build a grid inside a grid, showcasing advanced editing options and user interactions for a more dynamic data presentation.
128
- - Context Menu: Build context menus for any grid element - from cells to headers. Cut, copy, paste, add rows, modify columns, and more. Fully customizable with your own actions and behaviors.
129
-
130
- - **[AI Agents and MCP](https://rv-grid.com/guide/mcp)**: Connect Codex, Cursor, Claude Code, and VS Code to version-aware RevoGrid docs, examples, migrations, feature availability, and typed API context.
131
-
132
120
  - [Cell template](https://rv-grid.com/guide/cell/renderer) (create your own cell views).
133
121
  - [Cell editor](https://rv-grid.com/guide/cell/editor) (use predefined or apply your own custom editors and cell types).
134
122
 
123
+ - **[AI Agents and MCP](https://rv-grid.com/guide/mcp)**: Connect Codex, Cursor, Claude Code, and VS Code to version-aware RevoGrid docs, examples, migrations, feature availability, and typed API context.
124
+
135
125
  - **Rich API & Additional Improvements**: Explore hundreds of other small customizations and improvements in [RevoGrid](https://rv-grid.com/).
136
126
 
127
+
128
+ ## RevoGrid Pro Features
129
+
130
+ RevoGrid Pro extends the core grid with production plugins for advanced data entry, analytics, layout, validation, remote data workflows, and enterprise planning.
131
+
132
+ - **Advanced Data Structures**:
133
+ - **Hierarchical Data View**: Display tree data with expandable rows, nested relationships, sorting, filtering, editing, and drag-and-drop friendly hierarchy handling.
134
+ - **Row Transpose**: Flip records into a row-oriented view when users need to inspect one entity as a vertical form-like grid.
135
+
136
+ - **Headers, Columns, and Grid Structure**:
137
+ - **Multi-Level Headers / Column Groups**: Build stacked, nested headers so related columns can sit under shared parent groups.
138
+ - **Multi-Row Headers**: Render more than one header row for dense tables, grouped labels, or spreadsheet-like header layouts.
139
+ - **Column Group Panel**: Let users drag columns into a grouping panel to create row groups interactively.
140
+ - **Column Group Render Sync**: Keep grouped header rendering aligned during column moves, resizing, and virtualization updates.
141
+ - **Column Move with Groups**: Move columns while preserving grouped header relationships and valid group boundaries.
142
+ - **Column Collapse & Expand (Drill Down)**: Collapse grouped columns to focus on summary information, then expand when details are needed.
143
+ - **Column Hide**: Hide and reveal columns to create focused views without mutating the underlying dataset.
144
+ - **Column Add Popup**: Provide a UI flow for adding columns from available field definitions.
145
+ - **Column Selection**: Select entire columns from the header for bulk operations, copying, formatting, or analysis.
146
+ - **Column Stretch**: Distribute column widths to fill available grid space while respecting sizing constraints.
147
+ - **Column Autosize**: Measure content and automatically adjust column widths for readability.
148
+ - **Merge Cells**: Merge cells across rows and columns for grouped labels, reports, or spreadsheet-style layouts.
149
+ - **Auto Merge / Same-Value Merge**: Automatically merge neighboring cells with matching values to reduce visual repetition.
150
+ - **Sticky Cells and Rows**: Keep important rows, cells, totals, labels, or action areas visible while scrolling.
151
+ - **Overlay Layers**: Push temporary UI layers above the grid for richer interactions without replacing the main grid.
152
+
153
+ - **Remote Data and Large Dataset Workflows**:
154
+ - **Server Loading with Infinite Scroll**: Load remote data as users scroll, keeping memory and DOM usage controlled for large datasets.
155
+ - **Infinite Scroll**: Support total-based or dynamic scrolling patterns where rows are fetched and released in chunks.
156
+ - **Pagination**: Split large datasets into page-sized views with built-in navigation controls.
157
+ - **Remote Pagination**: Keep page index, page size, total counts, and server-loaded rows synchronized with the grid.
158
+ - **Server-Side Grouping**: Request grouped row blocks from a remote source, expand group paths on demand, and combine grouping with remote filtering, sorting, and export.
159
+
160
+ - **Data Management and Change Tracking**:
161
+ - **Audit Trail History**: Record data-change history for traceability, review, and compliance-oriented workflows.
162
+ - **History**: Track user edits and provide undo/redo controls for grid changes.
163
+ - **History Controls**: Add ready-made UI controls for navigating undo and redo stacks.
164
+ - **Range Apply Preview**: Preview copy, paste, or fill changes before applying them to target cells.
165
+ - **Smart Auto Fill**: Fill ranges from an initial value, series, or pattern to speed repetitive data entry.
166
+ - **Excel Export/Import**: Export and import Excel workbook formats including `xlsx`, `xlsm`, `xlsb`, and `xls`.
167
+ - **Multi-Column Export Headers**: Preserve grouped and multi-level column headers when exporting structured grids.
168
+ - **Clipboard with JSON**: Copy and paste structured JSON/object values while keeping control over parsing and rendering.
169
+
170
+ - **Selection and Range Operations**:
171
+ - **Multi-Range Selection**: Work with multiple selected ranges for spreadsheet-style copy, edit, and interaction flows.
172
+ - **Range Selection Limit**: Restrict selected ranges with configurable limits to protect performance and workflow rules.
173
+ - **Row Checkbox Selection**: Select rows through checkbox controls with bulk selection and keyboard-friendly behavior.
174
+ - **Row Advanced Drag and Drop**: Reorder rows with custom drag handles, multi-row behavior, and controlled drop handling.
175
+ - **Row Expand**: Add expandable row affordances for detail views, children, or custom row content.
176
+ - **Row Custom Heading**: Customize row header content for labels, actions, or contextual row information.
177
+
178
+ - **Filtering, Search, and Grouping**:
179
+ - **Advanced Selection Filtering**: Filter with multi-condition selection controls for categorical data.
180
+ - **Selection Filter Cascade**: Cascade filters so each choice narrows available values in dependent filters.
181
+ - **Advanced Slider Filtering**: Filter numeric values with range sliders.
182
+ - **Header Input Filtering**: Put filter inputs in the header area for fast per-column search.
183
+ - **Date Filter**: Filter temporal data by date-specific conditions and ranges.
184
+ - **Row Grouping Drag and Drop**: Drag fields into a panel to group rows dynamically.
185
+ - **Grouping Aggregation**: Calculate grouped summaries such as sum, average, count, min, and max.
186
+ - **Server-Side Group Aggregation**: Combine remote grouped data with aggregate values returned by the server.
187
+
188
+ - **Calculations and Formulas**:
189
+ - **Formula Engine**: Add Excel-like formulas with cell references, dynamic calculations, and a broad function set.
190
+ - **Formula Bar**: Give users a dedicated place to inspect and edit formulas.
191
+ - **Formula Name Manager**: Define reusable named references for formulas.
192
+ - **Formula Dependency Highlighting**: Highlight related cells so users can understand formula inputs and outputs.
193
+ - **Summary Header**: Render calculated summary values in header-level UI.
194
+
195
+ - **Data Visualization and Cell Rendering**:
196
+ - **Charts in Cells**: Render compact visuals such as progress lines, progress lines with values, sparklines, bar charts, timelines, rating stars, badges, change indicators, thumbs, and pie charts.
197
+ - **Heat and Cold Maps**: Color-code values with gradients and legends so users can compare magnitude quickly.
198
+ - **Conditional Formatting**: Apply styling rules based on cell values, row data, or custom logic.
199
+ - **Multi-Cell Formatting**: Choose different renderers or editors inside the same column based on row-level conditions.
200
+ - **Cell Flash**: Highlight recently changed values so live updates are easy to spot.
201
+ - **Avatar, Badge, Progress, Rate, Link, and Chart Column Types**: Use ready-made renderers for common visual data patterns.
202
+ - **Array Renderer**: Display array-like values inside cells with a purpose-built renderer.
203
+ - **Buttons**: Add action buttons inside grid cells for row-level commands.
204
+
205
+ - **Editing and Data Entry**:
206
+ - **Dynamic Form Editing**: Edit row data through a generated form with custom options and richer inputs.
207
+ - **Full Row Editing**: Edit multiple columns in a row as one coordinated editing flow.
208
+ - **Cell Checkbox Editors**: Use checkbox cells that act as both renderer and editor.
209
+ - **Cell Slider Editor**: Edit bounded numeric values with an inline slider.
210
+ - **Cell Counter Editor**: Adjust numeric values with plus/minus controls and configurable steps.
211
+ - **Textarea Editor**: Edit longer text values without leaving the grid.
212
+ - **Dropdown Editor**: Edit values through a dropdown or custom popup.
213
+ - **Timeline Editor**: Edit date ranges and timeline-like values with visual controls.
214
+ - **Cell Validation**: Highlight invalid cells and block or guide invalid edits with custom rules.
215
+ - **Input Validation**: Validate editor input before it is committed to the grid.
216
+
217
+ - **User Interaction and UX**:
218
+ - **Context Menus**: Build menus for cells, rows, columns, and headers with actions such as cut, copy, paste, insert, delete, and custom commands.
219
+ - **Tooltips**: Show contextual information on hover for cells or custom grid elements.
220
+ - **Next Line Focus (WCAG)**: Move focus automatically to the next row during data entry workflows.
221
+ - **WCAG Helpers**: Improve keyboard and screen-reader-oriented grid workflows.
222
+ - **Cell Focus Helpers**: Extend focus behavior for custom editing and navigation scenarios.
223
+ - **Info Panel**: Show contextual status or helper information around grid interactions.
224
+ - **Loader**: Display loading state while remote data, exports, or long-running operations are in progress.
225
+
226
+ - **Development and Integration**:
227
+ - **Event Manager**: Coordinate grid events through one managed layer for easier customization and cleanup.
228
+ - **Observable Props**: React to property changes and synchronize plugin state with grid configuration.
229
+ - **Plugin Dependencies**: Declare and resolve plugin relationships when features need to work together.
230
+ - **Dimension Animation**: Animate row and column dimension changes for smoother layout transitions.
231
+ - **Dropdown Infrastructure**: Reuse popup/dropdown services for custom editors and plugin UI.
232
+ - **Grid Presets and Utilities**: Compose reusable grid configurations, helper functions, and shared plugin behavior.
233
+
234
+ - **Enterprise Analytics and Planning**:
235
+ - **Pivot Table**: Build multidimensional analytics with dynamic row, column, and value dimensions; built-in and custom aggregations; hierarchical rows; generated column groups; flat headers; grand totals and subtotals; values-on-rows layouts; row and column drill-down; grouped aggregate values; drag-and-drop configuration; compact field panel; server-side engine/store contracts; remote sorting and filtering; drilldown contracts; field registry validation; cache keys; serializable errors; and state save/load.
236
+ - **Pivot Configurator**: Give users a drag-and-drop UI for choosing Pivot rows, columns, values, filters, and field layout.
237
+ - **Gantt & Scheduling**: Plan projects with task, dependency, calendar, resource, assignment, and baseline models; summary tasks and milestones; WBS hierarchy; automatic scheduling; working calendars and holidays; constrained scheduling; dependency validation; FS, SS, FF, and SF dependencies with lead/lag; critical path and slack; baselines; resource filtering; task move, resize, create, and progress controls; indent/outdent; timeline zoom; highlighted ranges; non-working time shading; labels; and custom markers.
238
+ - **Gantt Toolbar**: Provide ready-made timeline navigation, baseline, critical path, and export actions for Gantt views.
239
+ - **Gantt Task Editor Dialog**: Edit task fields, dependencies, resources, and scheduling details in a structured dialog.
240
+
241
+ - **Advanced Support**:
242
+ - **AI Agent Support**: Use Pro AI tooling to generate plugins, renderers, templates, and grid configurations.
243
+ - **RevoGrid MCP - AI-Native Grid Intelligence**: Connect AI coding tools to version-aware docs, examples, migrations, feature resolution, and typed API context.
244
+ - **Support via GitHub**: Get engineering support through GitHub-based workflows.
245
+ - **Support via Email**: Get direct support for Pro and enterprise implementation questions.
246
+
247
+
137
248
  <h2 align="center">Framework Friendly</h2>
138
249
 
139
250
  <p align="center">