vgapp 0.6.0 → 0.6.2

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 CHANGED
@@ -1,7 +1,4 @@
1
- # VEGAS-APP 0.6.0 (Август, 20, 2025)
2
- * Исправлены ошибки в разных модулях
3
-
4
- # VEGAS-APP 0.5.6 - 0.5.9 (Август, 08, 2025)
1
+ # VEGAS-APP 0.5.6 - 0.6.1 (Август, 21, 2025)
5
2
  * Разделение JS и CSS
6
3
  * Исправлены ошибки в разных модулях
7
4
 
@@ -103,7 +103,38 @@ class BaseModule {
103
103
  const isSmallScreen = window.innerWidth < 768;
104
104
  const isHighDPI = window.devicePixelRatio >= 2;
105
105
 
106
- return isMobileUA || (isTouchDevice && isSmallScreen && isHighDPI);
106
+ function detectIPadPro() {
107
+ const userAgent = navigator.userAgent;
108
+ const platform = navigator.platform;
109
+
110
+ const isIPad = /iPad/.test(userAgent) || (platform === 'MacIntel' && navigator.maxTouchPoints > 1);
111
+
112
+ if (!isIPad) return { isiPadPro: false };
113
+
114
+ const screenWidth = window.screen.width * window.devicePixelRatio;
115
+ const screenHeight = window.screen.height * window.devicePixelRatio;
116
+
117
+ const proResolutions = [
118
+ { width: 2048, height: 2732 }, // 12.9"
119
+ { width: 1668, height: 2388 }, // 11"
120
+ { width: 1668, height: 2224 } // 10.5"
121
+ ];
122
+
123
+ const isProResolution = proResolutions.some(res =>
124
+ (screenWidth === res.width && screenHeight === res.height) ||
125
+ (screenWidth === res.height && screenHeight === res.width)
126
+ );
127
+
128
+ return {
129
+ isiPadPro: isProResolution,
130
+ screenWidth: screenWidth,
131
+ screenHeight: screenHeight,
132
+ userAgent: userAgent,
133
+ platform: platform
134
+ };
135
+ }
136
+
137
+ return isMobileUA || (isTouchDevice && isSmallScreen && isHighDPI) || detectIPadPro().isiPadPro;
107
138
  }
108
139
 
109
140
  static getInstance(element) {
@@ -10,6 +10,7 @@ const NAME = 'dropdown';
10
10
  const NAME_KEY = 'vg.dropdown';
11
11
  const CLASS_NAME_SHOW = 'show';
12
12
  const CLASS_NAME_FADE = 'fade';
13
+ const CLASS_NAME_OPEN = 'open';
13
14
  const TARGET_CONTAINER = 'vg-dropdown-content';
14
15
  const PARENT_CONTAINER = 'vg-dropdown';
15
16
  const SELECTOR_DATA_TOGGLE = '[data-vg-toggle="dropdown"]';
@@ -35,7 +36,7 @@ class VGDropdown extends BaseModule {
35
36
  overflow: false,
36
37
  keyboard: false,
37
38
  placement: 'bottom',
38
- timeoutAnimation: 350,
39
+ timeoutAnimation: 10,
39
40
  hover: false,
40
41
  ajax: {
41
42
  route: '',
@@ -46,6 +47,7 @@ class VGDropdown extends BaseModule {
46
47
  output: true,
47
48
  },
48
49
  animation: {
50
+ fade: false,
49
51
  enable: false,
50
52
  in: 'animate__flipInY',
51
53
  out: 'animate__flipOutY',
@@ -65,7 +67,10 @@ class VGDropdown extends BaseModule {
65
67
  this._drop = target || Selectors.find('.' + TARGET_CONTAINER, this._parent);
66
68
  this._isPlacement = false;
67
69
 
68
- this._params.animation.delay = !this._params.animation.enable ? 0 : this._params.animation.delay;
70
+ this.isFade = this._params.animation.fade;
71
+ this.isAnimation = this._params.animation.enable;
72
+
73
+ this._params.animation.delay = !this.isAnimation ? 0 : this._params.animation.delay;
69
74
  this._animation(this._drop, VGDropdown.NAME_KEY, this._params.animation);
70
75
  }
71
76
 
@@ -114,10 +119,16 @@ class VGDropdown extends BaseModule {
114
119
  }
115
120
 
116
121
  const completeCallBack = () => {
117
- if (!this._params.animation.enable) this._drop.classList.add(CLASS_NAME_FADE);
122
+ if (this.isFade) {
123
+ this._drop.classList.add(CLASS_NAME_FADE);
124
+ } else if(!this.isAnimation) {
125
+ this._drop.classList.add(CLASS_NAME_OPEN);
126
+ }
127
+
118
128
  EventHandler.trigger(this._drop, EVENT_KEY_SHOWN, relatedTarget)
119
129
  }
120
- this._queueCallback(completeCallBack, this._drop, true, 50);
130
+
131
+ this._queueCallback(completeCallBack, this._drop, this.isAnimation || this.isFade, 50);
121
132
  }
122
133
 
123
134
  hide() {
@@ -152,7 +163,12 @@ class VGDropdown extends BaseModule {
152
163
  }
153
164
  }
154
165
 
155
- if (!this._params.animation.enable) this._drop.classList.remove(CLASS_NAME_FADE);
166
+ if (this.isFade) {
167
+ this._drop.classList.remove(CLASS_NAME_FADE);
168
+ } else if(!this.isAnimation) {
169
+ this._drop.classList.remove(CLASS_NAME_OPEN);
170
+ }
171
+
156
172
  this._element.classList.remove(CLASS_NAME_SHOW);
157
173
  this._element.setAttribute('aria-expanded', 'false');
158
174
 
@@ -175,7 +191,7 @@ class VGDropdown extends BaseModule {
175
191
  this._drop.classList.remove(CLASS_NAME_SHOW);
176
192
  EventHandler.trigger(this._drop, EVENT_KEY_HIDDEN, relatedTarget);
177
193
  }
178
- this._queueCallback(completeCallback, this._drop, true);
194
+ this._queueCallback(completeCallback, this._drop, this.isAnimation || this.isFade);
179
195
  }, this._params.animation.delay);
180
196
  }
