@andreyshpigunov/x 0.4.4 → 0.5.0
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/assets/css/app.css +1 -1
- package/assets/js/app.js +1 -1
- package/cheatsheet.html +18 -14
- package/dist/x.css +1 -1
- package/dist/x.js +1 -1
- package/index.html +102 -102
- package/package.json +1 -1
- package/src/components/x/animate.js +1 -1
- package/src/components/x/buttons.css +24 -24
- package/src/components/x/colors.css +18 -0
- package/src/components/x/dropdown.css +5 -5
- package/src/components/x/dropdown.js +19 -19
- package/src/components/x/helpers.css +10 -10
- package/src/components/x/icons.css +10 -10
- package/src/components/x/lib.js +4 -4
- package/src/components/x/links.css +10 -10
- package/src/components/x/modal.css +26 -26
- package/src/components/x/modal.js +23 -23
- package/src/components/x/scroll.css +14 -12
- package/src/components/x/sticky.js +5 -5
- package/src/css/x.css +17 -17
|
@@ -12,6 +12,8 @@ All right reserved.
|
|
|
12
12
|
.color-warning
|
|
13
13
|
.color-danger
|
|
14
14
|
.color-error
|
|
15
|
+
.color-black
|
|
16
|
+
.color-white
|
|
15
17
|
.color-grey
|
|
16
18
|
|
|
17
19
|
.bg-primary
|
|
@@ -19,6 +21,8 @@ All right reserved.
|
|
|
19
21
|
.bg-warning
|
|
20
22
|
.bg-danger
|
|
21
23
|
.bg-error
|
|
24
|
+
.bg-black
|
|
25
|
+
.bg-white
|
|
22
26
|
.bg-grey
|
|
23
27
|
*/
|
|
24
28
|
|
|
@@ -28,6 +32,8 @@ All right reserved.
|
|
|
28
32
|
--color-warning: #ff8800;
|
|
29
33
|
--color-danger: #ee3333;
|
|
30
34
|
--color-error: #ee3333;
|
|
35
|
+
--color-black: #fff;
|
|
36
|
+
--color-white: #000;
|
|
31
37
|
--color-grey: #f4f5f6;
|
|
32
38
|
}
|
|
33
39
|
|
|
@@ -46,6 +52,12 @@ All right reserved.
|
|
|
46
52
|
.color-error {
|
|
47
53
|
color: var(--color-error);
|
|
48
54
|
}
|
|
55
|
+
.color-black {
|
|
56
|
+
color: var(--color-black);
|
|
57
|
+
}
|
|
58
|
+
.color-white {
|
|
59
|
+
color: var(--color-white);
|
|
60
|
+
}
|
|
49
61
|
.color-grey {
|
|
50
62
|
color: var(--color-grey);
|
|
51
63
|
}
|
|
@@ -65,6 +77,12 @@ All right reserved.
|
|
|
65
77
|
.bg-error {
|
|
66
78
|
background-color: var(--color-error);
|
|
67
79
|
}
|
|
80
|
+
.bg-black {
|
|
81
|
+
background-color: var(--color-black);
|
|
82
|
+
}
|
|
83
|
+
.bg-white {
|
|
84
|
+
background-color: var(--color-white);
|
|
85
|
+
}
|
|
68
86
|
.bg-grey {
|
|
69
87
|
background-color: var(--color-grey);
|
|
70
88
|
}
|
|
@@ -87,24 +87,24 @@ All right reserved.
|
|
|
87
87
|
.dropdown {
|
|
88
88
|
position: relative;
|
|
89
89
|
|
|
90
|
-
&.
|
|
90
|
+
&.dropdown_right > [x-dropdown] {
|
|
91
91
|
right: 0;
|
|
92
92
|
left: auto;
|
|
93
93
|
}
|
|
94
|
-
&.
|
|
94
|
+
&.dropdown_bottom > [x-dropdown] {
|
|
95
95
|
bottom: 100%;
|
|
96
96
|
top: auto;
|
|
97
97
|
transform-origin: bottom;
|
|
98
98
|
}
|
|
99
|
-
&.
|
|
99
|
+
&.dropdown_ready > [x-dropdown] {
|
|
100
100
|
display: block;
|
|
101
101
|
pointer-events: auto;
|
|
102
102
|
}
|
|
103
|
-
&.
|
|
103
|
+
&.dropdown_open > [x-dropdown] {
|
|
104
104
|
opacity: 1;
|
|
105
105
|
transform: scale(1);
|
|
106
106
|
}
|
|
107
|
-
&.
|
|
107
|
+
&.dropdown_wrap > [x-dropdown] li {
|
|
108
108
|
& > a,
|
|
109
109
|
& > span {
|
|
110
110
|
white-space: wrap;
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* Preventing auto-close on click:
|
|
47
47
|
* ```html
|
|
48
48
|
* <ul x-dropdown>
|
|
49
|
-
* <li class="
|
|
49
|
+
* <li class="dropdown_stay">
|
|
50
50
|
* <button>This area won't close dropdown</button>
|
|
51
51
|
* </li>
|
|
52
52
|
* </ul>
|
|
@@ -80,10 +80,10 @@
|
|
|
80
80
|
* CSS classes:
|
|
81
81
|
*
|
|
82
82
|
* - `.dropdown` – Added to parent container
|
|
83
|
-
* - `.
|
|
84
|
-
* - `.
|
|
85
|
-
* - `.
|
|
86
|
-
* - `.
|
|
83
|
+
* - `.dropdown_open` – Added when dropdown is open
|
|
84
|
+
* - `.dropdown_right` – Added when menu needs to align right (overflow prevention)
|
|
85
|
+
* - `.dropdown_bottom` – Added when menu needs to align bottom (overflow prevention)
|
|
86
|
+
* - `.dropdown_ready` – Temporarily added during position calculation
|
|
87
87
|
* - `.active` – Added to trigger when dropdown is open
|
|
88
88
|
* - `.hover` – Added on focus for better visual feedback
|
|
89
89
|
*
|
|
@@ -123,7 +123,7 @@ import { lib } from './lib';
|
|
|
123
123
|
* Features:
|
|
124
124
|
* - Supports multiple dropdowns on the page.
|
|
125
125
|
* - Keyboard navigation (Enter, Space, ArrowDown, ArrowUp, Home, End, Escape).
|
|
126
|
-
* - Automatic positioning with overflow handling (adds `.
|
|
126
|
+
* - Automatic positioning with overflow handling (adds `.dropdown_right`, `.dropdown_bottom`).
|
|
127
127
|
* - Adds `.hover` class on focus for triggers and menu items.
|
|
128
128
|
* - Safe `init()` with cleanup and reinitialization support.
|
|
129
129
|
*
|
|
@@ -412,7 +412,7 @@ class Dropdown {
|
|
|
412
412
|
* @private
|
|
413
413
|
*/
|
|
414
414
|
_toggleDropdown(parent, trigger) {
|
|
415
|
-
const isOpen = parent.classList.contains('
|
|
415
|
+
const isOpen = parent.classList.contains('dropdown_open');
|
|
416
416
|
this.closeAllDropdowns();
|
|
417
417
|
if (!isOpen) this._open(parent, trigger);
|
|
418
418
|
}
|
|
@@ -432,7 +432,7 @@ class Dropdown {
|
|
|
432
432
|
this._adjustPosition(parent, menu);
|
|
433
433
|
|
|
434
434
|
lib.addClass(trigger, 'active');
|
|
435
|
-
lib.addClass(parent, '
|
|
435
|
+
lib.addClass(parent, 'dropdown_open', 20);
|
|
436
436
|
trigger.setAttribute('aria-expanded', 'true');
|
|
437
437
|
|
|
438
438
|
this._fireEvent(parent, 'aftershow');
|
|
@@ -446,22 +446,22 @@ class Dropdown {
|
|
|
446
446
|
* @private
|
|
447
447
|
*/
|
|
448
448
|
_adjustPosition(parent, menu) {
|
|
449
|
-
parent.classList.add('
|
|
449
|
+
parent.classList.add('dropdown_ready');
|
|
450
450
|
const rect = menu.getBoundingClientRect();
|
|
451
|
-
parent.classList.remove('
|
|
451
|
+
parent.classList.remove('dropdown_ready');
|
|
452
452
|
|
|
453
453
|
const vw = window.innerWidth;
|
|
454
454
|
const docHeight = document.documentElement.scrollHeight;
|
|
455
455
|
|
|
456
|
-
parent.classList.remove('
|
|
456
|
+
parent.classList.remove('dropdown_right', 'dropdown_bottom');
|
|
457
457
|
|
|
458
458
|
if (rect.right > vw) {
|
|
459
|
-
parent.classList.add('
|
|
459
|
+
parent.classList.add('dropdown_right');
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
const menuBottomInDoc = window.scrollY + rect.bottom;
|
|
463
463
|
if (menuBottomInDoc > docHeight) {
|
|
464
|
-
parent.classList.add('
|
|
464
|
+
parent.classList.add('dropdown_bottom');
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
467
|
|
|
@@ -498,8 +498,8 @@ class Dropdown {
|
|
|
498
498
|
* dropdown.closeAllDropdowns();
|
|
499
499
|
*/
|
|
500
500
|
closeAllDropdowns() {
|
|
501
|
-
if (!document.querySelector('.
|
|
502
|
-
const openDropdowns = lib.qsa('.
|
|
501
|
+
if (!document.querySelector('.dropdown_open')) return;
|
|
502
|
+
const openDropdowns = lib.qsa('.dropdown_open');
|
|
503
503
|
for (const parent of openDropdowns) {
|
|
504
504
|
this._close(parent);
|
|
505
505
|
}
|
|
@@ -523,8 +523,8 @@ class Dropdown {
|
|
|
523
523
|
trigger.setAttribute('aria-expanded', 'false');
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
-
await lib.removeClass(parent, '
|
|
527
|
-
parent.classList.remove('
|
|
526
|
+
await lib.removeClass(parent, 'dropdown_open', 200);
|
|
527
|
+
parent.classList.remove('dropdown_right', 'dropdown_bottom');
|
|
528
528
|
|
|
529
529
|
this._fireEvent(parent, 'afterhide');
|
|
530
530
|
|
|
@@ -551,8 +551,8 @@ class Dropdown {
|
|
|
551
551
|
if (Dropdown._globalListenersAttached) return;
|
|
552
552
|
|
|
553
553
|
this._globalClickHandler = e => {
|
|
554
|
-
if (e.target.closest('[x-dropdown-open]') || e.target.closest('[x-dropdown] .
|
|
555
|
-
if (!document.querySelector('.
|
|
554
|
+
if (e.target.closest('[x-dropdown-open]') || e.target.closest('[x-dropdown] .dropdown_stay')) return;
|
|
555
|
+
if (!document.querySelector('.dropdown_open')) return;
|
|
556
556
|
this.closeAllDropdowns();
|
|
557
557
|
};
|
|
558
558
|
document.addEventListener('click', this._globalClickHandler);
|
|
@@ -49,15 +49,15 @@ All right reserved.
|
|
|
49
49
|
.ratio2x3 (s,m,l,xl)
|
|
50
50
|
.ratio3x4 (s,m,l,xl)
|
|
51
51
|
.ratio9x16 (s,m,l,xl)
|
|
52
|
-
.
|
|
53
|
-
.
|
|
52
|
+
.breakWord
|
|
53
|
+
.visuallyHidden
|
|
54
54
|
.invisible
|
|
55
55
|
.scroll-responsive
|
|
56
56
|
.hidden (s,m,l,xl)
|
|
57
57
|
.hidden-next (s,m,l,xl)
|
|
58
58
|
.block (s,m,l,xl)
|
|
59
59
|
.inline (s,m,l,xl)
|
|
60
|
-
.
|
|
60
|
+
.inlineBlock (s,m,l,xl)
|
|
61
61
|
.fullscreen
|
|
62
62
|
.max (s,m,l,xl)
|
|
63
63
|
.w[10-190] step 10 (s,m,l,xl)
|
|
@@ -455,11 +455,11 @@ html.touch .touch-hide { display: none }
|
|
|
455
455
|
|
|
456
456
|
|
|
457
457
|
/* !- Break word, invisible, scroll */
|
|
458
|
-
.
|
|
458
|
+
.breakWord {
|
|
459
459
|
overflow-wrap: anywhere;
|
|
460
460
|
word-break: break-word;
|
|
461
461
|
}
|
|
462
|
-
.
|
|
462
|
+
.visuallyHidden {
|
|
463
463
|
position: absolute;
|
|
464
464
|
top: 0;
|
|
465
465
|
left: 0;
|
|
@@ -482,7 +482,7 @@ html.touch .touch-hide { display: none }
|
|
|
482
482
|
/* !- Display */
|
|
483
483
|
.block { display: block }
|
|
484
484
|
.inline { display: inline }
|
|
485
|
-
.
|
|
485
|
+
.inlineBlock { display: inline-block }
|
|
486
486
|
.table { display: table }
|
|
487
487
|
|
|
488
488
|
|
|
@@ -512,7 +512,7 @@ html.touch .touch-hide { display: none }
|
|
|
512
512
|
@media (min-width: 640px) {
|
|
513
513
|
.s\:block { display: block }
|
|
514
514
|
.s\:inline { display: inline }
|
|
515
|
-
.s\:
|
|
515
|
+
.s\:inlineBlock { display: inline-block }
|
|
516
516
|
.s\:table { display: table }
|
|
517
517
|
.s\:flex { display: flex }
|
|
518
518
|
.s\:grid { display: grid }
|
|
@@ -520,7 +520,7 @@ html.touch .touch-hide { display: none }
|
|
|
520
520
|
@media (min-width: 768px) {
|
|
521
521
|
.m\:block { display: block }
|
|
522
522
|
.m\:inline { display: inline }
|
|
523
|
-
.m\:
|
|
523
|
+
.m\:inlineBlock { display: inline-block }
|
|
524
524
|
.m\:table { display: table }
|
|
525
525
|
.m\:flex { display: flex }
|
|
526
526
|
.m\:grid { display: grid }
|
|
@@ -528,7 +528,7 @@ html.touch .touch-hide { display: none }
|
|
|
528
528
|
@media (min-width: 1024px) {
|
|
529
529
|
.l\:block { display: block }
|
|
530
530
|
.l\:inline { display: inline }
|
|
531
|
-
.l\:
|
|
531
|
+
.l\:inlineBlock { display: inline-block }
|
|
532
532
|
.l\:table { display: table }
|
|
533
533
|
.l\:flex { display: flex }
|
|
534
534
|
.l\:grid { display: grid }
|
|
@@ -536,7 +536,7 @@ html.touch .touch-hide { display: none }
|
|
|
536
536
|
@media (min-width: 1280px) {
|
|
537
537
|
.xl\:block { display: block }
|
|
538
538
|
.xl\:inline { display: inline }
|
|
539
|
-
.xl\:
|
|
539
|
+
.xl\:inlineBlock { display: inline-block }
|
|
540
540
|
.xl\:table { display: table }
|
|
541
541
|
.xl\:flex { display: flex }
|
|
542
542
|
.xl\:grid { display: grid }
|
|
@@ -9,7 +9,7 @@ All right reserved.
|
|
|
9
9
|
|
|
10
10
|
/*
|
|
11
11
|
.icon - base icon style
|
|
12
|
-
.icon
|
|
12
|
+
.icon[10-60] step 2 (m,l) - icon size in px
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
.icon,
|
|
@@ -27,9 +27,9 @@ All right reserved.
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
@for $i from 10 to 60 by 2 {
|
|
30
|
-
.icon
|
|
31
|
-
.icon
|
|
32
|
-
.icon
|
|
30
|
+
.icon$(i),
|
|
31
|
+
.icon$(i) > svg,
|
|
32
|
+
.icon$(i) > img {
|
|
33
33
|
width: calc($(i)rem / 10);
|
|
34
34
|
height: calc($(i)rem / 10);
|
|
35
35
|
}
|
|
@@ -37,9 +37,9 @@ All right reserved.
|
|
|
37
37
|
|
|
38
38
|
@media (min-width: 768px) {
|
|
39
39
|
@for $i from 10 to 60 by 2 {
|
|
40
|
-
.m\:icon
|
|
41
|
-
.m\:icon
|
|
42
|
-
.m\:icon
|
|
40
|
+
.m\:icon$(i),
|
|
41
|
+
.m\:icon$(i) > svg,
|
|
42
|
+
.m\:icon$(i) > img {
|
|
43
43
|
width: calc($(i)rem / 10);
|
|
44
44
|
height: calc($(i)rem / 10);
|
|
45
45
|
}
|
|
@@ -48,9 +48,9 @@ All right reserved.
|
|
|
48
48
|
|
|
49
49
|
@media (min-width: 1024px) {
|
|
50
50
|
@for $i from 10 to 60 by 2 {
|
|
51
|
-
.l\:icon
|
|
52
|
-
.l\:icon
|
|
53
|
-
.l\:icon
|
|
51
|
+
.l\:icon$(i),
|
|
52
|
+
.l\:icon$(i) > svg,
|
|
53
|
+
.l\:icon$(i) > img {
|
|
54
54
|
width: calc($(i)rem / 10);
|
|
55
55
|
height: calc($(i)rem / 10);
|
|
56
56
|
}
|
package/src/components/x/lib.js
CHANGED
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
* const items = lib.qsa('li', container);
|
|
91
91
|
*
|
|
92
92
|
* Classes with delay (for transitions):
|
|
93
|
-
* await lib.addClass('.element', 'active', 100); // Adds
|
|
94
|
-
* await lib.removeClass('.element', 'active', 200); // Removes active, waits 200ms, removes
|
|
93
|
+
* await lib.addClass('.element', 'active', 100); // Adds _ready class, waits 100ms, then adds active
|
|
94
|
+
* await lib.removeClass('.element', 'active', 200); // Removes active, waits 200ms, removes _ready
|
|
95
95
|
*
|
|
96
96
|
* Formatting:
|
|
97
97
|
* lib.price(1234.56); // "1 234.56"
|
|
@@ -333,7 +333,7 @@ class Lib {
|
|
|
333
333
|
if (!len) return;
|
|
334
334
|
|
|
335
335
|
if (delay > 0) {
|
|
336
|
-
const readyClass = className.replace(
|
|
336
|
+
const readyClass = className.replace(/_.*/, '') + '_ready';
|
|
337
337
|
for (let i = 0; i < len; i++) items[i].classList.add(readyClass);
|
|
338
338
|
await new Promise(res => setTimeout(res, delay));
|
|
339
339
|
}
|
|
@@ -357,7 +357,7 @@ class Lib {
|
|
|
357
357
|
|
|
358
358
|
if (delay > 0) {
|
|
359
359
|
await new Promise(res => setTimeout(res, delay));
|
|
360
|
-
const readyClass = className.replace(
|
|
360
|
+
const readyClass = className.replace(/_.*/, '') + '_ready';
|
|
361
361
|
for (let i = 0; i < len; i++) items[i].classList.remove(readyClass);
|
|
362
362
|
}
|
|
363
363
|
}
|
|
@@ -14,11 +14,11 @@ All right reserved.
|
|
|
14
14
|
a.link
|
|
15
15
|
a.hover
|
|
16
16
|
a.active
|
|
17
|
-
a.
|
|
18
|
-
a.
|
|
19
|
-
a.
|
|
20
|
-
a.
|
|
21
|
-
a.
|
|
17
|
+
a.link_noline
|
|
18
|
+
a.link_underline
|
|
19
|
+
a.link_dashed
|
|
20
|
+
a.link_dotted
|
|
21
|
+
a.link_wavy
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
:root {
|
|
@@ -82,19 +82,19 @@ a {
|
|
|
82
82
|
|
|
83
83
|
/* Link predefined styles */
|
|
84
84
|
|
|
85
|
-
&.
|
|
85
|
+
&.link_noline {
|
|
86
86
|
--link-decoration-line: none;
|
|
87
87
|
}
|
|
88
|
-
&.
|
|
88
|
+
&.link_underline {
|
|
89
89
|
--link-decoration-line: underline;
|
|
90
90
|
}
|
|
91
|
-
&.
|
|
91
|
+
&.link_dashed {
|
|
92
92
|
--link-decoration-style: dashed;
|
|
93
93
|
}
|
|
94
|
-
&.
|
|
94
|
+
&.link_dotted {
|
|
95
95
|
--link-decoration-style: dotted;
|
|
96
96
|
}
|
|
97
|
-
&.
|
|
97
|
+
&.link_wavy {
|
|
98
98
|
--link-decoration-style: wavy;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -49,21 +49,21 @@ html.modal--active body {
|
|
|
49
49
|
pointer-events: none;
|
|
50
50
|
display: none;
|
|
51
51
|
}
|
|
52
|
-
.
|
|
52
|
+
.modal_ready {
|
|
53
53
|
z-index: 10000;
|
|
54
54
|
pointer-events: all;
|
|
55
55
|
display: block;
|
|
56
56
|
}
|
|
57
|
-
.
|
|
58
|
-
.
|
|
59
|
-
.
|
|
60
|
-
.
|
|
61
|
-
.
|
|
62
|
-
.
|
|
63
|
-
.
|
|
64
|
-
.
|
|
65
|
-
.
|
|
66
|
-
.
|
|
57
|
+
.modal_z1 { z-index: 10001 }
|
|
58
|
+
.modal_z2 { z-index: 10002 }
|
|
59
|
+
.modal_z3 { z-index: 10003 }
|
|
60
|
+
.modal_z4 { z-index: 10004 }
|
|
61
|
+
.modal_z5 { z-index: 10005 }
|
|
62
|
+
.modal_z6 { z-index: 10006 }
|
|
63
|
+
.modal_z7 { z-index: 10007 }
|
|
64
|
+
.modal_z8 { z-index: 10008 }
|
|
65
|
+
.modal_z9 { z-index: 10009 }
|
|
66
|
+
.modal_z10 { z-index: 10010 }
|
|
67
67
|
|
|
68
68
|
/* !- Overlay */
|
|
69
69
|
.modal-overlay {
|
|
@@ -161,7 +161,7 @@ html.modal--active body {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
.
|
|
164
|
+
.modal_active .modal-rail {
|
|
165
165
|
|
|
166
166
|
.modal-close {
|
|
167
167
|
opacity: 1;
|
|
@@ -187,7 +187,7 @@ html.modal--active body {
|
|
|
187
187
|
opacity: 0;
|
|
188
188
|
transition: opacity .2s ease-out;
|
|
189
189
|
}
|
|
190
|
-
&.
|
|
190
|
+
&.modal_active .modal-overlay {
|
|
191
191
|
opacity: 1;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
@@ -201,68 +201,68 @@ html.modal--active body {
|
|
|
201
201
|
transform-origin: center top;
|
|
202
202
|
transition: all .2s ease-out;
|
|
203
203
|
}
|
|
204
|
-
&.
|
|
204
|
+
&.modal_active .modal-window {
|
|
205
205
|
transform: scale(1);
|
|
206
206
|
opacity: 1;
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
/* !- Zoom in */
|
|
211
|
-
.
|
|
211
|
+
.modal_effect-in {
|
|
212
212
|
& .modal-window {
|
|
213
213
|
transform: scale(.9);
|
|
214
214
|
}
|
|
215
|
-
&.
|
|
215
|
+
&.modal_active .modal-window {
|
|
216
216
|
transform: scale(1);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
/* !- Zoom out */
|
|
221
|
-
.
|
|
221
|
+
.modal_effect-out {
|
|
222
222
|
& .modal-window {
|
|
223
223
|
transform: scale(1.1);
|
|
224
224
|
}
|
|
225
|
-
&.
|
|
225
|
+
&.modal_active .modal-window {
|
|
226
226
|
transform: scale(1);
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/* !- Slide up */
|
|
231
|
-
.
|
|
231
|
+
.modal_effect-up {
|
|
232
232
|
& .modal-window {
|
|
233
233
|
transform: translateY(30px);
|
|
234
234
|
}
|
|
235
|
-
&.
|
|
235
|
+
&.modal_active .modal-window {
|
|
236
236
|
transform: translateY(0);
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
/* !- Slide down */
|
|
241
|
-
.
|
|
241
|
+
.modal_effect-down {
|
|
242
242
|
& .modal-window {
|
|
243
243
|
transform: translateY(-30px);
|
|
244
244
|
}
|
|
245
|
-
&.
|
|
245
|
+
&.modal_active .modal-window {
|
|
246
246
|
transform: translateY(0);
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
/* !- Slide from left */
|
|
251
|
-
.
|
|
251
|
+
.modal_effect-left {
|
|
252
252
|
& .modal-window {
|
|
253
253
|
transform: translateX(-30px);
|
|
254
254
|
}
|
|
255
|
-
&.
|
|
255
|
+
&.modal_active .modal-window {
|
|
256
256
|
transform: translateX(0);
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
/* !- Slide from right */
|
|
261
|
-
.
|
|
261
|
+
.modal_effect-right {
|
|
262
262
|
& .modal-window {
|
|
263
263
|
transform: translateX(30px);
|
|
264
264
|
}
|
|
265
|
-
&.
|
|
265
|
+
&.modal_active .modal-window {
|
|
266
266
|
transform: translateX(0);
|
|
267
267
|
}
|
|
268
268
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* modal.init();
|
|
14
14
|
*
|
|
15
15
|
* HTML structure:
|
|
16
|
-
* <div x-modal="myModal" class="
|
|
16
|
+
* <div x-modal="myModal" class="modal_hash" data-window-class="max800">
|
|
17
17
|
* <h2>Modal Title</h2>
|
|
18
18
|
* <p>Modal content goes here</p>
|
|
19
19
|
* <button class="modal-close">Close</button>
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
*
|
|
93
93
|
* - `x-modal="id"` - Required attribute to define modal
|
|
94
94
|
* - `x-modal-open="id"` - Attribute for links/buttons that open modal
|
|
95
|
-
* - `
|
|
96
|
-
* - `
|
|
95
|
+
* - `modal_hash` - Class to enable URL hash integration (#id)
|
|
96
|
+
* - `modal_uniq` - Class to close other modals when this one opens
|
|
97
97
|
* - `data-window-class` - Attribute to add classes to modal window
|
|
98
98
|
*
|
|
99
99
|
* Features:
|
|
@@ -102,8 +102,8 @@
|
|
|
102
102
|
* - ESC key to close topmost modal
|
|
103
103
|
* - Click overlay to close
|
|
104
104
|
* - Click .modal-close button to close
|
|
105
|
-
* - URL hash integration (
|
|
106
|
-
* - Unique modal mode (
|
|
105
|
+
* - URL hash integration (modal_hash class)
|
|
106
|
+
* - Unique modal mode (modal_uniq class)
|
|
107
107
|
* - Lock mechanism to prevent overlapping animations
|
|
108
108
|
* - Global classes on <html> element
|
|
109
109
|
*
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
* @example
|
|
137
137
|
* // Vanilla JS — plain HTML
|
|
138
138
|
* // index.html:
|
|
139
|
-
* // <div x-modal="myModal" class="
|
|
139
|
+
* // <div x-modal="myModal" class="modal_hash" data-window-class="max800">
|
|
140
140
|
* // <h2>Title</h2>
|
|
141
141
|
* // <p>Content</p>
|
|
142
142
|
* // <button type="button" class="modal-close">Close</button>
|
|
@@ -291,7 +291,7 @@ class Modal {
|
|
|
291
291
|
|
|
292
292
|
if (window.location.hash === '#' + id) {
|
|
293
293
|
const el = lib.qs('#' + id);
|
|
294
|
-
if (el && el.classList.contains('
|
|
294
|
+
if (el && el.classList.contains('modal_hash')) this.show(id);
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
}
|
|
@@ -304,7 +304,7 @@ class Modal {
|
|
|
304
304
|
*/
|
|
305
305
|
_setupGlobalListeners() {
|
|
306
306
|
this._clickHandler = e => {
|
|
307
|
-
if (!lib.qs('.
|
|
307
|
+
if (!lib.qs('.modal_active')) return;
|
|
308
308
|
const target = e.target;
|
|
309
309
|
const isClose = target.classList && target.classList.contains('modal-close');
|
|
310
310
|
const isOverlay = !target.closest || !target.closest('.modal-window');
|
|
@@ -317,7 +317,7 @@ class Modal {
|
|
|
317
317
|
|
|
318
318
|
this._keydownHandler = e => {
|
|
319
319
|
if (e.key !== 'Escape') return;
|
|
320
|
-
const modals = lib.qsa('.
|
|
320
|
+
const modals = lib.qsa('.modal_active');
|
|
321
321
|
const len = modals.length;
|
|
322
322
|
if (!len) return;
|
|
323
323
|
const id = modals[len - 1].getAttribute('id');
|
|
@@ -351,24 +351,24 @@ class Modal {
|
|
|
351
351
|
const modal = lib.qs('#' + id);
|
|
352
352
|
if (!modal) return;
|
|
353
353
|
|
|
354
|
-
if (modal.classList.contains('
|
|
354
|
+
if (modal.classList.contains('modal_uniq')) await this.hideAll();
|
|
355
355
|
|
|
356
356
|
this.lockCount++;
|
|
357
357
|
try {
|
|
358
|
-
await lib.addClass(modal, '
|
|
358
|
+
await lib.addClass(modal, 'modal_ready');
|
|
359
359
|
await lib.sleep(10);
|
|
360
360
|
modal.dispatchEvent(new CustomEvent('modal:ready'));
|
|
361
361
|
|
|
362
|
-
if (modal.classList.contains('
|
|
362
|
+
if (modal.classList.contains('modal_hash')) history.replaceState(null, '', '#' + id);
|
|
363
363
|
|
|
364
364
|
if (this.html) {
|
|
365
|
-
lib.addClass(this.html, '
|
|
366
|
-
lib.addClass(this.html, id + '
|
|
365
|
+
lib.addClass(this.html, 'modal_active');
|
|
366
|
+
lib.addClass(this.html, id + '_active');
|
|
367
367
|
}
|
|
368
368
|
lib.addClass('[x-modal-open=' + id + ']', 'active');
|
|
369
369
|
this.modalLevel++;
|
|
370
|
-
lib.addClass(modal, '
|
|
371
|
-
await lib.addClass(modal, '
|
|
370
|
+
lib.addClass(modal, 'modal_z' + this.modalLevel);
|
|
371
|
+
await lib.addClass(modal, 'modal_active');
|
|
372
372
|
|
|
373
373
|
const modalOuter = lib.qs('.modal-outer', modal);
|
|
374
374
|
if (modalOuter) modalOuter.scrollTo(0, 1);
|
|
@@ -398,16 +398,16 @@ class Modal {
|
|
|
398
398
|
|
|
399
399
|
this.lockCount++;
|
|
400
400
|
try {
|
|
401
|
-
if (modal.classList.contains('
|
|
401
|
+
if (modal.classList.contains('modal_hash') && window.location.hash === '#' + id) {
|
|
402
402
|
history.replaceState(null, document.title, window.location.pathname + window.location.search);
|
|
403
403
|
}
|
|
404
404
|
lib.removeClass('[x-modal-open=' + id + ']', 'active');
|
|
405
|
-
await lib.removeClass(modal, '
|
|
406
|
-
lib.removeClass(modal, '
|
|
405
|
+
await lib.removeClass(modal, 'modal_active', 200);
|
|
406
|
+
lib.removeClass(modal, 'modal_z' + this.modalLevel);
|
|
407
407
|
modal.dispatchEvent(new CustomEvent('modal:close'));
|
|
408
|
-
if (this.html) lib.removeClass(this.html, id + '
|
|
408
|
+
if (this.html) lib.removeClass(this.html, id + '_active');
|
|
409
409
|
this.modalLevel--;
|
|
410
|
-
if (this.modalLevel === 0 && this.html) lib.removeClass(this.html, '
|
|
410
|
+
if (this.modalLevel === 0 && this.html) lib.removeClass(this.html, 'modal_active');
|
|
411
411
|
} catch (_) {
|
|
412
412
|
} finally {
|
|
413
413
|
this.lockCount--;
|
|
@@ -422,7 +422,7 @@ class Modal {
|
|
|
422
422
|
*/
|
|
423
423
|
async hideAll() {
|
|
424
424
|
if (typeof document === 'undefined') return;
|
|
425
|
-
const modals = lib.qsa('.
|
|
425
|
+
const modals = lib.qsa('.modal_active');
|
|
426
426
|
for (let i = 0; i < modals.length; i++) {
|
|
427
427
|
const id = modals[i].getAttribute('id');
|
|
428
428
|
if (id) await this.hide(id);
|
|
@@ -437,7 +437,7 @@ class Modal {
|
|
|
437
437
|
isActive(id) {
|
|
438
438
|
if (typeof document === 'undefined' || !id || typeof id !== 'string' || !this._isValidId(id)) return false;
|
|
439
439
|
const modal = lib.qs('#' + id);
|
|
440
|
-
return modal ? modal.classList.contains('
|
|
440
|
+
return modal ? modal.classList.contains('modal_active') : false;
|
|
441
441
|
}
|
|
442
442
|
}
|
|
443
443
|
|