kmaterialize 2.0.0 → 2.3.3-1.0.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.
Files changed (150) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +55 -91
  3. package/components/appbar/_navbar.old.scss +223 -0
  4. package/components/appbar/appbar.css +235 -0
  5. package/components/appbar/appbar.mjs +54 -0
  6. package/components/appbar/appbar.test.mjs +9 -0
  7. package/components/atomic/atomic.mjs +19 -0
  8. package/components/atomic/component.mjs +67 -0
  9. package/components/badge/_badges.scss +75 -0
  10. package/components/badge/badge.mjs +11 -0
  11. package/components/breadcrumb/_breadcrumb.scss +27 -0
  12. package/components/button/_buttons.scss +352 -0
  13. package/components/button/button.mjs +11 -0
  14. package/components/button/buttons.stories.ts +150 -0
  15. package/components/button/buttons.ts +282 -0
  16. package/components/button/examples.iso.js +18 -0
  17. package/components/button/fabSpec.js +65 -0
  18. package/components/button/test-button.mjs +16 -0
  19. package/components/card/_cards.scss +229 -0
  20. package/components/card/card.mjs +10 -0
  21. package/components/card/cards.ts +185 -0
  22. package/components/card/cardsSpec.js +269 -0
  23. package/components/carousel/_carousel.scss +93 -0
  24. package/components/carousel/_slider.scss +119 -0
  25. package/components/carousel/carousel.ts +693 -0
  26. package/components/carousel/carouselSpec.js +61 -0
  27. package/components/carousel/slider.ts +431 -0
  28. package/components/carousel/sliderSpec.js +99 -0
  29. package/components/checkbox/_checkboxes.scss +281 -0
  30. package/components/checkbox/checkbox.mdx +24 -0
  31. package/components/checkbox/checkbox.stories.ts +120 -0
  32. package/components/chip/chip.mjs +37 -0
  33. package/components/chip/chip.test.mjs +10 -0
  34. package/components/chip/chips.css +126 -0
  35. package/components/chip/chips.mdx +33 -0
  36. package/components/chip/chips.ts +440 -0
  37. package/components/chip/chipsSpec.js +165 -0
  38. package/components/chip/readme.md +323 -0
  39. package/components/collapsible/_collapsible.scss +82 -0
  40. package/components/collapsible/collapsible.ts +230 -0
  41. package/components/collapsible/collapsibleSpec.js +240 -0
  42. package/components/datepicker/_datepicker.scss +268 -0
  43. package/components/datepicker/datepicker.ts +1450 -0
  44. package/components/datepicker/datepickerSpec.js +162 -0
  45. package/components/dialog/_materialbox.scss +42 -0
  46. package/components/dialog/_modal.scss +79 -0
  47. package/components/dialog/materialbox.ts +446 -0
  48. package/components/dialog/materialboxSpec.js +37 -0
  49. package/components/dialog/modal.ts +111 -0
  50. package/components/dialog/modalSpec.js +83 -0
  51. package/components/dialog/readme.md +5 -0
  52. package/components/divider/readme.md +15 -0
  53. package/components/dropdown/_dropdown.scss +83 -0
  54. package/components/dropdown/dropdown.ts +653 -0
  55. package/components/dropdown/dropdownSpec.js +108 -0
  56. package/components/list/_collection.scss +114 -0
  57. package/components/list/_list.scss +6 -0
  58. package/components/list/list.mjs +58 -0
  59. package/components/list/list.test.mjs +16 -0
  60. package/components/loading/loading.mjs +26 -0
  61. package/components/loading/loading.test.mjs +10 -0
  62. package/components/navigation-bar/_old +582 -0
  63. package/components/navigation-bar/navigation-bar.mdx +20 -0
  64. package/components/navigation-bar/navigation-bar.stories.ts +39 -0
  65. package/components/navigation-drawer/_sidenav.scss +247 -0
  66. package/components/navigation-drawer/sidenav.ts +546 -0
  67. package/components/navigation-drawer/sidenavSpec.js +124 -0
  68. package/components/pagination/_pagination.scss +47 -0
  69. package/components/progress/_preloader.scss +416 -0
  70. package/components/radio-button/_radio-buttons.scss +112 -0
  71. package/components/radio-button/radio-buttons.mdx +28 -0
  72. package/components/radio-button/radio-buttons.stories.ts +51 -0
  73. package/components/search/autocomplete.ts +620 -0
  74. package/components/search/autocompleteSpec.js +321 -0
  75. package/components/slider/_range.scss +157 -0
  76. package/components/slider/range.ts +216 -0
  77. package/components/snackbar/_toast.scss +68 -0
  78. package/components/snackbar/toastSpec.js +132 -0
  79. package/components/snackbar/toasts.ts +312 -0
  80. package/components/switch/_switches.scss +121 -0
  81. package/components/tabs/_tabs.scss +171 -0
  82. package/components/tabs/tabs.mjs +31 -0
  83. package/components/tabs/tabs.ts +358 -0
  84. package/components/tabs/tabsSpec.js +180 -0
  85. package/components/textfield/_file-input.scss +41 -0
  86. package/components/textfield/_input-fields.scss +368 -0
  87. package/components/textfield/_select.scss +104 -0
  88. package/components/textfield/formfields.css +311 -0
  89. package/components/textfield/forms.ts +182 -0
  90. package/components/textfield/formsSpec.js +142 -0
  91. package/components/textfield/select.ts +472 -0
  92. package/components/textfield/selectSpec.js +390 -0
  93. package/components/textfield/textfield.mjs +29 -0
  94. package/components/textfield/textfield.test.mjs +10 -0
  95. package/components/timepicker/_timepicker.scss +362 -0
  96. package/components/timepicker/timepicker.ts +905 -0
  97. package/components/tooltip/_tooltip.scss +40 -0
  98. package/components/tooltip/tooltip.ts +380 -0
  99. package/components/tooltip/tooltipSpec.js +145 -0
  100. package/dist/css/materialize.colors.min.css +6 -0
  101. package/dist/css/materialize.css +7578 -6326
  102. package/dist/css/materialize.min.css +6 -13
  103. package/dist/css/materialize.min.css.map +1 -0
  104. package/dist/js/materialize.cjs.js +8410 -0
  105. package/dist/js/materialize.d.ts +2625 -0
  106. package/dist/js/materialize.js +8415 -12374
  107. package/dist/js/materialize.min.js +6 -6
  108. package/dist/js/materialize.mjs +8382 -0
  109. package/package.json +82 -47
  110. package/sass/_colors.scss +417 -0
  111. package/sass/_global.scss +490 -0
  112. package/sass/_grid.scss +172 -0
  113. package/sass/_table_of_contents.scss +28 -0
  114. package/sass/_tapTarget.scss +102 -0
  115. package/sass/_typography.scss +58 -0
  116. package/sass/_variables.scss +56 -0
  117. package/sass/materialize.scss +51 -0
  118. package/sass/mixins.module.scss +168 -0
  119. package/extras/noUiSlider/nouislider.css +0 -406
  120. package/extras/noUiSlider/nouislider.js +0 -2147
  121. package/extras/noUiSlider/nouislider.min.js +0 -1
  122. package/js/anime.min.js +0 -34
  123. package/js/autocomplete.js +0 -448
  124. package/js/buttons.js +0 -354
  125. package/js/cards.js +0 -40
  126. package/js/carousel.js +0 -717
  127. package/js/cash.js +0 -960
  128. package/js/characterCounter.js +0 -136
  129. package/js/chips.js +0 -481
  130. package/js/collapsible.js +0 -275
  131. package/js/component.js +0 -44
  132. package/js/datepicker.js +0 -975
  133. package/js/dropdown.js +0 -635
  134. package/js/forms.js +0 -275
  135. package/js/global.js +0 -444
  136. package/js/materialbox.js +0 -453
  137. package/js/modal.js +0 -382
  138. package/js/parallax.js +0 -138
  139. package/js/pushpin.js +0 -148
  140. package/js/range.js +0 -263
  141. package/js/scrollspy.js +0 -295
  142. package/js/select.js +0 -450
  143. package/js/sidenav.js +0 -580
  144. package/js/slider.js +0 -359
  145. package/js/tabs.js +0 -402
  146. package/js/tapTarget.js +0 -314
  147. package/js/timepicker.js +0 -647
  148. package/js/toasts.js +0 -310
  149. package/js/tooltip.js +0 -303
  150. package/js/waves.js +0 -335
