vgapp 1.3.0 → 1.3.2

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 (89) hide show
  1. package/README.md +133 -133
  2. package/app/langs/en/buttons.json +17 -17
  3. package/app/langs/en/messages.json +36 -36
  4. package/app/langs/ru/buttons.json +17 -17
  5. package/app/langs/ru/messages.json +36 -36
  6. package/app/modules/base-module.js +111 -111
  7. package/app/modules/vgalert/js/vgalert.js +52 -29
  8. package/app/modules/vgalert/readme.md +105 -105
  9. package/app/modules/vgdynamictable/index.js +5 -5
  10. package/app/modules/vgdynamictable/js/editable.js +19 -19
  11. package/app/modules/vgdynamictable/js/filters.js +21 -21
  12. package/app/modules/vgdynamictable/js/fixed.js +179 -179
  13. package/app/modules/vgdynamictable/js/pagination.js +1 -1
  14. package/app/modules/vgdynamictable/js/search.js +12 -12
  15. package/app/modules/vgdynamictable/js/sortable.js +71 -71
  16. package/app/modules/vgdynamictable/js/summary-footer.js +28 -28
  17. package/app/modules/vgdynamictable/js/table-remote.js +79 -79
  18. package/app/modules/vgdynamictable/js/table-url-state.js +31 -31
  19. package/app/modules/vgdynamictable/js/utils/common.js +48 -48
  20. package/app/modules/vgdynamictable/js/vgdynamictable.js +268 -268
  21. package/app/modules/vgdynamictable/readme.md +250 -250
  22. package/app/modules/vgdynamictable/scss/_skeleton.scss +6 -6
  23. package/app/modules/vgdynamictable/scss/_sortable.scss +24 -24
  24. package/app/modules/vgdynamictable/scss/_table.scss +4 -4
  25. package/app/modules/vgdynamictable/scss/_variables.scss +79 -79
  26. package/app/modules/vgdynamictable/scss/vgdynamictable.scss +27 -27
  27. package/app/modules/vgfilepreview/js/i18n.js +56 -56
  28. package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
  29. package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
  30. package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
  31. package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
  32. package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
  33. package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
  34. package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
  35. package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
  36. package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
  37. package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
  38. package/app/modules/vgfilepreview/js/renderers/video-modal.js +272 -272
  39. package/app/modules/vgfilepreview/js/renderers/video.js +80 -80
  40. package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
  41. package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
  42. package/app/modules/vgfilepreview/js/vgfilepreview.js +7 -7
  43. package/app/modules/vgfilepreview/readme.md +68 -68
  44. package/app/modules/vgfilepreview/scss/_variables.scss +113 -113
  45. package/app/modules/vgfilepreview/scss/vgfilepreview.scss +464 -464
  46. package/app/modules/vgfiles/js/base.js +26 -26
  47. package/app/modules/vgfiles/js/droppable.js +260 -260
  48. package/app/modules/vgfiles/js/render.js +153 -153
  49. package/app/modules/vgfiles/js/vgfiles.js +104 -104
  50. package/app/modules/vgfiles/readme.md +123 -123
  51. package/app/modules/vgfiles/scss/_variables.scss +18 -18
  52. package/app/modules/vgfiles/scss/vgfiles.scss +148 -148
  53. package/app/modules/vgformsender/js/hideshowpass.js +16 -16
  54. package/app/modules/vgformsender/scss/vgformsender.scss +34 -34
  55. package/app/modules/vgmodal/js/vgmodal.drag.js +332 -332
  56. package/app/modules/vgmodal/js/vgmodal.js +188 -188
  57. package/app/modules/vgmodal/js/vgmodal.resize.js +27 -27
  58. package/app/modules/vgmodal/scss/vgmodal.scss +14 -14
  59. package/app/modules/vgnav/js/vgnav.js +135 -135
  60. package/app/modules/vgnav/readme.md +67 -67
  61. package/app/modules/vgnestable/README.md +307 -307
  62. package/app/modules/vgnestable/scss/_variables.scss +60 -60
  63. package/app/modules/vgnestable/scss/vgnestable.scss +163 -163
  64. package/app/modules/vgrangeslider/js/skins.js +222 -222
  65. package/app/modules/vgrangeslider/js/vgrangeslider.js +704 -704
  66. package/app/modules/vgrangeslider/readme.md +523 -523
  67. package/app/modules/vgrangeslider/scss/_variables.scss +53 -53
  68. package/app/modules/vgrangeslider/scss/vgrangeslider.scss +240 -240
  69. package/app/modules/vgselect/js/vgselect.js +39 -39
  70. package/app/modules/vgselect/scss/vgselect.scss +22 -22
  71. package/app/modules/vgspy/readme.md +28 -28
  72. package/app/modules/vgtoast/readme.md +18 -18
  73. package/app/modules/vgtoast/scss/vgtoast.scss +48 -48
  74. package/app/modules/vgtooltip/js/vgtooltip.js +89 -89
  75. package/app/modules/vgtooltip/readme.md +181 -181
  76. package/app/utils/js/components/ajax.js +117 -117
  77. package/app/utils/js/components/audio-metadata.js +240 -240
  78. package/app/utils/js/components/backdrop.js +17 -17
  79. package/app/utils/js/components/file-icon.js +109 -109
  80. package/app/utils/js/components/file-preview.js +304 -304
  81. package/app/utils/js/components/sanitize.js +150 -150
  82. package/app/utils/js/components/video-metadata.js +140 -140
  83. package/app/vgapp.js +130 -107
  84. package/build/vgapp.css +1 -1
  85. package/build/vgapp.css.map +1 -1
  86. package/build/vgapp.js +1 -1
  87. package/build/vgapp.js.map +1 -1
  88. package/index.js +14 -14
  89. package/package.json +1 -1