181
197
 
@@ -184,18 +200,11 @@ class VGDropdown extends BaseModule {
184
200
  const _this = this;
185
201
 
186
202
  if (!_this._isPlacement) {
187
- let placement = new Placement({
188
- element: this._parent,
189
- drop: this._drop
190
- })._getPlacement();
191
-
192
- if (placement.isFixed) {
193
- _this._drop.style.position = 'fixed';
194
- _this._drop.style.transform = 'translateY(-20%)'; // todo this is костыль поfixить
195
- }
203
+ const $placement = new Placement({
204
+ drop: _this._drop
205
+ })
196
206
 
197
- _this._drop.style.left = placement.left + 'px';
198
- _this._drop.style.top = placement.top + 'px';
207
+ $placement._setPlacement();
199
208
  }
200
209
 
201
210
  if (_this._params.offset) {
@@ -17,11 +17,17 @@
17
17
 
18
18
  &-content {
19
19
  z-index: var(--vg-dropdown-z-index);
20
- position: absolute;
21
- opacity: 0;
22
20
  transform: translateY(20%);
23
21
  transition: var(--vg-dropdown-transition);
24
22
  min-width: var(--vg-dropdown-min-width);
23
+ position: absolute;
24
+ opacity: 0;
25
+ left: 0;
26
+ top: 100%;
27
+
28
+ &.open {
29
+ transition: none;
30
+ }
25
31
 
26
32
  &:not(.show) {
27
33
  display: none;
@@ -31,10 +37,37 @@
31
37
  opacity: 1;
32
38
  }
33
39
 
34
- &.fade {
40
+ &.fade, &.open {
35
41
  opacity: 1;
36
42
  transform: translateY(0);
37
43
  }
44
+
45
+ &.top {
46
+ bottom: 0;
47
+ }
48
+
49
+ &.bottom {
50
+ top: 0;
51
+ }
52
+
53
+ &.left {
54
+ left: 0;
55
+ }
56
+
57
+ &.right {
58
+ left: auto;
59
+ right: 0;
60
+ }
61
+
62
+ &.show {
63
+ &.top {
64
+ bottom: 100%;
65
+ }
66
+
67
+ &.bottom {
68
+ top: 100%;
69
+ }
70
+ }
38
71
  }
39
72
 
40
73
  &-container {
@@ -359,9 +359,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
359
359
  execute(instance._params.callbacks.afterClick, [instance, event, this]);
360
360
  }
361
361
 
362
- if (instance._params.hover) {
363
- return;
364
- }
362
+ if (instance._params.hover && !instance.isMobileDevice()) return;
365
363
 
366
364
  event.preventDefault();
367
365
 
@@ -12,6 +12,14 @@
12
12
  right: 0;
13
13
  }
14
14
 
15
+ &.top, .top {
16
+ top: 0;
17
+ }
18
+
19
+ &.bottom, .bottom {
20
+ bottom: 0;
21
+ }
22
+
15
23
  .dropdown {
16
24
  ul.left {
17
25
  left: 100%;
@@ -20,6 +28,14 @@
20
28
  ul.right {
21
29
  right: 100%;
22
30
  }
31
+
32
+ ul.top {
33
+ top: 100%;
34
+ }
35
+
36
+ ul.bottom {
37
+ bottom: 100%;
38
+ }
23
39
  }
24
40
  }
25
41
  }
@@ -32,8 +48,6 @@
32
48
 
33
49
  .dropdown {
34
50
  > ul {
35
- top: 100%;
36
-
37
51
  &.left, .left {
38
52
  left: 100%;
39
53
  }
@@ -42,14 +56,34 @@
42
56
  right: 100%;
43
57
  }
44
58
 
59
+ &.top, .top {
60
+ top: 100%;
61
+ }
62
+
63
+ &.bottom, .bottom {
64
+ bottom: 100%;
65
+ }
66
+
45
67
  &.fade {
46
- top: 0;
68
+ &.top {
69
+ top: 0;
70
+ }
71
+ &.bottom {
72
+ bottom: 0;
73
+ }
47
74
  }
48
75
  }
49
76
 
50
77
  &.show {
51
- > ul {
52
- top: 0;
78
+ &.top {
79
+ > ul {
80
+ top: 0;
81
+ }
82
+ }
83
+ &.bottom {
84
+ > ul {
85
+ bottom: 0;
86
+ }
53
87
  }
54
88
  }
55
89
  }
@@ -62,7 +96,13 @@
62
96
  top: 100%;
63
97
 
64
98
  &.fade {
65
- top: 0;
99
+ &.top {
100
+ top: 0;
101
+ }
102
+
103
+ &.bottom {
104
+ bottom: 0;
105
+ }
66
106
  }
67
107
  }