@@ -0,0 +1,61 @@
1
+ describe('Carousel', () => {
2
+ const fixture = `<div class="carousel carousel-slider" id="slider-no-wrap">
3
+ <div class="carousel-item">
4
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
5
+ </div>
6
+ <div class="carousel-item">
7
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
8
+ </div>
9
+ <div class="carousel-item">
10
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
11
+ </div>
12
+ <div class="carousel-item">
13
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
14
+ </div>
15
+ </div>`;
16
+
17
+ beforeEach(() => XloadHtml(fixture));
18
+ afterEach(() => XunloadFixtures());
19
+
20
+ describe('carousel plugin', () => {
21
+ afterEach(() => {
22
+ M.Carousel.getInstance(document.querySelector('.carousel')).destroy();
23
+ });
24
+
25
+ it('No wrap next and prev should not overflow', (done) => {
26
+ const noWrap = M.Carousel.init(document.querySelector('#slider-no-wrap'), {
27
+ duration: 10,
28
+ noWrap: true
29
+ });
30
+ noWrap.prev();
31
+ expect(noWrap.center).toEqual(0, 'Prev should do nothing');
32
+
33
+ noWrap.set(3);
34
+ setTimeout(() => {
35
+ expect(noWrap.center).toEqual(3);
36
+
37
+ noWrap.next();
38
+ setTimeout(() => {
39
+ expect(noWrap.center).toEqual(3, 'Next should do nothing');
40
+ done();
41
+ }, 30);
42
+ }, 50);
43
+ });
44
+
45
+ it('should change index and focus its respective item on indicator click', (done) => {
46
+ const carousel = M.Carousel.init(document.querySelector('.carousel'), {
47
+ duration: 10,
48
+ indicators: true
49
+ });
50
+
51
+ document.querySelectorAll('.indicator-item')[1].click();
52
+ setTimeout(() => {
53
+ expect(carousel.center).toEqual(
54
+ 1,
55
+ 'carousel item was not visible after indicator interaction'
56
+ );
57
+ done();
58
+ }, 30);
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,431 @@
1
+ import { Utils } from '../../src/utils';
2
+ import { Component, BaseOptions, InitElements, MElement } from '../../src/component';
3
+
4
+ export interface SliderOptions extends BaseOptions {
5
+ /**
6
+ * Set to false to hide slide indicators.
7
+ * @default true
8
+ */
9
+ indicators: boolean;
10
+ /**
11
+ * Set height of slider.
12
+ * @default 400
13
+ */
14
+ height: number;
15
+ /**
16
+ * Set the duration of the transition animation in ms.
17
+ * @default 500
18
+ */
19
+ duration: number;
20
+ /**
21
+ * Set the duration between transitions in ms.
22
+ * @default 6000
23
+ */
24
+ interval: number;
25
+ /**
26
+ * If slider should pause when keyboard focus is received.
27
+ * @default true
28
+ */
29
+ pauseOnFocus: boolean;
30
+ /**
31
+ * If slider should pause when is hovered by a pointer.
32
+ * @default true
33
+ */
34
+ pauseOnHover: boolean;
35
+ /**
36
+ * Optional function used to generate ARIA label to indicators (for accessibility purposes).
37
+ * @param index Current index, starting from "1".
38
+ * @param current A which indicates whether it is the current element or not
39
+ * @returns a string to be used as label indicator.
40
+ * @default null
41
+ */
42
+ indicatorLabelFunc: (index: number, current: boolean) => string;
43
+ }
44
+
45
+ const _defaults: SliderOptions = {
46
+ indicators: true,
47
+ height: 400,
48
+ duration: 500,
49
+ interval: 6000,
50
+ pauseOnFocus: true,
51
+ pauseOnHover: true,
52
+ indicatorLabelFunc: null // Function which will generate a label for the indicators (ARIA)
53
+ };
54
+
55
+ export class Slider extends Component<SliderOptions> {
56
+ /** Index of current slide. */
57
+ activeIndex: number;
58
+ interval: string | number | NodeJS.Timeout;
59
+ eventPause: boolean;
60
+ _slider: HTMLUListElement;
61
+ _slides: HTMLLIElement[];
62
+ _activeSlide: HTMLLIElement;
63
+ _indicators: HTMLLIElement[];
64
+ _hovered: boolean;
65
+ _focused: boolean;
66
+ _focusCurrent: boolean;
67
+ _sliderId: string;
68
+
69
+ constructor(el: HTMLElement, options: Partial<SliderOptions>) {
70
+ super(el, options, Slider);
71
+ this.el['M_Slider'] = this;
72
+
73
+ this.options = {
74
+ ...Slider.defaults,
75
+ ...options
76
+ };
77
+
78
+ // init props
79
+ this.interval = null;
80
+ this.eventPause = false;
81
+ this._hovered = false;
82
+ this._focused = false;
83
+ this._focusCurrent = false;
84
+
85
+ // setup
86
+ this._slider = this.el.querySelector('.slides');
87
+ this._slides = Array.from(this._slider.querySelectorAll('li'));
88
+ this.activeIndex = this._slides.findIndex((li) => li.classList.contains('active'));
89
+
90
+ if (this.activeIndex !== -1) {
91
+ this._activeSlide = this._slides[this.activeIndex];
92
+ }
93
+
94
+ this._setSliderHeight();
95
+
96
+ // Sets element id if it does not have one
97
+ if (this._slider.hasAttribute('id')) this._sliderId = this._slider.getAttribute('id');
98
+ else {
99
+ this._sliderId = 'slider-' + Utils.guid();
100
+ this._slider.setAttribute('id', this._sliderId);
101
+ }
102
+
103
+ const placeholderBase64 =
104
+ 'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
105
+ // Set initial positions of captions
106
+ this._slides.forEach((slide) => {
107
+ // Caption
108
+ //const caption = <HTMLElement|null>slide.querySelector('.caption');
109
+ //if (caption) this._animateCaptionIn(caption, 0);
110
+ // Set Images as Background Images
111
+ const img = slide.querySelector('img');
112
+ if (img) {
113
+ if (img.src !== placeholderBase64) {
114
+ img.style.backgroundImage = 'url(' + img.src + ')';
115
+ img.src = placeholderBase64;
116
+ }
117
+ }
118
+ // Sets slide as focusable by code
119
+ if (!slide.hasAttribute('tabindex')) slide.setAttribute('tabindex', '-1');
120
+ // Removes initial visibility from "inactive" slides
121
+ slide.style.visibility = 'hidden';
122
+ });
123
+
124
+ this._setupIndicators();
125
+
126
+ // Show active slide
127
+ if (this._activeSlide) {
128
+ this._activeSlide.style.display = 'block';
129
+ this._activeSlide.style.visibility = 'visible';
130
+ } else {
131
+ this.activeIndex = 0;
132
+ this._slides[0].classList.add('active');
133
+ this._slides[0].style.visibility = 'visible';
134
+ this._activeSlide = this._slides[0];
135
+ this._animateSlide(this._slides[0], true);
136
+ // Update indicators
137
+ if (this.options.indicators) {
138
+ this._indicators[this.activeIndex].children[0].classList.add('active');
139
+ }
140
+ }
141
+ this._setupEventHandlers();
142
+ // auto scroll
143
+ this.start();
144
+ }
145
+
146
+ static get defaults() {
147
+ return _defaults;
148
+ }
149
+
150
+ /**
151
+ * Initializes instance of Slider.
152
+ * @param el HTML element.
153
+ * @param options Component options.
154
+ */
155
+ static init(el: HTMLElement, options?: Partial<SliderOptions>): Slider;
156
+ /**
157
+ * Initializes instances of Slider.
158
+ * @param els HTML elements.
159
+ * @param options Component options.
160
+ */
161
+ static init(els: InitElements<MElement>, options?: Partial<SliderOptions>): Slider[];
162
+ /**
163
+ * Initializes instances of Slider.
164
+ * @param els HTML elements.
165
+ * @param options Component options.
166
+ */
167
+ static init(
168
+ els: HTMLElement | InitElements<MElement>,
169
+ options: Partial<SliderOptions> = {}
170
+ ): Slider | Slider[] {
171
+ return super.init(els, options, Slider);
172
+ }
173
+
174
+ static getInstance(el: HTMLElement): Slider {
175
+ return el['M_Slider'];
176
+ }
177
+
178
+ destroy() {
179
+ this.pause();
180
+ this._removeIndicators();
181
+ this._removeEventHandlers();
182
+ this.el['M_Slider'] = undefined;
183
+ }
184
+
185
+ private _setupEventHandlers() {
186
+ if (this.options.pauseOnFocus) {
187
+ this.el.addEventListener('focusin', this._handleAutoPauseFocus);
188
+ this.el.addEventListener('focusout', this._handleAutoStartFocus);
189
+ }
190
+ if (this.options.pauseOnHover) {
191
+ this.el.addEventListener('mouseenter', this._handleAutoPauseHover);
192
+ this.el.addEventListener('mouseleave', this._handleAutoStartHover);
193
+ }
194
+ if (this.options.indicators) {
195
+ this._indicators.forEach((el) => {
196
+ el.addEventListener('click', this._handleIndicatorClick);
197
+ });
198
+ }
199
+ }
200
+
201
+ private _removeEventHandlers() {
202
+ if (this.options.pauseOnFocus) {
203
+ this.el.removeEventListener('focusin', this._handleAutoPauseFocus);
204
+ this.el.removeEventListener('focusout', this._handleAutoStartFocus);
205
+ }
206
+ if (this.options.pauseOnHover) {
207
+ this.el.removeEventListener('mouseenter', this._handleAutoPauseHover);
208
+ this.el.removeEventListener('mouseleave', this._handleAutoStartHover);
209
+ }
210
+ if (this.options.indicators) {
211
+ this._indicators.forEach((el) => {
212
+ el.removeEventListener('click', this._handleIndicatorClick);
213
+ });
214
+ }
215
+ }
216
+
217
+ private _handleIndicatorClick = (e: MouseEvent) => {
218
+ const el = (<HTMLElement>e.target).parentElement;
219
+ const currIndex = [...el.parentNode.children].indexOf(el);
220
+ this._focusCurrent = true;
221
+ this.set(currIndex);
222
+ };
223
+
224
+ private _handleAutoPauseHover = () => {
225
+ this._hovered = true;
226
+ if (this.interval != null) {
227
+ this._pause(true);
228
+ }
229
+ };
230
+
231
+ private _handleAutoPauseFocus = () => {
232
+ this._focused = true;
233
+ if (this.interval != null) {
234
+ this._pause(true);
235
+ }
236
+ };
237
+
238
+ private _handleAutoStartHover = () => {
239
+ this._hovered = false;
240
+ if (!(this.options.pauseOnFocus && this._focused) && this.eventPause) {
241
+ this.start();
242
+ }
243
+ };
244
+
245
+ private _handleAutoStartFocus = () => {
246
+ this._focused = false;
247
+ if (!(this.options.pauseOnHover && this._hovered) && this.eventPause) {
248
+ this.start();
249
+ }
250
+ };
251
+
252
+ private _handleInterval = () => {
253
+ const activeElem = this._slider.querySelector('.active');
254
+ let newActiveIndex = [...activeElem.parentNode.children].indexOf(activeElem);
255
+ if (this._slides.length === newActiveIndex + 1) newActiveIndex = 0; // loop to start
256
+ else newActiveIndex += 1;
257
+ this.set(newActiveIndex);
258
+ };
259
+
260
+ private _animateSlide(slide: HTMLElement, isDirectionIn: boolean): void {
261
+ let dx = 0,
262
+ dy = 0;
263
+ // from
264
+ slide.style.opacity = isDirectionIn ? '0' : '1';
265
+ setTimeout(() => {
266
+ slide.style.transition = `opacity ${this.options.duration}ms ease`;
267
+ // to
268
+ slide.style.opacity = isDirectionIn ? '1' : '0';
269
+ }, 1);
270
+ // Caption
271
+ const caption: HTMLElement = slide.querySelector('.caption');
272
+ if (!caption) return;
273
+ if (caption.classList.contains('center-align')) dy = -100;
274
+ else if (caption.classList.contains('right-align')) dx = 100;
275
+ else if (caption.classList.contains('left-align')) dx = -100;
276
+ // from
277
+ caption.style.opacity = isDirectionIn ? '0' : '1';
278
+ caption.style.transform = isDirectionIn ? `translate(${dx}px, ${dy}px)` : `translate(0, 0)`;
279
+ setTimeout(() => {
280
+ caption.style.transition = `opacity ${this.options.duration}ms ease, transform ${this.options.duration}ms ease`;
281
+ // to
282
+ caption.style.opacity = isDirectionIn ? '1' : '0';
283
+ caption.style.transform = isDirectionIn ? `translate(0, 0)` : `translate(${dx}px, ${dy}px)`;
284
+ }, this.options.duration); // delay
285
+ }
286
+
287
+ private _setSliderHeight() {
288
+ // If fullscreen, do nothing
289
+ if (!this.el.classList.contains('fullscreen')) {
290
+ if (this.options.indicators) {
291
+ // Add height if indicators are present
292
+ this.el.style.height = this.options.height + 40 + 'px'; //.css('height', this.options.height + 40 + 'px');
293
+ } else {
294
+ this.el.style.height = this.options.height + 'px';
295
+ }
296
+ this._slider.style.height = this.options.height + 'px';
297
+ }
298
+ }
299
+
300
+ private _setupIndicators() {
301
+ if (this.options.indicators) {
302
+ const ul = document.createElement('ul');
303
+ ul.classList.add('indicators');
304
+
305
+ const arrLi = [];
306
+ this._slides.forEach((el, i) => {
307
+ const label = this.options.indicatorLabelFunc
308
+ ? this.options.indicatorLabelFunc.call(this, i + 1, i === 0)
309
+ : `${i + 1}`;
310
+ const li = document.createElement('li');
311
+ li.classList.add('indicator-item');
312
+ li.innerHTML = `<button type="button" class="indicator-item-btn" aria-label="${label}" aria-controls="${this._sliderId}"></button>`;
313
+ arrLi.push(li);
314
+ ul.append(li);
315
+ });
316
+
317
+ this.el.append(ul);
318
+ this._indicators = arrLi;
319
+ }
320
+ }
321
+
322
+ private _removeIndicators() {
323
+ this.el.querySelector('ul.indicators').remove(); //find('ul.indicators').remove();
324
+ }
325
+
326
+ set(index: number) {
327
+ // Wrap around indices.
328
+ if (index >= this._slides.length) index = 0;
329
+ else if (index < 0) index = this._slides.length - 1;
330
+
331
+ // Only do if index changes
332
+ if (this.activeIndex === index) return;
333
+
334
+ this._activeSlide = this._slides[this.activeIndex];
335
+ const _caption = <HTMLElement | null>this._activeSlide.querySelector('.caption');
336
+
337
+ this._activeSlide.classList.remove('active');
338
+ // Enables every slide
339
+ this._slides.forEach((slide) => (slide.style.visibility = 'visible'));
340
+
341
+ //--- Hide active Slide + Caption
342
+ this._activeSlide.style.opacity = '0';
343
+ setTimeout(() => {
344
+ this._slides.forEach((slide) => {
345
+ if (slide.classList.contains('active')) return;
346
+ slide.style.opacity = '0';
347
+ slide.style.transform = 'translate(0, 0)';
348
+ // Disables invisible slides (for assistive technologies)
349
+ slide.style.visibility = 'hidden';
350
+ });
351
+ }, this.options.duration);
352
+
353
+ // Hide active Caption
354
+ //this._animateCaptionIn(_caption, this.options.duration);
355
+ _caption.style.opacity = '0';
356
+
357
+ // Update indicators
358
+ if (this.options.indicators) {
359
+ const activeIndicator = this._indicators[this.activeIndex].children[0];
360
+ const nextIndicator = this._indicators[index].children[0];
361
+ activeIndicator.classList.remove('active');
362
+ nextIndicator.classList.add('active');
363
+ if (typeof this.options.indicatorLabelFunc === 'function') {
364
+ activeIndicator.ariaLabel = this.options.indicatorLabelFunc.call(
365
+ this,
366
+ this.activeIndex,
367
+ false
368
+ );
369
+ nextIndicator.ariaLabel = this.options.indicatorLabelFunc.call(this, index, true);
370
+ }
371
+ }
372
+
373
+ //--- Show new Slide + Caption
374
+ this._animateSlide(this._slides[index], true);
375
+ this._slides[index].classList.add('active');
376
+ this.activeIndex = index;
377
+
378
+ // Reset interval, if allowed. This check prevents autostart
379
+ // when slider is paused, since it can be changed though indicators.
380
+ if (this.interval != null) {
381
+ this.start();
382
+ }
383
+ }
384
+
385
+ _pause(fromEvent: boolean) {
386
+ clearInterval(this.interval);
387
+ this.eventPause = fromEvent;
388
+ this.interval = null;
389
+ }
390
+
391
+ /**
392
+ * Pause slider autoslide.
393
+ */
394
+ pause = () => {
395
+ this._pause(false);
396
+ };
397
+
398
+ /**
399
+ * Start slider autoslide.
400
+ */
401
+ start = () => {
402
+ clearInterval(this.interval);
403
+ this.interval = setInterval(
404
+ this._handleInterval,
405
+ this.options.duration + this.options.interval
406
+ );
407
+ this.eventPause = false;
408
+ };
409
+
410
+ /**
411
+ * Move to next slider.
412
+ */
413
+ next = () => {
414
+ let newIndex = this.activeIndex + 1;
415
+ // Wrap around indices.
416
+ if (newIndex >= this._slides.length) newIndex = 0;
417
+ else if (newIndex < 0) newIndex = this._slides.length - 1;
418
+ this.set(newIndex);
419
+ };
420
+
421
+ /**
422
+ * Move to prev slider.
423
+ */
424
+ prev = () => {
425
+ let newIndex = this.activeIndex - 1;
426
+ // Wrap around indices.
427
+ if (newIndex >= this._slides.length) newIndex = 0;
428
+ else if (newIndex < 0) newIndex = this._slides.length - 1;
429
+ this.set(newIndex);
430
+ };
431
+ }
@@ -0,0 +1,99 @@
1
+ describe('Slider Plugin:', () => {
2
+ const fixture = `<div class="slider simple-slider">
3
+ <ul class="slides">
4
+ <li>
5
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="First slide">
6
+ <div class="caption center-align">
7
+ <h3>This is our big Tagline!</h3>
8
+ <h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
9
+ </div>
10
+ </li>
11
+ <li>
12
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Second slide">
13
+ <div class="caption left-align">
14
+ <h3>Left Aligned Caption</h3>
15
+ <h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
16
+ </div>
17
+ </li>
18
+ <li>
19
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Third slide">
20
+ <div class="caption right-align">
21
+ <h3>Right Aligned Caption</h3>
22
+ <h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
23
+ </div>
24
+ </li>
25
+ <li>
26
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Fourth slide">
27
+ <div class="caption center-align">
28
+ <h3>This is our big Tagline!</h3>
29
+ <h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
30
+ </div>
31
+ </li>
32
+ </ul>
33
+ </div>`;
34
+
35
+ beforeEach(() => XloadHtml(fixture));
36
+ afterEach(() => XunloadFixtures());
37
+
38
+ describe('Slider:', () => {
39
+ let slider;
40
+
41
+ beforeEach(() => {
42
+ slider = M.Slider.init(document.querySelector('.slider'), {
43
+ interval: 100,
44
+ duration: 0, // transition
45
+ pauseOnFocus: true,
46
+ indicatorLabelFunc: (idx) => 'Slide ' + idx
47
+ });
48
+ });
49
+
50
+ afterEach(() => {
51
+ if (slider) slider.destroy();
52
+ slider = null;
53
+ });
54
+
55
+ it('should change after first interval', (done) => {
56
+ const O_INDEX = slider.activeIndex;
57
+ setTimeout(() => {
58
+ expect(slider.activeIndex).not.toBe(O_INDEX);
59
+ done();
60
+ }, 150);
61
+ });
62
+
63
+ it('should not change if paused', (done) => {
64
+ const O_INDEX = slider.activeIndex;
65
+ slider.pause();
66
+ setTimeout(() => {
67
+ expect(slider.activeIndex).toBe(O_INDEX);
68
+ done();
69
+ }, 200);
70
+ });
71
+
72
+ it('should not change if focused', (done) => {
73
+ const O_INDEX = slider.activeIndex;
74
+ slider.start();
75
+ slider.el.dispatchEvent(new Event('focusin'));
76
+ //focus(slider.el);
77
+ setTimeout(() => {
78
+ expect(slider.eventPause).toBe(true);
79
+ expect(slider.activeIndex).toBe(O_INDEX);
80
+ done();
81
+ }, 150);
82
+ });
83
+
84
+ it("start with 'Slide ' in indicators labels ", () => {
85
+ expect(
86
+ Array.from(document.querySelectorAll('button')).map((btn) =>
87
+ btn.getAttribute('aria-label').startsWith('Slide ')
88
+ )
89
+ ).toEqual([true, true, true, true]);
90
+ });
91
+
92
+ it('should change index and focus its respective item on indicator click', () => {
93
+ const IDX = 2;
94
+ document.querySelectorAll('button')[IDX].click();
95
+ expect(slider.activeIndex).toBe(IDX);
96
+ //expect(document.activeElement).toBe(document.querySelectorAll(".slides > li")[IDX]);
97
+ });
98
+ });
99
+ });