@@ -131,26 +131,26 @@ class VGDynamicTable extends BaseModule {
131
131
  nextWidth: 0,
132
132
  frame: 0,
133
133
  };
134
- this._virtualState = {
135
- enabled: false,
136
- bound: false,
137
- lastPage: -1,
138
- lastPerPage: -1,
134
+ this._virtualState = {
135
+ enabled: false,
136
+ bound: false,
137
+ lastPage: -1,
138
+ lastPerPage: -1,
139
139
  start: 0,
140
140
  end: 0,
141
141
  page: -1,
142
- perPage: -1,
143
- frame: 0,
144
- lastScrollTop: -1,
145
- rowHeight: 44,
146
- };
147
- this._virtualSpacers = {
148
- top: null,
149
- bottom: null,
150
- };
151
- this._boundVirtualScroll = this._handleVirtualScroll.bind(this);
152
- this._expandable = null;
153
- }
142
+ perPage: -1,
143
+ frame: 0,
144
+ lastScrollTop: -1,
145
+ rowHeight: 44,
146
+ };
147
+ this._virtualSpacers = {
148
+ top: null,
149
+ bottom: null,
150
+ };
151
+ this._boundVirtualScroll = this._handleVirtualScroll.bind(this);
152
+ this._expandable = null;
153
+ }
154
154
 
155
155
  static get NAME() { return NAME; }
156
156
 
@@ -256,7 +256,7 @@ class VGDynamicTable extends BaseModule {
256
256
  });
257
257
  }
258
258
 
