vgapp 1.5.7 → 1.5.9
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.
- package/app/langs/en/buttons.json +17 -17
- package/app/langs/en/messages.json +36 -36
- package/app/langs/ru/buttons.json +17 -17
- package/app/langs/ru/messages.json +1 -1
- package/app/modules/vgalert/js/vgalert.js +15 -12
- package/app/modules/vgalert/scss/_variables.scss +16 -16
- package/app/modules/vgalert/scss/vgalert.scss +13 -6
- package/app/modules/vgcollapse/scss/_variables.scss +7 -7
- package/app/modules/vgcollapse/scss/vgcollapse.scss +5 -5
- package/app/modules/vgdropdown/scss/_variables.scss +14 -14
- package/app/modules/vgdropdown/scss/vgdropdown.scss +5 -5
- package/app/modules/vgfilepreview/js/i18n.js +56 -56
- package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
- package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
- package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
- package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
- package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
- package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
- package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
- package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
- package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
- package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
- package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
- package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
- package/app/modules/vgfilepreview/readme.md +68 -68
- package/app/modules/vgfiles/js/base.js +198 -198
- package/app/modules/vgfiles/js/droppable.js +17 -17
- package/app/modules/vgfiles/js/render.js +153 -153
- package/app/modules/vgfiles/js/sortable.js +52 -52
- package/app/modules/vgfiles/js/vgfiles.js +43 -43
- package/app/modules/vgfiles/readme.md +123 -123
- package/app/modules/vgfiles/scss/_mixins.scss +13 -13
- package/app/modules/vgfiles/scss/_variables.scss +10 -10
- package/app/modules/vgfiles/scss/vgfiles.scss +28 -28
- package/app/modules/vgformsender/js/hideshowpass.js +22 -22
- package/app/modules/vgformsender/readme.md +1 -1
- package/app/modules/vgformsender/scss/_variables.scss +5 -5
- package/app/modules/vgformsender/scss/vgformsender.scss +42 -42
- package/app/modules/vglawcookie/js/vglawcookie.js +19 -19
- package/app/modules/vglawcookie/scss/_variables.scss +13 -13
- package/app/modules/vglawcookie/scss/vglawcookie.scss +5 -5
- package/app/modules/vgmodal/js/vgmodal.interaction.js +216 -216
- package/app/modules/vgmodal/js/vgmodal.js +9 -9
- package/app/modules/vgmodal/js/vgmodal.minimized.js +227 -227
- package/app/modules/vgmodal/scss/_variables.scss +17 -17
- package/app/modules/vgmodal/scss/vgmodal.scss +77 -77
- package/app/modules/vgnav/js/vgnav.js +137 -84
- package/app/modules/vgnav/scss/_breakpoints.scss +36 -36
- package/app/modules/vgnav/scss/_hamburger.scss +5 -5
- package/app/modules/vgnav/scss/_placement.scss +5 -5
- package/app/modules/vgnav/scss/_toggle.scss +5 -5
- package/app/modules/vgnav/scss/_variables.scss +26 -26
- package/app/modules/vgnav/scss/vgnav.scss +41 -41
- package/app/modules/vgnestable/README.md +39 -39
- package/app/modules/vgrangeslider/js/skins.js +8 -8
- package/app/modules/vgrangeslider/js/vgrangeslider.js +29 -29
- package/app/modules/vgrangeslider/scss/_variables.scss +55 -55
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +239 -239
- package/app/modules/vgrollup/js/vgrollup.js +15 -15
- package/app/modules/vgrollup/scss/_variables.scss +15 -15
- package/app/modules/vgrollup/scss/vgrollup.scss +6 -6
- package/app/modules/vgselect/js/handlers.js +6 -6
- package/app/modules/vgselect/js/vgselect.js +167 -123
- package/app/modules/vgselect/readme.md +11 -11
- package/app/modules/vgselect/scss/_variables.scss +51 -51
- package/app/modules/vgselect/scss/vgselect.scss +1 -1
- package/app/modules/vgsidebar/js/vgsidebar.js +21 -21
- package/app/modules/vgsidebar/scss/_variables.scss +10 -10
- package/app/modules/vgsidebar/scss/vgsidebar.scss +5 -5
- package/app/modules/vgspy/js/vgspy.js +43 -43
- package/app/modules/vgtable/js/_filters.js +10 -6
- package/app/modules/vgtable/js/_options.js +16 -16
- package/app/modules/vgtable/js/_pagination.js +118 -118
- package/app/modules/vgtable/js/_responsive.js +79 -79
- package/app/modules/vgtable/js/_sticky-header.js +349 -280
- package/app/modules/vgtable/js/vgtable.js +98 -98
- package/app/modules/vgtable/scss/_fixed-columns.scss +23 -25
- package/app/modules/vgtable/scss/_sorting.scss +6 -6
- package/app/modules/vgtable/scss/_sticky-header.scss +31 -31
- package/app/modules/vgtable/scss/_variables.scss +6 -4
- package/app/modules/vgtable/scss/vgtable.scss +8 -4
- package/app/modules/vgtabs/js/vgtabs.js +91 -91
- package/app/modules/vgtabs/scss/_variables.scss +23 -23
- package/app/modules/vgtabs/scss/vgtabs.scss +5 -5
- package/app/modules/vgtoast/js/vgtoast.js +4 -4
- package/app/modules/vgtoast/scss/_variables.scss +13 -13
- package/app/modules/vgtoast/scss/vgtoast.scss +5 -5
- package/app/modules/vgtooltip/js/vgtooltip.js +127 -127
- package/app/modules/vgtooltip/scss/_variables.scss +10 -10
- package/app/modules/vgtooltip/scss/vgtooltip.scss +5 -5
- package/app/utils/js/components/audio-metadata.js +240 -240
- package/app/utils/js/components/backdrop.js +116 -116
- package/app/utils/js/components/file-icon.js +7 -7
- package/app/utils/js/components/file-preview.js +304 -304
- package/app/utils/js/components/responsive.js +165 -165
- package/app/utils/js/components/sanitize.js +150 -150
- package/app/utils/js/components/video-metadata.js +140 -140
- package/app/utils/scss/_backdrop.scss +5 -5
- package/app/utils/scss/_theme-default.scss +12 -12
- package/app/utils/scss/_theme.scss +7 -7
- package/app/utils/scss/default.scss +9 -9
- package/app/utils/scss/functions.scss +21 -21
- package/app/utils/scss/index.scss +4 -4
- package/app/utils/scss/mixin.scss +16 -16
- package/app/utils/scss/variables.scss +147 -147
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +1 -1
- package/build/vgapp.js.map +1 -1
- package/index.js +7 -7
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Описание: разметка Fixed Header с отдельными слоями заголовка и тела VGTable.
|
|
3
|
-
* Возможности: перенос настоящего thead без клона, intrinsic-минимумы и синхронизация ширин колонок и горизонтальной прокрутки.
|
|
4
|
-
*/
|
|
1
|
+
/**
|
|
2
|
+
* Описание: разметка Fixed Header с отдельными слоями заголовка и тела VGTable.
|
|
3
|
+
* Возможности: перенос настоящего thead без клона, intrinsic-минимумы и синхронизация ширин колонок и горизонтальной прокрутки.
|
|
4
|
+
*/
|
|
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 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];
|
|
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];
|
|
10
10
|
const GENERATED_LAYER_ATTRIBUTE = 'data-vg-table-sticky-generated';
|
|
11
11
|
|
|
12
12
|
class _stickyHeader {
|
|
@@ -19,25 +19,26 @@ class _stickyHeader {
|
|
|
19
19
|
this._header = null;
|
|
20
20
|
this._headerTable = null;
|
|
21
21
|
this._body = null;
|
|
22
|
-
this._previousClasses = new Map();
|
|
23
|
-
this._previousContainerClasses = new Map();
|
|
24
|
-
this._previousStyles = new Map();
|
|
25
|
-
this._columnWeights = new Map();
|
|
26
|
-
this._hardColumnWidths = new Map();
|
|
22
|
+
this._previousClasses = new Map();
|
|
23
|
+
this._previousContainerClasses = new Map();
|
|
24
|
+
this._previousStyles = new Map();
|
|
25
|
+
this._columnWeights = new Map();
|
|
26
|
+
this._hardColumnWidths = new Map();
|
|
27
27
|
this._columnMinimumWidths = new Map();
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
28
|
+
this._autoLayoutWidths = null;
|
|
29
|
+
this._hasSourceColgroup = false;
|
|
30
|
+
this._resizeObserver = null;
|
|
31
|
+
this._resizeFrame = null;
|
|
32
|
+
this._boundScroll = this._syncScroll.bind(this);
|
|
33
|
+
this._boundResize = this._scheduleRefresh.bind(this);
|
|
34
|
+
this._boundPageScroll = this._syncStickyState.bind(this);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
init() {
|
|
37
|
-
if (!this._wrapper || !this._container || !this._head) return this;
|
|
38
|
-
|
|
39
|
-
const widths = this._measureColumns();
|
|
40
|
-
this._rememberColumnGeometry(widths);
|
|
38
|
+
if (!this._wrapper || !this._container || !this._head) return this;
|
|
39
|
+
|
|
40
|
+
const widths = this._measureColumns();
|
|
41
|
+
this._rememberColumnGeometry(widths);
|
|
41
42
|
MODE_CLASSES.forEach((className) => this._previousClasses.set(className, this._wrapper.classList.contains(className)));
|
|
42
43
|
CONTAINER_MODE_CLASSES.forEach((className) => this._previousContainerClasses.set(className, this._container.classList.contains(className)));
|
|
43
44
|
STYLE_PROPERTIES.forEach((property) => this._previousStyles.set(property, this._container.style.getPropertyValue(property)));
|
|
@@ -50,17 +51,17 @@ class _stickyHeader {
|
|
|
50
51
|
this._container.style.setProperty('--vg-table-sticky-max-height', this._toCssLength(this._params.maxHeight, '24rem'));
|
|
51
52
|
this._element.setAttribute('data-vg-table-sticky-header', this._params.mode);
|
|
52
53
|
|
|
53
|
-
this._buildLayers(widths);
|
|
54
|
-
this._body.addEventListener('scroll', this._boundScroll, {passive: true});
|
|
55
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
56
|
-
this._resizeObserver = new ResizeObserver(this._boundResize);
|
|
57
|
-
this._resizeObserver.observe(this._container);
|
|
58
|
-
this._resizeObserver.observe(this._body);
|
|
59
|
-
} else if (typeof window !== 'undefined') {
|
|
60
|
-
window.addEventListener('resize', this._boundResize);
|
|
61
|
-
}
|
|
62
|
-
if (this._params.mode === 'page' && typeof window !== 'undefined') window.addEventListener('scroll', this._boundPageScroll, {passive: true});
|
|
63
|
-
this.refresh();
|
|
54
|
+
this._buildLayers(widths);
|
|
55
|
+
this._body.addEventListener('scroll', this._boundScroll, {passive: true});
|
|
56
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
57
|
+
this._resizeObserver = new ResizeObserver(this._boundResize);
|
|
58
|
+
this._resizeObserver.observe(this._container);
|
|
59
|
+
this._resizeObserver.observe(this._body);
|
|
60
|
+
} else if (typeof window !== 'undefined') {
|
|
61
|
+
window.addEventListener('resize', this._boundResize);
|
|
62
|
+
}
|
|
63
|
+
if (this._params.mode === 'page' && typeof window !== 'undefined') window.addEventListener('scroll', this._boundPageScroll, {passive: true});
|
|
64
|
+
this.refresh();
|
|
64
65
|
return this;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -68,18 +69,47 @@ class _stickyHeader {
|
|
|
68
69
|
return this._headerTable || this._element;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
getBody() {
|
|
72
|
-
return this._body;
|
|
73
|
-
}
|
|
74
|
-
|
|
72
|
+
getBody() {
|
|
73
|
+
return this._body;
|
|
74
|
+
}
|
|
75
|
+
|
|
75
76
|
refreshIntrinsicMinimums() {
|
|
77
|
+
const declaredMinimum = this._previousStyles.get(CONTENT_MIN_WIDTH_PROPERTY);
|
|
78
|
+
if (declaredMinimum) this._container.style.setProperty(CONTENT_MIN_WIDTH_PROPERTY, declaredMinimum);
|
|
79
|
+
else this._container.style.removeProperty(CONTENT_MIN_WIDTH_PROPERTY);
|
|
80
|
+
|
|
81
|
+
const autoWidths = this._measureAutoLayoutColumns();
|
|
76
82
|
const widths = this._measureIntrinsicColumnMinimums();
|
|
83
|
+
const activeKeys = new Set();
|
|
77
84
|
this._getHeaders().forEach((header, index) => {
|
|
78
85
|
const key = this._columnKey(header, index);
|
|
86
|
+
activeKeys.add(key);
|
|
79
87
|
if (this._hasDeclaredWidth(header) || this._hardColumnWidths.has(key) || !(widths[index] > 0)) return;
|
|
80
|
-
|
|
88
|
+
// AJAX может как расширить, так и сузить обычное содержимое. Пустой th
|
|
89
|
+
// является служебным заголовком (checkbox/actions) и должен сохранять
|
|
90
|
+
// уже измеренную по body ширину, иначе колонка схлопнется.
|
|
91
|
+
const previousMinimum = this._columnMinimumWidths.get(key) || 0;
|
|
92
|
+
const minimum = this._isEmptyHeader(header)
|
|
93
|
+
? Math.max(previousMinimum, widths[index])
|
|
94
|
+
: widths[index];
|
|
95
|
+
this._columnMinimumWidths.set(key, minimum);
|
|
96
|
+
this._columnWeights.set(key, this._isEmptyHeader(header)
|
|
97
|
+
? Math.max(this._columnWeights.get(key) || 0, minimum)
|
|
98
|
+
: widths[index]);
|
|
99
|
+
});
|
|
100
|
+
[this._columnWeights, this._hardColumnWidths, this._columnMinimumWidths].forEach((geometry) => {
|
|
101
|
+
Array.from(geometry.keys()).forEach((key) => {
|
|
102
|
+
if (!activeKeys.has(key)) geometry.delete(key);
|
|
103
|
+
});
|
|
81
104
|
});
|
|
82
|
-
|
|
105
|
+
this._autoLayoutWidths = autoWidths.length === this._getHeaders().length && autoWidths.every((width) => width > 0)
|
|
106
|
+
? autoWidths
|
|
107
|
+
: null;
|
|
108
|
+
try {
|
|
109
|
+
return this.refresh();
|
|
110
|
+
} finally {
|
|
111
|
+
this._autoLayoutWidths = null;
|
|
112
|
+
}
|
|
83
113
|
}
|
|
84
114
|
|
|
85
115
|
syncScroll() {
|
|
@@ -87,20 +117,20 @@ class _stickyHeader {
|
|
|
87
117
|
return this;
|
|
88
118
|
}
|
|
89
119
|
|
|
90
|
-
refresh() {
|
|
91
|
-
if (!this._header || !this._headerTable || !this._body) return this;
|
|
92
|
-
|
|
93
|
-
let widths = this._resolveLayoutWidths();
|
|
94
|
-
const attempts = this._getHeaders().length + 2;
|
|
95
|
-
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
96
|
-
this._applyColgroup(this._headerTable, widths);
|
|
97
|
-
this._applyColgroup(this._element, widths);
|
|
98
|
-
const headerChanged = this._captureOverflowingHeaderMinimums();
|
|
99
|
-
const contentChanged = this._syncContentMinimumWidth(widths);
|
|
100
|
-
if (!headerChanged && !contentChanged) break;
|
|
101
|
-
widths = this._resolveLayoutWidths();
|
|
102
|
-
}
|
|
103
|
-
const scrollbar = Math.max(0, this._body.offsetWidth - this._body.clientWidth);
|
|
120
|
+
refresh() {
|
|
121
|
+
if (!this._header || !this._headerTable || !this._body) return this;
|
|
122
|
+
|
|
123
|
+
let widths = this._resolveLayoutWidths();
|
|
124
|
+
const attempts = this._getHeaders().length + 2;
|
|
125
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
126
|
+
this._applyColgroup(this._headerTable, widths);
|
|
127
|
+
this._applyColgroup(this._element, widths);
|
|
128
|
+
const headerChanged = this._captureOverflowingHeaderMinimums();
|
|
129
|
+
const contentChanged = this._syncContentMinimumWidth(widths);
|
|
130
|
+
if (!headerChanged && !contentChanged) break;
|
|
131
|
+
widths = this._resolveLayoutWidths();
|
|
132
|
+
}
|
|
133
|
+
const scrollbar = Math.max(0, this._body.offsetWidth - this._body.clientWidth);
|
|
104
134
|
this._header.style.paddingInlineEnd = `${scrollbar}px`;
|
|
105
135
|
this._header.style.setProperty('--vg-table-sticky-scrollbar-width', `${scrollbar}px`);
|
|
106
136
|
this._header.classList.toggle('vg-table-header--scrollbar', scrollbar > 0);
|
|
@@ -110,17 +140,17 @@ class _stickyHeader {
|
|
|
110
140
|
return this;
|
|
111
141
|
}
|
|
112
142
|
|
|
113
|
-
dispose() {
|
|
114
|
-
if (this._body) this._body.removeEventListener('scroll', this._boundScroll);
|
|
115
|
-
this._resizeObserver?.disconnect();
|
|
116
|
-
if (this._resizeFrame !== null && typeof cancelAnimationFrame === 'function') {
|
|
117
|
-
cancelAnimationFrame(this._resizeFrame);
|
|
118
|
-
this._resizeFrame = null;
|
|
119
|
-
}
|
|
120
|
-
if (typeof window !== 'undefined') {
|
|
121
|
-
if (!this._resizeObserver) window.removeEventListener('resize', this._boundResize);
|
|
122
|
-
window.removeEventListener('scroll', this._boundPageScroll);
|
|
123
|
-
}
|
|
143
|
+
dispose() {
|
|
144
|
+
if (this._body) this._body.removeEventListener('scroll', this._boundScroll);
|
|
145
|
+
this._resizeObserver?.disconnect();
|
|
146
|
+
if (this._resizeFrame !== null && typeof cancelAnimationFrame === 'function') {
|
|
147
|
+
cancelAnimationFrame(this._resizeFrame);
|
|
148
|
+
this._resizeFrame = null;
|
|
149
|
+
}
|
|
150
|
+
if (typeof window !== 'undefined') {
|
|
151
|
+
if (!this._resizeObserver) window.removeEventListener('resize', this._boundResize);
|
|
152
|
+
window.removeEventListener('scroll', this._boundPageScroll);
|
|
153
|
+
}
|
|
124
154
|
this._header?.classList.remove('is-stuck');
|
|
125
155
|
if (this._head && this._headerTable?.contains(this._head)) this._element.prepend(this._head);
|
|
126
156
|
this._header?.remove();
|
|
@@ -135,25 +165,25 @@ class _stickyHeader {
|
|
|
135
165
|
CONTAINER_MODE_CLASSES.forEach((className) => {
|
|
136
166
|
this._container.classList.toggle(className, this._previousContainerClasses.get(className) === true);
|
|
137
167
|
});
|
|
138
|
-
STYLE_PROPERTIES.forEach((property) => {
|
|
168
|
+
STYLE_PROPERTIES.forEach((property) => {
|
|
139
169
|
const previous = this._previousStyles.get(property);
|
|
140
170
|
if (previous) this._container.style.setProperty(property, previous);
|
|
141
171
|
else this._container.style.removeProperty(property);
|
|
142
|
-
});
|
|
143
|
-
this._element.removeAttribute('data-vg-table-sticky-header');
|
|
144
|
-
}
|
|
145
|
-
|
|
172
|
+
});
|
|
173
|
+
this._element.removeAttribute('data-vg-table-sticky-header');
|
|
174
|
+
}
|
|
175
|
+
|
|
146
176
|
_scheduleRefresh() {
|
|
147
|
-
if (this._resizeFrame !== null) return;
|
|
177
|
+
if (this._resizeFrame !== null) return;
|
|
148
178
|
if (typeof requestAnimationFrame !== 'function') {
|
|
149
|
-
this.
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
179
|
+
this.refreshIntrinsicMinimums();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
152
182
|
this._resizeFrame = requestAnimationFrame(() => {
|
|
153
183
|
this._resizeFrame = null;
|
|
154
|
-
this.
|
|
184
|
+
this.refreshIntrinsicMinimums();
|
|
155
185
|
});
|
|
156
|
-
}
|
|
186
|
+
}
|
|
157
187
|
|
|
158
188
|
_buildLayers(widths) {
|
|
159
189
|
this._header = this._element.ownerDocument.createElement('div');
|
|
@@ -177,24 +207,24 @@ class _stickyHeader {
|
|
|
177
207
|
this._body.append(this._element);
|
|
178
208
|
}
|
|
179
209
|
|
|
180
|
-
_measureColumns() {
|
|
181
|
-
return this._measureBodyColumns();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
_measureBodyColumns() {
|
|
185
|
-
const headerRow = this._head?.rows[this._head.rows.length - 1];
|
|
186
|
-
const headerWidths = this._measureRow(headerRow);
|
|
187
|
-
const rows = Array.from(this._element.tBodies || []).flatMap((body) => Array.from(body.rows || []));
|
|
188
|
-
for (const row of rows) {
|
|
189
|
-
if (row.hidden || row.hasAttribute('data-vg-table-state-row') || row.hasAttribute('data-vg-table-skeleton') || row.hasAttribute('data-vg-table-skeleton-row')) continue;
|
|
190
|
-
if (row.querySelector('[data-vg-table-state]')) continue;
|
|
191
|
-
const widths = this._measureRow(row);
|
|
192
|
-
if (widths.length === headerWidths.length && widths.some((width) => width > 0)) return widths;
|
|
193
|
-
}
|
|
194
|
-
return headerWidths;
|
|
195
|
-
}
|
|
210
|
+
_measureColumns() {
|
|
211
|
+
return this._measureBodyColumns();
|
|
212
|
+
}
|
|
196
213
|
|
|
197
|
-
|
|
214
|
+
_measureBodyColumns() {
|
|
215
|
+
const headerRow = this._head?.rows[this._head.rows.length - 1];
|
|
216
|
+
const headerWidths = this._measureRow(headerRow);
|
|
217
|
+
const rows = Array.from(this._element.tBodies || []).flatMap((body) => Array.from(body.rows || []));
|
|
218
|
+
for (const row of rows) {
|
|
219
|
+
if (row.hidden || row.hasAttribute('data-vg-table-state-row') || row.hasAttribute('data-vg-table-skeleton') || row.hasAttribute('data-vg-table-skeleton-row')) continue;
|
|
220
|
+
if (row.querySelector('[data-vg-table-state]')) continue;
|
|
221
|
+
const widths = this._measureRow(row);
|
|
222
|
+
if (widths.length === headerWidths.length && widths.some((width) => width > 0)) return widths;
|
|
223
|
+
}
|
|
224
|
+
return headerWidths;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
_measureRow(row) {
|
|
198
228
|
if (!row) return [];
|
|
199
229
|
return Array.from(row.cells).flatMap((cell) => {
|
|
200
230
|
const span = Math.max(1, cell.colSpan || 1);
|
|
@@ -203,30 +233,62 @@ class _stickyHeader {
|
|
|
203
233
|
});
|
|
204
234
|
}
|
|
205
235
|
|
|
206
|
-
_applyColgroup(table, widths) {
|
|
207
|
-
if (!widths.length) return;
|
|
208
|
-
if (table.querySelector(':scope > colgroup:not([data-vg-table-sticky-colgroup])')) return;
|
|
209
|
-
let colgroup = table.querySelector(':scope > colgroup[data-vg-table-sticky-colgroup]');
|
|
236
|
+
_applyColgroup(table, widths) {
|
|
237
|
+
if (!widths.length) return;
|
|
238
|
+
if (table.querySelector(':scope > colgroup:not([data-vg-table-sticky-colgroup])')) return;
|
|
239
|
+
let colgroup = table.querySelector(':scope > colgroup[data-vg-table-sticky-colgroup]');
|
|
210
240
|
if (!colgroup) {
|
|
211
241
|
colgroup = table.ownerDocument.createElement('colgroup');
|
|
212
|
-
colgroup.setAttribute('data-vg-table-sticky-colgroup', '');
|
|
213
|
-
table.prepend(colgroup);
|
|
214
|
-
}
|
|
215
|
-
while (colgroup.children.length < widths.length) colgroup.append(table.ownerDocument.createElement('col'));
|
|
216
|
-
while (colgroup.children.length > widths.length) colgroup.lastElementChild.remove();
|
|
217
|
-
const headers = this._getHeaders();
|
|
218
|
-
widths.forEach((width, index) => {
|
|
219
|
-
const col = colgroup.children[index];
|
|
220
|
-
if (width > 0) col.style.width = `${width}px`;
|
|
221
|
-
else col.style.removeProperty('width');
|
|
222
|
-
const hidden = headers[index]?.hidden === true;
|
|
223
|
-
col.hidden = hidden;
|
|
224
|
-
col.toggleAttribute('data-vg-table-column-hidden', hidden);
|
|
225
|
-
});
|
|
242
|
+
colgroup.setAttribute('data-vg-table-sticky-colgroup', '');
|
|
243
|
+
table.prepend(colgroup);
|
|
244
|
+
}
|
|
245
|
+
while (colgroup.children.length < widths.length) colgroup.append(table.ownerDocument.createElement('col'));
|
|
246
|
+
while (colgroup.children.length > widths.length) colgroup.lastElementChild.remove();
|
|
247
|
+
const headers = this._getHeaders();
|
|
248
|
+
widths.forEach((width, index) => {
|
|
249
|
+
const col = colgroup.children[index];
|
|
250
|
+
if (width > 0) col.style.width = `${width}px`;
|
|
251
|
+
else col.style.removeProperty('width');
|
|
252
|
+
const hidden = headers[index]?.hidden === true;
|
|
253
|
+
col.hidden = hidden;
|
|
254
|
+
col.toggleAttribute('data-vg-table-column-hidden', hidden);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_measureIntrinsicColumnMinimums() {
|
|
259
|
+
if (!this._wrapper || !this._head) return [];
|
|
260
|
+
|
|
261
|
+
const probe = this._element.cloneNode(true);
|
|
262
|
+
probe.removeAttribute('data-vg-table');
|
|
263
|
+
probe.removeAttribute('data-vg-table-sticky-header');
|
|
264
|
+
probe.setAttribute('aria-hidden', 'true');
|
|
265
|
+
probe.querySelector(':scope > colgroup[data-vg-table-sticky-colgroup]')?.remove();
|
|
266
|
+
probe.insertBefore(this._head.cloneNode(true), probe.tBodies[0] || null);
|
|
267
|
+
probe.querySelectorAll('thead th').forEach((header) => header.style.setProperty('white-space', 'nowrap', 'important'));
|
|
268
|
+
[
|
|
269
|
+
['position', 'absolute'],
|
|
270
|
+
['inset', '0 auto auto 0'],
|
|
271
|
+
['visibility', 'hidden'],
|
|
272
|
+
['pointer-events', 'none'],
|
|
273
|
+
['width', 'min-content'],
|
|
274
|
+
['min-width', '0'],
|
|
275
|
+
['max-width', 'none'],
|
|
276
|
+
['table-layout', 'auto'],
|
|
277
|
+
].forEach(([property, value]) => probe.style.setProperty(property, value, 'important'));
|
|
278
|
+
|
|
279
|
+
this._wrapper.append(probe);
|
|
280
|
+
try {
|
|
281
|
+
const rows = Array.from(probe.tHead?.rows || []);
|
|
282
|
+
return this._measureRow(rows.at(-1));
|
|
283
|
+
} finally {
|
|
284
|
+
probe.remove();
|
|
285
|
+
}
|
|
226
286
|
}
|
|
227
287
|
|
|
228
|
-
|
|
288
|
+
_measureAutoLayoutColumns() {
|
|
229
289
|
if (!this._wrapper || !this._head) return [];
|
|
290
|
+
const viewport = this._body?.clientWidth || this._container?.clientWidth || 0;
|
|
291
|
+
if (!(viewport > 0)) return [];
|
|
230
292
|
|
|
231
293
|
const probe = this._element.cloneNode(true);
|
|
232
294
|
probe.removeAttribute('data-vg-table');
|
|
@@ -234,13 +296,12 @@ class _stickyHeader {
|
|
|
234
296
|
probe.setAttribute('aria-hidden', 'true');
|
|
235
297
|
probe.querySelector(':scope > colgroup[data-vg-table-sticky-colgroup]')?.remove();
|
|
236
298
|
probe.insertBefore(this._head.cloneNode(true), probe.tBodies[0] || null);
|
|
237
|
-
probe.querySelectorAll('thead th').forEach((header) => header.style.setProperty('white-space', 'nowrap', 'important'));
|
|
238
299
|
[
|
|
239
300
|
['position', 'absolute'],
|
|
240
301
|
['inset', '0 auto auto 0'],
|
|
241
302
|
['visibility', 'hidden'],
|
|
242
303
|
['pointer-events', 'none'],
|
|
243
|
-
['width',
|
|
304
|
+
['width', `${viewport}px`],
|
|
244
305
|
['min-width', '0'],
|
|
245
306
|
['max-width', 'none'],
|
|
246
307
|
['table-layout', 'auto'],
|
|
@@ -248,181 +309,189 @@ class _stickyHeader {
|
|
|
248
309
|
|
|
249
310
|
this._wrapper.append(probe);
|
|
250
311
|
try {
|
|
251
|
-
const
|
|
252
|
-
|
|
312
|
+
const headerRow = Array.from(probe.tHead?.rows || []).at(-1);
|
|
313
|
+
const headerWidths = this._measureRow(headerRow);
|
|
314
|
+
const row = Array.from(probe.tBodies || [])
|
|
315
|
+
.flatMap((body) => Array.from(body.rows || []))
|
|
316
|
+
.find((item) => !item.hidden && !item.hasAttribute('data-vg-table-state-row') && !item.hasAttribute('data-vg-table-skeleton'));
|
|
317
|
+
const bodyWidths = this._measureRow(row);
|
|
318
|
+
return bodyWidths.length === headerWidths.length && bodyWidths.some((width) => width > 0)
|
|
319
|
+
? bodyWidths
|
|
320
|
+
: headerWidths;
|
|
253
321
|
} finally {
|
|
254
322
|
probe.remove();
|
|
255
323
|
}
|
|
256
324
|
}
|
|
257
|
-
|
|
258
|
-
_rememberColumnGeometry(widths) {
|
|
259
|
-
const headers = this._getHeaders();
|
|
260
|
-
const sourceCols = Array.from(this._element.querySelector(':scope > colgroup:not([data-vg-table-sticky-colgroup])')?.children || []);
|
|
261
|
-
this._hasSourceColgroup = sourceCols.length > 0;
|
|
262
|
-
headers.forEach((header, index) => {
|
|
263
|
-
const key = this._columnKey(header, index);
|
|
264
|
-
this._columnWeights.set(key, widths[index] > 0 ? widths[index] : 1);
|
|
265
|
-
if (this._hasDeclaredWidth(header) || this._hasDeclaredWidth(sourceCols[index])) {
|
|
266
|
-
this._hardColumnWidths.set(key, widths[index] > 0 ? widths[index] : 0);
|
|
267
|
-
} else if (this._isEmptyHeader(header) && widths[index] > 0) {
|
|
268
|
-
this._columnMinimumWidths.set(key, widths[index]);
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
325
|
+
|
|
326
|
+
_rememberColumnGeometry(widths) {
|
|
327
|
+
const headers = this._getHeaders();
|
|
328
|
+
const sourceCols = Array.from(this._element.querySelector(':scope > colgroup:not([data-vg-table-sticky-colgroup])')?.children || []);
|
|
329
|
+
this._hasSourceColgroup = sourceCols.length > 0;
|
|
330
|
+
headers.forEach((header, index) => {
|
|
331
|
+
const key = this._columnKey(header, index);
|
|
332
|
+
this._columnWeights.set(key, widths[index] > 0 ? widths[index] : 1);
|
|
333
|
+
if (this._hasDeclaredWidth(header) || this._hasDeclaredWidth(sourceCols[index])) {
|
|
334
|
+
this._hardColumnWidths.set(key, widths[index] > 0 ? widths[index] : 0);
|
|
335
|
+
} else if (this._isEmptyHeader(header) && widths[index] > 0) {
|
|
336
|
+
this._columnMinimumWidths.set(key, widths[index]);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
273
341
|
_resolveLayoutWidths() {
|
|
274
342
|
const headers = this._getHeaders();
|
|
343
|
+
if (this._autoLayoutWidths?.length === headers.length) return this._autoLayoutWidths.slice();
|
|
275
344
|
const measured = this._measureBodyColumns();
|
|
276
|
-
if (this._hasSourceColgroup || !headers.length) return measured;
|
|
277
|
-
|
|
278
|
-
const bodyRow = Array.from(this._element.tBodies || [])
|
|
279
|
-
.flatMap((body) => Array.from(body.rows || []))
|
|
280
|
-
.find((row) => !row.hidden && !row.hasAttribute('data-vg-table-state-row'));
|
|
281
|
-
const hard = new Map();
|
|
282
|
-
const flexible = [];
|
|
283
|
-
headers.forEach((header, index) => {
|
|
284
|
-
const key = this._columnKey(header, index);
|
|
285
|
-
const bodyCell = bodyRow?.cells[index];
|
|
286
|
-
if (this._hasDeclaredWidth(header) || this._hasDeclaredWidth(bodyCell) || this._hardColumnWidths.has(key)) {
|
|
287
|
-
const declared = this._readDeclaredPixelWidth(header) || this._readDeclaredPixelWidth(bodyCell);
|
|
288
|
-
const width = declared || this._hardColumnWidths.get(key) || measured[index] || 0;
|
|
289
|
-
this._hardColumnWidths.set(key, width);
|
|
290
|
-
hard.set(index, width);
|
|
291
|
-
} else {
|
|
292
|
-
flexible.push(index);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
const measuredTotal = measured.reduce((total, width) => total + width, 0);
|
|
297
|
-
const viewport = this._body?.clientWidth || this._container?.clientWidth || measuredTotal;
|
|
298
|
-
const minimum = this._readTableMinimumWidth();
|
|
299
|
-
const target = Math.max(viewport, minimum, 0);
|
|
300
|
-
const hardTotal = Array.from(hard.values()).reduce((total, width) => total + width, 0);
|
|
301
|
-
const available = Math.max(0, target - hardTotal);
|
|
302
|
-
const widths = Array(headers.length).fill(0);
|
|
303
|
-
hard.forEach((width, index) => { widths[index] = width; });
|
|
304
|
-
|
|
305
|
-
if (!flexible.length) return widths;
|
|
306
|
-
this._distributeFlexibleWidths(widths, flexible, available, headers, measured);
|
|
307
|
-
return widths;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
_distributeFlexibleWidths(widths, indexes, available, headers, measured) {
|
|
311
|
-
let pending = indexes.slice();
|
|
312
|
-
let remaining = available;
|
|
313
|
-
const minimumTotal = pending.reduce((total, index) => {
|
|
314
|
-
const key = this._columnKey(headers[index], index);
|
|
315
|
-
return total + (this._columnMinimumWidths.get(key) || 0);
|
|
316
|
-
}, 0);
|
|
317
|
-
|
|
318
|
-
if (minimumTotal > remaining) {
|
|
319
|
-
pending.forEach((index) => {
|
|
320
|
-
const key = this._columnKey(headers[index], index);
|
|
321
|
-
widths[index] = this._columnMinimumWidths.get(key) || 0;
|
|
322
|
-
});
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
while (pending.length) {
|
|
327
|
-
const weights = pending.map((index) => {
|
|
328
|
-
const key = this._columnKey(headers[index], index);
|
|
329
|
-
return this._columnWeights.get(key) || measured[index] || 1;
|
|
330
|
-
});
|
|
331
|
-
const weightTotal = weights.reduce((total, weight) => total + weight, 0) || pending.length;
|
|
332
|
-
const constrained = pending.filter((index, position) => {
|
|
333
|
-
const key = this._columnKey(headers[index], index);
|
|
334
|
-
const minimum = this._columnMinimumWidths.get(key) || 0;
|
|
335
|
-
return minimum > remaining * weights[position] / weightTotal;
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
if (!constrained.length) {
|
|
339
|
-
let distributed = 0;
|
|
340
|
-
pending.forEach((index, position) => {
|
|
341
|
-
const width = position === pending.length - 1
|
|
342
|
-
? Math.max(0, remaining - distributed)
|
|
343
|
-
: remaining * weights[position] / weightTotal;
|
|
344
|
-
widths[index] = width;
|
|
345
|
-
distributed += width;
|
|
346
|
-
});
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
constrained.forEach((index) => {
|
|
351
|
-
const key = this._columnKey(headers[index], index);
|
|
352
|
-
const minimum = this._columnMinimumWidths.get(key) || 0;
|
|
353
|
-
widths[index] = minimum;
|
|
354
|
-
remaining -= minimum;
|
|
355
|
-
});
|
|
356
|
-
pending = pending.filter((index) => !constrained.includes(index));
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
_captureOverflowingHeaderMinimums() {
|
|
361
|
-
let changed = false;
|
|
362
|
-
this._getHeaders().forEach((header, index) => {
|
|
363
|
-
const key = this._columnKey(header, index);
|
|
364
|
-
if (this._hasDeclaredWidth(header) || this._hardColumnWidths.has(key)) return;
|
|
365
|
-
|
|
366
|
-
const rendered = header.getBoundingClientRect?.().width || header.clientWidth || 0;
|
|
367
|
-
const required = header.scrollWidth || 0;
|
|
368
|
-
const current = this._columnMinimumWidths.get(key) || 0;
|
|
369
|
-
if (required <= rendered + 1 || required <= current + 1) return;
|
|
370
|
-
|
|
371
|
-
this._columnMinimumWidths.set(key, required);
|
|
372
|
-
changed = true;
|
|
373
|
-
});
|
|
374
|
-
return changed;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
_syncContentMinimumWidth(widths) {
|
|
378
|
-
const total = widths.reduce((sum, width) => sum + width, 0);
|
|
379
|
-
const viewport = this._body?.clientWidth || this._container?.clientWidth || total;
|
|
380
|
-
const previous = this._previousStyles.get(CONTENT_MIN_WIDTH_PROPERTY);
|
|
381
|
-
const required = Math.max(total, this._element?.scrollWidth || 0);
|
|
382
|
-
const next = required > viewport + 1 ? `${Math.ceil(required)}px` : previous;
|
|
383
|
-
const current = this._container.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY);
|
|
384
|
-
if (next) this._container.style.setProperty(CONTENT_MIN_WIDTH_PROPERTY, next);
|
|
385
|
-
else this._container.style.removeProperty(CONTENT_MIN_WIDTH_PROPERTY);
|
|
386
|
-
return current !== (next || '');
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
_getHeaders() {
|
|
390
|
-
const rows = Array.from(this._head?.rows || []);
|
|
391
|
-
return rows.length ? Array.from(rows.at(-1).cells || []) : [];
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
_columnKey(header, index) {
|
|
395
|
-
return String(header?.getAttribute('data-field') || index).trim();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
_isEmptyHeader(header) {
|
|
399
|
-
return Boolean(header) && header.childElementCount === 0 && String(header.textContent || '').trim() === '';
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
_hasDeclaredWidth(element) {
|
|
403
|
-
if (!element) return false;
|
|
404
|
-
return element.hasAttribute('width')
|
|
405
|
-
|| element.hasAttribute('data-column-width')
|
|
406
|
-
|| Boolean(element.style?.width || element.style?.minWidth || element.style?.maxWidth);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
_readDeclaredPixelWidth(element) {
|
|
410
|
-
if (!element || !this._hasDeclaredWidth(element)) return 0;
|
|
411
|
-
const fixed = element.style?.minWidth && element.style.minWidth === element.style.maxWidth
|
|
412
|
-
? Number.parseFloat(element.style.width || element.style.minWidth)
|
|
413
|
-
: 0;
|
|
414
|
-
if (Number.isFinite(fixed) && fixed > 0) return fixed;
|
|
415
|
-
const measured = element.getBoundingClientRect?.().width || element.offsetWidth || 0;
|
|
416
|
-
return measured > 0 ? measured : 0;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
_readTableMinimumWidth() {
|
|
420
|
-
const generated = Number.parseFloat(this._container?.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY) || '0');
|
|
421
|
-
if (typeof getComputedStyle !== 'function') return Number.isFinite(generated) ? generated : 0;
|
|
422
|
-
const declared = Number.parseFloat(getComputedStyle(this._element).minWidth || '0');
|
|
423
|
-
return Math.max(Number.isFinite(generated) ? generated : 0, Number.isFinite(declared) ? declared : 0);
|
|
424
|
-
}
|
|
425
|
-
|
|
345
|
+
if (this._hasSourceColgroup || !headers.length) return measured;
|
|
346
|
+
|
|
347
|
+
const bodyRow = Array.from(this._element.tBodies || [])
|
|
348
|
+
.flatMap((body) => Array.from(body.rows || []))
|
|
349
|
+
.find((row) => !row.hidden && !row.hasAttribute('data-vg-table-state-row'));
|
|
350
|
+
const hard = new Map();
|
|
351
|
+
const flexible = [];
|
|
352
|
+
headers.forEach((header, index) => {
|
|
353
|
+
const key = this._columnKey(header, index);
|
|
354
|
+
const bodyCell = bodyRow?.cells[index];
|
|
355
|
+
if (this._hasDeclaredWidth(header) || this._hasDeclaredWidth(bodyCell) || this._hardColumnWidths.has(key)) {
|
|
356
|
+
const declared = this._readDeclaredPixelWidth(header) || this._readDeclaredPixelWidth(bodyCell);
|
|
357
|
+
const width = declared || this._hardColumnWidths.get(key) || measured[index] || 0;
|
|
358
|
+
this._hardColumnWidths.set(key, width);
|
|
359
|
+
hard.set(index, width);
|
|
360
|
+
} else {
|
|
361
|
+
flexible.push(index);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const measuredTotal = measured.reduce((total, width) => total + width, 0);
|
|
366
|
+
const viewport = this._body?.clientWidth || this._container?.clientWidth || measuredTotal;
|
|
367
|
+
const minimum = this._readTableMinimumWidth();
|
|
368
|
+
const target = Math.max(viewport, minimum, 0);
|
|
369
|
+
const hardTotal = Array.from(hard.values()).reduce((total, width) => total + width, 0);
|
|
370
|
+
const available = Math.max(0, target - hardTotal);
|
|
371
|
+
const widths = Array(headers.length).fill(0);
|
|
372
|
+
hard.forEach((width, index) => { widths[index] = width; });
|
|
373
|
+
|
|
374
|
+
if (!flexible.length) return widths;
|
|
375
|
+
this._distributeFlexibleWidths(widths, flexible, available, headers, measured);
|
|
376
|
+
return widths;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
_distributeFlexibleWidths(widths, indexes, available, headers, measured) {
|
|
380
|
+
let pending = indexes.slice();
|
|
381
|
+
let remaining = available;
|
|
382
|
+
const minimumTotal = pending.reduce((total, index) => {
|
|
383
|
+
const key = this._columnKey(headers[index], index);
|
|
384
|
+
return total + (this._columnMinimumWidths.get(key) || 0);
|
|
385
|
+
}, 0);
|
|
386
|
+
|
|
387
|
+
if (minimumTotal > remaining) {
|
|
388
|
+
pending.forEach((index) => {
|
|
389
|
+
const key = this._columnKey(headers[index], index);
|
|
390
|
+
widths[index] = this._columnMinimumWidths.get(key) || 0;
|
|
391
|
+
});
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
while (pending.length) {
|
|
396
|
+
const weights = pending.map((index) => {
|
|
397
|
+
const key = this._columnKey(headers[index], index);
|
|
398
|
+
return this._columnWeights.get(key) || measured[index] || 1;
|
|
399
|
+
});
|
|
400
|
+
const weightTotal = weights.reduce((total, weight) => total + weight, 0) || pending.length;
|
|
401
|
+
const constrained = pending.filter((index, position) => {
|
|
402
|
+
const key = this._columnKey(headers[index], index);
|
|
403
|
+
const minimum = this._columnMinimumWidths.get(key) || 0;
|
|
404
|
+
return minimum > remaining * weights[position] / weightTotal;
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
if (!constrained.length) {
|
|
408
|
+
let distributed = 0;
|
|
409
|
+
pending.forEach((index, position) => {
|
|
410
|
+
const width = position === pending.length - 1
|
|
411
|
+
? Math.max(0, remaining - distributed)
|
|
412
|
+
: remaining * weights[position] / weightTotal;
|
|
413
|
+
widths[index] = width;
|
|
414
|
+
distributed += width;
|
|
415
|
+
});
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
constrained.forEach((index) => {
|
|
420
|
+
const key = this._columnKey(headers[index], index);
|
|
421
|
+
const minimum = this._columnMinimumWidths.get(key) || 0;
|
|
422
|
+
widths[index] = minimum;
|
|
423
|
+
remaining -= minimum;
|
|
424
|
+
});
|
|
425
|
+
pending = pending.filter((index) => !constrained.includes(index));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
_captureOverflowingHeaderMinimums() {
|
|
430
|
+
let changed = false;
|
|
431
|
+
this._getHeaders().forEach((header, index) => {
|
|
432
|
+
const key = this._columnKey(header, index);
|
|
433
|
+
if (this._hasDeclaredWidth(header) || this._hardColumnWidths.has(key)) return;
|
|
434
|
+
|
|
435
|
+
const rendered = header.getBoundingClientRect?.().width || header.clientWidth || 0;
|
|
436
|
+
const required = header.scrollWidth || 0;
|
|
437
|
+
const current = this._columnMinimumWidths.get(key) || 0;
|
|
438
|
+
if (required <= rendered + 1 || required <= current + 1) return;
|
|
439
|
+
|
|
440
|
+
this._columnMinimumWidths.set(key, required);
|
|
441
|
+
changed = true;
|
|
442
|
+
});
|
|
443
|
+
return changed;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_syncContentMinimumWidth(widths) {
|
|
447
|
+
const total = widths.reduce((sum, width) => sum + width, 0);
|
|
448
|
+
const viewport = this._body?.clientWidth || this._container?.clientWidth || total;
|
|
449
|
+
const previous = this._previousStyles.get(CONTENT_MIN_WIDTH_PROPERTY);
|
|
450
|
+
const required = Math.max(total, this._element?.scrollWidth || 0);
|
|
451
|
+
const next = required > viewport + 1 ? `${Math.ceil(required)}px` : previous;
|
|
452
|
+
const current = this._container.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY);
|
|
453
|
+
if (next) this._container.style.setProperty(CONTENT_MIN_WIDTH_PROPERTY, next);
|
|
454
|
+
else this._container.style.removeProperty(CONTENT_MIN_WIDTH_PROPERTY);
|
|
455
|
+
return current !== (next || '');
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
_getHeaders() {
|
|
459
|
+
const rows = Array.from(this._head?.rows || []);
|
|
460
|
+
return rows.length ? Array.from(rows.at(-1).cells || []) : [];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
_columnKey(header, index) {
|
|
464
|
+
return String(header?.getAttribute('data-field') || index).trim();
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
_isEmptyHeader(header) {
|
|
468
|
+
return Boolean(header) && header.childElementCount === 0 && String(header.textContent || '').trim() === '';
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
_hasDeclaredWidth(element) {
|
|
472
|
+
if (!element) return false;
|
|
473
|
+
return element.hasAttribute('width')
|
|
474
|
+
|| element.hasAttribute('data-column-width')
|
|
475
|
+
|| Boolean(element.style?.width || element.style?.minWidth || element.style?.maxWidth);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
_readDeclaredPixelWidth(element) {
|
|
479
|
+
if (!element || !this._hasDeclaredWidth(element)) return 0;
|
|
480
|
+
const fixed = element.style?.minWidth && element.style.minWidth === element.style.maxWidth
|
|
481
|
+
? Number.parseFloat(element.style.width || element.style.minWidth)
|
|
482
|
+
: 0;
|
|
483
|
+
if (Number.isFinite(fixed) && fixed > 0) return fixed;
|
|
484
|
+
const measured = element.getBoundingClientRect?.().width || element.offsetWidth || 0;
|
|
485
|
+
return measured > 0 ? measured : 0;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
_readTableMinimumWidth() {
|
|
489
|
+
const generated = Number.parseFloat(this._container?.style.getPropertyValue(CONTENT_MIN_WIDTH_PROPERTY) || '0');
|
|
490
|
+
if (typeof getComputedStyle !== 'function') return Number.isFinite(generated) ? generated : 0;
|
|
491
|
+
const declared = Number.parseFloat(getComputedStyle(this._element).minWidth || '0');
|
|
492
|
+
return Math.max(Number.isFinite(generated) ? generated : 0, Number.isFinite(declared) ? declared : 0);
|
|
493
|
+
}
|
|
494
|
+
|
|
426
495
|
_syncScroll() {
|
|
427
496
|
if (this._header && this._body) this._header.scrollLeft = this._body.scrollLeft;
|
|
428
497
|
}
|