vgapp 0.3.2 → 0.3.3

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.
@@ -0,0 +1,193 @@
1
+ import BaseModule from "../../base-module";
2
+ import EventHandler from "../../../utils/js/dom/event";
3
+ import {dismissTrigger} from "../../module-fn";
4
+ import {execute, isDisabled, makeRandomString, mergeDeepObject, noop} from "../../../utils/js/functions";
5
+ import Selectors from "../../../utils/js/dom/selectors";
6
+
7
+ /**
8
+ * Constants
9
+ */
10
+ const NAME = 'spy';
11
+ const NAME_KEY = 'vg.spy';
12
+
13
+
14
+ class VGSpy extends BaseModule {
15
+ constructor(element, params = {}) {
16
+ super(element, params);
17
+
18
+ this._params = this._getParams(element, mergeDeepObject({
19
+ offset: 0,
20
+ isState: false,
21
+ onActive: noop,
22
+ onClick: noop,
23
+ activeClass: ['active']
24
+ }, params));
25
+
26
+ this.isClick = false;
27
+
28
+ this.links = this._element.querySelectorAll('[data-vg-target]').length ?
29
+ this._element.querySelectorAll('[data-vg-target]') :
30
+ this._element.querySelectorAll('a')
31
+ ;
32
+
33
+ this.onLoad();
34
+ this.onClick();
35
+ this.onScroll();
36
+ }
37
+
38
+ static get NAME() {
39
+ return NAME;
40
+ }
41
+
42
+ static get NAME_KEY() {
43
+ return NAME_KEY
44
+ }
45
+
46
+ onLoad() {
47
+ let _this = this;
48
+
49
+ document.addEventListener('DOMContentLoaded', function () {
50
+ _this.setCurrentSection(null);
51
+ });
52
+ }
53
+
54
+ onClick() {
55
+ let _this = this;
56
+
57
+ _this.links.forEach(el => {
58
+ if (el) {
59
+ el.onclick = function (e) {
60
+ execute(_this._params.onClick, [e, this])
61
+ _this.setCurrentSection(this);
62
+
63
+ return false;
64
+ }
65
+ }
66
+ });
67
+ }
68
+
69
+ onScroll() {
70
+ let _this = this;
71
+
72
+ if (!_this.isClick) {
73
+ window.onscroll = function () {
74
+ _this.setCurrentSection(null);
75
+ }
76
+ }
77
+ }
78
+
79
+ setCurrentSection($link = null) {
80
+ if (this._params.isState) {
81
+ // TODO не тестили
82
+ let target = window.location.hash;
83
+ if (target) {
84
+ let $element = document.querySelector('[href="'+ target +'"]') ||
85
+ document.querySelector('[href="\/' + target +'"]') ||
86
+ document.querySelector('[data-vg-target="'+ target.replace('#', '') +'"]') || null;
87
+
88
+ if ($element !== null) {
89
+ $link = $element;
90
+ }
91
+ }
92
+ }
93
+
94
+ if ($link) {
95
+ let target = this.attributes($link, 'target'),
96
+ offset = this.attributes($link, 'offset'),
97
+ section = document.getElementById(target);
98
+
99
+ if (section) {
100
+ let to = section.offsetTop + (offset) + (this._params.offset)
101
+ this.removeCurrentActive();
102
+ this.setActive($link, section);
103
+ window.scrollTo(0, to);
104
+
105
+ this.isClick = false;
106
+ }
107
+ } else {
108
+ for (let i = 0; i < this.links.length; i++) {
109
+ let target = this.attributes(this.links[i], 'target'),
110
+ offset = this.attributes(this.links[i], 'offset'),
111
+ section = document.getElementById(target);
112
+
113
+ if (section) {
114
+ let start = section.offsetTop + (offset) + (this._params.offset),
115
+ end = start + section.offsetHeight,
116
+ currentPosition = (document.documentElement.scrollTop || document.body.scrollTop),
117
+ isInView = currentPosition >= start && currentPosition < end;
118
+
119
+ if (isInView) {
120
+ this.removeCurrentActive({ignore: this.links[i]});
121
+ this.setActive(this.links[i], section);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ setActive($link, $section) {
129
+ const isActive = this._params.activeClass.every(function (value){
130
+ return $link.classList.contains(value);
131
+ });
132
+
133
+ if (this._params.isState) {
134
+ let text = this.attributes($link, 'text'),
135
+ target = this.attributes($link, 'target');
136
+
137
+ history.pushState("", document.title + text, '#' + target);
138
+ }
139
+
140
+ if (!isActive) {
141
+ if ($section) {
142
+ $section.classList.add(...this._params.activeClass);
143
+ }
144
+
145
+ if ($link) {
146
+ $link.classList.add(...this._params.activeClass);
147
+ }
148
+
149
+ execute(this._params.onActive, [$link, $section]);
150
+ }
151
+ }
152
+
153
+ removeCurrentActive(options = { ignore: null }) {
154
+ for (let i = 0; i < this.links.length; i++) {
155
+ let target = this.attributes(this.links[i], 'target'),
156
+ section = document.getElementById(target);
157
+
158
+ if ((options.ignore !== this.links[i]) && section) {
159
+ this.links[i].classList.remove(...this._params.activeClass);
160
+ section.classList.remove(...this._params.activeClass);
161
+ }
162
+ }
163
+ }
164
+
165
+ attributes(self, prop = '') {
166
+ let target = self.getAttribute('href') || self.dataset.vgTarget;
167
+
168
+ if (target !== 'undefined' && target.indexOf('#') !== -1) {
169
+ target = target.replace(/(^.+)#/gm, '');
170
+
171
+ if (target.indexOf('#') !== -1) {
172
+ target = target.replace('#', '');
173
+ }
174
+ } else if (target !== 'undefined' && target.indexOf('#') === -1) {
175
+ target = ''
176
+ }
177
+
178
+ let offset = self.dataset.vgOffset ? parseInt(self.dataset.vgOffset) : 0;
179
+ let text = self.innerHTML;
180
+
181
+ if (prop === 'target') return target;
182
+ if (prop === 'offset') return offset;
183
+ if (prop === 'text') return text;
184
+
185
+ return {
186
+ target: target,
187
+ offset: offset,
188
+ text: text
189
+ };
190
+ }
191
+ }
192
+
193
+ export default VGSpy;
@@ -0,0 +1,26 @@
1
+ $toast-map: (
2
+ indent: 1rem,
3
+ height: auto,
4
+ width: auto,
5
+ z-index: $toast-index,
6
+ transition: all .3s ease-in-out,
7
+ padding: 8px 22px,
8
+ font-size: 1.125rem,
9
+ background-color: $bg-color,
10
+ color: $color,
11
+ border-width: $border-width,
12
+ border-color: transparent,
13
+ border-style: $border-style,
14
+ border-radius: 20px,
15
+ box-shadow: $box-shadow,
16
+ header-font-weight: 500,
17
+ header-font-size: .975rem,
18
+ body-font-size: 1rem,
19
+ body-font-weight: 400,
20
+ );
21
+
22
+ $toast-danger-map: $danger-map;
23
+ $toast-success-map: $success-map;
24
+ $toast-warning-map: $warning-map;
25
+ $toast-info-map: $info-map;
26
+ $toast-dark-map: $dark-map;
@@ -0,0 +1,133 @@
1
+ @charset "UTF-8";
2
+ /**
3
+ *--------------------------------------------------------------------------
4
+ * Модуль: VGToast
5
+ * Автор: Vegas DEV
6
+ * Лицензия: смотри LICENSE
7
+ *--------------------------------------------------------------------------
8
+ **/
9
+ .vg-toast {
10
+ --vg-toast-indent: 1rem ;
11
+ --vg-toast-height: auto ;
12
+ --vg-toast-width: auto ;
13
+ --vg-toast-z-index: 1050 ;
14
+ --vg-toast-transition: all 0.3s ease-in-out ;
15
+ --vg-toast-padding: 8px 22px ;
16
+ --vg-toast-font-size: 1.125rem ;
17
+ --vg-toast-background-color: #fff ;
18
+ --vg-toast-color: #000000 ;
19
+ --vg-toast-border-width: 1px ;
20
+ --vg-toast-border-color: transparent ;
21
+ --vg-toast-border-style: solid ;
22
+ --vg-toast-border-radius: 20px ;
23
+ --vg-toast-box-shadow: 0 8px 14px 5px rgba(0, 0, 0, 0.2) ;
24
+ --vg-toast-header-font-weight: 500 ;
25
+ --vg-toast-header-font-size: 0.975rem ;
26
+ --vg-toast-body-font-size: 1rem ;
27
+ --vg-toast-body-font-weight: 400 ;
28
+ --vg-toast-danger-color: #58151c ;
29
+ --vg-toast-danger-border-color: #f1aeb5 ;
30
+ --vg-toast-danger-background-color: #f8d7da ;
31
+ --vg-toast-success-color: #0a3622 ;
32
+ --vg-toast-success-border-color: #a3cfbb ;
33
+ --vg-toast-success-background-color: #d1e7dd ;
34
+ --vg-toast-warning-color: #664d03 ;
35
+ --vg-toast-warning-border-color: #ffe69c ;
36
+ --vg-toast-warning-background-color: #fff3cd ;
37
+ --vg-toast-info-color: #055160 ;
38
+ --vg-toast-info-border-color: #9eeaf9 ;
39
+ --vg-toast-info-background-color: #cff4fc ;
40
+ --vg-toast-dark-color: #a7a7a7 ;
41
+ --vg-toast-dark-border-color: #0e0e0e ;
42
+ --vg-toast-dark-background-color: #070707 ;
43
+ position: fixed;
44
+ width: var(--vg-toast-width);
45
+ height: var(--vg-toast-height);
46
+ z-index: var(--vg-toast-z-index);
47
+ padding: var(--vg-toast-indent);
48
+ transition: var(--vg-toast-transition);
49
+ }
50
+ .vg-toast.bottom {
51
+ padding-top: 0;
52
+ }
53
+ .vg-toast.top {
54
+ padding-bottom: 0;
55
+ }
56
+ .vg-toast-danger {
57
+ --vg-toast-color: var(--vg-toast-danger-color);
58
+ --vg-toast-background-color: var(--vg-toast-danger-background-color);
59
+ --vg-toast-border-color: var(--vg-toast-danger-border-color);
60
+ }
61
+ .vg-toast-success {
62
+ --vg-toast-color: var(--vg-toast-success-color);
63
+ --vg-toast-background-color: var(--vg-toast-success-background-color);
64
+ --vg-toast-border-color: var(--vg-toast-success-border-color);
65
+ }
66
+ .vg-toast-warning {
67
+ --vg-toast-color: var(--vg-toast-warning-color);
68
+ --vg-toast-background-color: var(--vg-toast-warning-background-color);
69
+ --vg-toast-border-color: var(--vg-toast-warning-border-color);
70
+ }
71
+ .vg-toast-info {
72
+ --vg-toast-color: var(--vg-toast-info-color);
73
+ --vg-toast-background-color: var(--vg-toast-info-background-color);
74
+ --vg-toast-border-color: var(--vg-toast-info-border-color);
75
+ }
76
+ .vg-toast-dark {
77
+ --vg-toast-color: var(--vg-toast-dark-color);
78
+ --vg-toast-background-color: var(--vg-toast-dark-background-color);
79
+ --vg-toast-border-color: var(--vg-toast-dark-border-color);
80
+ }
81
+ .vg-toast:not(.show) {
82
+ display: none;
83
+ }
84
+ .vg-toast-wrapper {
85
+ background-color: var(--vg-toast-background-color);
86
+ padding: var(--vg-toast-padding);
87
+ color: var(--vg-toast-color);
88
+ border-width: var(--vg-toast-border-width);
89
+ border-style: var(--vg-toast-border-style);
90
+ border-color: var(--vg-toast-border-color);
91
+ border-radius: var(--vg-toast-border-radius);
92
+ box-shadow: var(--vg-toast-box-shadow);
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 8px;
96
+ }
97
+ .vg-toast-header {
98
+ font-size: var(--vg-toast-header-font-size);
99
+ font-weight: var(--vg-toast-header-font-weight);
100
+ }
101
+ .vg-toast-body {
102
+ font-size: var(--vg-toast-body-font-size);
103
+ font-weight: var(--vg-toast-body-font-weight);
104
+ }
105
+ .vg-toast-pointer {
106
+ cursor: pointer;
107
+ }
108
+ .vg-toast-button {
109
+ width: auto;
110
+ height: 100%;
111
+ display: flex;
112
+ align-items: center;
113
+ }
114
+ .vg-toast-button .vg-btn-close {
115
+ position: relative;
116
+ left: unset;
117
+ top: unset;
118
+ right: unset;
119
+ bottom: unset;
120
+ height: 100%;
121
+ display: flex;
122
+ align-items: center;
123
+ padding: 0;
124
+ }
125
+ .vg-toast-button .vg-btn-close svg {
126
+ width: 14px;
127
+ height: 14px;
128
+ }
129
+ .vg-toast-button .vg-btn-close svg polygon {
130
+ fill: var(--vg-toast-color);
131
+ }
132
+
133
+ /*# sourceMappingURL=vgtoast.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["vgtoast.scss","../../../utils/scss/mixin.scss"],"names":[],"mappings":";AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA;ECNG;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EDaF;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAGD;EACC;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGD;EACC;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;;AAGD;EACC;EACA;;AAGD;EACC;;AAGD;EACC;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;AAEA;EACC","file":"vgtoast.css"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ *--------------------------------------------------------------------------
3
+ * Модуль: VGToast
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-toast {
15
+ @include mix-vars('toast', $toast-map);
16
+ @include mix-vars('toast-danger', $toast-danger-map);
17
+ @include mix-vars('toast-success', $toast-success-map);
18
+ @include mix-vars('toast-warning', $toast-warning-map);
19
+ @include mix-vars('toast-info', $toast-info-map);
20
+ @include mix-vars('toast-dark', $toast-dark-map);
21
+ position: fixed;
22
+ width: var(--vg-toast-width);
23
+ height: var(--vg-toast-height);
24
+ z-index: var(--vg-toast-z-index);
25
+ padding: var(--vg-toast-indent);
26
+ transition: var(--vg-toast-transition);
27
+
28
+ &.bottom {
29
+ padding-top: 0;
30
+ }
31
+
32
+ &.top {
33
+ padding-bottom: 0;
34
+ }
35
+
36
+ &-danger {
37
+ --vg-toast-color: var(--vg-toast-danger-color);
38
+ --vg-toast-background-color: var(--vg-toast-danger-background-color);
39
+ --vg-toast-border-color: var(--vg-toast-danger-border-color);
40
+ }
41
+
42
+ &-success {
43
+ --vg-toast-color: var(--vg-toast-success-color);
44
+ --vg-toast-background-color: var(--vg-toast-success-background-color);
45
+ --vg-toast-border-color: var(--vg-toast-success-border-color);
46
+ }
47
+
48
+ &-warning {
49
+ --vg-toast-color: var(--vg-toast-warning-color);
50
+ --vg-toast-background-color: var(--vg-toast-warning-background-color);
51
+ --vg-toast-border-color: var(--vg-toast-warning-border-color);
52
+ }
53
+
54
+ &-info {
55
+ --vg-toast-color: var(--vg-toast-info-color);
56
+ --vg-toast-background-color: var(--vg-toast-info-background-color);
57
+ --vg-toast-border-color: var(--vg-toast-info-border-color);
58
+ }
59
+
60
+ &-dark {
61
+ --vg-toast-color: var(--vg-toast-dark-color);
62
+ --vg-toast-background-color: var(--vg-toast-dark-background-color);
63
+ --vg-toast-border-color: var(--vg-toast-dark-border-color);
64
+ }
65
+
66
+ &:not(.show) {
67
+ display: none;
68
+ }
69
+
70
+ &-wrapper {
71
+ background-color: var(--vg-toast-background-color);
72
+ padding: var(--vg-toast-padding);
73
+ color: var(--vg-toast-color);
74
+ border-width: var(--vg-toast-border-width);
75
+ border-style: var(--vg-toast-border-style);
76
+ border-color: var(--vg-toast-border-color);
77
+ border-radius: var(--vg-toast-border-radius);
78
+ box-shadow: var(--vg-toast-box-shadow);
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 8px;
82
+ }
83
+
84
+ &-header {
85
+ font-size: var(--vg-toast-header-font-size);
86
+ font-weight: var(--vg-toast-header-font-weight);
87
+ }
88
+
89
+ &-body {
90
+ font-size: var(--vg-toast-body-font-size);
91
+ font-weight: var(--vg-toast-body-font-weight);
92
+ }
93
+
94
+ &-pointer {
95
+ cursor: pointer;
96
+ }
97
+
98
+ &-button {
99
+ width: auto;
100
+ height: 100%;
101
+ display: flex;
102
+ align-items: center;
103
+
104
+ .vg-btn-close {
105
+ position: relative;
106
+ left: unset;
107
+ top: unset;
108
+ right: unset;
109
+ bottom: unset;
110
+ height: 100%;
111
+ display: flex;
112
+ align-items: center;
113
+ padding: 0;
114
+
115
+ svg {
116
+ width: 14px;
117
+ height: 14px;
118
+
119
+ polygon {
120
+ fill: var(--vg-toast-color);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
@@ -14,10 +14,12 @@ class Animation {
14
14
  in: 'animate__backInUp',
15
15
  out: 'animate__backOutUp',
16
16
  delay: 0,
17
+ duration: 800,
17
18
  }, params);
18
19
 
19
20
  this.classes = {
20
- animated: 'animate__animated'
21
+ animated: 'animate__animated',
22
+ duration: 'animate__duration-' + this._params.duration
21
23
  }
22
24
 
23
25
  if (!this._params.enable) return;
@@ -28,6 +30,7 @@ class Animation {
28
30
 
29
31
  if (!this._element.classList.contains(this.classes.animated)) {
30
32
  this._element.classList.add(this.classes.animated);
33
+ this._element.classList.add(this.classes.duration);
31
34
  }
32
35
 
33
36
  this._triggers();
@@ -1,8 +1,6 @@
1
1
  import {execute, mergeDeepObject} from "../functions";
2
2
 
3
3
  const TEMPLATES = [
4
- {type: 'collapse', template: ''},
5
- {type: 'modal', template: '<div class="vg-modal"></div>'},
6
4
  {type: 'pass-open', template: '<span data-vg-toggle="vgpass" class="[[classes]]" title="Показать / Скрыть" data-bs-toggle="tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M288 80c-65.2 0-118.8 29.6-159.9 67.7C89.6 183.5 63 226 49.4 256c13.6 30 40.2 72.5 78.6 108.3C169.2 402.4 222.8 432 288 432s118.8-29.6 159.9-67.7C486.4 328.5 513 286 526.6 256c-13.6-30-40.2-72.5-78.6-108.3C406.8 109.6 353.2 80 288 80zM95.4 112.6C142.5 68.8 207.2 32 288 32s145.5 36.8 192.6 80.6c46.8 43.5 78.1 95.4 93 131.1c3.3 7.9 3.3 16.7 0 24.6c-14.9 35.7-46.2 87.7-93 131.1C433.5 443.2 368.8 480 288 480s-145.5-36.8-192.6-80.6C48.6 356 17.3 304 2.5 268.3c-3.3-7.9-3.3-16.7 0-24.6C17.3 208 48.6 156 95.4 112.6zM288 336c44.2 0 80-35.8 80-80s-35.8-80-80-80c-.7 0-1.3 0-2 0c1.3 5.1 2 10.5 2 16c0 35.3-28.7 64-64 64c-5.5 0-10.9-.7-16-2c0 .7 0 1.3 0 2c0 44.2 35.8 80 80 80zm0-208a128 128 0 1 1 0 256 128 128 0 1 1 0-256z"/></svg></span>'},
7
5
  {type: 'pass-close', template: '<span data-vg-toggle="vgpass" class="[[classes]]" title="Показать / Скрыть" data-bs-toggle="tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zm151 118.3C226 97.7 269.5 80 320 80c65.2 0 118.8 29.6 159.9 67.7C518.4 183.5 545 226 558.6 256c-12.6 28-36.6 66.8-70.9 100.9l-53.8-42.2c9.1-17.6 14.2-37.5 14.2-58.7c0-70.7-57.3-128-128-128c-32.2 0-61.7 11.9-84.2 31.5l-46.1-36.1zM394.9 284.2l-81.5-63.9c4.2-8.5 6.6-18.2 6.6-28.3c0-5.5-.7-10.9-2-16c.7 0 1.3 0 2 0c44.2 0 80 35.8 80 80c0 9.9-1.8 19.4-5.1 28.2zm9.4 130.3C378.8 425.4 350.7 432 320 432c-65.2 0-118.8-29.6-159.9-67.7C121.6 328.5 95 286 81.4 256c8.3-18.4 21.5-41.5 39.4-64.8L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5l-41.9-33zM192 256c0 70.7 57.3 128 128 128c13.3 0 26.1-2 38.2-5.8L302 334c-23.5-5.4-43.1-21.2-53.7-42.3l-56.1-44.2c-.2 2.8-.3 5.6-.3 8.5z"/></svg></span>'},
8
6
  ]
@@ -19,8 +17,6 @@ class Templater {
19
17
  insert: 'afterend',
20
18
  classes: []
21
19
  }, params);
22
-
23
- this.templateBuild = null;
24
20
  }
25
21
 
26
22
  render(content, callback) {
@@ -4072,3 +4072,10 @@
4072
4072
  -webkit-animation-name: slideOutUp;
4073
4073
  animation-name: slideOutUp;
4074
4074
  }
4075
+
4076
+
4077
+ @for $i from 1 through 10 {
4078
+ .animate__duration-#{$i * 100} {
4079
+ --animate-duration: #{$i * 100}ms;
4080
+ }
4081
+ }