vgapp 1.5.3 → 1.5.4

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.
@@ -5,7 +5,8 @@
5
5
 
6
6
  const MODE_CLASSES = ['vg-table-wrapper--sticky-container', 'vg-table-wrapper--sticky-page'];
7
7
  const CONTAINER_MODE_CLASSES = ['vg-table-container--sticky-container', 'vg-table-container--sticky-page'];
8
- const STYLE_PROPERTIES = ['--vg-table-sticky-top', '--vg-table-sticky-max-height'];
8
+ const CONTENT_MIN_WIDTH_PROPERTY = '--vg-table-sticky-content-min-width';
9
+ const STYLE_PROPERTIES = ['--vg-table-sticky-top', '--vg-table-sticky-max-height', CONTENT_MIN_WIDTH_PROPERTY];
9
10
  const GENERATED_LAYER_ATTRIBUTE = 'data-vg-table-sticky-generated';
10
11
 
11
12
  class _stickyHeader {
@@ -76,13 +77,20 @@ class _stickyHeader {
76
77
  return this;
77
78
  }
78
79
 
79
- refresh() {
80
- if (!this._header || !this._headerTable || !this._body) return this;
81
-
82
- const widths = this._resolveLayoutWidths();
83
- this._applyColgroup(this._headerTable, widths);
84
- this._applyColgroup(this._element, widths);
85
- const scrollbar = Math.max(0, this._body.offsetWidth - this._body.clientWidth);
80
+ refresh() {
81
+ if (!this._header || !this._headerTable || !this._body) return this;
82
+
83
+ let widths = this._resolveLayoutWidths();
84
+ const attempts = this._getHeaders().length + 2;
85
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
86
+ this._applyColgroup(this._headerTable, widths);
87
+ this._applyColgroup(this._element, widths);
88
+ const headerChanged = this._captureOverflowingHeaderMinimums();
89
+ const contentChanged = this._syncContentMinimumWidth(widths);
90
+ if (!headerChanged && !contentChanged) break;
91
+ widths = this._resolveLayoutWidths();
92
+ }
93
+ const scrollbar = Math.max(0, this._body.offsetWidth - this._body.clientWidth);
86
94
  this._header.style.paddingInlineEnd = `${scrollbar}px`;
87
95
  this._header.style.setProperty('--vg-table-sticky-scrollbar-width', `${scrollbar}px`);
88
96
  this._header.classList.toggle('vg-table-header--scrollbar', scrollbar > 0);
@@ -309,6 +317,35 @@ class _stickyHeader {
309
317
  }
310
318
  }
311
319
 
320
+ _captureOverflowingHeaderMinimums() {
321
+ let changed = false;
322
+ this._getHeaders().forEach((header, index) => {
323
+ const key = this._columnKey(header, index);
324
+ if (this._hasDeclaredWidth(header) || this._hardColumnWidths.has(key)) return;
325
+
326
+ const rendered = header.getBoundingClientRect?.().width || header.clientWidth || 0;
327
+ const required = header.scrollWidth || 0;
328
+ const current = this._columnMinimumWidths.get(key) || 0;
329
+ if (required <= rendered + 1 || required <= current + 1) return;
330
+
331
+ this._columnMinimumWidths.set(key, required);
332
+ changed = true;
333
+ });
334
+ return changed;
335
+ }
336
+
337
+ _syncContentMinimumWidth(widths) {
338
+ const total = widths.reduce((sum, width) => sum + width, 0);
339
+ const viewport = this._body?.clientWidth || this._container?.clientWidth || total;
340
+ const previous = this._previousStyles.get(CONTENT_MIN_WIDTH_PROPERTY);
341
+ const required = Math.max(total, this._element?.scrollWidth || 0);
342
+ const next = required > viewport + 1 ? `${Math.ceil(required)}px` : previous;
343
+ const current = this._container.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY);
344
+ if (next) this._container.style.setProperty(CONTENT_MIN_WIDTH_PROPERTY, next);
345
+ else this._container.style.removeProperty(CONTENT_MIN_WIDTH_PROPERTY);
346
+ return current !== (next || '');
347
+ }
348
+
312
349
  _getHeaders() {
313
350
  const rows = Array.from(this._head?.rows || []);
314
351
  return rows.length ? Array.from(rows.at(-1).cells || []) : [];
@@ -340,9 +377,10 @@ class _stickyHeader {
340
377
  }
341
378
 
342
379
  _readTableMinimumWidth() {
343
- if (typeof getComputedStyle !== 'function') return 0;
344
- const value = Number.parseFloat(getComputedStyle(this._element).minWidth || '0');
345
- return Number.isFinite(value) ? value : 0;
380
+ const generated = Number.parseFloat(this._container?.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY) || '0');
381
+ if (typeof getComputedStyle !== 'function') return Number.isFinite(generated) ? generated : 0;
382
+ const declared = Number.parseFloat(getComputedStyle(this._element).minWidth || '0');
383
+ return Math.max(Number.isFinite(generated) ? generated : 0, Number.isFinite(declared) ? declared : 0);
346
384
  }
347
385
 
348
386
  _syncScroll() {
@@ -146,11 +146,12 @@ class VGTable extends BaseModule {
146
146
  if (!this._complex && !this._sorting && this._params.sort.enabled === true && this._params.rowReorder.enabled !== true) {
147
147
  this._sorting = new _sorting(this._element, Object.assign({}, this._params.sort, {remote: this._isRemote}), this._stickyHeader?.getHeaderTable());
148
148
  this._sorting.init();
149
- this._element.addEventListener(
150
- 'sortchange.vg.table',
151
- this._isRemote ? this._boundRemoteSortChange : this._boundLocalSortChange
152
- );
153
- }
149
+ this._element.addEventListener(
150
+ 'sortchange.vg.table',
151
+ this._isRemote ? this._boundRemoteSortChange : this._boundLocalSortChange
152
+ );
153
+ this._stickyHeader?.refresh?.();
154
+ }
154
155
 
155
156
  // Фиксируем настоящие ячейки через native sticky, включая отдельный слой Fixed Header
156
157
  if (!this._complex && !this._fixedColumns && this._params.fixedColumns.enabled === true) {
@@ -57,9 +57,9 @@
57
57
 
58
58
  .vg-table-header__table,
59
59
  .vg-table-body > .vg-table {
60
- width: 100%;
61
- min-width: 100%;
62
- table-layout: fixed;
60
+ width: 100%;
61
+ min-width: max(100%, var(--vg-table-sticky-content-min-width, 0px));
62
+ table-layout: fixed;
63
63
  overflow: visible;
64
64
  border: 0;
65
65
  border-radius: 0;