vgapp 0.0.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.
- package/.gitattributes +1 -0
- package/CHANGELOG.md +0 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/app/modules/base-module.js +97 -0
- package/app/modules/module-fn.js +119 -0
- package/app/modules/vgcollapse/js/vgcollapse.js +219 -0
- package/app/modules/vgdropdown/js/vgdropdown.js +279 -0
- package/app/modules/vgdropdown/scss/_variables.scss +9 -0
- package/app/modules/vgdropdown/scss/vgdropdown.scss +41 -0
- package/app/modules/vgformsender/js/vgformsender.js +400 -0
- package/app/modules/vgformsender/scss/vgformsender.scss +19 -0
- package/app/modules/vgmodal/js/vgmodal.js +346 -0
- package/app/modules/vgmodal/scss/_variables.scss +25 -0
- package/app/modules/vgmodal/scss/vgmodal.scss +111 -0
- package/app/modules/vgnav/js/vgnav.js +498 -0
- package/app/modules/vgnav/scss/_breakpoints.scss +127 -0
- package/app/modules/vgnav/scss/_hamburger.scss +62 -0
- package/app/modules/vgnav/scss/_placement.scss +70 -0
- package/app/modules/vgnav/scss/_toggle.scss +20 -0
- package/app/modules/vgnav/scss/_variables.scss +68 -0
- package/app/modules/vgnav/scss/vgnav.scss +150 -0
- package/app/modules/vgsidebar/js/vgsidebar.js +165 -0
- package/app/modules/vgsidebar/scss/_variables.scss +19 -0
- package/app/modules/vgsidebar/scss/vgsidebar.scss +90 -0
- package/app/utils/js/components/backdrop.js +54 -0
- package/app/utils/js/components/overflow.js +28 -0
- package/app/utils/js/components/params.js +44 -0
- package/app/utils/js/components/placement.js +59 -0
- package/app/utils/js/components/responsive.js +83 -0
- package/app/utils/js/components/scrollbar.js +114 -0
- package/app/utils/js/dom/data.js +51 -0
- package/app/utils/js/dom/event.js +331 -0
- package/app/utils/js/dom/manipulator.js +62 -0
- package/app/utils/js/dom/selectors.js +65 -0
- package/app/utils/js/functions.js +272 -0
- package/app/utils/scss/animate.scss +4074 -0
- package/app/utils/scss/default.scss +277 -0
- package/app/utils/scss/functions.scss +3 -0
- package/app/utils/scss/mixin.scss +11 -0
- package/app/utils/scss/variables.scss +80 -0
- package/build/vgapp.css +4538 -0
- package/build/vgapp.css.map +1 -0
- package/build/vgapp.js +3230 -0
- package/build/vgapp.js.map +1 -0
- package/index.js +29 -0
- package/package.json +43 -0
- package/webpack.config.js +63 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import BaseModule from "../../base-module";
|
|
2
|
+
import EventHandler from "../../../utils/js/dom/event";
|
|
3
|
+
import Selectors from "../../../utils/js/dom/selectors";
|
|
4
|
+
import {isDisabled, mergeDeepObject, noop} from "../../../utils/js/functions";
|
|
5
|
+
import Placement from "../../../utils/js/components/placement";
|
|
6
|
+
|
|
7
|
+
const NAME = 'dropdown';
|
|
8
|
+
const NAME_KEY = 'vg.dropdown';
|
|
9
|
+
const CLASS_NAME_SHOW = 'show';
|
|
10
|
+
const CLASS_NAME_FADE = 'fade';
|
|
11
|
+
const TARGET_CONTAINER = 'vg-dropdown-content';
|
|
12
|
+
const PARENT_CONTAINER = 'vg-dropdown';
|
|
13
|
+
const SELECTOR_DATA_TOGGLE = '[data-vg-toggle="dropdown"]';
|
|
14
|
+
|
|
15
|
+
const EVENT_KEY_HIDE = `${NAME_KEY}.hide`;
|
|
16
|
+
const EVENT_KEY_HIDDEN = `${NAME_KEY}.hidden`;
|
|
17
|
+
const EVENT_KEY_SHOW = `${NAME_KEY}.show`;
|
|
18
|
+
const EVENT_KEY_SHOWN = `${NAME_KEY}.shown`;
|
|
19
|
+
|
|
20
|
+
const EVENT_KEYUP_DATA_API = `keyup.${NAME_KEY}.data.api`;
|
|
21
|
+
const EVENT_KEYDOWN_DATA_API = `keydown.${NAME_KEY}.data.api`;
|
|
22
|
+
const EVENT_CLICK_DATA_API = `click.${NAME_KEY}.data.api`;
|
|
23
|
+
const EVENT_MOUSEOVER_DATA_API = `mouseover.${NAME_KEY}.data.api`;
|
|
24
|
+
const EVENT_MOUSEOUT_DATA_API = `mouseout.${NAME_KEY}.data.api`;
|
|
25
|
+
|
|
26
|
+
class VGDropdown extends BaseModule {
|
|
27
|
+
constructor(element, params) {
|
|
28
|
+
super(element, params);
|
|
29
|
+
|
|
30
|
+
this._params = this._getParams(element, mergeDeepObject({
|
|
31
|
+
offset: [0, 2],
|
|
32
|
+
over: false,
|
|
33
|
+
backdrop: true,
|
|
34
|
+
overflow: true,
|
|
35
|
+
keyboard: true,
|
|
36
|
+
placement: 'bottom',
|
|
37
|
+
animation: true,
|
|
38
|
+
timeoutAnimation: 300,
|
|
39
|
+
hover: false,
|
|
40
|
+
ajax: {
|
|
41
|
+
route: '',
|
|
42
|
+
target: '',
|
|
43
|
+
method: 'get'
|
|
44
|
+
}
|
|
45
|
+
}, params));
|
|
46
|
+
|
|
47
|
+
this._parent = this._element.parentNode;
|
|
48
|
+
this._drop = Selectors.find('.' + TARGET_CONTAINER, this._parent);
|
|
49
|
+
this._isPlacement = false;
|
|
50
|
+
|
|
51
|
+
if (this._params.animation === false) {
|
|
52
|
+
this._params.timeoutAnimation = 10
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static get NAME() {
|
|
57
|
+
return NAME;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static get NAME_KEY() {
|
|
61
|
+
return NAME_KEY;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
toggle() {
|
|
65
|
+
return this._isShown() ? this.hide() : this.show();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
show() {
|
|
69
|
+
if (isDisabled(this._element) || this._isShown()) return;
|
|
70
|
+
|
|
71
|
+
const relatedTarget = {
|
|
72
|
+
relatedTarget: this._element
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const showEvent = EventHandler.trigger(this._element, EVENT_KEY_SHOW, relatedTarget)
|
|
76
|
+
if (showEvent.defaultPrevented) return;
|
|
77
|
+
|
|
78
|
+
if ('ontouchstart' in document.documentElement) {
|
|
79
|
+
for (const element of [].concat(...document.body.children)) {
|
|
80
|
+
EventHandler.on(element, 'mouseover', noop);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this._route();
|
|
85
|
+
|
|
86
|
+
this._element.setAttribute('aria-expanded', true);
|
|
87
|
+
this._element.classList.add(CLASS_NAME_SHOW);
|
|
88
|
+
this._drop.classList.add(CLASS_NAME_SHOW);
|
|
89
|
+
this._setPlacement();
|
|
90
|
+
|
|
91
|
+
const completeCallBack = () => {
|
|
92
|
+
this._drop.classList.add(CLASS_NAME_FADE);
|
|
93
|
+
EventHandler.trigger(this._element, EVENT_KEY_SHOWN, relatedTarget)
|
|
94
|
+
}
|
|
95
|
+
this._queueCallback(completeCallBack, this._drop, true, 50);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
hide() {
|
|
99
|
+
if (isDisabled(this._element) || !this._isShown()) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const relatedTarget = {
|
|
104
|
+
relatedTarget: this._element
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this._completeHide(relatedTarget);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
dispose() {
|
|
111
|
+
return super.dispose();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
_isShown() {
|
|
115
|
+
return this._element.classList.contains(CLASS_NAME_SHOW);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_completeHide(relatedTarget) {
|
|
119
|
+
const hideEvent = EventHandler.trigger(this._element, EVENT_KEY_HIDE, relatedTarget)
|
|
120
|
+
if (hideEvent.defaultPrevented) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if ('ontouchstart' in document.documentElement) {
|
|
125
|
+
for (const element of [].concat(...document.body.children)) {
|
|
126
|
+
EventHandler.off(element, 'mouseover', noop);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this._drop.classList.remove(CLASS_NAME_FADE);
|
|
131
|
+
this._element.classList.remove(CLASS_NAME_SHOW);
|
|
132
|
+
this._element.setAttribute('aria-expanded', 'false');
|
|
133
|
+
|
|
134
|
+
const completeCallback = () => {
|
|
135
|
+
this._drop.classList.remove(CLASS_NAME_SHOW);
|
|
136
|
+
EventHandler.trigger(this._element, EVENT_KEY_HIDDEN, relatedTarget);
|
|
137
|
+
}
|
|
138
|
+
this._queueCallback(completeCallback, this._parent, true, this._params.timeoutAnimation);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// TODO class Placement isn't done
|
|
142
|
+
_setPlacement() {
|
|
143
|
+
const _this = this;
|
|
144
|
+
|
|
145
|
+
if (!_this._isPlacement) {
|
|
146
|
+
let placement = new Placement({
|
|
147
|
+
element: this._parent,
|
|
148
|
+
drop: this._drop
|
|
149
|
+
})._getPlacement();
|
|
150
|
+
|
|
151
|
+
if (placement.isFixed) {
|
|
152
|
+
_this._drop.style.position = 'fixed';
|
|
153
|
+
_this._drop.style.transform = 'translateY(-20%)'; // todo this is костыль поfixить
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
_this._drop.style.left = placement.left + 'px';
|
|
157
|
+
_this._drop.style.top = placement.top + 'px';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (_this._params.offset) {
|
|
161
|
+
_this._drop.style.paddingTop = _this._params.offset[1] + 'px';
|
|
162
|
+
_this._drop.style.paddingRight = _this._params.offset[0] + 'px';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_this._isPlacement = true;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static init(element, params = {}) {
|
|
169
|
+
const instance = VGDropdown.getOrCreateInstance(element, params);
|
|
170
|
+
|
|
171
|
+
if (instance._params.hover) {
|
|
172
|
+
let currentElem = null;
|
|
173
|
+
EventHandler.on(instance._parent, EVENT_MOUSEOVER_DATA_API, function (event) {
|
|
174
|
+
if (currentElem) return;
|
|
175
|
+
VGDropdown.hideOpenToggles(event);
|
|
176
|
+
|
|
177
|
+
let target = event.target.closest('.' + PARENT_CONTAINER);
|
|
178
|
+
if (!target) return;
|
|
179
|
+
|
|
180
|
+
if (!instance._parent.contains(target)) return;
|
|
181
|
+
currentElem = target;
|
|
182
|
+
instance.show();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
EventHandler.on(instance._parent, EVENT_MOUSEOUT_DATA_API, function (event) {
|
|
186
|
+
if (!currentElem) return;
|
|
187
|
+
|
|
188
|
+
let relatedTarget = event.relatedTarget;
|
|
189
|
+
|
|
190
|
+
while (relatedTarget) {
|
|
191
|
+
if (relatedTarget === currentElem) return;
|
|
192
|
+
relatedTarget = relatedTarget.parentNode;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
currentElem = null;
|
|
196
|
+
instance._completeHide({relatedTarget: instance._element});
|
|
197
|
+
})
|
|
198
|
+
} else {
|
|
199
|
+
EventHandler.on(document, EVENT_KEYUP_DATA_API, SELECTOR_DATA_TOGGLE, VGDropdown.keydownHandler);
|
|
200
|
+
EventHandler.on(document, EVENT_KEYDOWN_DATA_API, '.' + TARGET_CONTAINER, VGDropdown.keydownHandler);
|
|
201
|
+
EventHandler.on(document, EVENT_KEYUP_DATA_API, VGDropdown.clearDrops);
|
|
202
|
+
EventHandler.on(document, EVENT_CLICK_DATA_API, VGDropdown.clearDrops);
|
|
203
|
+
EventHandler.on(element, EVENT_CLICK_DATA_API, function (event) {
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
instance.toggle();
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
static hideOpenToggles(event) {
|
|
211
|
+
const openToggles = Selectors.findAll('[data-vg-toggle="dropdown"]:not(.disabled):not(:disabled).show');
|
|
212
|
+
for (const toggle of openToggles) {
|
|
213
|
+
const context = VGDropdown.getInstance(toggle);
|
|
214
|
+
if (!context) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (event.target.closest('.' + TARGET_CONTAINER) === context._drop) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const composedPath = event.composedPath();
|
|
223
|
+
if (composedPath.includes(context._element)) {
|
|
224
|
+
continue
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const relatedTarget = { relatedTarget: context._element }
|
|
228
|
+
|
|
229
|
+
if (event.type === 'click') {
|
|
230
|
+
relatedTarget.clickEvent = event
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
context._completeHide(relatedTarget)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static keydownHandler(event) {
|
|
238
|
+
const isInput = /input|textarea/i.test(event.target.tagName)
|
|
239
|
+
const isEscapeEvent = event.key === 'Escape'
|
|
240
|
+
const isUpOrDownEvent = ['ArrowUp', 'ArrowDown'].includes(event.key)
|
|
241
|
+
|
|
242
|
+
if (!isUpOrDownEvent && !isEscapeEvent) {
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (isInput && !isEscapeEvent) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
event.preventDefault()
|
|
251
|
+
|
|
252
|
+
const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?
|
|
253
|
+
this : (Selectors.find(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode))
|
|
254
|
+
|
|
255
|
+
const instance = VGDropdown.getOrCreateInstance(getToggleButton)
|
|
256
|
+
|
|
257
|
+
if (isUpOrDownEvent) {
|
|
258
|
+
event.stopPropagation()
|
|
259
|
+
instance.show()
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (instance._isShown()) {
|
|
264
|
+
event.stopPropagation()
|
|
265
|
+
instance.hide()
|
|
266
|
+
getToggleButton.focus()
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static clearDrops(event) {
|
|
271
|
+
if (event.button === 2 || (event.type === 'keyup' && event.key !== 'Tab')) {
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
VGDropdown.hideOpenToggles(event)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export default VGDropdown;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*--------------------------------------------------------------------------
|
|
3
|
+
* Модуль: VGDropdown
|
|
4
|
+
* Автор: Vegas DEV
|
|
5
|
+
* Лицензия: смотри LICENSE
|
|
6
|
+
*--------------------------------------------------------------------------
|
|
7
|
+
**/
|
|
8
|
+
|
|
9
|
+
@import "../../../utils/scss/functions";
|
|
10
|
+
@import "../../../utils/scss/mixin";
|
|
11
|
+
@import "../../../utils/scss/variables";
|
|
12
|
+
@import "variables";
|
|
13
|
+
|
|
14
|
+
.vg-dropdown {
|
|
15
|
+
position: relative;
|
|
16
|
+
|
|
17
|
+
&-content {
|
|
18
|
+
@include mix-vars('dropdown', $dropdown-map);
|
|
19
|
+
z-index: var(--vg-dropdown-z-index);
|
|
20
|
+
position: absolute;
|
|
21
|
+
opacity: 0;
|
|
22
|
+
transform: translateY(20%);
|
|
23
|
+
transition: var(--vg-dropdonw-transition);
|
|
24
|
+
min-width: var(--vg-dropdown-min-width);
|
|
25
|
+
|
|
26
|
+
&:not(.show) {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.fade {
|
|
31
|
+
opacity: 1;
|
|
32
|
+
transform: translateY(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&-container {
|
|
36
|
+
background-color: var(--vg-dropdown-bg-color);
|
|
37
|
+
color: var(--vg-dropdown-color);
|
|
38
|
+
border: var(--vg-dropdown-border);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|