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.
Files changed (48) hide show
  1. package/.gitattributes +1 -0
  2. package/CHANGELOG.md +0 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/app/modules/base-module.js +97 -0
  6. package/app/modules/module-fn.js +119 -0
  7. package/app/modules/vgcollapse/js/vgcollapse.js +219 -0
  8. package/app/modules/vgdropdown/js/vgdropdown.js +279 -0
  9. package/app/modules/vgdropdown/scss/_variables.scss +9 -0
  10. package/app/modules/vgdropdown/scss/vgdropdown.scss +41 -0
  11. package/app/modules/vgformsender/js/vgformsender.js +400 -0
  12. package/app/modules/vgformsender/scss/vgformsender.scss +19 -0
  13. package/app/modules/vgmodal/js/vgmodal.js +346 -0
  14. package/app/modules/vgmodal/scss/_variables.scss +25 -0
  15. package/app/modules/vgmodal/scss/vgmodal.scss +111 -0
  16. package/app/modules/vgnav/js/vgnav.js +498 -0
  17. package/app/modules/vgnav/scss/_breakpoints.scss +127 -0
  18. package/app/modules/vgnav/scss/_hamburger.scss +62 -0
  19. package/app/modules/vgnav/scss/_placement.scss +70 -0
  20. package/app/modules/vgnav/scss/_toggle.scss +20 -0
  21. package/app/modules/vgnav/scss/_variables.scss +68 -0
  22. package/app/modules/vgnav/scss/vgnav.scss +150 -0
  23. package/app/modules/vgsidebar/js/vgsidebar.js +165 -0
  24. package/app/modules/vgsidebar/scss/_variables.scss +19 -0
  25. package/app/modules/vgsidebar/scss/vgsidebar.scss +90 -0
  26. package/app/utils/js/components/backdrop.js +54 -0
  27. package/app/utils/js/components/overflow.js +28 -0
  28. package/app/utils/js/components/params.js +44 -0
  29. package/app/utils/js/components/placement.js +59 -0
  30. package/app/utils/js/components/responsive.js +83 -0
  31. package/app/utils/js/components/scrollbar.js +114 -0
  32. package/app/utils/js/dom/data.js +51 -0
  33. package/app/utils/js/dom/event.js +331 -0
  34. package/app/utils/js/dom/manipulator.js +62 -0
  35. package/app/utils/js/dom/selectors.js +65 -0
  36. package/app/utils/js/functions.js +272 -0
  37. package/app/utils/scss/animate.scss +4074 -0
  38. package/app/utils/scss/default.scss +277 -0
  39. package/app/utils/scss/functions.scss +3 -0
  40. package/app/utils/scss/mixin.scss +11 -0
  41. package/app/utils/scss/variables.scss +80 -0
  42. package/build/vgapp.css +4538 -0
  43. package/build/vgapp.css.map +1 -0
  44. package/build/vgapp.js +3230 -0
  45. package/build/vgapp.js.map +1 -0
  46. package/index.js +29 -0
  47. package/package.json +43 -0
  48. package/webpack.config.js +63 -0
