vgapp 1.1.2 → 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.
Files changed (53) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +19 -16
  3. package/app/langs/en/buttons.json +17 -2
  4. package/app/langs/en/messages.json +36 -1
  5. package/app/langs/ru/buttons.json +17 -2
  6. package/app/langs/ru/messages.json +69 -34
  7. package/app/modules/module-fn.js +15 -9
  8. package/app/modules/vgfilepreview/index.js +3 -0
  9. package/app/modules/vgfilepreview/js/i18n.js +56 -0
  10. package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -0
  11. package/app/modules/vgfilepreview/js/renderers/image.js +92 -0
  12. package/app/modules/vgfilepreview/js/renderers/index.js +19 -0
  13. package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -0
  14. package/app/modules/vgfilepreview/js/renderers/office.js +79 -0
  15. package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -0
  16. package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -0
  17. package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -0
  18. package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -0
  19. package/app/modules/vgfilepreview/js/renderers/text.js +83 -0
  20. package/app/modules/vgfilepreview/js/renderers/video-modal.js +272 -0
  21. package/app/modules/vgfilepreview/js/renderers/video.js +80 -0
  22. package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -0
  23. package/app/modules/vgfilepreview/js/renderers/zip.js +89 -0
  24. package/app/modules/vgfilepreview/js/vgfilepreview.js +532 -0
  25. package/app/modules/vgfilepreview/readme.md +68 -0
  26. package/app/modules/vgfilepreview/scss/_variables.scss +113 -0
  27. package/app/modules/vgfilepreview/scss/vgfilepreview.scss +460 -0
  28. package/app/modules/vgfiles/js/base.js +463 -175
  29. package/app/modules/vgfiles/js/droppable.js +260 -260
  30. package/app/modules/vgfiles/js/render.js +153 -153
  31. package/app/modules/vgfiles/js/vgfiles.js +41 -29
  32. package/app/modules/vgfiles/readme.md +116 -217
  33. package/app/modules/vgfiles/scss/_variables.scss +18 -10
  34. package/app/modules/vgfiles/scss/vgfiles.scss +153 -59
  35. package/app/modules/vgformsender/js/vgformsender.js +13 -13
  36. package/app/modules/vgmodal/js/vgmodal.js +12 -0
  37. package/app/modules/vgnav/js/vgnav.js +135 -135
  38. package/app/modules/vgnav/readme.md +67 -67
  39. package/app/modules/vgnestable/README.md +307 -307
  40. package/app/modules/vgnestable/scss/_variables.scss +60 -60
  41. package/app/modules/vgnestable/scss/vgnestable.scss +163 -163
  42. package/app/modules/vgselect/js/vgselect.js +39 -39
  43. package/app/modules/vgselect/scss/vgselect.scss +22 -22
  44. package/app/modules/vgspy/readme.md +28 -28
  45. package/app/utils/js/components/audio-metadata.js +240 -0
  46. package/app/utils/js/components/file-icon.js +109 -0
  47. package/app/utils/js/components/file-preview.js +304 -0
  48. package/app/utils/js/components/sanitize.js +150 -150
  49. package/build/vgapp.css +1 -1
  50. package/build/vgapp.css.map +1 -1
  51. package/index.js +1 -0
  52. package/index.scss +9 -6
  53. package/package.json +1 -1
@@ -13,11 +13,11 @@ const CLASS_NAME_DROP_HOVER = 'drop-hover';
13
13
  const NAME = 'drop-and-drop';
14
14
  const NAME_KEY = 'vg.drop-and-drop';
15
15
 
