vgapp 1.4.9 → 1.5.0
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/modules/vgfiles/js/base.js +9 -7
- package/app/modules/vgfiles/js/vgfiles.js +6 -3
- package/app/modules/vgfiles/scss/_mixins.scss +12 -2
- package/app/modules/vgtable/js/_sticky-header.js +47 -22
- package/app/modules/vgtable/scss/_sticky-header.scss +27 -21
- 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/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Описание: базовая логика выбора, валидации и отображения файлов VGFiles.
|
|
3
|
-
* Возможности: управляет набором файлов, ошибками, списками, статистикой и скрытыми полями формы.
|
|
2
|
+
* Описание: базовая логика выбора, валидации и отображения файлов VGFiles.
|
|
3
|
+
* Возможности: управляет набором файлов, ошибками, списками, кастомными действиями, статистикой и скрытыми полями формы.
|
|
4
4
|
*/
|
|
5
5
|
import BaseModule from "../../base-module";
|
|
6
6
|
import {mergeDeepObject} from "../../../utils/js/functions";
|
|
@@ -422,7 +422,7 @@ class VGFilesBase extends BaseModule {
|
|
|
422
422
|
};
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
_renderUIDropList(files) {
|
|
425
|
+
_renderUIDropList(files) {
|
|
426
426
|
if (!this._nodes.drop) return;
|
|
427
427
|
|
|
428
428
|
let $list = Selectors.find(`.${this._getClass('drop-list')}`, this._nodes.drop);
|
|
@@ -435,9 +435,10 @@ class VGFilesBase extends BaseModule {
|
|
|
435
435
|
const fragment = document.createDocumentFragment();
|
|
436
436
|
|
|
437
437
|
files.forEach((file) => {
|
|
438
|
-
let classes =
|
|
438
|
+
let classes = [...$itemsTemplateClasses];
|
|
439
439
|
|
|
440
|
-
if (this._params.detach) classes.push('with-remove')
|
|
440
|
+
if (this._params.detach) classes.push('with-remove')
|
|
441
|
+
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
441
442
|
if (this._params.sortable.enabled) classes.push('with-sortable')
|
|
442
443
|
if (this._params.limits.count === 1) {
|
|
443
444
|
classes.push('single');
|
|
@@ -606,12 +607,13 @@ class VGFilesBase extends BaseModule {
|
|
|
606
607
|
return '';
|
|
607
608
|
}
|
|
608
609
|
|
|
609
|
-
_createInfoListItem(file, i, itemsTemplate, itemTemplateClasses, fileKey, signature) {
|
|
610
|
+
_createInfoListItem(file, i, itemsTemplate, itemTemplateClasses, fileKey, signature) {
|
|
610
611
|
let classes = [...itemTemplateClasses];
|
|
611
612
|
|
|
612
613
|
if (this._params.image) classes.push('with-image');
|
|
613
614
|
if (this._params.info) classes.push('with-info');
|
|
614
|
-
if (this._params.detach) classes.push('with-remove')
|
|
615
|
+
if (this._params.detach) classes.push('with-remove')
|
|
616
|
+
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
615
617
|
if (this._params.sortable.enabled) classes.push('with-sortable');
|
|
616
618
|
const previewPath = this._resolveFilePreviewPath(file);
|
|
617
619
|
const displayName = this._resolveDisplayName(file);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Описание: основной класс выбора, отображения и AJAX-загрузки файлов VGFiles.
|
|
3
|
-
* Возможности: управляет списками и dropzone, прогрессом, удалением, повторной загрузкой и сортировкой.
|
|
3
|
+
* Возможности: управляет списками и dropzone, прогрессом, кастомными действиями, удалением, повторной загрузкой и сортировкой.
|
|
4
4
|
*/
|
|
5
5
|
import VGFilesBase from "./base";
|
|
6
6
|
import FileUploader from "./loader";
|
|
@@ -47,8 +47,11 @@ class VGFiles extends VGFilesBase {
|
|
|
47
47
|
prepend: true,
|
|
48
48
|
replace: true,
|
|
49
49
|
rename: false,
|
|
50
|
-
smartdrop: false,
|
|
51
|
-
|
|
50
|
+
smartdrop: false,
|
|
51
|
+
customButtons: {
|
|
52
|
+
hideOnUploadState: true
|
|
53
|
+
},
|
|
54
|
+
uploads: {
|
|
52
55
|
mode: 'sequential',
|
|
53
56
|
route: '',
|
|
54
57
|
maxParallel: 3,
|
|
@@ -23,8 +23,18 @@
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
@mixin vgfiles-state() {
|
|
27
|
-
&.
|
|
26
|
+
@mixin vgfiles-state() {
|
|
27
|
+
&.hide-custom-buttons-on-upload-state {
|
|
28
|
+
&.pending,
|
|
29
|
+
&.loading,
|
|
30
|
+
&.failing {
|
|
31
|
+
.file-actions {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&.pending {
|
|
28
38
|
> * {
|
|
29
39
|
opacity: .32;
|
|
30
40
|
pointer-events: none;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Описание: разметка Fixed Header с отдельными слоями заголовка и тела VGTable.
|
|
3
|
-
* Возможности: перенос настоящего thead без клона, синхронизация колонок и горизонтальной прокрутки.
|
|
3
|
+
* Возможности: перенос настоящего thead без клона, синхронизация ширин колонок и горизонтальной прокрутки.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const MODE_CLASSES = ['vg-table-wrapper--sticky-container', 'vg-table-wrapper--sticky-page'];
|
|
@@ -19,8 +19,9 @@ class _stickyHeader {
|
|
|
19
19
|
this._headerTable = null;
|
|
20
20
|
this._body = null;
|
|
21
21
|
this._previousClasses = new Map();
|
|
22
|
-
this._previousContainerClasses = new Map();
|
|
23
|
-
this._previousStyles = new Map();
|
|
22
|
+
this._previousContainerClasses = new Map();
|
|
23
|
+
this._previousStyles = new Map();
|
|
24
|
+
this._previousHeaderWidths = new Map();
|
|
24
25
|
this._boundScroll = this._syncScroll.bind(this);
|
|
25
26
|
this._boundResize = this.refresh.bind(this);
|
|
26
27
|
this._boundPageScroll = this._syncStickyState.bind(this);
|
|
@@ -68,9 +69,10 @@ class _stickyHeader {
|
|
|
68
69
|
refresh() {
|
|
69
70
|
if (!this._header || !this._headerTable || !this._body) return this;
|
|
70
71
|
|
|
71
|
-
const widths = this._measureBodyColumns();
|
|
72
|
-
this._applyColgroup(this._headerTable, widths);
|
|
73
|
-
this._applyColgroup(this._element, widths);
|
|
72
|
+
const widths = this._measureBodyColumns();
|
|
73
|
+
this._applyColgroup(this._headerTable, widths);
|
|
74
|
+
this._applyColgroup(this._element, widths);
|
|
75
|
+
this._applyHeaderWidths(widths);
|
|
74
76
|
const scrollbar = Math.max(0, this._body.offsetWidth - this._body.clientWidth);
|
|
75
77
|
this._header.style.paddingInlineEnd = `${scrollbar}px`;
|
|
76
78
|
this._header.style.setProperty('--vg-table-sticky-scrollbar-width', `${scrollbar}px`);
|
|
@@ -101,12 +103,16 @@ class _stickyHeader {
|
|
|
101
103
|
CONTAINER_MODE_CLASSES.forEach((className) => {
|
|
102
104
|
this._container.classList.toggle(className, this._previousContainerClasses.get(className) === true);
|
|
103
105
|
});
|
|
104
|
-
STYLE_PROPERTIES.forEach((property) => {
|
|
106
|
+
STYLE_PROPERTIES.forEach((property) => {
|
|
105
107
|
const previous = this._previousStyles.get(property);
|
|
106
108
|
if (previous) this._container.style.setProperty(property, previous);
|
|
107
109
|
else this._container.style.removeProperty(property);
|
|
108
|
-
});
|
|
109
|
-
this.
|
|
110
|
+
});
|
|
111
|
+
this._previousHeaderWidths.forEach((width, cell) => {
|
|
112
|
+
cell.style.width = width;
|
|
113
|
+
});
|
|
114
|
+
this._previousHeaderWidths.clear();
|
|
115
|
+
this._element.removeAttribute('data-vg-table-sticky-header');
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
_buildLayers(widths) {
|
|
@@ -131,16 +137,22 @@ class _stickyHeader {
|
|
|
131
137
|
this._body.append(this._element);
|
|
132
138
|
}
|
|
133
139
|
|
|
134
|
-
_measureColumns() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
_measureColumns() {
|
|
141
|
+
return this._measureBodyColumns();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_measureBodyColumns() {
|
|
145
|
+
const headerRow = this._head?.rows[this._head.rows.length - 1];
|
|
146
|
+
const headerWidths = this._measureRow(headerRow);
|
|
147
|
+
const rows = Array.from(this._element.tBodies || []).flatMap((body) => Array.from(body.rows || []));
|
|
148
|
+
for (const row of rows) {
|
|
149
|
+
if (row.hidden || row.hasAttribute('data-vg-table-state-row') || row.hasAttribute('data-vg-table-skeleton') || row.hasAttribute('data-vg-table-skeleton-row')) continue;
|
|
150
|
+
if (row.querySelector('[data-vg-table-state]')) continue;
|
|
151
|
+
const widths = this._measureRow(row);
|
|
152
|
+
if (widths.length === headerWidths.length && widths.some((width) => width > 0)) return widths;
|
|
153
|
+
}
|
|
154
|
+
return headerWidths;
|
|
155
|
+
}
|
|
144
156
|
|
|
145
157
|
_measureRow(row) {
|
|
146
158
|
if (!row) return [];
|
|
@@ -151,7 +163,7 @@ class _stickyHeader {
|
|
|
151
163
|
});
|
|
152
164
|
}
|
|
153
165
|
|
|
154
|
-
_applyColgroup(table, widths) {
|
|
166
|
+
_applyColgroup(table, widths) {
|
|
155
167
|
if (!widths.length) return;
|
|
156
168
|
if (table.querySelector(':scope > colgroup:not([data-vg-table-sticky-colgroup])')) return;
|
|
157
169
|
let colgroup = table.querySelector(':scope > colgroup[data-vg-table-sticky-colgroup]');
|
|
@@ -164,8 +176,21 @@ class _stickyHeader {
|
|
|
164
176
|
const col = table.ownerDocument.createElement('col');
|
|
165
177
|
if (width > 0) col.style.width = `${width}px`;
|
|
166
178
|
return col;
|
|
167
|
-
}));
|
|
168
|
-
}
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
_applyHeaderWidths(widths) {
|
|
183
|
+
const row = this._head?.rows[this._head.rows.length - 1];
|
|
184
|
+
if (!row || !widths.length) return;
|
|
185
|
+
let columnIndex = 0;
|
|
186
|
+
Array.from(row.cells).forEach((cell) => {
|
|
187
|
+
if (!this._previousHeaderWidths.has(cell)) this._previousHeaderWidths.set(cell, cell.style.width);
|
|
188
|
+
const span = Math.max(1, cell.colSpan || 1);
|
|
189
|
+
const width = widths.slice(columnIndex, columnIndex + span).reduce((total, value) => total + value, 0);
|
|
190
|
+
if (width > 0) cell.style.width = `${width}px`;
|
|
191
|
+
columnIndex += span;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
169
194
|
|
|
170
195
|
_syncScroll() {
|
|
171
196
|
if (this._header && this._body) this._header.scrollLeft = this._body.scrollLeft;
|
|
@@ -23,17 +23,18 @@
|
|
|
23
23
|
border-radius: var(--vg-table-sticky-radius);
|
|
24
24
|
background: var(--vg-table-sticky-bg);
|
|
25
25
|
|
|
26
|
-
.vg-table-header,
|
|
27
|
-
.vg-table-body {
|
|
28
|
-
width: 100%;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.vg-table-header {
|
|
32
|
-
position: relative;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
border-start-
|
|
26
|
+
.vg-table-header,
|
|
27
|
+
.vg-table-body {
|
|
28
|
+
width: 100%;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.vg-table-header {
|
|
32
|
+
position: relative;
|
|
33
|
+
z-index: var(--vg-table-sticky-z-index);
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
background: var(--vg-table-thead-bg);
|
|
36
|
+
border-start-start-radius: var(--vg-table-sticky-inner-radius);
|
|
37
|
+
border-start-end-radius: var(--vg-table-sticky-inner-radius);
|
|
37
38
|
|
|
38
39
|
&--scrollbar::after {
|
|
39
40
|
content: "";
|
|
@@ -46,11 +47,16 @@
|
|
|
46
47
|
border-bottom: var(--vg-table-sticky-border-width) var(--vg-table-sticky-border-style) var(--vg-table-sticky-border-color);
|
|
47
48
|
background: var(--vg-table-fixed-header-bg, var(--vg-table-thead-bg));
|
|
48
49
|
pointer-events: none;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.vg-table-
|
|
53
|
-
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.vg-table-body {
|
|
54
|
+
position: relative;
|
|
55
|
+
z-index: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.vg-table-header__table,
|
|
59
|
+
.vg-table-body > .vg-table {
|
|
54
60
|
width: 100%;
|
|
55
61
|
min-width: 100%;
|
|
56
62
|
table-layout: fixed;
|
|
@@ -114,8 +120,8 @@
|
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
|
|
117
|
-
.vg-table-body {
|
|
118
|
-
overflow:
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
123
|
+
.vg-table-body {
|
|
124
|
+
overflow: auto;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|