259
- setLocale(locale) {
259
+ setLocale(locale) {
260
260
  const normalized = String(locale || '').toLowerCase().trim() || 'ru';
261
261
  this._params.locale = normalized;
262
262
  this._writePersistentState('locale', normalized);
@@ -511,8 +511,8 @@ class VGDynamicTable extends BaseModule {
511
511
 
512
512
  this._ensureTableViewport(directParent);
513
513
  this._bindViewportPan();
514
- this._restorePersistentState();
515
- this._ensureLiveRegion();
514
+ this._restorePersistentState();
515
+ this._ensureLiveRegion();
516
516
  this._ensureSummaryNode();
517
517
  this._ensurePanHintNode();
518
518
  this._applyFooterVisibility();
@@ -554,9 +554,9 @@ class VGDynamicTable extends BaseModule {
554
554
  this._bindPopState();
555
555
  this._refreshStickyAndFixedLayout();
556
556
 
557
- if (paginationEnabled) {
558
- this.setPagination();
559
- this._emitAction('init', {
557
+ if (paginationEnabled) {
558
+ this.setPagination();
559
+ this._emitAction('init', {
560
560
  page: this._pageState.page,
561
561
  perPage: this._pageState.perPage,
562
562
  });
@@ -656,10 +656,10 @@ class VGDynamicTable extends BaseModule {
656
656
  this._renderFooterFromCurrentState();
657
657
  }
658
658
 
659
- _setRemotePagination() {
660
- const page = this._getInitialPage();
661
- const perPage = this._getInitialPerPage();
662
- this._pageState = { page, perPage };
659
+ _setRemotePagination() {
660
+ const page = this._getInitialPage();
661
+ const perPage = this._getInitialPerPage();
662
+ this._pageState = { page, perPage };
663
663
 
664
664
  const userOnChange = this._params.pagination.onChange;
665
665
  const userOnPerPageChange = this._params.pagination.onPerPageChange;
@@ -704,13 +704,13 @@ class VGDynamicTable extends BaseModule {
704
704
  this._loadRemotePage(page, perPage, null, filtersRequestMeta);
705
705
  }
706
706
 
707
- _getTableRows() {
708
- const body = this._element.tBodies && this._element.tBodies[0];
709
- if (!body) {
710
- return [];
711
- }
712
- return Array.from(body.rows).filter((row) => String(row.getAttribute('data-virtual-spacer') || '') !== '1');
713
- }
707
+ _getTableRows() {
708
+ const body = this._element.tBodies && this._element.tBodies[0];
709
+ if (!body) {
710
+ return [];
711
+ }
712
+ return Array.from(body.rows).filter((row) => String(row.getAttribute('data-virtual-spacer') || '') !== '1');
713
+ }
714
714
 
715
715
  _getTotalPages(perPage) {
716
716
  if (!this._rows.length) {
@@ -719,62 +719,62 @@ class VGDynamicTable extends BaseModule {
719
719
  return Math.max(1, Math.ceil(this._rows.length / perPage));
720
720
  }
721
721
 
722
- _renderPageRows(page, perPage) {
723
- if (!this._rows.length) {
724
- return;
725
- }
726
-
727
- const isVirtualEnabled = this._isVirtualEnabled();
728
- const start = (page - 1) * perPage;
729
- const end = start + perPage;
730
-
731
- this._rows.forEach((row, index) => {
732
- row.hidden = index < start || index >= end;
733
- });
734
- if (isVirtualEnabled) {
735
- this._virtualState.lastPage = page;
736
- this._virtualState.lastPerPage = perPage;
737
- this._applyVirtualWindow(page, perPage);
738
- } else {
739
- this._teardownVirtualWindow();
740
- }
741
- this._refreshExpandable();
742
- this._renderFooterFromCurrentState();
743
- this._refreshStickyAndFixedLayout();
744
- }
745
-
746
- _isVirtualEnabled() {
747
- const options = this._params.virtual || {};
748
- const attr = this._element.getAttribute('data-virtual-enable');
749
- const enabled = attr !== null
750
- ? this._isTruthy(attr)
751
- : Boolean(options.enable);
752
- if (!enabled) {
753
- return false;
754
- }
755
- const thresholdRaw = this._element.getAttribute('data-virtual-threshold');
756
- const threshold = this._normalizePositiveInt(
757
- thresholdRaw !== null ? thresholdRaw : options.threshold,
758
- 500
759
- );
760
- return this._rows.length >= threshold;
761
- }
762
-
763
- _initVirtualization() {
764
- if (!this._tableViewport || this._virtualState.bound) {
765
- return;
766
- }
767
- this._tableViewport.addEventListener('scroll', this._boundVirtualScroll, { passive: true });
768
- this._virtualState.bound = true;
769
- }
770
-
771
- _teardownVirtualizationBinding() {
772
- if (!this._tableViewport || !this._virtualState.bound) {
773
- return;
774
- }
775
- this._tableViewport.removeEventListener('scroll', this._boundVirtualScroll);
776
- this._virtualState.bound = false;
777
- }
722
+ _renderPageRows(page, perPage) {
723
+ if (!this._rows.length) {
724
+ return;
725
+ }
726
+
727
+ const isVirtualEnabled = this._isVirtualEnabled();
728
+ const start = (page - 1) * perPage;
729
+ const end = start + perPage;
730
+
731
+ this._rows.forEach((row, index) => {
732
+ row.hidden = index < start || index >= end;
733
+ });
734
+ if (isVirtualEnabled) {
735
+ this._virtualState.lastPage = page;
736
+ this._virtualState.lastPerPage = perPage;
737
+ this._applyVirtualWindow(page, perPage);
738
+ } else {
739
+ this._teardownVirtualWindow();
740
+ }
741
+ this._refreshExpandable();
742
+ this._renderFooterFromCurrentState();
743
+ this._refreshStickyAndFixedLayout();
744
+ }
745
+
746
+ _isVirtualEnabled() {
747
+ const options = this._params.virtual || {};
748
+ const attr = this._element.getAttribute('data-virtual-enable');
749
+ const enabled = attr !== null
750
+ ? this._isTruthy(attr)
751
+ : Boolean(options.enable);
752
+ if (!enabled) {
753
+ return false;
754
+ }
755
+ const thresholdRaw = this._element.getAttribute('data-virtual-threshold');
756
+ const threshold = this._normalizePositiveInt(
757
+ thresholdRaw !== null ? thresholdRaw : options.threshold,
758
+ 500
759
+ );
760
+ return this._rows.length >= threshold;
761
+ }
762
+
763
+ _initVirtualization() {
764
+ if (!this._tableViewport || this._virtualState.bound) {
765
+ return;
766
+ }
767
+ this._tableViewport.addEventListener('scroll', this._boundVirtualScroll, { passive: true });
768
+ this._virtualState.bound = true;
769
+ }
770
+
771
+ _teardownVirtualizationBinding() {
772
+ if (!this._tableViewport || !this._virtualState.bound) {
773
+ return;
774
+ }
775
+ this._tableViewport.removeEventListener('scroll', this._boundVirtualScroll);
776
+ this._virtualState.bound = false;
777
+ }
778
778
 
779
779
  _handleVirtualScroll() {
780
780
  if (!this._isVirtualEnabled()) {
@@ -801,43 +801,43 @@ class VGDynamicTable extends BaseModule {
801
801
  });
802
802
  }
803
803
 
804
- _applyVirtualWindow(page, perPage) {
805
- if (!this._isVirtualEnabled() || !this._tableViewport) {
806
- this._teardownVirtualWindow();
807
- return;
808
- }
809
-
810
- this._initVirtualization();
811
- const body = this._getBody();
812
- if (!body) {
813
- this._teardownVirtualWindow();
814
- return;
815
- }
816
- const options = this._params.virtual || {};
817
- const rowHeight = this._resolveVirtualRowHeight(page, perPage, options);
818
- const overscanRaw = this._element.getAttribute('data-virtual-overscan');
819
- const overscan = Math.max(0, this._normalizePositiveInt(overscanRaw !== null ? overscanRaw : options.overscan, 8));
820
- const visibleCount = Math.max(1, Math.ceil((this._tableViewport.clientHeight || 0) / rowHeight));
804
+ _applyVirtualWindow(page, perPage) {
805
+ if (!this._isVirtualEnabled() || !this._tableViewport) {
806
+ this._teardownVirtualWindow();
807
+ return;
808
+ }
809
+
810
+ this._initVirtualization();
811
+ const body = this._getBody();
812
+ if (!body) {
813
+ this._teardownVirtualWindow();
814
+ return;
815
+ }
816
+ const options = this._params.virtual || {};
817
+ const rowHeight = this._resolveVirtualRowHeight(page, perPage, options);
818
+ const overscanRaw = this._element.getAttribute('data-virtual-overscan');
819
+ const overscan = Math.max(0, this._normalizePositiveInt(overscanRaw !== null ? overscanRaw : options.overscan, 8));
820
+ const visibleCount = Math.max(1, Math.ceil((this._tableViewport.clientHeight || 0) / rowHeight));
821
821
  const pageStart = (page - 1) * perPage;
822
822
  const pageEnd = Math.min(pageStart + perPage, this._rows.length);
823
823
 
824
- const scrolledRows = Math.floor((this._tableViewport.scrollTop || 0) / rowHeight);
825
- const windowStart = Math.max(pageStart, pageStart + scrolledRows - overscan);
826
- const windowEnd = Math.min(pageEnd, pageStart + scrolledRows + visibleCount + overscan);
827
-
828
- const topSpacerHeight = Math.max(0, (windowStart - pageStart) * rowHeight);
829
- const bottomSpacerHeight = Math.max(0, (pageEnd - windowEnd) * rowHeight);
830
- if (
831
- this._virtualState.start === windowStart
832
- && this._virtualState.end === windowEnd
833
- && this._virtualState.page === page
834
- && this._virtualState.perPage === perPage
835
- ) {
836
- this._syncVirtualSpacers(body, windowStart, windowEnd, topSpacerHeight, bottomSpacerHeight);
837
- return;
838
- }
839
-
840
- const isSameContext = this._virtualState.page === page && this._virtualState.perPage === perPage;
824
+ const scrolledRows = Math.floor((this._tableViewport.scrollTop || 0) / rowHeight);
825
+ const windowStart = Math.max(pageStart, pageStart + scrolledRows - overscan);
826
+ const windowEnd = Math.min(pageEnd, pageStart + scrolledRows + visibleCount + overscan);
827
+
828
+ const topSpacerHeight = Math.max(0, (windowStart - pageStart) * rowHeight);
829
+ const bottomSpacerHeight = Math.max(0, (pageEnd - windowEnd) * rowHeight);
830
+ if (
831
+ this._virtualState.start === windowStart
832
+ && this._virtualState.end === windowEnd
833
+ && this._virtualState.page === page
834
+ && this._virtualState.perPage === perPage
835
+ ) {
836
+ this._syncVirtualSpacers(body, windowStart, windowEnd, topSpacerHeight, bottomSpacerHeight);
837
+ return;
838
+ }
839
+
840
+ const isSameContext = this._virtualState.page === page && this._virtualState.perPage === perPage;
841
841
  const prevStart = this._virtualState.start;
842
842
  const prevEnd = this._virtualState.end;
843
843
  const updateFrom = isSameContext
@@ -846,145 +846,145 @@ class VGDynamicTable extends BaseModule {
846
846
  const updateTo = isSameContext
847
847
  ? Math.min(pageEnd, Math.max(prevEnd, windowEnd))
848
848
  : pageEnd;
849
- for (let index = updateFrom; index < updateTo; index += 1) {
850
- const row = this._rows[index];
851
- if (!row) {
852
- continue;
853
- }
854
- row.hidden = index < windowStart || index >= windowEnd;
855
- }
856
- this._syncVirtualSpacers(body, windowStart, windowEnd, topSpacerHeight, bottomSpacerHeight);
857
- this._virtualState.start = windowStart;
858
- this._virtualState.end = windowEnd;
859
- this._virtualState.page = page;
860
- this._virtualState.perPage = perPage;
861
- this._virtualState.rowHeight = rowHeight;
862
- }
863
-
864
- _resolveVirtualRowHeight(page, perPage, options = {}) {
865
- const attrRowHeight = this._element.getAttribute('data-virtual-row-height');
866
- if (attrRowHeight !== null && String(attrRowHeight).trim() !== '') {
867
- return Math.max(24, this._normalizePositiveInt(attrRowHeight, 44));
868
- }
869
-
870
- const optionRowHeight = this._normalizePositiveInt(options.rowheight, 0);
871
- const pageStart = Math.max(0, (page - 1) * perPage);
872
- const pageEnd = Math.min(pageStart + perPage, this._rows.length);
873
- const measuredHeight = this._measureVirtualRowHeight(pageStart, pageEnd);
874
- if (measuredHeight > 0) {
875
- return measuredHeight;
876
- }
877
- if (optionRowHeight > 0) {
878
- return Math.max(24, optionRowHeight);
879
- }
880
- const cachedHeight = this._normalizePositiveInt(this._virtualState.rowHeight, 44);
881
- return Math.max(24, cachedHeight);
882
- }
883
-
884
- _measureVirtualRowHeight(pageStart, pageEnd) {
885
- const samples = [];
886
- for (let index = pageStart; index < pageEnd; index += 1) {
887
- const row = this._rows[index];
888
- if (!row || row.hidden) {
889
- continue;
890
- }
891
- const rect = row.getBoundingClientRect();
892
- const height = Math.round(rect && rect.height ? rect.height : 0);
893
- if (height > 0) {
894
- samples.push(height);
895
- }
896
- if (samples.length >= 6) {
897
- break;
898
- }
899
- }
900
- if (!samples.length) {
901
- return 0;
902
- }
903
- const total = samples.reduce((sum, value) => sum + value, 0);
904
- return Math.max(24, Math.round(total / samples.length));
905
- }
906
-
907
- _syncVirtualSpacers(body, windowStart, windowEnd, topHeight, bottomHeight) {
908
- const columns = this._getRenderedColumnsCount();
909
- const topSpacer = this._ensureVirtualSpacer('top', columns);
910
- const bottomSpacer = this._ensureVirtualSpacer('bottom', columns);
911
- const firstVisibleRow = this._rows[windowStart] || null;
912
- const afterVisibleRow = this._rows[windowEnd] || null;
913
-
914
- this._updateVirtualSpacer(topSpacer, topHeight, columns);
915
- this._updateVirtualSpacer(bottomSpacer, bottomHeight, columns);
916
-
917
- if (firstVisibleRow) {
918
- body.insertBefore(topSpacer, firstVisibleRow);
919
- } else if (!topSpacer.parentElement) {
920
- body.appendChild(topSpacer);
921
- }
922
-
923
- if (afterVisibleRow) {
924
- body.insertBefore(bottomSpacer, afterVisibleRow);
925
- } else {
926
- body.appendChild(bottomSpacer);
927
- }
928
- }
929
-
930
- _ensureVirtualSpacer(position, columns) {
931
- const current = this._virtualSpacers && this._virtualSpacers[position]
932
- ? this._virtualSpacers[position]
933
- : null;
934
- if (current && current.isConnected) {
935
- this._syncVirtualSpacerColumns(current, columns);
936
- return current;
937
- }
938
-
939
- const spacer = document.createElement('tr');
940
- spacer.setAttribute('data-virtual-spacer', '1');
941
- spacer.setAttribute('data-virtual-spacer-position', position);
942
- spacer.setAttribute('data-group-header', '1');
943
- spacer.setAttribute('aria-hidden', 'true');
944
- const cell = document.createElement('td');
945
- cell.setAttribute('data-virtual-spacer-cell', '1');
946
- cell.colSpan = Math.max(1, columns);
947
- spacer.appendChild(cell);
948
- this._virtualSpacers[position] = spacer;
949
- return spacer;
950
- }
951
-
952
- _syncVirtualSpacerColumns(spacer, columns) {
953
- if (!spacer || !spacer.cells || !spacer.cells[0]) {
954
- return;
955
- }
956
- spacer.cells[0].colSpan = Math.max(1, columns);
957
- }
958
-
959
- _updateVirtualSpacer(spacer, height, columns) {
960
- if (!spacer || !spacer.cells || !spacer.cells[0]) {
961
- return;
962
- }
963
- const safeHeight = Math.max(0, Math.round(height));
964
- this._syncVirtualSpacerColumns(spacer, columns);
965
- const cell = spacer.cells[0];
966
- cell.style.height = `${safeHeight}px`;
967
- spacer.hidden = safeHeight <= 0;
968
- }
969
-
970
- _teardownVirtualWindow() {
971
- this._teardownVirtualizationBinding();
972
- if (this._virtualState.frame && typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') {
973
- window.cancelAnimationFrame(this._virtualState.frame);
974
- }
975
- this._virtualState.start = 0;
976
- this._virtualState.end = 0;
977
- this._virtualState.page = -1;
978
- this._virtualState.perPage = -1;
979
- this._virtualState.frame = 0;
980
- this._virtualState.lastScrollTop = -1;
981
- Object.keys(this._virtualSpacers || {}).forEach((key) => {
982
- const spacer = this._virtualSpacers[key];
983
- if (spacer && spacer.parentElement) {
984
- spacer.parentElement.removeChild(spacer);
985
- }
986
- });
987
- }
849
+ for (let index = updateFrom; index < updateTo; index += 1) {
850
+ const row = this._rows[index];
851
+ if (!row) {
852
+ continue;
853
+ }
854
+ row.hidden = index < windowStart || index >= windowEnd;
855
+ }
856
+ this._syncVirtualSpacers(body, windowStart, windowEnd, topSpacerHeight, bottomSpacerHeight);
857
+ this._virtualState.start = windowStart;
858
+ this._virtualState.end = windowEnd;
859
+ this._virtualState.page = page;
860
+ this._virtualState.perPage = perPage;
861
+ this._virtualState.rowHeight = rowHeight;
862
+ }
863
+
864
+ _resolveVirtualRowHeight(page, perPage, options = {}) {
865
+ const attrRowHeight = this._element.getAttribute('data-virtual-row-height');
866
+ if (attrRowHeight !== null && String(attrRowHeight).trim() !== '') {
867
+ return Math.max(24, this._normalizePositiveInt(attrRowHeight, 44));
868
+ }
869
+
870
+ const optionRowHeight = this._normalizePositiveInt(options.rowheight, 0);
871
+ const pageStart = Math.max(0, (page - 1) * perPage);
872
+ const pageEnd = Math.min(pageStart + perPage, this._rows.length);
873
+ const measuredHeight = this._measureVirtualRowHeight(pageStart, pageEnd);
874
+ if (measuredHeight > 0) {
875
+ return measuredHeight;
876
+ }
877
+ if (optionRowHeight > 0) {
878
+ return Math.max(24, optionRowHeight);
879
+ }
880
+ const cachedHeight = this._normalizePositiveInt(this._virtualState.rowHeight, 44);
881
+ return Math.max(24, cachedHeight);
882
+ }
883
+
884
+ _measureVirtualRowHeight(pageStart, pageEnd) {
885
+ const samples = [];
886
+ for (let index = pageStart; index < pageEnd; index += 1) {
887
+ const row = this._rows[index];
888
+ if (!row || row.hidden) {
889
+ continue;
890
+ }
891
+ const rect = row.getBoundingClientRect();
892
+ const height = Math.round(rect && rect.height ? rect.height : 0);
893
+ if (height > 0) {
894
+ samples.push(height);
895
+ }
896
+ if (samples.length >= 6) {
897
+ break;
898
+ }
899
+ }
900
+ if (!samples.length) {
901
+ return 0;
902
+ }
903
+ const total = samples.reduce((sum, value) => sum + value, 0);
904
+ return Math.max(24, Math.round(total / samples.length));
905
+ }
906
+
907
+ _syncVirtualSpacers(body, windowStart, windowEnd, topHeight, bottomHeight) {
908
+ const columns = this._getRenderedColumnsCount();
909
+ const topSpacer = this._ensureVirtualSpacer('top', columns);
910
+ const bottomSpacer = this._ensureVirtualSpacer('bottom', columns);
911
+ const firstVisibleRow = this._rows[windowStart] || null;
912
+ const afterVisibleRow = this._rows[windowEnd] || null;
913
+
914
+ this._updateVirtualSpacer(topSpacer, topHeight, columns);
915
+ this._updateVirtualSpacer(bottomSpacer, bottomHeight, columns);
916
+
917
+ if (firstVisibleRow) {
918
+ body.insertBefore(topSpacer, firstVisibleRow);
919
+ } else if (!topSpacer.parentElement) {
920
+ body.appendChild(topSpacer);
921
+ }
922
+
923
+ if (afterVisibleRow) {
924
+ body.insertBefore(bottomSpacer, afterVisibleRow);
925
+ } else {
926
+ body.appendChild(bottomSpacer);
927
+ }
928
+ }
929
+
930
+ _ensureVirtualSpacer(position, columns) {
931
+ const current = this._virtualSpacers && this._virtualSpacers[position]
932
+ ? this._virtualSpacers[position]
933
+ : null;
934
+ if (current && current.isConnected) {
935
+ this._syncVirtualSpacerColumns(current, columns);
936
+ return current;
937
+ }
938
+
939
+ const spacer = document.createElement('tr');
940
+ spacer.setAttribute('data-virtual-spacer', '1');
941
+ spacer.setAttribute('data-virtual-spacer-position', position);
942
+ spacer.setAttribute('data-group-header', '1');
943
+ spacer.setAttribute('aria-hidden', 'true');
944
+ const cell = document.createElement('td');
945
+ cell.setAttribute('data-virtual-spacer-cell', '1');
946
+ cell.colSpan = Math.max(1, columns);
947
+ spacer.appendChild(cell);
948
+ this._virtualSpacers[position] = spacer;
949
+ return spacer;
950
+ }
951
+
952
+ _syncVirtualSpacerColumns(spacer, columns) {
953
+ if (!spacer || !spacer.cells || !spacer.cells[0]) {
954
+ return;
955
+ }
956
+ spacer.cells[0].colSpan = Math.max(1, columns);
957
+ }
958
+
959
+ _updateVirtualSpacer(spacer, height, columns) {
960
+ if (!spacer || !spacer.cells || !spacer.cells[0]) {
961
+ return;
962
+ }
963
+ const safeHeight = Math.max(0, Math.round(height));
964
+ this._syncVirtualSpacerColumns(spacer, columns);
965
+ const cell = spacer.cells[0];
966
+ cell.style.height = `${safeHeight}px`;
967
+ spacer.hidden = safeHeight <= 0;
968
+ }
969
+
970
+ _teardownVirtualWindow() {
971
+ this._teardownVirtualizationBinding();
972
+ if (this._virtualState.frame && typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') {
973
+ window.cancelAnimationFrame(this._virtualState.frame);
974
+ }
975
+ this._virtualState.start = 0;
976
+ this._virtualState.end = 0;
977
+ this._virtualState.page = -1;
978
+ this._virtualState.perPage = -1;
979
+ this._virtualState.frame = 0;
980
+ this._virtualState.lastScrollTop = -1;
981
+ Object.keys(this._virtualSpacers || {}).forEach((key) => {
982
+ const spacer = this._virtualSpacers[key];
983
+ if (spacer && spacer.parentElement) {
984
+ spacer.parentElement.removeChild(spacer);
985
+ }
986
+ });
987
+ }
988
988
 
989
989
 
990
990
  _normalizePositiveInt(value, fallback) {
@@ -1003,7 +1003,7 @@ class VGDynamicTable extends BaseModule {
1003
1003
  }
1004
1004
 
1005
1005
  _restorePersistentState() {
1006
- const storedLocale = this._readPersistentState('locale');
1006
+ const storedLocale = this._readPersistentState('locale');
1007
1007
  if (storedLocale) {
1008
1008
  this._params.locale = String(storedLocale).toLowerCase().trim();
1009
1009
  }
@@ -1028,9 +1028,9 @@ class VGDynamicTable extends BaseModule {
1028
1028
  }
1029
1029
 
1030
1030
  const attrNameMap = {
1031
- locale: 'data-persistence-locale',
1032
- filtersApplyMode: 'data-persistence-filters-apply-mode',
1033
- };
1031
+ locale: 'data-persistence-locale',
1032
+ filtersApplyMode: 'data-persistence-filters-apply-mode',
1033
+ };
1034
1034
  const attrName = attrNameMap[key];
1035
1035
  if (attrName) {
1036
1036
  const attrValue = this._element.getAttribute(attrName);
@@ -3653,7 +3653,7 @@ class VGDynamicTable extends BaseModule {
3653
3653
  this._syncCloneStickyHeader();
3654
3654
  }
3655
3655
 
3656
- _renderRemoteRows(rows) {
3656
+ _renderRemoteRows(rows) {
3657
3657
  const body = this._getBody();
3658
3658
 
3659
3659
  if (!rows.length) {