vgapp 1.3.0 → 1.3.1

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 (88) hide show
  1. package/README.md +133 -133
  2. package/app/langs/en/buttons.json +17 -17
  3. package/app/langs/en/messages.json +36 -36
  4. package/app/langs/ru/buttons.json +17 -17
  5. package/app/langs/ru/messages.json +36 -36
  6. package/app/modules/base-module.js +111 -111
  7. package/app/modules/vgalert/readme.md +105 -105
  8. package/app/modules/vgdynamictable/index.js +5 -5
  9. package/app/modules/vgdynamictable/js/editable.js +19 -19
  10. package/app/modules/vgdynamictable/js/filters.js +21 -21
  11. package/app/modules/vgdynamictable/js/fixed.js +179 -179
  12. package/app/modules/vgdynamictable/js/pagination.js +1 -1
  13. package/app/modules/vgdynamictable/js/search.js +12 -12
  14. package/app/modules/vgdynamictable/js/sortable.js +71 -71
  15. package/app/modules/vgdynamictable/js/summary-footer.js +28 -28
  16. package/app/modules/vgdynamictable/js/table-remote.js +79 -79
  17. package/app/modules/vgdynamictable/js/table-url-state.js +31 -31
  18. package/app/modules/vgdynamictable/js/utils/common.js +48 -48
  19. package/app/modules/vgdynamictable/js/vgdynamictable.js +268 -268
  20. package/app/modules/vgdynamictable/readme.md +250 -250
  21. package/app/modules/vgdynamictable/scss/_skeleton.scss +6 -6
  22. package/app/modules/vgdynamictable/scss/_sortable.scss +24 -24
  23. package/app/modules/vgdynamictable/scss/_table.scss +4 -4
  24. package/app/modules/vgdynamictable/scss/_variables.scss +79 -79
  25. package/app/modules/vgdynamictable/scss/vgdynamictable.scss +27 -27
  26. package/app/modules/vgfilepreview/js/i18n.js +56 -56
  27. package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
  28. package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
  29. package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
  30. package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
  31. package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
  32. package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
  33. package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
  34. package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
  35. package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
  36. package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
  37. package/app/modules/vgfilepreview/js/renderers/video-modal.js +272 -272
  38. package/app/modules/vgfilepreview/js/renderers/video.js +80 -80
  39. package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
  40. package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
  41. package/app/modules/vgfilepreview/js/vgfilepreview.js +7 -7
  42. package/app/modules/vgfilepreview/readme.md +68 -68
  43. package/app/modules/vgfilepreview/scss/_variables.scss +113 -113
  44. package/app/modules/vgfilepreview/scss/vgfilepreview.scss +464 -464
  45. package/app/modules/vgfiles/js/base.js +26 -26
  46. package/app/modules/vgfiles/js/droppable.js +260 -260
  47. package/app/modules/vgfiles/js/render.js +153 -153
  48. package/app/modules/vgfiles/js/vgfiles.js +104 -104
  49. package/app/modules/vgfiles/readme.md +123 -123
  50. package/app/modules/vgfiles/scss/_variables.scss +18 -18
  51. package/app/modules/vgfiles/scss/vgfiles.scss +148 -148
  52. package/app/modules/vgformsender/js/hideshowpass.js +16 -16
  53. package/app/modules/vgformsender/scss/vgformsender.scss +34 -34
  54. package/app/modules/vgmodal/js/vgmodal.drag.js +332 -332
  55. package/app/modules/vgmodal/js/vgmodal.js +188 -188
  56. package/app/modules/vgmodal/js/vgmodal.resize.js +27 -27
  57. package/app/modules/vgmodal/scss/vgmodal.scss +14 -14
  58. package/app/modules/vgnav/js/vgnav.js +135 -135
  59. package/app/modules/vgnav/readme.md +67 -67
  60. package/app/modules/vgnestable/README.md +307 -307
  61. package/app/modules/vgnestable/scss/_variables.scss +60 -60
  62. package/app/modules/vgnestable/scss/vgnestable.scss +163 -163
  63. package/app/modules/vgrangeslider/js/skins.js +222 -222
  64. package/app/modules/vgrangeslider/js/vgrangeslider.js +704 -704
  65. package/app/modules/vgrangeslider/readme.md +523 -523
  66. package/app/modules/vgrangeslider/scss/_variables.scss +53 -53
  67. package/app/modules/vgrangeslider/scss/vgrangeslider.scss +240 -240
  68. package/app/modules/vgselect/js/vgselect.js +39 -39
  69. package/app/modules/vgselect/scss/vgselect.scss +22 -22
  70. package/app/modules/vgspy/readme.md +28 -28
  71. package/app/modules/vgtoast/readme.md +18 -18
  72. package/app/modules/vgtoast/scss/vgtoast.scss +48 -48
  73. package/app/modules/vgtooltip/js/vgtooltip.js +89 -89
  74. package/app/modules/vgtooltip/readme.md +181 -181
  75. package/app/utils/js/components/ajax.js +117 -117
  76. package/app/utils/js/components/audio-metadata.js +240 -240
  77. package/app/utils/js/components/backdrop.js +17 -17
  78. package/app/utils/js/components/file-icon.js +109 -109
  79. package/app/utils/js/components/file-preview.js +304 -304
  80. package/app/utils/js/components/sanitize.js +150 -150
  81. package/app/utils/js/components/video-metadata.js +140 -140
  82. package/app/vgapp.js +130 -107
  83. package/build/vgapp.css +2 -2
  84. package/build/vgapp.js +2 -2
  85. package/build/vgapp.js.LICENSE.txt +1 -1
  86. package/build/vgapp.js.map +1 -1
  87. package/index.js +14 -14
  88. package/package.json +1 -1