68
108
  }
@@ -1,13 +1,15 @@
1
1
  import {mergeDeepObject, normalizeData} from "../functions";
2
- import Selectors from "../dom/selectors";
2
+ import {Classes} from "../dom/manipulator";
3
3
 
4
4
  /**
5
5
  * Класс Placement, определяет и устанавливает местоположение элемента на странице.
6
6
  * TODO класс не дописан, не определяет сверху и снизу
7
7
  */
8
8
 
9
- const CLASS_NAME_RIGHT = 'right';
10
- const CLASS_NAME_LEFT = 'left';
9
+ const CLASS_NAME_RIGHT = 'right';
10
+ const CLASS_NAME_LEFT = 'left';
11
+ const CLASS_NAME_TOP = 'top';
12
+ const CLASS_NAME_BOTTOM = 'bottom';
11
13
 
12
14
  class Placement {
13
15
  constructor(arg = {}) {
@@ -21,6 +23,8 @@ class Placement {
21
23
 
22
24
  this._element = null;
23
25
  this.element = this.params.element;
26
+
27
+ if (!this.drop) return false;
24
28
  }
25
29
 
26
30
  get drop() {
@@ -47,13 +51,28 @@ class Placement {
47
51
  }
48
52
 
49
53
  _setPlacement() {
50
- this.drop.classList.remove(CLASS_NAME_RIGHT);
51
- this.drop.classList.remove(CLASS_NAME_LEFT);
54
+ let rect = this._isElementInViewport(this.drop);
52
55
 
53
- if (this._isElementInViewport(this.drop)) {
54
- this.drop.classList.add(CLASS_NAME_LEFT);
55
- } else {
56
- this.drop.classList.add(CLASS_NAME_RIGHT);
56
+ if (!rect.isView) {
57
+ if (!rect.isViewRight) {
58
+ Classes.remove(this.drop, CLASS_NAME_LEFT);
59
+ Classes.add(this.drop, CLASS_NAME_RIGHT);
60
+ }
61
+
62
+ if (!rect.isViewLeft) {
63
+ Classes.remove(this.drop, CLASS_NAME_RIGHT);
64
+ Classes.add(this.drop, CLASS_NAME_LEFT);
65
+ }
66
+
67
+ if (!rect.isViewTop) {
68
+ Classes.remove(this.drop, CLASS_NAME_BOTTOM);
69
+ Classes.add(this.drop, CLASS_NAME_TOP);
70
+ }
71
+
72
+ if (!rect.isViewBottom) {
73
+ Classes.remove(this.drop, CLASS_NAME_TOP);
74
+ Classes.add(this.drop, CLASS_NAME_BOTTOM);
75
+ }
57
76
  }
58
77
  }
59
78
 
@@ -104,12 +123,18 @@ class Placement {
104
123
  const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
105
124
  const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
106
125
 
107
- return (
108
- rect.top >= 0 &&
109
- rect.left >= 0 &&
110
- rect.bottom <= viewportHeight &&
111
- rect.right <= viewportWidth
112
- );
126
+ return {
127
+ isView: (
128
+ rect.top >= 0 &&
129
+ rect.left >= 0 &&
130
+ rect.bottom <= viewportHeight &&
131
+ rect.right <= viewportWidth
132
+ ),
133
+ isViewRight: rect.right <= viewportWidth,
134
+ isViewLeft: rect.left >= 0,
135
+ isViewTop: rect.top >= 0,
136
+ isViewBottom: rect.bottom <= viewportHeight,
137
+ };
113
138
  }
114
139
  }
115
140
 
@@ -69,4 +69,32 @@ const Manipulator = {
69
69
  },
70
70
  }
71
71
 
72
- export {Manipulator}
72
+ let Classes = {
73
+ remove(element, className) {
74
+ if (className && element) {
75
+ if (typeof className === 'string') {
76
+ className = className.split(' ');
77
+ }
78
+
79
+ element.classList.remove(...className);
80
+ }
81
+ },
82
+
83
+ add(element, className, isString = false) {
84
+ if (className) {
85
+ if (typeof className === 'string') {
86
+ className = className.split(' ');
87
+ }
88
+
89
+ if (isString) {
90
+ return '' + className.join(' ');
91
+ }
92
+
93
+ if (element) {
94
+ element.classList.add(...className);
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ export {Manipulator, Classes}