16
- class VGFilesDroppable extends BaseModule {
17
- /**
18
- * @param {HTMLElement} element
19
- * @param {Object} params
20
- */
16
+ class VGFilesDroppable extends BaseModule {
17
+ /**
18
+ * @param {HTMLElement} element
19
+ * @param {Object} params
20
+ */
21
21
  constructor(element, params = {}) {
22
22
  super(element, params);
23
23
  this._element = element;
@@ -31,15 +31,15 @@ class VGFilesDroppable extends BaseModule {
31
31
  static get NAME() { return NAME; }
32
32
  static get NAME_KEY() { return NAME_KEY; }
33
33
 
34
- _init() {
35
- VGFilesDroppable._instances.add(this);
36
- if (this._params?.smartdrop) {
37
- VGFilesDroppable._smartInstances.add(this);
38
- this._bindGlobalEvents();
39
- }
40
- this._findInput();
41
- this._setupEvents();
42
- }
34
+ _init() {
35
+ VGFilesDroppable._instances.add(this);
36
+ if (this._params?.smartdrop) {
37
+ VGFilesDroppable._smartInstances.add(this);
38
+ this._bindGlobalEvents();
39
+ }
40
+ this._findInput();
41
+ this._setupEvents();
42
+ }
43
43
 
44
44
  /**
45
45
  * Поиск связанного input[type="file"] внутри или рядом с drop-зоной
@@ -58,8 +58,8 @@ class VGFilesDroppable extends BaseModule {
58
58
  /**
59
59
  * Настройка событий перетаскивания
60
60
  */
61
- _setupEvents() {
62
- if (!isElement(this._element)) return;
61
+ _setupEvents() {
62
+ if (!isElement(this._element)) return;
63
63
 
64
64
  const isSortableDrag = (e) => {
65
65
  // 1) если sortable реально активен — на элементе есть класс dragging
@@ -69,76 +69,76 @@ class VGFilesDroppable extends BaseModule {
69
69
  let plain = '';
70
70
  try { plain = e.dataTransfer?.getData?.('text/plain') || ''; } catch (_) {}
71
71
  return plain === 'vgsortable';
72
- };
72
+ };
73
73
 
74
- EventHandler.on(this._element, 'dragover', (e) => {
75
- e.preventDefault();
76
- e.stopPropagation();
74
+ EventHandler.on(this._element, 'dragover', (e) => {
75
+ e.preventDefault();
76
+ e.stopPropagation();
77
77
 
78
78
  // ✅ Сортировка: НЕ подсвечиваем dropzone
79
- if (isSortableDrag(e)) {
80
- Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
81
- VGFilesDroppable._setDropMessageTitleState(this._element, false);
82
- e.dataTransfer.dropEffect = 'none';
83
- return;
84
- }
79
+ if (isSortableDrag(e)) {
80
+ Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
81
+ VGFilesDroppable._setDropMessageTitleState(this._element, false);
82
+ e.dataTransfer.dropEffect = 'none';
83
+ return;
84
+ }
85
85
 
86
86
  if (!Classes.has(this._element, CLASS_NAME_DROP_ACTIVE)) {
87
87
  Classes.add(this._element, CLASS_NAME_DROP_HOVER);
88
88
  }
89
89
  });
90
90
 
91
- EventHandler.on(this._element, 'dragenter', (e) => {
92
- e.preventDefault();
93
- e.stopPropagation();
91
+ EventHandler.on(this._element, 'dragenter', (e) => {
92
+ e.preventDefault();
93
+ e.stopPropagation();
94
94
 
95
95
  // ✅ Сортировка: НЕ подсвечиваем dropzone
96
- if (isSortableDrag(e)) {
97
- Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
98
- VGFilesDroppable._setDropMessageTitleState(this._element, false);
99
- return;
100
- }
101
-
102
- Classes.add(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
103
- VGFilesDroppable._setDropMessageTitleState(this._element, true);
104
- });
96
+ if (isSortableDrag(e)) {
97
+ Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
98
+ VGFilesDroppable._setDropMessageTitleState(this._element, false);
99
+ return;
100
+ }
101
+
102
+ Classes.add(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
103
+ VGFilesDroppable._setDropMessageTitleState(this._element, true);
104
+ });
105
105
 
106
106
  EventHandler.on(this._element, 'dragleave', (e) => {
107
107
  e.preventDefault();
108
108
  e.stopPropagation();
109
109
 
110
110
  // ✅ Сортировка: гарантированно без подсветки
111
- if (isSortableDrag(e)) {
112
- Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
113
- VGFilesDroppable._setDropMessageTitleState(this._element, false);
114
- return;
115
- }
111
+ if (isSortableDrag(e)) {
112
+ Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
113
+ VGFilesDroppable._setDropMessageTitleState(this._element, false);
114
+ return;
115
+ }
116
116
 
117
117
  if (e.target === this._element || e.target.closest('.' + CLASS_NAME_DROP) === this._element) {
118
118
  Classes.remove(this._element, CLASS_NAME_DROP_HOVER);
119
119
  setTimeout(() => {
120
- if (!this._element.matches(':hover')) {
121
- Classes.remove(this._element, CLASS_NAME_DROP_ACTIVE);
122
- VGFilesDroppable._setDropMessageTitleState(this._element, false);
123
- }
124
- }, 50);
125
- }
126
- });
127
-
128
- EventHandler.on(this._element, 'drop', (e) => {
129
- e.preventDefault();
130
- e.stopPropagation();
131
-
132
- Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
133
- VGFilesDroppable._setDropMessageTitleState(this._element, false);
120
+ if (!this._element.matches(':hover')) {
121
+ Classes.remove(this._element, CLASS_NAME_DROP_ACTIVE);
122
+ VGFilesDroppable._setDropMessageTitleState(this._element, false);
123
+ }
124
+ }, 50);
125
+ }
126
+ });
127
+
128
+ EventHandler.on(this._element, 'drop', (e) => {
129
+ e.preventDefault();
130
+ e.stopPropagation();
131
+
132
+ Classes.remove(this._element, [CLASS_NAME_DROP_ACTIVE, CLASS_NAME_DROP_HOVER]);
133
+ VGFilesDroppable._setDropMessageTitleState(this._element, false);
134
134
 
135
135
  // ✅ сортировка: не трогаем input
136
- if (isSortableDrag(e)) {
137
- return;
138
- }
139
-
140
- const files = e.dataTransfer?.files;
141
- if (!files || !files.length) return;
136
+ if (isSortableDrag(e)) {
137
+ return;
138
+ }
139
+
140
+ const files = e.dataTransfer?.files;
141
+ if (!files || !files.length) return;
142
142
 
143
143
  this._files = files;
144
144
 
@@ -146,209 +146,209 @@ class VGFilesDroppable extends BaseModule {
146
146
  this._input.files = files;
147
147
  EventHandler.trigger(this._input, 'change');
148
148
  }
149
- });
150
- }
151
-
152
- _bindGlobalEvents() {
153
- if (VGFilesDroppable._isGlobalEventsBound) return;
154
-
155
- VGFilesDroppable._globalHandlers = {
156
- dragenter: (e) => this._updateSuggestedDrop(e),
157
- dragover: (e) => this._updateSuggestedDrop(e),
158
- dragleave: (e) => {
159
- if (!this._isFileDrag(e)) return;
160
- if (e.relatedTarget === null || e.target === document || e.target === document.documentElement) {
161
- VGFilesDroppable._clearSuggestedDrop();
162
- }
163
- },
164
- drop: (e) => {
165
- if (!this._isFileDrag(e)) {
166
- VGFilesDroppable._clearSuggestedDrop();
167
- return;
168
- }
169
-
170
- const activeDrop = VGFilesDroppable._activeSuggestedDrop;
171
- if (activeDrop) {
172
- const instance = Array.from(VGFilesDroppable._smartInstances).find(i => i._element === activeDrop);
173
- const files = e.dataTransfer?.files;
174
-
175
- if (instance && files && files.length && isElement(instance._input)) {
176
- e.preventDefault();
177
- e.stopPropagation();
178
- instance._files = files;
179
- instance._input.files = files;
180
- EventHandler.trigger(instance._input, 'change');
181
- }
182
- }
183
-
184
- VGFilesDroppable._clearSuggestedDrop();
185
- },
186
- dragend: () => VGFilesDroppable._clearSuggestedDrop(),
187
- };
188
-
189
- EventHandler.on(document, 'dragenter', VGFilesDroppable._globalHandlers.dragenter);
190
- EventHandler.on(document, 'dragover', VGFilesDroppable._globalHandlers.dragover);
191
- EventHandler.on(document, 'dragleave', VGFilesDroppable._globalHandlers.dragleave);
192
- EventHandler.on(document, 'drop', VGFilesDroppable._globalHandlers.drop);
193
- EventHandler.on(document, 'dragend', VGFilesDroppable._globalHandlers.dragend);
194
-
195
- EventHandler.on(window, 'dragenter', VGFilesDroppable._globalHandlers.dragenter);
196
- EventHandler.on(window, 'dragover', VGFilesDroppable._globalHandlers.dragover);
197
- EventHandler.on(window, 'dragleave', VGFilesDroppable._globalHandlers.dragleave);
198
- EventHandler.on(window, 'drop', VGFilesDroppable._globalHandlers.drop);
199
- EventHandler.on(window, 'dragend', VGFilesDroppable._globalHandlers.dragend);
200
-
201
- VGFilesDroppable._isGlobalEventsBound = true;
202
- }
203
-
204
- _updateSuggestedDrop(e) {
205
- if (!this._isFileDrag(e)) {
206
- VGFilesDroppable._clearSuggestedDrop();
207
- return;
208
- }
209
-
210
- const visibleDrops = this._getVisibleDropZonesInViewport();
211
-
212
- if (visibleDrops.length === 1) {
213
- const [dropZone] = visibleDrops;
214
- if (VGFilesDroppable._activeSuggestedDrop !== dropZone) {
215
- VGFilesDroppable._clearSuggestedDrop();
216
- Classes.add(dropZone, CLASS_NAME_DROP_ACTIVE);
217
- VGFilesDroppable._setDropMessageTitleState(dropZone, true);
218
- VGFilesDroppable._activeSuggestedDrop = dropZone;
219
- }
220
-
221
- if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
222
- e.preventDefault();
223
- return;
224
- }
225
-
226
- VGFilesDroppable._clearSuggestedDrop();
227
- }
228
-
229
- _isFileDrag(e) {
230
- try {
231
- const dt = e?.dataTransfer;
232
- if (!dt) return false;
233
-
234
- if (dt.files && dt.files.length > 0) return true;
235
-
236
- if (dt.items && dt.items.length > 0) {
237
- return Array.from(dt.items).some(item => item.kind === 'file');
238
- }
239
-
240
- if (dt.types) {
241
- return Array.from(dt.types).includes('Files');
242
- }
243
-
244
- return false;
245
- } catch (_) {
246
- return false;
247
- }
248
- }
249
-
250
- _getVisibleDropZonesInViewport() {
251
- const dropZones = Array.from(Selectors.findAll(`.${CLASS_NAME_DROP}`) || []);
252
- return dropZones.filter((el) => this._isVisibleInViewport(el));
253
- }
254
-
255
- _isVisibleInViewport(el) {
256
- if (!isElement(el) || !el.isConnected) return false;
257
-
258
- const style = window.getComputedStyle(el);
259
- if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
260
- return false;
261
- }
262
-
263
- const rect = el.getBoundingClientRect();
264
- if (!rect.width || !rect.height) return false;
265
-
266
- const inViewport =
267
- rect.bottom > 0 &&
268
- rect.right > 0 &&
269
- rect.top < window.innerHeight &&
270
- rect.left < window.innerWidth;
271
-
272
- return inViewport;
273
- }
274
-
275
- static _clearSuggestedDrop() {
276
- if (!VGFilesDroppable._activeSuggestedDrop) return;
277
-
278
- VGFilesDroppable._setDropMessageTitleState(VGFilesDroppable._activeSuggestedDrop, false);
279
- Classes.remove(VGFilesDroppable._activeSuggestedDrop, CLASS_NAME_DROP_ACTIVE);
280
- VGFilesDroppable._activeSuggestedDrop = null;
281
- }
282
-
283
- static _setDropMessageTitleState(dropElement, isActive) {
284
- if (!isElement(dropElement)) return;
285
-
286
- const title = Selectors.find('.vg-files-drop-message .title', dropElement);
287
- if (!title) return;
288
-
289
- const originalText = (title.getAttribute('data-drop-original-text') || '').trim() || (title.textContent || '').trim();
290
- title.setAttribute('data-drop-original-text', originalText);
291
-
292
- const activeText = (dropElement.getAttribute('data-drop-active-text') || '').trim();
293
- if (isActive && activeText) {
294
- title.textContent = activeText;
295
- return;
296
- }
297
-
298
- title.textContent = originalText;
299
- }
300
-
301
- static _unbindGlobalEvents() {
302
- if (!VGFilesDroppable._isGlobalEventsBound) return;
303
-
304
- const handlers = VGFilesDroppable._globalHandlers || {};
305
-
306
- EventHandler.off(document, 'dragenter', handlers.dragenter);
307
- EventHandler.off(document, 'dragover', handlers.dragover);
308
- EventHandler.off(document, 'dragleave', handlers.dragleave);
309
- EventHandler.off(document, 'drop', handlers.drop);
310
- EventHandler.off(document, 'dragend', handlers.dragend);
311
-
312
- EventHandler.off(window, 'dragenter', handlers.dragenter);
313
- EventHandler.off(window, 'dragover', handlers.dragover);
314
- EventHandler.off(window, 'dragleave', handlers.dragleave);
315
- EventHandler.off(window, 'drop', handlers.drop);
316
- EventHandler.off(window, 'dragend', handlers.dragend);
317
-
318
- VGFilesDroppable._isGlobalEventsBound = false;
319
- VGFilesDroppable._globalHandlers = null;
320
- VGFilesDroppable._clearSuggestedDrop();
321
- }
149
+ });
150
+ }
151
+
152
+ _bindGlobalEvents() {
153
+ if (VGFilesDroppable._isGlobalEventsBound) return;
154
+
155
+ VGFilesDroppable._globalHandlers = {
156
+ dragenter: (e) => this._updateSuggestedDrop(e),
157
+ dragover: (e) => this._updateSuggestedDrop(e),
158
+ dragleave: (e) => {
159
+ if (!this._isFileDrag(e)) return;
160
+ if (e.relatedTarget === null || e.target === document || e.target === document.documentElement) {
161
+ VGFilesDroppable._clearSuggestedDrop();
162
+ }
163
+ },
164
+ drop: (e) => {
165
+ if (!this._isFileDrag(e)) {
166
+ VGFilesDroppable._clearSuggestedDrop();
167
+ return;
168
+ }
169
+
170
+ const activeDrop = VGFilesDroppable._activeSuggestedDrop;
171
+ if (activeDrop) {
172
+ const instance = Array.from(VGFilesDroppable._smartInstances).find(i => i._element === activeDrop);
173
+ const files = e.dataTransfer?.files;
174
+
175
+ if (instance && files && files.length && isElement(instance._input)) {
176
+ e.preventDefault();
177
+ e.stopPropagation();
178
+ instance._files = files;
179
+ instance._input.files = files;
180
+ EventHandler.trigger(instance._input, 'change');
181
+ }
182
+ }
183
+
184
+ VGFilesDroppable._clearSuggestedDrop();
185
+ },
186
+ dragend: () => VGFilesDroppable._clearSuggestedDrop(),
187
+ };
188
+
189
+ EventHandler.on(document, 'dragenter', VGFilesDroppable._globalHandlers.dragenter);
190
+ EventHandler.on(document, 'dragover', VGFilesDroppable._globalHandlers.dragover);
191
+ EventHandler.on(document, 'dragleave', VGFilesDroppable._globalHandlers.dragleave);
192
+ EventHandler.on(document, 'drop', VGFilesDroppable._globalHandlers.drop);
193
+ EventHandler.on(document, 'dragend', VGFilesDroppable._globalHandlers.dragend);
194
+
195
+ EventHandler.on(window, 'dragenter', VGFilesDroppable._globalHandlers.dragenter);
196
+ EventHandler.on(window, 'dragover', VGFilesDroppable._globalHandlers.dragover);
197
+ EventHandler.on(window, 'dragleave', VGFilesDroppable._globalHandlers.dragleave);
198
+ EventHandler.on(window, 'drop', VGFilesDroppable._globalHandlers.drop);
199
+ EventHandler.on(window, 'dragend', VGFilesDroppable._globalHandlers.dragend);
200
+
201
+ VGFilesDroppable._isGlobalEventsBound = true;
202
+ }
203
+
204
+ _updateSuggestedDrop(e) {
205
+ if (!this._isFileDrag(e)) {
206
+ VGFilesDroppable._clearSuggestedDrop();
207
+ return;
208
+ }
209
+
210
+ const visibleDrops = this._getVisibleDropZonesInViewport();
211
+
212
+ if (visibleDrops.length === 1) {
213
+ const [dropZone] = visibleDrops;
214
+ if (VGFilesDroppable._activeSuggestedDrop !== dropZone) {
215
+ VGFilesDroppable._clearSuggestedDrop();
216
+ Classes.add(dropZone, CLASS_NAME_DROP_ACTIVE);
217
+ VGFilesDroppable._setDropMessageTitleState(dropZone, true);
218
+ VGFilesDroppable._activeSuggestedDrop = dropZone;
219
+ }
220
+
221
+ if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
222
+ e.preventDefault();
223
+ return;
224
+ }
225
+
226
+ VGFilesDroppable._clearSuggestedDrop();
227
+ }
228
+
229
+ _isFileDrag(e) {
230
+ try {
231
+ const dt = e?.dataTransfer;
232
+ if (!dt) return false;
233
+
234
+ if (dt.files && dt.files.length > 0) return true;
235
+
236
+ if (dt.items && dt.items.length > 0) {
237
+ return Array.from(dt.items).some(item => item.kind === 'file');
238
+ }
239
+
240
+ if (dt.types) {
241
+ return Array.from(dt.types).includes('Files');
242
+ }
243
+
244
+ return false;
245
+ } catch (_) {
246
+ return false;
247
+ }
248
+ }
249
+
250
+ _getVisibleDropZonesInViewport() {
251
+ const dropZones = Array.from(Selectors.findAll(`.${CLASS_NAME_DROP}`) || []);
252
+ return dropZones.filter((el) => this._isVisibleInViewport(el));
253
+ }
254
+
255
+ _isVisibleInViewport(el) {
256
+ if (!isElement(el) || !el.isConnected) return false;
257
+
258
+ const style = window.getComputedStyle(el);
259
+ if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
260
+ return false;
261
+ }
262
+
263
+ const rect = el.getBoundingClientRect();
264
+ if (!rect.width || !rect.height) return false;
265
+
266
+ const inViewport =
267
+ rect.bottom > 0 &&
268
+ rect.right > 0 &&
269
+ rect.top < window.innerHeight &&
270
+ rect.left < window.innerWidth;
271
+
272
+ return inViewport;
273
+ }
274
+
275
+ static _clearSuggestedDrop() {
276
+ if (!VGFilesDroppable._activeSuggestedDrop) return;
277
+
278
+ VGFilesDroppable._setDropMessageTitleState(VGFilesDroppable._activeSuggestedDrop, false);
279
+ Classes.remove(VGFilesDroppable._activeSuggestedDrop, CLASS_NAME_DROP_ACTIVE);
280
+ VGFilesDroppable._activeSuggestedDrop = null;
281
+ }
282
+
283
+ static _setDropMessageTitleState(dropElement, isActive) {
284
+ if (!isElement(dropElement)) return;
285
+
286
+ const title = Selectors.find('.vg-files-drop-message .title', dropElement);
287
+ if (!title) return;
288
+
289
+ const originalText = (title.getAttribute('data-drop-original-text') || '').trim() || (title.textContent || '').trim();
290
+ title.setAttribute('data-drop-original-text', originalText);
291
+
292
+ const activeText = (dropElement.getAttribute('data-drop-active-text') || '').trim();
293
+ if (isActive && activeText) {
294
+ title.textContent = activeText;
295
+ return;
296
+ }
297
+
298
+ title.textContent = originalText;
299
+ }
300
+
301
+ static _unbindGlobalEvents() {
302
+ if (!VGFilesDroppable._isGlobalEventsBound) return;
303
+
304
+ const handlers = VGFilesDroppable._globalHandlers || {};
305
+
306
+ EventHandler.off(document, 'dragenter', handlers.dragenter);
307
+ EventHandler.off(document, 'dragover', handlers.dragover);
308
+ EventHandler.off(document, 'dragleave', handlers.dragleave);
309
+ EventHandler.off(document, 'drop', handlers.drop);
310
+ EventHandler.off(document, 'dragend', handlers.dragend);
311
+
312
+ EventHandler.off(window, 'dragenter', handlers.dragenter);
313
+ EventHandler.off(window, 'dragover', handlers.dragover);
314
+ EventHandler.off(window, 'dragleave', handlers.dragleave);
315
+ EventHandler.off(window, 'drop', handlers.drop);
316
+ EventHandler.off(window, 'dragend', handlers.dragend);
317
+
318
+ VGFilesDroppable._isGlobalEventsBound = false;
319
+ VGFilesDroppable._globalHandlers = null;
320
+ VGFilesDroppable._clearSuggestedDrop();
321
+ }
322
322
 
323
323
  getFiles() {
324
324
  return this._files;
325
325
  }
326
326
 
327
- dispose() {
328
- EventHandler.off(this._element, 'dragover');
329
- EventHandler.off(this._element, 'dragenter');
330
- EventHandler.off(this._element, 'dragleave');
331
- EventHandler.off(this._element, 'drop');
332
-
333
- VGFilesDroppable._instances.delete(this);
334
- VGFilesDroppable._smartInstances.delete(this);
335
- if (!VGFilesDroppable._smartInstances.size) {
336
- VGFilesDroppable._unbindGlobalEvents();
337
- }
338
-
339
- this._input = null;
340
- this._files = null;
341
- }
327
+ dispose() {
328
+ EventHandler.off(this._element, 'dragover');
329
+ EventHandler.off(this._element, 'dragenter');
330
+ EventHandler.off(this._element, 'dragleave');
331
+ EventHandler.off(this._element, 'drop');
332
+
333
+ VGFilesDroppable._instances.delete(this);
334
+ VGFilesDroppable._smartInstances.delete(this);
335
+ if (!VGFilesDroppable._smartInstances.size) {
336
+ VGFilesDroppable._unbindGlobalEvents();
337
+ }
338
+
339
+ this._input = null;
340
+ this._files = null;
341
+ }
342
342
 
343
343
  init() {
344
344
  return this;
345
345
  }
346
- }
347
-
348
- VGFilesDroppable._instances = new Set();
349
- VGFilesDroppable._smartInstances = new Set();
350
- VGFilesDroppable._isGlobalEventsBound = false;
351
- VGFilesDroppable._activeSuggestedDrop = null;
352
- VGFilesDroppable._globalHandlers = null;
353
-
354
- export default VGFilesDroppable;
346
+ }
347
+
348
+ VGFilesDroppable._instances = new Set();
349
+ VGFilesDroppable._smartInstances = new Set();
350
+ VGFilesDroppable._isGlobalEventsBound = false;
351
+ VGFilesDroppable._activeSuggestedDrop = null;
352
+ VGFilesDroppable._globalHandlers = null;
353
+
354
+ export default VGFilesDroppable;