vgapp 1.1.6 → 1.1.7

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 (54) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +48 -48
  3. package/app/langs/en/buttons.json +17 -17
  4. package/app/langs/en/messages.json +36 -36
  5. package/app/langs/ru/buttons.json +17 -17
  6. package/app/langs/ru/messages.json +36 -36
  7. package/app/modules/vgfilepreview/js/i18n.js +56 -56
  8. package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
  9. package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
  10. package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
  11. package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
  12. package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
  13. package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
  14. package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
  15. package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
  16. package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
  17. package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
  18. package/app/modules/vgfilepreview/js/renderers/video-modal.js +272 -272
  19. package/app/modules/vgfilepreview/js/renderers/video.js +80 -80
  20. package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
  21. package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
  22. package/app/modules/vgfilepreview/js/vgfilepreview.js +7 -7
  23. package/app/modules/vgfilepreview/readme.md +68 -68
  24. package/app/modules/vgfilepreview/scss/_variables.scss +113 -113
  25. package/app/modules/vgfilepreview/scss/vgfilepreview.scss +464 -464
  26. package/app/modules/vgfiles/js/base.js +26 -26
  27. package/app/modules/vgfiles/js/droppable.js +260 -260
  28. package/app/modules/vgfiles/js/render.js +153 -153
  29. package/app/modules/vgfiles/js/vgfiles.js +41 -41
  30. package/app/modules/vgfiles/readme.md +123 -123
  31. package/app/modules/vgfiles/scss/_variables.scss +18 -18
  32. package/app/modules/vgfiles/scss/vgfiles.scss +148 -148
  33. package/app/modules/vgformsender/js/vgformsender.js +1 -1
  34. package/app/modules/vgmodal/js/vgmodal.drag.js +332 -332
  35. package/app/modules/vgmodal/js/vgmodal.js +33 -33
  36. package/app/modules/vgmodal/js/vgmodal.resize.js +435 -435
  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 -240
  46. package/app/utils/js/components/file-icon.js +109 -109
  47. package/app/utils/js/components/file-preview.js +304 -304
  48. package/app/utils/js/components/sanitize.js +150 -150
  49. package/app/utils/js/components/video-metadata.js +140 -140
  50. package/build/vgapp.css +1 -1
  51. package/build/vgapp.css.map +1 -1
  52. package/build/vgapp.js.map +1 -1
  53. package/index.scss +9 -9
  54. package/package.json +1 -1