@@ -16,38 +16,38 @@ $sizes-4: map-get($spacers, 4);
16
16
  $sizes-5: map-get($spacers, 5);
17
17
 
18
18
  $dynamic-table-map: (
19
- wrap: (
20
- border-radius: 14px,
21
- box-shadow: none,
22
- border-width: 1px,
23
- background: transparent,
24
- border-color: transparent,
25
- ),
26
- cell: (
27
- padding: $sizes-3 $sizes-4,
28
- font-size: $sizes-3,
29
- row-content-height: 20px,
30
- border-color: transparent,
31
- text-color: #1f1f1f,
32
- ),
33
- header: (
34
- font-weight: 600,
35
- background: #f7f4ef,
36
- text-color: #1f1f1f,
37
- ),
38
- bordered: (
39
- border-width: 1px,
40
- border-color: rgba(0, 0, 0, 0.1),
41
- ),
42
- striped: (
43
- background: rgba(0, 0, 0, 0.03),
44
- ),
45
- hover: (
46
- background: rgba(0, 0, 0, 0.05),
47
- ),
48
- table: (
49
- min-width: 640px,
50
- ),
19
+ wrap: (
20
+ border-radius: 14px,
21
+ box-shadow: none,
22
+ border-width: 1px,
23
+ background: transparent,
24
+ border-color: transparent,
25
+ ),
26
+ cell: (
27
+ padding: $sizes-3 $sizes-4,
28
+ font-size: $sizes-3,
29
+ row-content-height: 20px,
30
+ border-color: transparent,
31
+ text-color: #1f1f1f,
32
+ ),
33
+ header: (
34
+ font-weight: 600,
35
+ background: #f7f4ef,
36
+ text-color: #1f1f1f,
37
+ ),
38
+ bordered: (
39
+ border-width: 1px,
40
+ border-color: rgba(0, 0, 0, 0.1),
41
+ ),
42
+ striped: (
43
+ background: rgba(0, 0, 0, 0.03),
44
+ ),
45
+ hover: (
46
+ background: rgba(0, 0, 0, 0.05),
47
+ ),
48
+ table: (
49
+ min-width: 640px,
50
+ ),
51
51
  table-sm: (
52
52
  padding: $sizes-1 $sizes-2,
53
53
  ),
@@ -60,9 +60,9 @@ $dynamic-table-map: (
60
60
  table-xl: (
61
61
  padding: $sizes-4 $sizes-5,
62
62
  ),
63
- pagination: (
64
- padding-y: 12px,
65
- padding-x: 14px,
63
+ pagination: (
64
+ padding-y: 12px,
65
+ padding-x: 14px,
66
66
  gap: 12px,
67
67
  toolbar-radius: 12px,
68
68
  toolbar-padding-y: 8px,
@@ -78,53 +78,53 @@ $dynamic-table-map: (
78
78
  button-disabled-opacity: 0.45,
79
79
  per-page-radius: 10px,
80
80
  per-page-height: 36px,
81
- per-page-padding-x: 10px,
82
- jump-width: 64px,
83
- jump-gap: 6px,
84
- jump-button-min-width: 54px,
85
- border-color: rgba(0, 0, 0, 0.08),
86
- toolbar-bg: #faf8f4,
87
- label-color: #5f5a52,
88
- button-border: 1px solid rgba(0, 0, 0, 0.12),
89
- button-border-color: rgba(0, 0, 0, 0.12),
90
- button-bg: #ffffff,
91
- button-text: #2e2a24,
92
- button-hover-bg: #f1ece4,
93
- button-hover-border: rgba(0, 0, 0, 0.2),
94
- button-active-bg: #24201b,
95
- button-active-text: #ffffff,
96
- button-active-border: #24201b,
97
- per-page-bg: #ffffff,
98
- per-page-border-color: rgba(0, 0, 0, 0.12),
99
- per-page-text: #2e2a24,
100
- ),
101
- sortable: (
102
- header-padding-right: 1.8rem,
103
- controls-right: 0.6rem,
81
+ per-page-padding-x: 10px,
82
+ jump-width: 64px,
83
+ jump-gap: 6px,
84
+ jump-button-min-width: 54px,
85
+ border-color: rgba(0, 0, 0, 0.08),
86
+ toolbar-bg: #faf8f4,
87
+ label-color: #5f5a52,
88
+ button-border: 1px solid rgba(0, 0, 0, 0.12),
89
+ button-border-color: rgba(0, 0, 0, 0.12),
90
+ button-bg: #ffffff,
91
+ button-text: #2e2a24,
92
+ button-hover-bg: #f1ece4,
93
+ button-hover-border: rgba(0, 0, 0, 0.2),
94
+ button-active-bg: #24201b,
95
+ button-active-text: #ffffff,
96
+ button-active-border: #24201b,
97
+ per-page-bg: #ffffff,
98
+ per-page-border-color: rgba(0, 0, 0, 0.12),
99
+ per-page-text: #2e2a24,
100
+ ),
101
+ sortable: (
102
+ header-padding-right: 1.8rem,
103
+ controls-right: 0.6rem,
104
104
  controls-gap: 0,
105
105
  arrow-width: 14px,
106
106
  arrow-height: 10px,
107
- arrow-line-height: 0.7rem,
108
- arrow-font-size: 0.55rem,
109
- arrow-opacity: 0.35,
110
- arrow-active-opacity: 1,
111
- arrow-color: currentColor,
112
- column-highlight-background: rgba(191, 153, 92, 0.14),
113
- ),
114
- fixed: (
115
- shadow-width: 14px,
116
- shadow-color: rgba(0, 0, 0, 0.16),
117
- cell-background: rgba(247, 244, 239, 0.92),
118
- ),
119
- skeleton: (
120
- padding: 12px 14px,
121
- line-height: 10px,
122
- radius: 999px,
123
- duration: 1.2s,
124
- row-bg: rgba(255, 255, 255, 0.5),
125
- border-color: rgba(0, 0, 0, 0.04),
126
- glow: rgba(255, 255, 255, 0.55),
107
+ arrow-line-height: 0.7rem,
108
+ arrow-font-size: 0.55rem,
109
+ arrow-opacity: 0.35,
110
+ arrow-active-opacity: 1,
111
+ arrow-color: currentColor,
112
+ column-highlight-background: rgba(191, 153, 92, 0.14),
113
+ ),
114
+ fixed: (
115
+ shadow-width: 14px,
116
+ shadow-color: rgba(0, 0, 0, 0.16),
117
+ cell-background: rgba(247, 244, 239, 0.92),
118
+ ),
119
+ skeleton: (
120
+ padding: 12px 14px,
121
+ line-height: 10px,
122
+ radius: 999px,
123
+ duration: 1.2s,
124
+ row-bg: rgba(255, 255, 255, 0.5),
125
+ border-color: rgba(0, 0, 0, 0.04),
126
+ glow: rgba(255, 255, 255, 0.55),
127
127
  gradient-1: #ebe6df,
128
128
  gradient-2: #f5f1ea,
129
129
  ),
130
- );
130
+ );
@@ -11,9 +11,9 @@
11
11
  @import "../../../utils/scss/variables";
12
12
  @import "variables";
13
13
 
14
- .vg-dynamic-table {
15
- @include mix-vars('dynamic-table', $dynamic-table-map);
16
- background: var(--vg-dynamic-table-wrap-background);
14
+ .vg-dynamic-table {
15
+ @include mix-vars('dynamic-table', $dynamic-table-map);
16
+ background: var(--vg-dynamic-table-wrap-background);
17
17
  border-radius: var(--vg-dynamic-table-wrap-border-radius);
18
18
  box-shadow: var(--vg-dynamic-table-wrap-box-shadow);
19
19
  overflow: visible;
@@ -62,30 +62,30 @@
62
62
  @import "skeleton";
63
63
  @import "actions";
64
64
 
65
- &.table-striped {
66
- tbody {
67
- tr:nth-of-type(odd) {
68
- background-color: var(--vg-dynamic-table-striped-background);
69
- }
70
-
71
- tr[data-virtual-spacer="1"] {
72
- background-color: transparent;
73
- }
74
- }
75
-
76
- tbody tr:nth-of-type(odd) td[data-fixed-side][data-fixed-overlap="1"] {
77
- background: var(--vg-dynamic-table-striped-background);
78
- }
79
- }
80
-
81
- tbody tr[data-virtual-spacer="1"] > td {
82
- padding: 0;
83
- border: 0;
84
- height: 0;
85
- background: transparent;
86
- line-height: 0;
87
- pointer-events: none;
88
- }
65
+ &.table-striped {
66
+ tbody {
67
+ tr:nth-of-type(odd) {
68
+ background-color: var(--vg-dynamic-table-striped-background);
69
+ }
70
+
71
+ tr[data-virtual-spacer="1"] {
72
+ background-color: transparent;
73
+ }
74
+ }
75
+
76
+ tbody tr:nth-of-type(odd) td[data-fixed-side][data-fixed-overlap="1"] {
77
+ background: var(--vg-dynamic-table-striped-background);
78
+ }
79
+ }
80
+
81
+ tbody tr[data-virtual-spacer="1"] > td {
82
+ padding: 0;
83
+ border: 0;
84
+ height: 0;
85
+ background: transparent;
86
+ line-height: 0;
87
+ pointer-events: none;
88
+ }
89
89
 
90
90
  &.table-bordered {
91
91
  border: var(--vg-dynamic-table-bordered-border-width) solid var(--vg-dynamic-table-bordered-border-color);
@@ -1,56 +1,56 @@
1
- import { lang_buttons, lang_messages } from "../../../utils/js/components/lang";
2
-
3
- const SUPPORTED_LANGS = new Set(["ru", "en"]);
4
-
5
- const normalizeLang = (value, fallback = "ru") => {
6
- const candidate = String(value || "").trim().toLowerCase();
7
- if (!candidate) {
8
- return fallback;
9
- }
10
-
11
- const short = candidate.split("-")[0];
12
- return SUPPORTED_LANGS.has(short) ? short : fallback;
13
- };
14
-
15
- const resolveFilePreviewLang = (paramsLang, element) => {
16
- const fromParams = normalizeLang(paramsLang, "");
17
- if (fromParams) {
18
- return fromParams;
19
- }
20
-
21
- const fromElement = normalizeLang(element?.getAttribute("lang"), "");
22
- if (fromElement) {
23
- return fromElement;
24
- }
25
-
26
- const fromClosest = normalizeLang(element?.closest("[lang]")?.getAttribute("lang"), "");
27
- if (fromClosest) {
28
- return fromClosest;
29
- }
30
-
31
- const fromHtml = normalizeLang(document?.documentElement?.getAttribute("lang"), "");
32
- if (fromHtml) {
33
- return fromHtml;
34
- }
35
-
36
- const fromNavigator = normalizeLang(window?.navigator?.language, "");
37
- if (fromNavigator) {
38
- return fromNavigator;
39
- }
40
-
41
- return "ru";
42
- };
43
-
44
- const createFilePreviewI18n = (lang = "ru") => {
45
- const normalizedLang = normalizeLang(lang, "ru");
46
- const messages = lang_messages(normalizedLang, "filepreview") || {};
47
- const buttons = lang_buttons(normalizedLang, "filepreview") || {};
48
-
49
- return {
50
- lang: normalizedLang,
51
- message: (key, fallback = "") => messages[key] || fallback,
52
- button: (key, fallback = "") => buttons[key] || fallback
53
- };
54
- };
55
-
56
- export { createFilePreviewI18n, resolveFilePreviewLang };
1
+ import { lang_buttons, lang_messages } from "../../../utils/js/components/lang";
2
+
3
+ const SUPPORTED_LANGS = new Set(["ru", "en"]);
4
+
5
+ const normalizeLang = (value, fallback = "ru") => {
6
+ const candidate = String(value || "").trim().toLowerCase();
7
+ if (!candidate) {
8
+ return fallback;
9
+ }
10
+
11
+ const short = candidate.split("-")[0];
12
+ return SUPPORTED_LANGS.has(short) ? short : fallback;
13
+ };
14
+
15
+ const resolveFilePreviewLang = (paramsLang, element) => {
16
+ const fromParams = normalizeLang(paramsLang, "");
17
+ if (fromParams) {
18
+ return fromParams;
19
+ }
20
+
21
+ const fromElement = normalizeLang(element?.getAttribute("lang"), "");
22
+ if (fromElement) {
23
+ return fromElement;
24
+ }
25
+
26
+ const fromClosest = normalizeLang(element?.closest("[lang]")?.getAttribute("lang"), "");
27
+ if (fromClosest) {
28
+ return fromClosest;
29
+ }
30
+
31
+ const fromHtml = normalizeLang(document?.documentElement?.getAttribute("lang"), "");
32
+ if (fromHtml) {
33
+ return fromHtml;
34
+ }
35
+
36
+ const fromNavigator = normalizeLang(window?.navigator?.language, "");
37
+ if (fromNavigator) {
38
+ return fromNavigator;
39
+ }
40
+
41
+ return "ru";
42
+ };
43
+
44
+ const createFilePreviewI18n = (lang = "ru") => {
45
+ const normalizedLang = normalizeLang(lang, "ru");
46
+ const messages = lang_messages(normalizedLang, "filepreview") || {};
47
+ const buttons = lang_buttons(normalizedLang, "filepreview") || {};
48
+
49
+ return {
50
+ lang: normalizedLang,
51
+ message: (key, fallback = "") => messages[key] || fallback,
52
+ button: (key, fallback = "") => buttons[key] || fallback
53
+ };
54
+ };
55
+
56
+ export { createFilePreviewI18n, resolveFilePreviewLang };
@@ -1,145 +1,145 @@
1
- import VGModal from "../../../vgmodal";
2
-
3
- class ImageModal {
4
- constructor() {
5
- this._modalId = 'vg-filepreview-image-modal';
6
- }
7
-
8
- static getInstance() {
9
- if (!ImageModal._instance) {
10
- ImageModal._instance = new ImageModal();
11
- }
12
-
13
- return ImageModal._instance;
14
- }
15
-
16
- open(payload = {}) {
17
- const src = String(payload.src || '').trim();
18
- if (!src) {
19
- return;
20
- }
21
-
22
- this._ensureModal();
23
- if (!this._modal || !this._image) {
24
- return;
25
- }
26
-
27
- const defaultTitle = String(payload.defaultTitle || '').trim();
28
- const title = String(payload.title || '').trim();
29
- this._title.textContent = title || defaultTitle;
30
- this._image.src = src;
31
- this._image.alt = title || defaultTitle;
32
-
33
- this._modal.show();
34
- }
35
-
36
- close() {
37
- if (!this._modal) {
38
- return;
39
- }
40
-
41
- this._modal.hide();
42
- }
43
-
44
- _ensureModal() {
45
- if (this._modal && this._root) {
46
- return;
47
- }
48
-
49
- this._initModal();
50
- }
51
-
52
- _initModal() {
53
- const params = {
54
- centered: true,
55
- dismiss: true,
56
- backdrop: true,
57
- keyboard: true,
58
- sizes: {
59
- width: 'fit-content',
60
- },
61
- animation: {
62
- enable: false
63
- }
64
- };
65
-
66
- const existed = document.getElementById(this._modalId);
67
- if (existed) {
68
- this._root = existed;
69
- this._modal = VGModal.getOrCreateInstance(existed, params);
70
- this._bindElements(existed);
71
- this._bindLifecycle(existed);
72
- return;
73
- }
74
-
75
- this._modal = VGModal.build(this._modalId, params, (modalInstance) => {
76
- const element = modalInstance._element;
77
- this._root = element;
78
- element.classList.add('vg-filepreview-image-modal');
79
-
80
- const body = element.querySelector('.vg-modal-body');
81
- const content = element.querySelector('.vg-modal-content');
82
- if (!body || !content) {
83
- return;
84
- }
85
-
86
- body.classList.add('vg-filepreview-image-modal__body');
87
- body.innerHTML = '';
88
-
89
- let header = element.querySelector('.vg-modal-header');
90
- if (!header) {
91
- header = document.createElement('div');
92
- header.className = 'vg-modal-header';
93
- content.prepend(header);
94
- }
95
-
96
- this._title = document.createElement('div');
97
- this._title.className = 'vg-modal-title';
98
- this._title.textContent = '';
99
-
100
- this._image = document.createElement('img');
101
- this._image.className = 'vg-filepreview-image-modal__img';
102
- this._image.loading = 'eager';
103
- this._image.decoding = 'async';
104
-
105
- header.appendChild(this._title);
106
- body.appendChild(this._image);
107
-
108
- this._bindLifecycle(element);
109
- });
110
- }
111
-
112
- _bindElements(root) {
113
- this._title = root.querySelector('.vg-filepreview-image-modal__title');
114
- this._image = root.querySelector('.vg-filepreview-image-modal__img');
115
- }
116
-
117
- _bindLifecycle(root) {
118
- if (!root || root.hasAttribute('data-vg-filepreview-image-lifecycle-bind')) {
119
- return;
120
- }
121
-
122
- root.setAttribute('data-vg-filepreview-image-lifecycle-bind', 'true');
123
- root.addEventListener('vg.modal.hidden', () => {
124
- this._destroyModal();
125
- });
126
- }
127
-
128
- _destroyModal() {
129
- if (this._modal && typeof this._modal.dispose === 'function') {
130
- this._modal.dispose();
131
- }
132
-
133
- if (this._root && this._root.parentNode) {
134
- this._root.parentNode.removeChild(this._root);
135
- }
136
-
137
- this._root = null;
138
- this._modal = null;
139
- this._title = null;
140
- this._image = null;
141
- }
142
-
143
- }
144
-
145
- export default ImageModal;
1
+ import VGModal from "../../../vgmodal";
2
+
3
+ class ImageModal {
4
+ constructor() {
5
+ this._modalId = 'vg-filepreview-image-modal';
6
+ }
7
+
8
+ static getInstance() {
9
+ if (!ImageModal._instance) {
10
+ ImageModal._instance = new ImageModal();
11
+ }
12
+
13
+ return ImageModal._instance;
14
+ }
15
+
16
+ open(payload = {}) {
17
+ const src = String(payload.src || '').trim();
18
+ if (!src) {
19
+ return;
20
+ }
21
+
22
+ this._ensureModal();
23
+ if (!this._modal || !this._image) {
24
+ return;
25
+ }
26
+
27
+ const defaultTitle = String(payload.defaultTitle || '').trim();
28
+ const title = String(payload.title || '').trim();
29
+ this._title.textContent = title || defaultTitle;
30
+ this._image.src = src;
31
+ this._image.alt = title || defaultTitle;
32
+
33
+ this._modal.show();
34
+ }
35
+
36
+ close() {
37
+ if (!this._modal) {
38
+ return;
39
+ }
40
+
41
+ this._modal.hide();
42
+ }
43
+
44
+ _ensureModal() {
45
+ if (this._modal && this._root) {
46
+ return;
47
+ }
48
+
49
+ this._initModal();
50
+ }
51
+
52
+ _initModal() {
53
+ const params = {
54
+ centered: true,
55
+ dismiss: true,
56
+ backdrop: true,
57
+ keyboard: true,
58
+ sizes: {
59
+ width: 'fit-content',
60
+ },
61
+ animation: {
62
+ enable: false
63
+ }
64
+ };
65
+
66
+ const existed = document.getElementById(this._modalId);
67
+ if (existed) {
68
+ this._root = existed;
69
+ this._modal = VGModal.getOrCreateInstance(existed, params);
70
+ this._bindElements(existed);
71
+ this._bindLifecycle(existed);
72
+ return;
73
+ }
74
+
75
+ this._modal = VGModal.build(this._modalId, params, (modalInstance) => {
76
+ const element = modalInstance._element;
77
+ this._root = element;
78
+ element.classList.add('vg-filepreview-image-modal');
79
+
80
+ const body = element.querySelector('.vg-modal-body');
81
+ const content = element.querySelector('.vg-modal-content');
82
+ if (!body || !content) {
83
+ return;
84
+ }
85
+
86
+ body.classList.add('vg-filepreview-image-modal__body');
87
+ body.innerHTML = '';
88
+
89
+ let header = element.querySelector('.vg-modal-header');
90
+ if (!header) {
91
+ header = document.createElement('div');
92
+ header.className = 'vg-modal-header';
93
+ content.prepend(header);
94
+ }
95
+
96
+ this._title = document.createElement('div');
97
+ this._title.className = 'vg-modal-title';
98
+ this._title.textContent = '';
99
+
100
+ this._image = document.createElement('img');
101
+ this._image.className = 'vg-filepreview-image-modal__img';
102
+ this._image.loading = 'eager';
103
+ this._image.decoding = 'async';
104
+
105
+ header.appendChild(this._title);
106
+ body.appendChild(this._image);
107
+
108
+ this._bindLifecycle(element);
109
+ });
110
+ }
111
+
112
+ _bindElements(root) {
113
+ this._title = root.querySelector('.vg-filepreview-image-modal__title');
114
+ this._image = root.querySelector('.vg-filepreview-image-modal__img');
115
+ }
116
+
117
+ _bindLifecycle(root) {
118
+ if (!root || root.hasAttribute('data-vg-filepreview-image-lifecycle-bind')) {
119
+ return;
120
+ }
121
+
122
+ root.setAttribute('data-vg-filepreview-image-lifecycle-bind', 'true');
123
+ root.addEventListener('vg.modal.hidden', () => {
124
+ this._destroyModal();
125
+ });
126
+ }
127
+
128
+ _destroyModal() {
129
+ if (this._modal && typeof this._modal.dispose === 'function') {
130
+ this._modal.dispose();
131
+ }
132
+
133
+ if (this._root && this._root.parentNode) {
134
+ this._root.parentNode.removeChild(this._root);
135
+ }
136
+
137
+ this._root = null;
138
+ this._modal = null;
139
+ this._title = null;
140
+ this._image = null;
141
+ }
142
+
143
+ }
144
+
145
+ export default ImageModal;