vgapp 1.1.1 → 1.1.3
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/CHANGELOG.md +8 -0
- package/README.md +19 -16
- package/app/langs/en/buttons.json +17 -2
- package/app/langs/en/messages.json +36 -1
- package/app/langs/ru/buttons.json +17 -2
- package/app/langs/ru/messages.json +69 -34
- package/app/modules/module-fn.js +15 -9
- package/app/modules/vgfilepreview/index.js +3 -0
- package/app/modules/vgfilepreview/js/i18n.js +56 -0
- package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -0
- package/app/modules/vgfilepreview/js/renderers/image.js +92 -0
- package/app/modules/vgfilepreview/js/renderers/index.js +19 -0
- package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -0
- package/app/modules/vgfilepreview/js/renderers/office.js +79 -0
- package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -0
- package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -0
- package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -0
- package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -0
- package/app/modules/vgfilepreview/js/renderers/text.js +83 -0
- package/app/modules/vgfilepreview/js/renderers/video-modal.js +272 -0
- package/app/modules/vgfilepreview/js/renderers/video.js +80 -0
- package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -0
- package/app/modules/vgfilepreview/js/renderers/zip.js +89 -0
- package/app/modules/vgfilepreview/js/vgfilepreview.js +532 -0
- package/app/modules/vgfilepreview/readme.md +68 -0
- package/app/modules/vgfilepreview/scss/_variables.scss +113 -0
- package/app/modules/vgfilepreview/scss/vgfilepreview.scss +460 -0
- package/app/modules/vgfiles/js/base.js +463 -175
- package/app/modules/vgfiles/js/droppable.js +260 -260
- package/app/modules/vgfiles/js/render.js +153 -153
- package/app/modules/vgfiles/js/vgfiles.js +41 -29
- package/app/modules/vgfiles/readme.md +116 -217
- package/app/modules/vgfiles/scss/_variables.scss +18 -10
- package/app/modules/vgfiles/scss/vgfiles.scss +153 -59
- package/app/modules/vgformsender/js/vgformsender.js +7 -2
- package/app/modules/vgmodal/js/vgmodal.js +12 -0
- package/app/modules/vgnav/js/vgnav.js +135 -135
- package/app/modules/vgnav/readme.md +67 -67
- package/app/modules/vgnestable/README.md +307 -307
- package/app/modules/vgnestable/scss/_variables.scss +60 -60
- package/app/modules/vgnestable/scss/vgnestable.scss +163 -163
- package/app/modules/vgselect/js/vgselect.js +62 -59
- package/app/modules/vgselect/scss/vgselect.scss +22 -22
- package/app/modules/vgspy/readme.md +28 -28
- package/app/utils/js/components/audio-metadata.js +240 -0
- package/app/utils/js/components/file-icon.js +109 -0
- package/app/utils/js/components/file-preview.js +304 -0
- package/app/utils/js/components/sanitize.js +150 -150
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/index.js +1 -0
- package/index.scss +9 -6
- package/package.json +1 -1
|
@@ -1,224 +1,123 @@
|
|
|
1
|
-
# VGFiles
|
|
2
|
-
|
|
3
|
-
`VGFiles` —
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
ajax: true,
|
|
28
|
-
uploads: {
|
|
29
|
-
route: '/api/upload',
|
|
30
|
-
mode: 'sequential'
|
|
31
|
-
},
|
|
32
|
-
limits: {
|
|
33
|
-
count: 10,
|
|
34
|
-
sizes: 5, // MB
|
|
35
|
-
total: 50
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## ⚙️ Параметры конфигурации
|
|
43
|
-
|
|
44
|
-
| Параметр | Тип | По умолчанию | Описание |
|
|
45
|
-
|--------|------|-------------|---------|
|
|
46
|
-
| `init` | `boolean` | `true` | Автоматическая инициализация |
|
|
47
|
-
| `allowed` | `boolean` | `false` | Разрешить дроп файлов |
|
|
48
|
-
| `lang` | `string` | `'ru'` | Язык интерфейса (поддерживается через `lang_buttons`, `lang_messages`) |
|
|
49
|
-
| `limits.count` | `number` | `0` | Макс. количество файлов (0 — без ограничений) |
|
|
50
|
-
| `limits.sizes` | `number` | `10` | Макс. размер одного файла (в МБ) |
|
|
51
|
-
| `limits.total` | `number` | `0` | Общий лимит размера (в МБ, 0 — без ограничений) |
|
|
52
|
-
| `image` | `boolean` | `false` | Отображать превью изображений |
|
|
53
|
-
| `detach` | `boolean` | `true` | Откреплять файлы после загрузки |
|
|
54
|
-
| `info` | `boolean` | `true` | Показывать кнопку удаления |
|
|
55
|
-
| `types` | `array` | `[]` | Разрешённые MIME-типы (например, `['image/png', 'application/pdf']`) |
|
|
56
|
-
| `ajax` | `boolean` | `false` | Использовать AJAX-загрузку |
|
|
57
|
-
| `prepend` | `boolean` | `true` | Добавлять новые файлы в начало списка |
|
|
58
|
-
| `uploads.route` | `string` | `''` | URL для загрузки файлов |
|
|
59
|
-
| `uploads.mode` | `'sequential' \| 'parallel'` | `'sequential'` | Режим отправки файлов |
|
|
60
|
-
| `uploads.maxParallel` | `number` | `3` | Макс. файлов при параллельной загрузке |
|
|
61
|
-
| `uploads.maxConcurrent` | `number` | `1` | Макс. одновременных запросов |
|
|
62
|
-
| `uploads.retryAttempts` | `number` | `1` | Кол-во попыток повтора при ошибке |
|
|
63
|
-
| `uploads.retryDelay` | `number` | `1000` | Задержка между попытками (мс) |
|
|
64
|
-
| `removes.single.route` | `string` | `''` | URL для удаления одного файла |
|
|
65
|
-
| `removes.all.route` | `string` | `''` | URL для удаления всех файлов |
|
|
66
|
-
| `removes.all.alert` | `boolean` | `true` | Показывать подтверждение при удалении всех файлов |
|
|
67
|
-
| `removes.all.toast` | `boolean` | `true` | Показывать уведомление после удаления всех файлов |
|
|
68
|
-
| `removes.all.confirm` | `function \| null` | `null` | Кастомный confirm-обработчик для удаления всех файлов |
|
|
69
|
-
| `removes.single.alert` | `boolean` | `true` | Показывать подтверждение при удалении |
|
|
70
|
-
| `removes.single.toast` | `boolean` | `true` | Показывать уведомление после удаления |
|
|
71
|
-
| `removes.single.confirm` | `function \| null` | `null` | Кастомный confirm-обработчик для удаления одного файла |
|
|
72
|
-
| `sortable.enabled` | `boolean` | `false` | Включить сортировку |
|
|
73
|
-
| `sortable.route` | `string` | `''` | URL для сохранения порядка файлов |
|
|
74
|
-
| `callbacks` | `object` | `null` | Колбэки на события (см. ниже) |
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 📢 События и колбэки
|
|
79
|
-
|
|
80
|
-
Модуль поддерживает как DOM-события, так и JS-колбэки:
|
|
81
|
-
|
|
82
|
-
### DOM-события
|
|
83
|
-
- `vg.files.change` — изменение списка файлов
|
|
84
|
-
- `vg.files.upload.allComplete` — все файлы загружены
|
|
85
|
-
- `vg.files.remove` — файл удалён
|
|
86
|
-
|
|
87
|
-
### Колбэки (`callbacks`)
|
|
88
|
-
| Колбэк | Параметры | Описание |
|
|
89
|
-
|-------|----------|--------|
|
|
90
|
-
| `onInit` | `(data)` | Инициализация завершена |
|
|
91
|
-
| `onChange` | `{ files, input, inputFiles }` | Изменён список файлов (`inputFiles` — снимок исходных `input.files`) |
|
|
92
|
-
| `onUploadStart` | `{ files, total }` | Началась загрузка |
|
|
93
|
-
| `onUploadProgress` | `{ file, progress, bytesSent, totalBytes }` | Прогресс загрузки |
|
|
94
|
-
| `onUploadComplete` | `{ file, response, status, id }` | Файл успешно загружен |
|
|
95
|
-
| `onUploadError` | `{ file }` | Ошибка загрузки |
|
|
96
|
-
| `onUploadAllComplete` | `{ uploaded, failed, total }` | Все файлы загружены |
|
|
97
|
-
| `onRemoveFile` | `{ button, name, size, id, remaining }` | Удалён файл |
|
|
98
|
-
| `onClear` | `{}` | Очищен весь список |
|
|
99
|
-
| `onReload` | `{ button, file }` | Повторная попытка загрузки |
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 📊 Статусы файлов
|
|
104
|
-
|
|
105
|
-
Модуль отслеживает статусы в реальном времени:
|
|
106
|
-
- **`pending`** — ожидает загрузки
|
|
107
|
-
- **`loading`** — идёт загрузка
|
|
108
|
-
- **`completed`** — успешно загружен
|
|
109
|
-
- **`failing`** — ошибка загрузки
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## 🔁 Внешние (уже загруженные) файлы
|
|
114
|
-
|
|
115
|
-
Модуль может отображать уже загруженные файлы, переданные через `data-file`:
|
|
116
|
-
-- TODO описать полностью
|
|
117
|
-
|
|
118
|
-
## 🧹 Очистка и удаление
|
|
119
|
-
|
|
120
|
-
- **Удаление одного файла**: кнопка с `data-vg-dismiss="file"` → вызов `removeFile()`.
|
|
121
|
-
- **Очистка всех**: кнопка с `data-vg-dismiss="vg-files"` → `clear()`.
|
|
122
|
-
|
|
123
|
-
Поддержка подтверждения через `VGAlert` и уведомлений через `VGToast`.
|
|
124
|
-
|
|
125
|
-
### Кастомный confirm для удаления
|
|
126
|
-
|
|
127
|
-
Если задан `removes.single.confirm` или `removes.all.confirm`, модуль вызовет вашу функцию вместо дефолтного `VGAlert`.
|
|
1
|
+
# VGFiles
|
|
2
|
+
|
|
3
|
+
`VGFiles` — модуль загрузки и управления файлами с поддержкой локального режима и AJAX.
|
|
4
|
+
|
|
5
|
+
## Новые фичи
|
|
6
|
+
|
|
7
|
+
- Поддержка `replace` для single-mode (`limits.count = 1`): новый файл заменяет предыдущий без накопления.
|
|
8
|
+
- Переименование входящих файлов через `rename: true | (file, index) => string`.
|
|
9
|
+
- `smartdrop`: глобальная подсветка dropzone, если на экране только одна видимая зона дропа.
|
|
10
|
+
- Расширенный lifecycle для внешних файлов из `data-file`: парсинг `customData`, `src/image`, бинарных метаданных.
|
|
11
|
+
- Интеграция с `VGFilePreview` в info-списке (`ui.nameOnly: true`) для inline-аудио, скачивания и предпросмотра по клику.
|
|
12
|
+
- Авто-обогащение аудиофайлов метаданными (title/cover) через `extractAudioMetadata`.
|
|
13
|
+
- Гибкие confirm-хуки для удаления (`removes.single.confirm`, `removes.all.confirm`) с контрактом `accepted/data`.
|
|
14
|
+
- Повторная загрузка упавших файлов через `data-vg-reload="file"` и кнопки retry.
|
|
15
|
+
- Проброс `customData` файла в `data-*` атрибуты элементов списка.
|
|
16
|
+
|
|
17
|
+
## Базовые возможности
|
|
18
|
+
|
|
19
|
+
- Выбор файлов через `<input type="file">` и drag&drop.
|
|
20
|
+
- Лимиты: количество, размер файла, общий размер, MIME-типы.
|
|
21
|
+
- Режимы загрузки: `sequential` и `parallel`.
|
|
22
|
+
- Автоматическая/ручная инициализация.
|
|
23
|
+
- Сортировка загруженных файлов с сохранением порядка на сервере.
|
|
24
|
+
- Удаление одного файла и очистка всего списка.
|
|
25
|
+
|
|
26
|
+
## Инициализация
|
|
128
27
|
|
|
129
28
|
```js
|
|
130
|
-
new VGFiles(document.querySelector('.vg-files'), {
|
|
29
|
+
const files = new VGFiles(document.querySelector('.vg-files'), {
|
|
131
30
|
ajax: true,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
31
|
+
smartdrop: true,
|
|
32
|
+
rename: true,
|
|
33
|
+
replace: true,
|
|
34
|
+
uploads: {
|
|
35
|
+
route: '/api/upload',
|
|
36
|
+
mode: 'sequential'
|
|
37
|
+
},
|
|
38
|
+
limits: {
|
|
39
|
+
count: 10,
|
|
40
|
+
sizes: 5,
|
|
41
|
+
total: 50
|
|
141
42
|
}
|
|
142
43
|
});
|
|
143
44
|
```
|
|
144
45
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
`
|
|
149
|
-
`
|
|
150
|
-
`
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
- `
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
> 🚀 Автор: VEGAS STUDIO (vegas-dev.com)
|
|
224
|
-
> 📍 Поддерживается в проектах VEGAS
|
|
46
|
+
## Ключевые параметры
|
|
47
|
+
|
|
48
|
+
- `allowed` — разрешить drag-drop режим и особенности drop-зоны.
|
|
49
|
+
- `ajax` — включить серверную загрузку.
|
|
50
|
+
- `replace` (`default: true`) — замена файла в single-mode.
|
|
51
|
+
- `rename` (`default: false`) — переименование файлов до добавления в список.
|
|
52
|
+
- `smartdrop` (`default: false`) — глобальная логика подсказки drop-зоны.
|
|
53
|
+
- `prepend` (`default: true`) — добавление новых файлов в начало.
|
|
54
|
+
- `uploads.mode` — `'sequential' | 'parallel'`.
|
|
55
|
+
- `uploads.maxParallel`, `uploads.maxConcurrent`, `uploads.retryAttempts`, `uploads.retryDelay`.
|
|
56
|
+
- `removes.single.confirm`, `removes.all.confirm` — кастомные confirm-обработчики.
|
|
57
|
+
- `sortable.enabled`, `sortable.route`, `sortable.handle`, `sortable.lists`.
|
|
58
|
+
|
|
59
|
+
## Внешние (уже загруженные) файлы
|
|
60
|
+
|
|
61
|
+
Модуль может стартовать с предзаполненным списком через `data-file` в `<li>`.
|
|
62
|
+
|
|
63
|
+
Поддерживаемые поля объекта:
|
|
64
|
+
|
|
65
|
+
- `id`, `name`, `size`, `type`, `src` (обязательный набор для валидного внешнего файла)
|
|
66
|
+
- `image` (опционально)
|
|
67
|
+
- `lastModified` / `last-modified` (опционально)
|
|
68
|
+
- любые дополнительные поля -> попадают в `customData`
|
|
69
|
+
|
|
70
|
+
`customData` дальше пробрасывается в `data-*` атрибуты элементов файла и может использоваться в шаблонах/интеграциях.
|
|
71
|
+
|
|
72
|
+
## AJAX-события и callbacks
|
|
73
|
+
|
|
74
|
+
DOM-события:
|
|
75
|
+
|
|
76
|
+
- `vg.files.change`
|
|
77
|
+
- `vg.files.upload.start`
|
|
78
|
+
- `vg.files.upload.progress`
|
|
79
|
+
- `vg.files.upload.complete`
|
|
80
|
+
- `vg.files.upload.error`
|
|
81
|
+
- `vg.files.upload.allComplete`
|
|
82
|
+
- `vg.files.remove`
|
|
83
|
+
- `vg.files.reload`
|
|
84
|
+
|
|
85
|
+
Callbacks (`params.callbacks`):
|
|
86
|
+
|
|
87
|
+
- `onInit`
|
|
88
|
+
- `onChange` (`{ files, input, inputFiles }`)
|
|
89
|
+
- `onUploadStart`
|
|
90
|
+
- `onUploadProgress`
|
|
91
|
+
- `onUploadComplete`
|
|
92
|
+
- `onUploadError`
|
|
93
|
+
- `onUploadAllComplete`
|
|
94
|
+
- `onRemoveFile`
|
|
95
|
+
- `onClear`
|
|
96
|
+
- `onReload`
|
|
97
|
+
|
|
98
|
+
## Удаление с кастомным confirm
|
|
99
|
+
|
|
100
|
+
Если передан `removes.single.confirm` или `removes.all.confirm`, модуль вызывает вашу функцию вместо стандартного `VGAlert`.
|
|
101
|
+
|
|
102
|
+
Контракт результата:
|
|
103
|
+
|
|
104
|
+
- `true` или `{ accepted: true }` — подтвердить.
|
|
105
|
+
- `false` или `{ accepted: false }` — отменить.
|
|
106
|
+
- `{ accepted: true, data }` — подтвердить и использовать готовый ответ удаления (без дополнительного AJAX-запроса).
|
|
107
|
+
|
|
108
|
+
## Статусы файлов
|
|
109
|
+
|
|
110
|
+
- `pending` — ожидает загрузки.
|
|
111
|
+
- `loading` — идет загрузка.
|
|
112
|
+
- `completed` — успешно загружен.
|
|
113
|
+
- `failing` — ошибка загрузки (доступен reload).
|
|
114
|
+
|
|
115
|
+
## Методы API
|
|
116
|
+
|
|
117
|
+
- `upload(file)`
|
|
118
|
+
- `uploadAll(files)`
|
|
119
|
+
- `reload(button)`
|
|
120
|
+
- `removeFile(button)`
|
|
121
|
+
- `clear(resetInput, uiOnly)`
|
|
122
|
+
- `dispose()`
|
|
123
|
+
|
|
@@ -70,19 +70,27 @@ $files-map: (
|
|
|
70
70
|
info-radius: 4px,
|
|
71
71
|
info-list-max-height: 360px,
|
|
72
72
|
|
|
73
|
-
info-gap: 8px,
|
|
74
|
-
info-padding: 8px,
|
|
75
|
-
info-border-bottom-color: var(--vg-secondary-bg),
|
|
76
|
-
info-hover-bg: rgba(var(--vg-secondary-bg-rgb), .4),
|
|
77
|
-
|
|
78
|
-
info-
|
|
73
|
+
info-gap: 8px,
|
|
74
|
+
info-padding: 8px,
|
|
75
|
+
info-border-bottom-color: var(--vg-secondary-bg),
|
|
76
|
+
info-hover-bg: rgba(var(--vg-secondary-bg-rgb), .4),
|
|
77
|
+
info-audio-progress-track: rgba(var(--vg-secondary-bg-rgb), .3),
|
|
78
|
+
info-audio-progress-fill: #000,
|
|
79
|
+
info-audio-progress-opacity: .33,
|
|
80
|
+
info-audio-row-min-height: 64px,
|
|
81
|
+
info-audio-image-size: 48px,
|
|
82
|
+
|
|
83
|
+
info-image-radius: 4px,
|
|
79
84
|
info-iteration-font-size: 16px,
|
|
80
85
|
info-name-font-size: 16px,
|
|
81
86
|
info-size-font-size: 14px,
|
|
82
87
|
|
|
83
|
-
info-remove-icon-size: 16px,
|
|
84
|
-
info-row-remove-size: 22px,
|
|
85
|
-
info-row-remove-icon-size: 10px,
|
|
88
|
+
info-remove-icon-size: 16px,
|
|
89
|
+
info-row-remove-size: 22px,
|
|
90
|
+
info-row-remove-icon-size: 10px,
|
|
91
|
+
info-failing-actions-gap: 6px,
|
|
92
|
+
info-failing-actions-margin-start: 8px,
|
|
93
|
+
drop-failing-actions-gap: 6px,
|
|
86
94
|
|
|
87
95
|
// legacy (оставлено для совместимости со старым API темы)
|
|
88
96
|
info-mb: 10px,
|
|
@@ -104,4 +112,4 @@ $files-map: (
|
|
|
104
112
|
info-list-span-me: 6px,
|
|
105
113
|
info-list-button-fs: 12px,
|
|
106
114
|
info-list-button-color: #999999,
|
|
107
|
-
);
|
|
115
|
+
);
|
|
@@ -261,15 +261,15 @@
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
.file {
|
|
265
|
-
--vg-button-color: var(--vg-secondary);
|
|
266
|
-
display: flex;
|
|
267
|
-
align-items: center;
|
|
268
|
-
gap: var(--vg-files-info-gap);
|
|
269
|
-
padding: var(--vg-files-info-padding);
|
|
270
|
-
border-bottom: 1px solid var(--vg-files-info-border-bottom-color);
|
|
271
|
-
transition: all .2s ease-in-out;
|
|
272
|
-
position: relative;
|
|
264
|
+
.file {
|
|
265
|
+
--vg-button-color: var(--vg-secondary);
|
|
266
|
+
display: flex;
|
|
267
|
+
align-items: center;
|
|
268
|
+
gap: var(--vg-files-info-gap);
|
|
269
|
+
padding: var(--vg-files-info-padding);
|
|
270
|
+
border-bottom: 1px solid var(--vg-files-info-border-bottom-color);
|
|
271
|
+
transition: all .2s ease-in-out;
|
|
272
|
+
position: relative;
|
|
273
273
|
|
|
274
274
|
@include vgfiles-sortable();
|
|
275
275
|
@include vgfiles-state();
|
|
@@ -278,13 +278,45 @@
|
|
|
278
278
|
border-bottom: none;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
&:hover {
|
|
282
|
-
background-color: var(--vg-files-info-hover-bg);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
281
|
+
&:hover {
|
|
282
|
+
background-color: var(--vg-files-info-hover-bg);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
&[data-vg-filepreview-renderer="audio"] {
|
|
286
|
+
--vg-filepreview-audio-inline-progress: 0%;
|
|
287
|
+
position: relative;
|
|
288
|
+
overflow: hidden;
|
|
289
|
+
isolation: isolate;
|
|
290
|
+
min-height: var(--vg-files-info-audio-row-min-height);
|
|
291
|
+
background-color: var(--vg-files-info-audio-progress-track);
|
|
292
|
+
|
|
293
|
+
&::before {
|
|
294
|
+
content: '';
|
|
295
|
+
position: absolute;
|
|
296
|
+
inset: 0 auto 0 0;
|
|
297
|
+
width: var(--vg-filepreview-audio-inline-progress);
|
|
298
|
+
background: var(--vg-files-info-audio-progress-fill);
|
|
299
|
+
opacity: var(--vg-files-info-audio-progress-opacity);
|
|
300
|
+
pointer-events: none;
|
|
301
|
+
z-index: 0;
|
|
302
|
+
transition: width .12s linear;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
> * {
|
|
306
|
+
position: relative;
|
|
307
|
+
z-index: 1;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.file-image {
|
|
311
|
+
flex: 0 0 var(--vg-files-info-audio-image-size);
|
|
312
|
+
width: var(--vg-files-info-audio-image-size);
|
|
313
|
+
height: var(--vg-files-info-audio-image-size);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
> * {
|
|
318
|
+
transition: all .2s ease-in-out;
|
|
319
|
+
}
|
|
288
320
|
|
|
289
321
|
&-image {
|
|
290
322
|
flex: 0 0 var(--vg-files-image-width);
|
|
@@ -330,26 +362,63 @@
|
|
|
330
362
|
display: none;
|
|
331
363
|
}
|
|
332
364
|
|
|
333
|
-
.name {
|
|
334
|
-
display: block;
|
|
335
|
-
overflow: hidden;
|
|
336
|
-
text-overflow: ellipsis;
|
|
337
|
-
white-space: nowrap;
|
|
338
|
-
font-size: var(--vg-files-info-name-font-size);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
365
|
+
.name {
|
|
366
|
+
display: block;
|
|
367
|
+
overflow: hidden;
|
|
368
|
+
text-overflow: ellipsis;
|
|
369
|
+
white-space: nowrap;
|
|
370
|
+
font-size: var(--vg-files-info-name-font-size);
|
|
371
|
+
|
|
372
|
+
&.vg-filepreview-audio-inline {
|
|
373
|
+
display: inline-flex;
|
|
374
|
+
gap: var(--vg-filepreview-audio-inline-gap);
|
|
375
|
+
align-items: center;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
&.is-preview-action {
|
|
379
|
+
cursor: pointer;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.size {
|
|
384
|
+
color: var(--vg-secondary);
|
|
385
|
+
font-size: var(--vg-files-info-size-font-size);
|
|
386
|
+
white-space: nowrap;
|
|
387
|
+
margin-left: auto;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.download {
|
|
391
|
+
margin-left: 8px;
|
|
392
|
+
|
|
393
|
+
.vg-filepreview-download-trigger {
|
|
394
|
+
padding: 0;
|
|
395
|
+
background: transparent;
|
|
396
|
+
color: var(--vg-secondary);
|
|
397
|
+
border-radius: 0;
|
|
398
|
+
font-size: var(--vg-files-info-size-font-size);
|
|
399
|
+
font-weight: 500;
|
|
400
|
+
gap: 4px;
|
|
401
|
+
|
|
402
|
+
&:hover {
|
|
403
|
+
color: var(--vg-body-color);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
&__icon svg {
|
|
407
|
+
width: 14px;
|
|
408
|
+
height: 14px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
&__text {
|
|
412
|
+
display: none;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
&-remove {
|
|
419
|
+
flex: 0 0 var(--vg-files-remove-width);
|
|
420
|
+
width: var(--vg-files-remove-width);
|
|
421
|
+
margin-left: auto;
|
|
353
422
|
|
|
354
423
|
button {
|
|
355
424
|
width: var(--vg-files-remove-width);
|
|
@@ -382,14 +451,21 @@
|
|
|
382
451
|
fill: var(--vg-button-color);
|
|
383
452
|
}
|
|
384
453
|
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
.file-
|
|
391
|
-
|
|
392
|
-
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
&.failing {
|
|
459
|
+
.file-remove {
|
|
460
|
+
flex: 0 0 auto;
|
|
461
|
+
width: auto;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
&:not(.with-image) {
|
|
466
|
+
.file-info {
|
|
467
|
+
.iteration {
|
|
468
|
+
display: block;
|
|
393
469
|
}
|
|
394
470
|
}
|
|
395
471
|
}
|
|
@@ -436,12 +512,26 @@
|
|
|
436
512
|
}
|
|
437
513
|
}
|
|
438
514
|
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.file-failing-actions {
|
|
521
|
+
display: inline-flex;
|
|
522
|
+
align-items: center;
|
|
523
|
+
gap: var(--vg-files-info-failing-actions-gap);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
&-info--list {
|
|
527
|
+
.file.failing {
|
|
528
|
+
.file-remove {
|
|
529
|
+
margin-left: var(--vg-files-info-failing-actions-margin-start);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
&-drop {
|
|
445
535
|
background-color: var(--vg-files-drop-bg);
|
|
446
536
|
border: var(--vg-files-drop-border-width) var(--vg-files-drop-border-style) var(--vg-files-drop-border-color);
|
|
447
537
|
cursor: pointer;
|
|
@@ -465,8 +555,8 @@
|
|
|
465
555
|
}
|
|
466
556
|
}
|
|
467
557
|
|
|
468
|
-
&:hover {
|
|
469
|
-
animation: stripes var(--vg-files-drop-stripes-duration) linear infinite;
|
|
558
|
+
&:hover {
|
|
559
|
+
animation: stripes var(--vg-files-drop-stripes-duration) linear infinite;
|
|
470
560
|
background-image: linear-gradient(
|
|
471
561
|
-45deg,
|
|
472
562
|
rgba(var(--vg-secondary-rgb), var(--vg-files-drop-stripes-alpha)) 25%,
|
|
@@ -486,9 +576,9 @@
|
|
|
486
576
|
box-shadow: var(--vg-files-drop-hover-shadow);
|
|
487
577
|
}
|
|
488
578
|
|
|
489
|
-
> * {
|
|
490
|
-
display: block;
|
|
491
|
-
}
|
|
579
|
+
> * {
|
|
580
|
+
display: block;
|
|
581
|
+
}
|
|
492
582
|
|
|
493
583
|
&-message {
|
|
494
584
|
width: 100%;
|
|
@@ -621,10 +711,14 @@
|
|
|
621
711
|
flex-direction: column;
|
|
622
712
|
gap: 8px;
|
|
623
713
|
|
|
624
|
-
.file-remove {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
714
|
+
.file-remove {
|
|
715
|
+
.file-failing-actions {
|
|
716
|
+
gap: var(--vg-files-drop-failing-actions-gap);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
button {
|
|
720
|
+
background: var(--vg-body-bg);
|
|
721
|
+
color: var(--vg-body-color);
|
|
628
722
|
border: none;
|
|
629
723
|
cursor: pointer;
|
|
630
724
|
outline: none;
|
|
@@ -276,8 +276,13 @@ class VGFormSender extends BaseModule {
|
|
|
276
276
|
request(event, data = null) {
|
|
277
277
|
const _this = this;
|
|
278
278
|
const mergeFormData = (target, source) => {
|
|
279
|
+
const replacedKeys = new Set();
|
|
279
280
|
source.forEach((value, key) => {
|
|
280
|
-
|
|
281
|
+
if (!replacedKeys.has(key)) {
|
|
282
|
+
target.delete(key);
|
|
283
|
+
replacedKeys.add(key);
|
|
284
|
+
}
|
|
285
|
+
target.append(key, value);
|
|
281
286
|
});
|
|
282
287
|
return target;
|
|
283
288
|
}
|
|
@@ -777,4 +782,4 @@ EventHandler.on(document, EVENT_SUBMIT_DATA_API, function (event) {
|
|
|
777
782
|
}
|
|
778
783
|
})
|
|
779
784
|
|
|
780
|
-
export default VGFormSender;
|
|
785
|
+
export default VGFormSender;
|