@@ -1,435 +1,435 @@
1
- const DEFAULT_OPTIONS = {
2
- enable: false,
3
- minWidth: 300,
4
- minHeight: 160,
5
- edgeSize: 8,
6
- debug: false,
7
- };
8
-
9
- const DIRECTION_TO_CURSOR = {
10
- n: 'ns-resize',
11
- s: 'ns-resize',
12
- e: 'ew-resize',
13
- w: 'ew-resize',
14
- ne: 'nesw-resize',
15
- sw: 'nesw-resize',
16
- nw: 'nwse-resize',
17
- se: 'nwse-resize',
18
- };
19
-
20
- class VGModalResize {
21
- constructor(modalElement, dialogElement, options = {}) {
22
- this._modalElement = modalElement;
23
- this._dialogElement = dialogElement;
24
- this._contentElement = this._dialogElement ? this._dialogElement.querySelector('.vg-modal-content') : null;
25
- this._options = this._normalizeOptions(options);
26
- this._pointerId = null;
27
- this._direction = '';
28
- this._startX = 0;
29
- this._startY = 0;
30
- this._currentX = 0;
31
- this._currentY = 0;
32
- this._startWidth = 0;
33
- this._startHeight = 0;
34
- this._startLeft = 0;
35
- this._startTop = 0;
36
- this._startRight = 0;
37
- this._startBottom = 0;
38
- this._isEnabled = false;
39
- this._observer = null;
40
- this._syncFrameId = null;
41
- this._resizeFrameId = null;
42
- this._lockedIframes = [];
43
- this._debugElement = null;
44
- this._previousMaxWidth = '';
45
- this._previousMaxHeight = '';
46
- this._previousPointerEvents = '';
47
- this._previousMinHeight = '';
48
- this._previousOverflow = '';
49
- this._previousTransition = '';
50
- this._previousWillChange = '';
51
- this._previousContentHeight = '';
52
- this._previousContentMaxHeight = '';
53
- this._previousContentOverflow = '';
54
-
55
- this._onPointerDown = this._onPointerDown.bind(this);
56
- this._onPointerMove = this._onPointerMove.bind(this);
57
- this._onPointerUp = this._onPointerUp.bind(this);
58
- this._onPointerLeave = this._onPointerLeave.bind(this);
59
- this._applyResizePosition = this._applyResizePosition.bind(this);
60
- }
61
-
62
- setOptions(options = {}) {
63
- this._options = this._normalizeOptions(options, this._options);
64
- this._updateDebugOverlay();
65
- }
66
-
67
- enable() {
68
- if (!this._dialogElement || this._isEnabled) return;
69
-
70
- this._updateDebugOverlay();
71
- this._modalElement.addEventListener('pointermove', this._onPointerMove);
72
- this._modalElement.addEventListener('pointerdown', this._onPointerDown);
73
- this._modalElement.addEventListener('pointerleave', this._onPointerLeave);
74
- this._startObserveSizeChanges();
75
- this._isEnabled = true;
76
- }
77
-
78
- disable() {
79
- if (!this._isEnabled) return;
80
-
81
- this._modalElement.removeEventListener('pointermove', this._onPointerMove);
82
- this._modalElement.removeEventListener('pointerdown', this._onPointerDown);
83
- this._modalElement.removeEventListener('pointerleave', this._onPointerLeave);
84
- document.removeEventListener('pointermove', this._onPointerMove);
85
- document.removeEventListener('pointerup', this._onPointerUp);
86
- document.removeEventListener('pointercancel', this._onPointerUp);
87
- this._cancelResizeFrame();
88
- this._stopObserveSizeChanges();
89
- this._pointerId = null;
90
- this._direction = '';
91
- this._dialogElement.style.cursor = '';
92
- delete this._modalElement.dataset.vgModalResizing;
93
- this._unlockEmbeddedFrames();
94
- this._restoreResizeStyles();
95
- this._setDebugVisibility(false);
96
- this._isEnabled = false;
97
- }
98
-
99
- syncToViewport() {
100
- if (this._modalElement && this._modalElement.dataset.vgModalDragging === 'true') return;
101
- if (!this._isPreparedForInteraction()) return;
102
-
103
- const rect = this._dialogElement.getBoundingClientRect();
104
- const currentWidth = this._dialogElement.offsetWidth || rect.width;
105
- const currentHeight = this._dialogElement.offsetHeight || rect.height;
106
- const currentLeftValue = Number.parseFloat(this._dialogElement.style.left);
107
- const currentTopValue = Number.parseFloat(this._dialogElement.style.top);
108
- const currentLeft = Number.isFinite(currentLeftValue) ? currentLeftValue : rect.left;
109
- const currentTop = Number.isFinite(currentTopValue) ? currentTopValue : rect.top;
110
- const maxWidth = window.innerWidth;
111
- const maxHeight = window.innerHeight;
112
- const width = Math.max(this._options.minWidth, Math.min(currentWidth, maxWidth));
113
- const height = Math.max(this._options.minHeight, Math.min(currentHeight, maxHeight));
114
- const maxLeft = Math.max(0, window.innerWidth - width);
115
- const maxTop = Math.max(0, window.innerHeight - height);
116
- const left = Math.min(maxLeft, Math.max(0, currentLeft));
117
- const top = Math.min(maxTop, Math.max(0, currentTop));
118
-
119
- if (Math.abs(currentWidth - width) > 0.5) {
120
- this._dialogElement.style.width = `${width}px`;
121
- }
122
-
123
- if (Math.abs(currentHeight - height) > 0.5) {
124
- this._dialogElement.style.height = `${height}px`;
125
- }
126
-
127
- this._dialogElement.style.left = `${left}px`;
128
- this._dialogElement.style.top = `${top}px`;
129
- this._updateDebugValues();
130
- }
131
-
132
- _onPointerDown(event) {
133
- if (event.button !== 0) return;
134
- if (event.defaultPrevented) return;
135
-
136
- const direction = this._getDirectionFromPointer(event);
137
- if (!direction) return;
138
-
139
- event.preventDefault();
140
- this._pointerId = event.pointerId;
141
- this._direction = direction;
142
-
143
- const rect = this._dialogElement.getBoundingClientRect();
144
- this._applyResizeStyles();
145
- this._preparePosition(rect);
146
- this._startX = event.clientX;
147
- this._startY = event.clientY;
148
- this._currentX = event.clientX;
149
- this._currentY = event.clientY;
150
- this._startWidth = rect.width;
151
- this._startHeight = rect.height;
152
- this._startLeft = rect.left;
153
- this._startTop = rect.top;
154
- this._startRight = rect.right;
155
- this._startBottom = rect.bottom;
156
- this._lockEmbeddedFrames();
157
- this._modalElement.dataset.vgModalResizing = 'true';
158
- this._setDebugVisibility(true);
159
- this._updateDebugValues();
160
-
161
- document.addEventListener('pointermove', this._onPointerMove);
162
- document.addEventListener('pointerup', this._onPointerUp);
163
- document.addEventListener('pointercancel', this._onPointerUp);
164
- }
165
-
166
- _onPointerMove(event) {
167
- if (this._pointerId === null) {
168
- const direction = this._getDirectionFromPointer(event);
169
- this._dialogElement.style.cursor = direction ? DIRECTION_TO_CURSOR[direction] : '';
170
- return;
171
- }
172
-
173
- if (event.pointerId !== this._pointerId) return;
174
-
175
- this._currentX = event.clientX;
176
- this._currentY = event.clientY;
177
- if (this._resizeFrameId !== null) return;
178
- this._resizeFrameId = window.requestAnimationFrame(this._applyResizePosition);
179
- }
180
-
181
- _applyResizePosition() {
182
- this._resizeFrameId = null;
183
- if (this._pointerId === null) return;
184
-
185
- const deltaX = this._currentX - this._startX;
186
- const deltaY = this._currentY - this._startY;
187
- let width = this._startWidth;
188
- let height = this._startHeight;
189
- let left = this._startLeft;
190
- let top = this._startTop;
191
-
192
- if (this._direction.includes('e')) {
193
- const maxWidth = Math.max(this._options.minWidth, window.innerWidth - this._startLeft);
194
- width = Math.min(maxWidth, Math.max(this._options.minWidth, this._startWidth + deltaX));
195
- }
196
-
197
- if (this._direction.includes('s')) {
198
- const maxHeight = Math.max(this._options.minHeight, window.innerHeight - this._startTop);
199
- height = Math.min(maxHeight, Math.max(this._options.minHeight, this._startHeight + deltaY));
200
- }
201
-
202
- if (this._direction.includes('w')) {
203
- const maxLeft = this._startRight - this._options.minWidth;
204
- left = Math.min(maxLeft, Math.max(0, this._startLeft + deltaX));
205
- width = this._startRight - left;
206
- }
207
-
208
- if (this._direction.includes('n')) {
209
- const maxTop = this._startBottom - this._options.minHeight;
210
- top = Math.min(maxTop, Math.max(0, this._startTop + deltaY));
211
- height = this._startBottom - top;
212
- }
213
-
214
- this._dialogElement.style.left = `${left}px`;
215
- this._dialogElement.style.top = `${top}px`;
216
- this._dialogElement.style.width = `${width}px`;
217
- this._dialogElement.style.height = `${height}px`;
218
- this._updateDebugValues();
219
- }
220
-
221
- _onPointerUp(event) {
222
- if (event.pointerId !== this._pointerId) return;
223
-
224
- document.removeEventListener('pointermove', this._onPointerMove);
225
- document.removeEventListener('pointerup', this._onPointerUp);
226
- document.removeEventListener('pointercancel', this._onPointerUp);
227
- this._cancelResizeFrame();
228
- this._applyResizePosition();
229
- this._pointerId = null;
230
- this._direction = '';
231
- delete this._modalElement.dataset.vgModalResizing;
232
- this._unlockEmbeddedFrames();
233
- this._setDebugVisibility(this._options.debug);
234
- this._updateDebugValues();
235
- }
236
-
237
- _onPointerLeave() {
238
- if (this._pointerId !== null) return;
239
- this._dialogElement.style.cursor = '';
240
- }
241
-
242
- _getDirectionFromPointer(event) {
243
- const rect = this._dialogElement.getBoundingClientRect();
244
- const offsetX = event.clientX - rect.left;
245
- const offsetY = event.clientY - rect.top;
246
- const edgeSize = this._options.edgeSize;
247
- const insideDialog = offsetX >= 0 && offsetX <= rect.width && offsetY >= 0 && offsetY <= rect.height;
248
- if (!insideDialog) return '';
249
-
250
- const nearTop = offsetY >= 0 && offsetY <= edgeSize;
251
- const nearBottom = offsetY <= rect.height && offsetY >= rect.height - edgeSize;
252
- const nearLeft = offsetX >= 0 && offsetX <= edgeSize;
253
- const nearRight = offsetX <= rect.width && offsetX >= rect.width - edgeSize;
254
-
255
- if (nearTop && nearLeft) return 'nw';
256
- if (nearTop && nearRight) return 'ne';
257
- if (nearBottom && nearLeft) return 'sw';
258
- if (nearBottom && nearRight) return 'se';
259
- if (nearTop) return 'n';
260
- if (nearBottom) return 's';
261
- if (nearLeft) return 'w';
262
- if (nearRight) return 'e';
263
-
264
- return '';
265
- }
266
-
267
- _preparePosition(rect) {
268
- this._dialogElement.style.position = 'fixed';
269
- this._dialogElement.style.margin = '0';
270
- this._dialogElement.style.left = `${rect.left}px`;
271
- this._dialogElement.style.top = `${rect.top}px`;
272
- this._dialogElement.style.width = `${rect.width}px`;
273
- this._dialogElement.style.height = `${rect.height}px`;
274
- this._dialogElement.style.transform = 'none';
275
- }
276
-
277
- _isPreparedForInteraction() {
278
- return this._dialogElement.style.position === 'fixed' && this._dialogElement.style.transform === 'none';
279
- }
280
-
281
- _startObserveSizeChanges() {
282
- if (typeof ResizeObserver === 'undefined' || this._observer) return;
283
-
284
- this._observer = new ResizeObserver(() => {
285
- if (this._pointerId !== null) return;
286
- if (this._modalElement && this._modalElement.dataset.vgModalDragging === 'true') return;
287
- if (this._syncFrameId !== null) return;
288
-
289
- this._syncFrameId = window.requestAnimationFrame(() => {
290
- this._syncFrameId = null;
291
- this.syncToViewport();
292
- });
293
- });
294
-
295
- this._observer.observe(this._dialogElement);
296
- }
297
-
298
- _stopObserveSizeChanges() {
299
- if (this._observer) {
300
- this._observer.disconnect();
301
- this._observer = null;
302
- }
303
-
304
- if (this._syncFrameId !== null) {
305
- window.cancelAnimationFrame(this._syncFrameId);
306
- this._syncFrameId = null;
307
- }
308
- }
309
-
310
- _applyResizeStyles() {
311
- this._previousMaxWidth = this._dialogElement.style.maxWidth;
312
- this._previousMaxHeight = this._dialogElement.style.maxHeight;
313
- this._previousPointerEvents = this._dialogElement.style.pointerEvents;
314
- this._previousMinHeight = this._dialogElement.style.minHeight;
315
- this._previousOverflow = this._dialogElement.style.overflow;
316
- this._previousTransition = this._dialogElement.style.transition;
317
- this._previousWillChange = this._dialogElement.style.willChange;
318
-
319
- this._dialogElement.style.maxWidth = 'none';
320
- this._dialogElement.style.maxHeight = 'none';
321
- this._dialogElement.style.pointerEvents = 'auto';
322
- this._dialogElement.style.minHeight = `${this._options.minHeight}px`;
323
- this._dialogElement.style.overflow = 'hidden';
324
- this._dialogElement.style.transition = 'none';
325
- this._dialogElement.style.willChange = 'left, top, width, height';
326
-
327
- if (this._contentElement) {
328
- this._previousContentHeight = this._contentElement.style.height;
329
- this._previousContentMaxHeight = this._contentElement.style.maxHeight;
330
- this._previousContentOverflow = this._contentElement.style.overflow;
331
- this._contentElement.style.height = '100%';
332
- this._contentElement.style.maxHeight = '100%';
333
- this._contentElement.style.overflow = 'auto';
334
- }
335
- }
336
-
337
- _restoreResizeStyles() {
338
- this._dialogElement.style.maxWidth = this._previousMaxWidth;
339
- this._dialogElement.style.maxHeight = this._previousMaxHeight;
340
- this._dialogElement.style.pointerEvents = this._previousPointerEvents;
341
- this._dialogElement.style.minHeight = this._previousMinHeight;
342
- this._dialogElement.style.overflow = this._previousOverflow;
343
- this._dialogElement.style.transition = this._previousTransition;
344
- this._dialogElement.style.willChange = this._previousWillChange;
345
-
346
- if (this._contentElement) {
347
- this._contentElement.style.height = this._previousContentHeight;
348
- this._contentElement.style.maxHeight = this._previousContentMaxHeight;
349
- this._contentElement.style.overflow = this._previousContentOverflow;
350
- }
351
- }
352
-
353
- _normalizeOptions(options, base = DEFAULT_OPTIONS) {
354
- const merged = {...base, ...options};
355
- const minWidth = Number(merged.minWidth);
356
- const minHeight = Number(merged.minHeight);
357
- const edgeSize = Number(merged.edgeSize);
358
-
359
- return {
360
- ...merged,
361
- minWidth: Number.isFinite(minWidth) && minWidth > 0 ? minWidth : DEFAULT_OPTIONS.minWidth,
362
- minHeight: Number.isFinite(minHeight) && minHeight > 0 ? minHeight : DEFAULT_OPTIONS.minHeight,
363
- edgeSize: Number.isFinite(edgeSize) && edgeSize > 0 ? edgeSize : DEFAULT_OPTIONS.edgeSize,
364
- debug: Boolean(merged.debug),
365
- };
366
- }
367
-
368
- _cancelResizeFrame() {
369
- if (this._resizeFrameId === null) return;
370
- window.cancelAnimationFrame(this._resizeFrameId);
371
- this._resizeFrameId = null;
372
- }
373
-
374
- _lockEmbeddedFrames() {
375
- if (!this._dialogElement || this._lockedIframes.length) return;
376
-
377
- const iframes = this._dialogElement.querySelectorAll('iframe');
378
- for (const frame of iframes) {
379
- this._lockedIframes.push({
380
- element: frame,
381
- pointerEvents: frame.style.pointerEvents,
382
- });
383
- frame.style.pointerEvents = 'none';
384
- }
385
- }
386
-
387
- _unlockEmbeddedFrames() {
388
- if (!this._lockedIframes.length) return;
389
-
390
- for (const item of this._lockedIframes) {
391
- item.element.style.pointerEvents = item.pointerEvents;
392
- }
393
- this._lockedIframes = [];
394
- }
395
-
396
- _updateDebugOverlay() {
397
- if (!this._options.debug) {
398
- this._setDebugVisibility(false);
399
- return;
400
- }
401
-
402
- if (!this._debugElement) {
403
- this._debugElement = document.createElement('div');
404
- this._debugElement.style.position = 'absolute';
405
- this._debugElement.style.left = '8px';
406
- this._debugElement.style.bottom = '8px';
407
- this._debugElement.style.zIndex = '6';
408
- this._debugElement.style.padding = '4px 6px';
409
- this._debugElement.style.borderRadius = '4px';
410
- this._debugElement.style.background = 'rgba(0, 0, 0, 0.72)';
411
- this._debugElement.style.color = '#fff';
412
- this._debugElement.style.fontSize = '11px';
413
- this._debugElement.style.lineHeight = '1.3';
414
- this._debugElement.style.pointerEvents = 'none';
415
- this._dialogElement.append(this._debugElement);
416
- }
417
-
418
- this._setDebugVisibility(true);
419
- this._updateDebugValues();
420
- }
421
-
422
- _setDebugVisibility(visible) {
423
- if (!this._debugElement) return;
424
- this._debugElement.style.display = visible ? 'block' : 'none';
425
- }
426
-
427
- _updateDebugValues() {
428
- if (!this._debugElement || !this._options.debug) return;
429
-
430
- const rect = this._dialogElement.getBoundingClientRect();
431
- this._debugElement.textContent = `w:${Math.round(rect.width)} h:${Math.round(rect.height)} x:${Math.round(rect.left)} y:${Math.round(rect.top)}`;
432
- }
433
- }
434
-
435
- export default VGModalResize;
1
+ const DEFAULT_OPTIONS = {
2
+ enable: false,
3
+ minWidth: 300,
4
+ minHeight: 160,
5
+ edgeSize: 8,
6
+ debug: false,
7
+ };
8
+
9
+ const DIRECTION_TO_CURSOR = {
10
+ n: 'ns-resize',
11
+ s: 'ns-resize',
12
+ e: 'ew-resize',
13
+ w: 'ew-resize',
14
+ ne: 'nesw-resize',
15
+ sw: 'nesw-resize',
16
+ nw: 'nwse-resize',
17
+ se: 'nwse-resize',
18
+ };
19
+
20
+ class VGModalResize {
21
+ constructor(modalElement, dialogElement, options = {}) {
22
+ this._modalElement = modalElement;
23
+ this._dialogElement = dialogElement;
24
+ this._contentElement = this._dialogElement ? this._dialogElement.querySelector('.vg-modal-content') : null;
25
+ this._options = this._normalizeOptions(options);
26
+ this._pointerId = null;
27
+ this._direction = '';
28
+ this._startX = 0;
29
+ this._startY = 0;
30
+ this._currentX = 0;
31
+ this._currentY = 0;
32
+ this._startWidth = 0;
33
+ this._startHeight = 0;
34
+ this._startLeft = 0;
35
+ this._startTop = 0;
36
+ this._startRight = 0;
37
+ this._startBottom = 0;
38
+ this._isEnabled = false;
39
+ this._observer = null;
40
+ this._syncFrameId = null;
41
+ this._resizeFrameId = null;
42
+ this._lockedIframes = [];
43
+ this._debugElement = null;
44
+ this._previousMaxWidth = '';
45
+ this._previousMaxHeight = '';
46
+ this._previousPointerEvents = '';
47
+ this._previousMinHeight = '';
48
+ this._previousOverflow = '';
49
+ this._previousTransition = '';
50
+ this._previousWillChange = '';
51
+ this._previousContentHeight = '';
52
+ this._previousContentMaxHeight = '';
53
+ this._previousContentOverflow = '';
54
+
55
+ this._onPointerDown = this._onPointerDown.bind(this);
56
+ this._onPointerMove = this._onPointerMove.bind(this);
57
+ this._onPointerUp = this._onPointerUp.bind(this);
58
+ this._onPointerLeave = this._onPointerLeave.bind(this);
59
+ this._applyResizePosition = this._applyResizePosition.bind(this);
60
+ }
61
+
62
+ setOptions(options = {}) {
63
+ this._options = this._normalizeOptions(options, this._options);
64
+ this._updateDebugOverlay();
65
+ }
66
+
67
+ enable() {
68
+ if (!this._dialogElement || this._isEnabled) return;
69
+
70
+ this._updateDebugOverlay();
71
+ this._modalElement.addEventListener('pointermove', this._onPointerMove);
72
+ this._modalElement.addEventListener('pointerdown', this._onPointerDown);
73
+ this._modalElement.addEventListener('pointerleave', this._onPointerLeave);
74
+ this._startObserveSizeChanges();
75
+ this._isEnabled = true;
76
+ }
77
+
78
+ disable() {
79
+ if (!this._isEnabled) return;
80
+
81
+ this._modalElement.removeEventListener('pointermove', this._onPointerMove);
82
+ this._modalElement.removeEventListener('pointerdown', this._onPointerDown);
83
+ this._modalElement.removeEventListener('pointerleave', this._onPointerLeave);
84
+ document.removeEventListener('pointermove', this._onPointerMove);
85
+ document.removeEventListener('pointerup', this._onPointerUp);
86
+ document.removeEventListener('pointercancel', this._onPointerUp);
87
+ this._cancelResizeFrame();
88
+ this._stopObserveSizeChanges();
89
+ this._pointerId = null;
90
+ this._direction = '';
91
+ this._dialogElement.style.cursor = '';
92
+ delete this._modalElement.dataset.vgModalResizing;
93
+ this._unlockEmbeddedFrames();
94
+ this._restoreResizeStyles();
95
+ this._setDebugVisibility(false);
96
+ this._isEnabled = false;
97
+ }
98
+
99
+ syncToViewport() {
100
+ if (this._modalElement && this._modalElement.dataset.vgModalDragging === 'true') return;
101
+ if (!this._isPreparedForInteraction()) return;
102
+
103
+ const rect = this._dialogElement.getBoundingClientRect();
104
+ const currentWidth = this._dialogElement.offsetWidth || rect.width;
105
+ const currentHeight = this._dialogElement.offsetHeight || rect.height;
106
+ const currentLeftValue = Number.parseFloat(this._dialogElement.style.left);
107
+ const currentTopValue = Number.parseFloat(this._dialogElement.style.top);
108
+ const currentLeft = Number.isFinite(currentLeftValue) ? currentLeftValue : rect.left;
109
+ const currentTop = Number.isFinite(currentTopValue) ? currentTopValue : rect.top;
110
+ const maxWidth = window.innerWidth;
111
+ const maxHeight = window.innerHeight;
112
+ const width = Math.max(this._options.minWidth, Math.min(currentWidth, maxWidth));
113
+ const height = Math.max(this._options.minHeight, Math.min(currentHeight, maxHeight));
114
+ const maxLeft = Math.max(0, window.innerWidth - width);
115
+ const maxTop = Math.max(0, window.innerHeight - height);
116
+ const left = Math.min(maxLeft, Math.max(0, currentLeft));
117
+ const top = Math.min(maxTop, Math.max(0, currentTop));
118
+
119
+ if (Math.abs(currentWidth - width) > 0.5) {
120
+ this._dialogElement.style.width = `${width}px`;
121
+ }
122
+
123
+ if (Math.abs(currentHeight - height) > 0.5) {
124
+ this._dialogElement.style.height = `${height}px`;
125
+ }
126
+
127
+ this._dialogElement.style.left = `${left}px`;
128
+ this._dialogElement.style.top = `${top}px`;
129
+ this._updateDebugValues();
130
+ }
131
+
132
+ _onPointerDown(event) {
133
+ if (event.button !== 0) return;
134
+ if (event.defaultPrevented) return;
135
+
136
+ const direction = this._getDirectionFromPointer(event);
137
+ if (!direction) return;
138
+
139
+ event.preventDefault();
140
+ this._pointerId = event.pointerId;
141
+ this._direction = direction;
142
+
143
+ const rect = this._dialogElement.getBoundingClientRect();
144
+ this._applyResizeStyles();
145
+ this._preparePosition(rect);
146
+ this._startX = event.clientX;
147
+ this._startY = event.clientY;
148
+ this._currentX = event.clientX;
149
+ this._currentY = event.clientY;
150
+ this._startWidth = rect.width;
151
+ this._startHeight = rect.height;
152
+ this._startLeft = rect.left;
153
+ this._startTop = rect.top;
154
+ this._startRight = rect.right;
155
+ this._startBottom = rect.bottom;
156
+ this._lockEmbeddedFrames();
157
+ this._modalElement.dataset.vgModalResizing = 'true';
158
+ this._setDebugVisibility(true);
159
+ this._updateDebugValues();
160
+
161
+ document.addEventListener('pointermove', this._onPointerMove);
162
+ document.addEventListener('pointerup', this._onPointerUp);
163
+ document.addEventListener('pointercancel', this._onPointerUp);
164
+ }
165
+
166
+ _onPointerMove(event) {
167
+ if (this._pointerId === null) {
168
+ const direction = this._getDirectionFromPointer(event);
169
+ this._dialogElement.style.cursor = direction ? DIRECTION_TO_CURSOR[direction] : '';
170
+ return;
171
+ }
172
+
173
+ if (event.pointerId !== this._pointerId) return;
174
+
175
+ this._currentX = event.clientX;
176
+ this._currentY = event.clientY;
177
+ if (this._resizeFrameId !== null) return;
178
+ this._resizeFrameId = window.requestAnimationFrame(this._applyResizePosition);
179
+ }
180
+
181
+ _applyResizePosition() {
182
+ this._resizeFrameId = null;
183
+ if (this._pointerId === null) return;
184
+
185
+ const deltaX = this._currentX - this._startX;
186
+ const deltaY = this._currentY - this._startY;
187
+ let width = this._startWidth;
188
+ let height = this._startHeight;
189
+ let left = this._startLeft;
190
+ let top = this._startTop;
191
+
192
+ if (this._direction.includes('e')) {
193
+ const maxWidth = Math.max(this._options.minWidth, window.innerWidth - this._startLeft);
194
+ width = Math.min(maxWidth, Math.max(this._options.minWidth, this._startWidth + deltaX));
195
+ }
196
+
197
+ if (this._direction.includes('s')) {
198
+ const maxHeight = Math.max(this._options.minHeight, window.innerHeight - this._startTop);
199
+ height = Math.min(maxHeight, Math.max(this._options.minHeight, this._startHeight + deltaY));
200
+ }
201
+
202
+ if (this._direction.includes('w')) {
203
+ const maxLeft = this._startRight - this._options.minWidth;
204
+ left = Math.min(maxLeft, Math.max(0, this._startLeft + deltaX));
205
+ width = this._startRight - left;
206
+ }
207
+
208
+ if (this._direction.includes('n')) {
209
+ const maxTop = this._startBottom - this._options.minHeight;
210
+ top = Math.min(maxTop, Math.max(0, this._startTop + deltaY));
211
+ height = this._startBottom - top;
212
+ }
213
+
214
+ this._dialogElement.style.left = `${left}px`;
215
+ this._dialogElement.style.top = `${top}px`;
216
+ this._dialogElement.style.width = `${width}px`;
217
+ this._dialogElement.style.height = `${height}px`;
218
+ this._updateDebugValues();
219
+ }
220
+
221
+ _onPointerUp(event) {
222
+ if (event.pointerId !== this._pointerId) return;
223
+
224
+ document.removeEventListener('pointermove', this._onPointerMove);
225
+ document.removeEventListener('pointerup', this._onPointerUp);
226
+ document.removeEventListener('pointercancel', this._onPointerUp);
227
+ this._cancelResizeFrame();
228
+ this._applyResizePosition();
229
+ this._pointerId = null;
230
+ this._direction = '';
231
+ delete this._modalElement.dataset.vgModalResizing;
232
+ this._unlockEmbeddedFrames();
233
+ this._setDebugVisibility(this._options.debug);
234
+ this._updateDebugValues();
235
+ }
236
+
237
+ _onPointerLeave() {
238
+ if (this._pointerId !== null) return;
239
+ this._dialogElement.style.cursor = '';
240
+ }
241
+
242
+ _getDirectionFromPointer(event) {
243
+ const rect = this._dialogElement.getBoundingClientRect();
244
+ const offsetX = event.clientX - rect.left;
245
+ const offsetY = event.clientY - rect.top;
246
+ const edgeSize = this._options.edgeSize;
247
+ const insideDialog = offsetX >= 0 && offsetX <= rect.width && offsetY >= 0 && offsetY <= rect.height;
248
+ if (!insideDialog) return '';
249
+
250
+ const nearTop = offsetY >= 0 && offsetY <= edgeSize;
251
+ const nearBottom = offsetY <= rect.height && offsetY >= rect.height - edgeSize;
252
+ const nearLeft = offsetX >= 0 && offsetX <= edgeSize;
253
+ const nearRight = offsetX <= rect.width && offsetX >= rect.width - edgeSize;
254
+
255
+ if (nearTop && nearLeft) return 'nw';
256
+ if (nearTop && nearRight) return 'ne';
257
+ if (nearBottom && nearLeft) return 'sw';
258
+ if (nearBottom && nearRight) return 'se';
259
+ if (nearTop) return 'n';
260
+ if (nearBottom) return 's';
261
+ if (nearLeft) return 'w';
262
+ if (nearRight) return 'e';
263
+
264
+ return '';
265
+ }
266
+
267
+ _preparePosition(rect) {
268
+ this._dialogElement.style.position = 'fixed';
269
+ this._dialogElement.style.margin = '0';
270
+ this._dialogElement.style.left = `${rect.left}px`;
271
+ this._dialogElement.style.top = `${rect.top}px`;
272
+ this._dialogElement.style.width = `${rect.width}px`;
273
+ this._dialogElement.style.height = `${rect.height}px`;
274
+ this._dialogElement.style.transform = 'none';
275
+ }
276
+
277
+ _isPreparedForInteraction() {
278
+ return this._dialogElement.style.position === 'fixed' && this._dialogElement.style.transform === 'none';
279
+ }
280
+
281
+ _startObserveSizeChanges() {
282
+ if (typeof ResizeObserver === 'undefined' || this._observer) return;
283
+
284
+ this._observer = new ResizeObserver(() => {
285
+ if (this._pointerId !== null) return;
286
+ if (this._modalElement && this._modalElement.dataset.vgModalDragging === 'true') return;
287
+ if (this._syncFrameId !== null) return;
288
+
289
+ this._syncFrameId = window.requestAnimationFrame(() => {
290
+ this._syncFrameId = null;
291
+ this.syncToViewport();
292
+ });
293
+ });
294
+
295
+ this._observer.observe(this._dialogElement);
296
+ }
297
+
298
+ _stopObserveSizeChanges() {
299
+ if (this._observer) {
300
+ this._observer.disconnect();
301
+ this._observer = null;
302
+ }
303
+
304
+ if (this._syncFrameId !== null) {
305
+ window.cancelAnimationFrame(this._syncFrameId);
306
+ this._syncFrameId = null;
307
+ }
308
+ }
309
+
310
+ _applyResizeStyles() {
311
+ this._previousMaxWidth = this._dialogElement.style.maxWidth;
312
+ this._previousMaxHeight = this._dialogElement.style.maxHeight;
313
+ this._previousPointerEvents = this._dialogElement.style.pointerEvents;
314
+ this._previousMinHeight = this._dialogElement.style.minHeight;
315
+ this._previousOverflow = this._dialogElement.style.overflow;
316
+ this._previousTransition = this._dialogElement.style.transition;
317
+ this._previousWillChange = this._dialogElement.style.willChange;
318
+
319
+ this._dialogElement.style.maxWidth = 'none';
320
+ this._dialogElement.style.maxHeight = 'none';
321
+ this._dialogElement.style.pointerEvents = 'auto';
322
+ this._dialogElement.style.minHeight = `${this._options.minHeight}px`;
323
+ this._dialogElement.style.overflow = 'hidden';
324
+ this._dialogElement.style.transition = 'none';
325
+ this._dialogElement.style.willChange = 'left, top, width, height';
326
+
327
+ if (this._contentElement) {
328
+ this._previousContentHeight = this._contentElement.style.height;
329
+ this._previousContentMaxHeight = this._contentElement.style.maxHeight;
330
+ this._previousContentOverflow = this._contentElement.style.overflow;
331
+ this._contentElement.style.height = '100%';
332
+ this._contentElement.style.maxHeight = '100%';
333
+ this._contentElement.style.overflow = 'auto';
334
+ }
335
+ }
336
+
337
+ _restoreResizeStyles() {
338
+ this._dialogElement.style.maxWidth = this._previousMaxWidth;
339
+ this._dialogElement.style.maxHeight = this._previousMaxHeight;
340
+ this._dialogElement.style.pointerEvents = this._previousPointerEvents;
341
+ this._dialogElement.style.minHeight = this._previousMinHeight;
342
+ this._dialogElement.style.overflow = this._previousOverflow;
343
+ this._dialogElement.style.transition = this._previousTransition;
344
+ this._dialogElement.style.willChange = this._previousWillChange;
345
+
346
+ if (this._contentElement) {
347
+ this._contentElement.style.height = this._previousContentHeight;
348
+ this._contentElement.style.maxHeight = this._previousContentMaxHeight;
349
+ this._contentElement.style.overflow = this._previousContentOverflow;
350
+ }
351
+ }
352
+
353
+ _normalizeOptions(options, base = DEFAULT_OPTIONS) {
354
+ const merged = {...base, ...options};
355
+ const minWidth = Number(merged.minWidth);
356
+ const minHeight = Number(merged.minHeight);
357
+ const edgeSize = Number(merged.edgeSize);
358
+
359
+ return {
360
+ ...merged,
361
+ minWidth: Number.isFinite(minWidth) && minWidth > 0 ? minWidth : DEFAULT_OPTIONS.minWidth,
362
+ minHeight: Number.isFinite(minHeight) && minHeight > 0 ? minHeight : DEFAULT_OPTIONS.minHeight,
363
+ edgeSize: Number.isFinite(edgeSize) && edgeSize > 0 ? edgeSize : DEFAULT_OPTIONS.edgeSize,
364
+ debug: Boolean(merged.debug),
365
+ };
366
+ }
367
+
368
+ _cancelResizeFrame() {
369
+ if (this._resizeFrameId === null) return;
370
+ window.cancelAnimationFrame(this._resizeFrameId);
371
+ this._resizeFrameId = null;
372
+ }
373
+
374
+ _lockEmbeddedFrames() {
375
+ if (!this._dialogElement || this._lockedIframes.length) return;
376
+
377
+ const iframes = this._dialogElement.querySelectorAll('iframe');
378
+ for (const frame of iframes) {
379
+ this._lockedIframes.push({
380
+ element: frame,
381
+ pointerEvents: frame.style.pointerEvents,
382
+ });
383
+ frame.style.pointerEvents = 'none';
384
+ }
385
+ }
386
+
387
+ _unlockEmbeddedFrames() {
388
+ if (!this._lockedIframes.length) return;
389
+
390
+ for (const item of this._lockedIframes) {
391
+ item.element.style.pointerEvents = item.pointerEvents;
392
+ }
393
+ this._lockedIframes = [];
394
+ }
395
+
396
+ _updateDebugOverlay() {
397
+ if (!this._options.debug) {
398
+ this._setDebugVisibility(false);
399
+ return;
400
+ }
401
+
402
+ if (!this._debugElement) {
403
+ this._debugElement = document.createElement('div');
404
+ this._debugElement.style.position = 'absolute';
405
+ this._debugElement.style.left = '8px';
406
+ this._debugElement.style.bottom = '8px';
407
+ this._debugElement.style.zIndex = '6';
408
+ this._debugElement.style.padding = '4px 6px';
409
+ this._debugElement.style.borderRadius = '4px';
410
+ this._debugElement.style.background = 'rgba(0, 0, 0, 0.72)';
411
+ this._debugElement.style.color = '#fff';
412
+ this._debugElement.style.fontSize = '11px';
413
+ this._debugElement.style.lineHeight = '1.3';
414
+ this._debugElement.style.pointerEvents = 'none';
415
+ this._dialogElement.append(this._debugElement);
416
+ }
417
+
418
+ this._setDebugVisibility(true);
419
+ this._updateDebugValues();
420
+ }
421
+
422
+ _setDebugVisibility(visible) {
423
+ if (!this._debugElement) return;
424
+ this._debugElement.style.display = visible ? 'block' : 'none';
425
+ }
426
+
427
+ _updateDebugValues() {
428
+ if (!this._debugElement || !this._options.debug) return;
429
+
430
+ const rect = this._dialogElement.getBoundingClientRect();
431
+ this._debugElement.textContent = `w:${Math.round(rect.width)} h:${Math.round(rect.height)} x:${Math.round(rect.left)} y:${Math.round(rect.top)}`;
432
+ }
433
+ }
434
+
435
+ export default VGModalResize;