@@ -0,0 +1,346 @@
1
+ import BaseModule from "../../base-module";
2
+ import ScrollBarHelper from "../../../utils/js/components/scrollbar";
3
+ import Backdrop from "../../../utils/js/components/backdrop";
4
+ import Overflow from "../../../utils/js/components/overflow";
5
+ import Selectors from "../../../utils/js/dom/selectors";
6
+ import EventHandler from "../../../utils/js/dom/event";
7
+ import {Manipulator} from "../../../utils/js/dom/manipulator";
8
+ import {execute, isDisabled, isRTL, isVisible, mergeDeepObject, reflow} from "../../../utils/js/functions";
9
+ import {dismissTrigger} from "../../module-fn";
10
+
11
+ /**
12
+ * Constants
13
+ */
14
+ const NAME = 'modal';
15
+ const NAME_KEY = 'vg.modal';
16
+
17
+ const ESCAPE_KEY = 'Escape';
18
+
19
+ const OPEN_SELECTOR = '.vg-modal.show';
20
+ const SELECTOR_DIALOG = '.vg-modal-dialog';
21
+ const SELECTOR_MODAL_BODY = '.vg-modal-body';
22
+ const SELECTOR_DATA_TOGGLE = '[data-vg-toggle="modal"]';
23
+
24
+ const CLASS_NAME_OPEN = 'vg-modal-open';
25
+ const CLASS_NAME_SHOW = 'show';
26
+ const CLASS_NAME_FADE = 'fade';
27
+ const CLASS_NAME_STATIC = 'vg-modal-static'
28
+
29
+ const EVENT_KEY_HIDE = `${NAME_KEY}.hide`;
30
+ const EVENT_KEY_HIDDEN = `${NAME_KEY}.hidden`;
31
+ const EVENT_KEY_SHOW = `${NAME_KEY}.show`;
32
+ const EVENT_KEY_SHOWN = `${NAME_KEY}.shown`;
33
+ const EVENT_KEY_RESIZE = `${NAME_KEY}.resize`
34
+
35
+ const EVENT_KEY_KEYDOWN_DISMISS = `keydown.dismiss.${NAME_KEY}`;
36
+ const EVENT_KEY_HIDE_PREVENTED = `hidePrevented.${NAME_KEY}`;
37
+ const EVENT_KEY_CLICK_DATA_API = `click.${NAME_KEY}.data.api`;
38
+ const EVENT_KEY_MOUSEDOWN_DISMISS = `mousedown.dismiss${NAME_KEY}`
39
+ const EVENT_KEY_CLICK_DISMISS = `click.dismiss${NAME_KEY}`
40
+
41
+ class VGModal extends BaseModule {
42
+ constructor(element, params = {}) {
43
+ super(element, params);
44
+
45
+ this._params = this._getParams(element, mergeDeepObject({
46
+ backdrop: true,
47
+ focus: true,
48
+ keyboard: true,
49
+ fields: [],
50
+ ajax: {
51
+ route: '',
52
+ target: '',
53
+ method: 'get',
54
+ loader: false
55
+ },
56
+ animation: {
57
+ name: ['animate__backInUp', 'animate__backOutUp'], // до / после не более двух элементов
58
+ duration: 1000, // ms
59
+ delay: 1000, // ms
60
+ repeat: 1
61
+ },
62
+ classes: {
63
+ general: 'vg-modal',
64
+ dialog: 'vg-modal-dialog',
65
+ content: 'vg-modal-content',
66
+ header: 'vg-modal-header',
67
+ title: 'vg-modal-title',
68
+ body: 'vg-modal-body',
69
+ footer: 'vg-modal-footer',
70
+ animated: 'animate__animated'
71
+ }
72
+ }, params));
73
+ this._button = null;
74
+ this._dialog = Selectors.find(SELECTOR_DIALOG, this._element);
75
+ this._isShown = false;
76
+ this._isTransitioning = false;
77
+ this._scrollBar = new ScrollBarHelper();
78
+
79
+ this._addEventListeners();
80
+ this._dismissElement();
81
+ }
82
+
83
+ static get NAME() {
84
+ return NAME;
85
+ }
86
+
87
+ static get NAME_KEY() {
88
+ return NAME_KEY;
89
+ }
90
+
91
+ static init(element, params, callback) {
92
+ VGModal.build(element, params, callback);
93
+ }
94
+
95
+ static build(id, params, callback) {
96
+ if (typeof id !== "string") return;
97
+
98
+ let _element = document.createElement('div');
99
+ _element.classList.add('vg-modal', 'fade');
100
+ _element.id = id;let dialog = document.createElement('div');
101
+ dialog.classList.add('vg-modal-dialog');
102
+
103
+ let content = document.createElement('div');
104
+ content.classList.add('vg-modal-content');
105
+
106
+ let btnClose = document.createElement('button');
107
+ Manipulator.set(btnClose, 'type', 'button');
108
+ Manipulator.set(btnClose, 'data-vg-dismiss', 'modal');
109
+ Manipulator.set(btnClose, 'data-vg-target', '#' + id);
110
+ Manipulator.set(btnClose, 'aria-label', 'close');
111
+ btnClose.classList.add('vg-btn-close');
112
+
113
+ content.append(btnClose);
114
+
115
+ let body = document.createElement('div');
116
+ body.classList.add('vg-modal-body');
117
+
118
+ content.append(body);
119
+ dialog.append(content);
120
+ _element.append(dialog);
121
+
122
+ document.body.append(_element);
123
+
124
+ const modal = VGModal.getOrCreateInstance(_element, params);
125
+
126
+ execute(callback, [modal]);
127
+ }
128
+
129
+ toggle(relatedTarget) {
130
+ return !this._isShown ? this.show(relatedTarget) : this.hide();
131
+ }
132
+
133
+ show(relatedTarget) {
134
+ const _this = this;
135
+ if (isDisabled(_this._element)) return;
136
+
137
+ this._route();
138
+
139
+ const showEvent = EventHandler.trigger(this._element, EVENT_KEY_SHOW, { relatedTarget })
140
+ if (showEvent.defaultPrevented) return;
141
+
142
+ this._isShown = true;
143
+ this._isTransitioning = true;
144
+
145
+ this._scrollBar.hide();
146
+
147
+ document.body.classList.add(CLASS_NAME_OPEN);
148
+
149
+ this._addFieldsInModal(relatedTarget);
150
+ this._adjustDialog();
151
+
152
+ Backdrop.show(() => this._showElement(relatedTarget));
153
+ }
154
+
155
+ hide() {
156
+ if (!this._isShown || this._isTransitioning) return;
157
+
158
+ const hideEvent = EventHandler.trigger(this._element, EVENT_KEY_HIDE);
159
+ if (hideEvent.defaultPrevented) return;
160
+
161
+ this._isShown = false;
162
+ this._isTransitioning = true;
163
+
164
+ this._element.classList.remove(CLASS_NAME_SHOW);
165
+
166
+ this._queueCallback(() => this._hideModal(), this._element, this._isAnimated());
167
+ }
168
+
169
+ _hideModal() {
170
+ this._element.style.display = 'none';
171
+ this._element.setAttribute('aria-hidden', true);
172
+ this._element.removeAttribute('aria-modal');
173
+ this._element.removeAttribute('role');
174
+ this._isTransitioning = false;
175
+
176
+ Backdrop.hide(() => {
177
+ document.body.classList.remove(CLASS_NAME_OPEN);
178
+ this._resetAdjustments();
179
+ this._scrollBar.reset();
180
+ EventHandler.trigger(this._element, EVENT_KEY_HIDDEN);
181
+ })
182
+ }
183
+
184
+ _showElement(relatedTarget) {
185
+ if (!document.body.contains(this._element)) {
186
+ document.body.append(this._element);
187
+ }
188
+
189
+ this._element.style.display = 'block';
190
+ this._element.removeAttribute('aria-hidden');
191
+ this._element.setAttribute('aria-modal', true);
192
+ this._element.setAttribute('role', 'dialog');
193
+ this._element.scrollTop = 0;
194
+
195
+ const modalBody = Selectors.find(SELECTOR_MODAL_BODY, this._dialog);
196
+ if (modalBody) {
197
+ modalBody.scrollTop = 0;
198
+ }
199
+
200
+ reflow(this._element);
201
+
202
+ this._element.classList.add(CLASS_NAME_SHOW)
203
+
204
+ const transitionComplete = () => {
205
+ if (this._params.focus) {
206
+ // TODO сделать фокус
207
+ }
208
+
209
+ this._isTransitioning = false
210
+ EventHandler.trigger(this._element, EVENT_KEY_SHOWN, {
211
+ relatedTarget
212
+ })
213
+ }
214
+
215
+ this._queueCallback(transitionComplete, this._dialog, this._isAnimated())
216
+ }
217
+
218
+ _isAnimated() {
219
+ return this._element.classList.contains(CLASS_NAME_FADE)
220
+ }
221
+
222
+ _adjustDialog() {
223
+ const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight
224
+ const scrollbarWidth = this._scrollBar.getWidth()
225
+ const isBodyOverflowing = scrollbarWidth > 0
226
+
227
+ if (isBodyOverflowing && !isModalOverflowing) {
228
+ const property = isRTL() ? 'paddingLeft' : 'paddingRight'
229
+ this._element.style[property] = `${scrollbarWidth}px`
230
+ }
231
+
232
+ if (!isBodyOverflowing && isModalOverflowing) {
233
+ const property = isRTL() ? 'paddingRight' : 'paddingLeft'
234
+ this._element.style[property] = `${scrollbarWidth}px`
235
+ }
236
+ }
237
+
238
+ _resetAdjustments() {
239
+ this._element.style.paddingLeft = ''
240
+ this._element.style.paddingRight = ''
241
+ }
242
+
243
+ _addEventListeners() {
244
+ EventHandler.on(this._element, EVENT_KEY_KEYDOWN_DISMISS, event => {
245
+ if (event.key !== ESCAPE_KEY) return;
246
+
247
+ if (this._params.keyboard) {
248
+ this.hide();
249
+ return;
250
+ }
251
+
252
+ this._triggerBackdropTransition();
253
+ })
254
+
255
+ EventHandler.on(window, EVENT_KEY_RESIZE, () => {
256
+ if (this._isShown && !this._isTransitioning) this._adjustDialog();
257
+ })
258
+
259
+ EventHandler.on(this._element, EVENT_KEY_MOUSEDOWN_DISMISS, event => {
260
+ EventHandler.one(this._element, EVENT_KEY_CLICK_DISMISS, event2 => {
261
+ if (this._element !== event.target || this._element !== event2.target) return;
262
+
263
+ if (this._params.backdrop === 'static') {
264
+ this._triggerBackdropTransition();
265
+ return;
266
+ }
267
+
268
+ if (this._params.backdrop) {
269
+ this.hide();
270
+ }
271
+ })
272
+ })
273
+ }
274
+
275
+ _triggerBackdropTransition() {
276
+ const hideEvent = EventHandler.trigger(this._element, EVENT_KEY_HIDE_PREVENTED);
277
+ if (hideEvent.defaultPrevented) return;
278
+
279
+ const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
280
+ const initialOverflowY = this._element.style.overflowY;
281
+
282
+ if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) return;
283
+ if (!isModalOverflowing) this._element.style.overflowY = 'hidden';
284
+
285
+ this._element.classList.add(CLASS_NAME_STATIC);
286
+
287
+ this._queueCallback(() => {
288
+ this._element.classList.remove(CLASS_NAME_STATIC);
289
+ this._queueCallback(() => {
290
+ this._element.style.overflowY = initialOverflowY;
291
+ }, this._dialog);
292
+ }, this._dialog);
293
+
294
+ this._element.focus();
295
+ }
296
+
297
+ _addFieldsInModal(relatedTarget) {
298
+ this._params = this._getParams(relatedTarget, this._params);
299
+
300
+ if (!this._params.fields.length) return;
301
+
302
+ this._params.fields.forEach(function (item) {
303
+ if (!'name' in item && !'value' in item) return;
304
+
305
+ let elements = Selectors.findAll('[data-' + item.name + ']');
306
+ if (!elements.length) return;
307
+
308
+ for (const elm of elements) {
309
+ switch (elm.tagName) {
310
+ case 'INPUT': elm.value = item.value; break;
311
+ case 'IMG': Manipulator.set(elm, 'src', item.value); break;
312
+ default: elm.innerHTML = item.value;
313
+ }
314
+ }
315
+ });
316
+ }
317
+ }
318
+
319
+ dismissTrigger(VGModal);
320
+
321
+
322
+ /**
323
+ * Data API implementation
324
+ */
325
+
326
+ EventHandler.on(document, EVENT_KEY_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
327
+ const target = Selectors.getElementFromSelector(this);
328
+
329
+ if (['A', 'AREA'].includes(this.tagName)) event.preventDefault();
330
+
331
+ EventHandler.one(target, EVENT_KEY_SHOW, showEvent => {
332
+ if (showEvent.defaultPrevented) return;
333
+
334
+ EventHandler.one(target, EVENT_KEY_HIDDEN, () => {
335
+ if (isVisible(this)) this.focus();
336
+ });
337
+ });
338
+
339
+ const alreadyOpen = Selectors.find(OPEN_SELECTOR);
340
+ if (alreadyOpen) VGModal.getInstance(alreadyOpen).hide();
341
+
342
+ const data = VGModal.getOrCreateInstance(target);
343
+ data.toggle(this);
344
+ })
345
+
346
+ export default VGModal;
@@ -0,0 +1,25 @@
1
+ $modal-sm: 300px !default;
2
+ $modal-md: 500px !default;
3
+ $modal-lg: 800px !default;
4
+ $modal-xl: 1140px !default;
5
+
6
+ $modal-dialog-margin-y-sm-up: 1.75rem !default;
7
+ $modal-content-box-shadow-sm-up: $box-shadow !default;
8
+
9
+ $modal-map: (
10
+ z-index: $modal-index,
11
+ margin: .5rem,
12
+ padding: 1rem,
13
+ width: $modal-md,
14
+ color: $color,
15
+ background-color: $bg-color,
16
+ border-width: $border-width,
17
+ border-color: transparent,
18
+ border-style: $border-style,
19
+ border-radius: $border-radius,
20
+ box-shadow: $box-shadow,
21
+ transition: $transition-base,
22
+ fade-transform: translate(0, -50px),
23
+ show-transform: none,
24
+ scale-transform: scale(1.02),
25
+ );
@@ -0,0 +1,111 @@
1
+ /**
2
+ *--------------------------------------------------------------------------
3
+ * Модуль: VGSidebar
4
+ * Автор: Vegas DEV
5
+ * Лицензия: смотри LICENSE.md
6
+ *--------------------------------------------------------------------------
7
+ **/
8
+
9
+ @import "../../../utils/scss/functions";
10
+ @import "../../../utils/scss/mixin";
11
+ @import "../../../utils/scss/variables";
12
+ @import "../../../utils/scss/animate";
13
+ @import "variables";
14
+
15
+ .vg-modal {
16
+ @include mix-vars('modal', $modal-map);
17
+ position: fixed;
18
+ left: 0;
19
+ top: 0;
20
+ width: 100%;
21
+ height: 100%;
22
+ z-index: var(--vg-modal-z-index);
23
+ display: none;
24
+ overflow-x: hidden;
25
+ overflow-y: auto;
26
+ outline: 0;
27
+
28
+ &-dialog {
29
+ position: relative;
30
+ width: auto;
31
+ margin: var(--vg-modal-margin);
32
+ pointer-events: none;
33
+
34
+ .vg-modal.fade & {
35
+ transform: var(--vg-modal-fade-transform);
36
+ transition: var(--vg-modal-transition);
37
+ }
38
+
39
+ .vg-modal.show & {
40
+ transform: var(--vg-modal-show-transform);
41
+ }
42
+
43
+ .vg-modal.vg-modal-static & {
44
+ transform: var(--vg-modal-scale-transform);
45
+ }
46
+
47
+ &-scrollable {
48
+ height: calc(100% - var(--vg-modal-margin) * 2);
49
+
50
+ .vg-modal-content {
51
+ max-height: 100%;
52
+ overflow: hidden;
53
+ }
54
+
55
+ .vg-modal-body {
56
+ overflow-y: auto;
57
+ }
58
+ }
59
+
60
+ &-centered {
61
+ display: flex;
62
+ align-items: center;
63
+ min-height: calc(100% - var(--vg-modal-margin) * 2);
64
+ }
65
+ }
66
+
67
+ &-content {
68
+ position: relative;
69
+ display: flex;
70
+ flex-direction: column;
71
+ width: 100%;
72
+ color: var(--vg-modal-color);
73
+ pointer-events: auto;
74
+ background-color: var(--vg-modal-background-color);
75
+ background-clip: padding-box;
76
+ border: var(--vg-modal-border-width) var(--vg-modal-border-style) var(--vg-modal-border-color);
77
+ border-radius: var(--vg-modal-border-radius);
78
+ box-shadow: var(--vg-modal-box-shadow);
79
+ outline: 0;
80
+ padding: var(--vg-modal-padding);
81
+ }
82
+ }
83
+
84
+ @media screen and (min-width: 576px){
85
+ .vg-modal {
86
+ --vg-modal-margin: #{$modal-dialog-margin-y-sm-up};
87
+ --vg-modal-box-shadow: #{$modal-content-box-shadow-sm-up};
88
+ }
89
+
90
+ .vg-modal-dialog {
91
+ max-width: var(--vg-modal-width);
92
+ margin-right: auto;
93
+ margin-left: auto;
94
+ }
95
+
96
+ .vg-modal-sm {
97
+ --vg-modal-width: #{$modal-sm};
98
+ }
99
+ }
100
+
101
+ @media screen and (min-width: 992px){
102
+ .vg-modal-lg, .vg-modal-xl {
103
+ --vg-modal-width: #{$modal-lg};
104
+ }
105
+ }
106
+
107
+ @media screen and (min-width: 1399px) {
108
+ .vg-modal-xl {
109
+ --vg-modal-width: #{$modal-xl};
110
+ }
111
+ }