@materializecss/materialize 2.0.0-alpha → 2.0.2-alpha

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 (46) hide show
  1. package/Gruntfile.js +7 -4
  2. package/README.md +24 -12
  3. package/dist/css/materialize.css +90 -86
  4. package/dist/css/materialize.min.css +2 -2
  5. package/dist/js/materialize.js +2869 -2764
  6. package/dist/js/materialize.min.js +2 -2
  7. package/dist/js/materialize.min.js.map +1 -1
  8. package/package.json +1 -1
  9. package/sass/components/_collapsible.scss +0 -41
  10. package/sass/components/_global.scss +3 -2
  11. package/sass/components/_icons-material-design.scss +2 -1
  12. package/sass/components/_navbar.scss +6 -3
  13. package/sass/components/_sidenav.scss +66 -37
  14. package/sass/components/_theme_variables.scss +98 -0
  15. package/sass/components/_typography.scss +2 -2
  16. package/sass/components/forms/_input-fields.scss +4 -10
  17. package/sass/materialize.scss +0 -4
  18. package/src/autocomplete.ts +188 -94
  19. package/src/buttons.ts +225 -260
  20. package/src/cards.ts +5 -6
  21. package/src/carousel.ts +611 -542
  22. package/src/characterCounter.ts +50 -21
  23. package/src/chips.ts +152 -63
  24. package/src/collapsible.ts +97 -32
  25. package/src/component.ts +99 -10
  26. package/src/datepicker.ts +905 -726
  27. package/src/dropdown.ts +576 -484
  28. package/src/edges.ts +4 -4
  29. package/src/forms.ts +17 -14
  30. package/src/global.ts +56 -325
  31. package/src/materialbox.ts +354 -298
  32. package/src/modal.ts +296 -211
  33. package/src/parallax.ts +129 -105
  34. package/src/pushpin.ts +148 -103
  35. package/src/range.ts +166 -150
  36. package/src/scrollspy.ts +214 -174
  37. package/src/select.ts +434 -398
  38. package/src/sidenav.ts +447 -381
  39. package/src/slider.ts +421 -362
  40. package/src/tabs.ts +284 -227
  41. package/src/tapTarget.ts +246 -213
  42. package/src/timepicker.ts +738 -614
  43. package/src/toasts.ts +254 -230
  44. package/src/tooltip.ts +315 -252
  45. package/src/utils.ts +271 -0
  46. package/src/waves.ts +10 -10
package/src/carousel.ts CHANGED
@@ -1,607 +1,676 @@
1
- import { Component } from "./component";
2
- import { M } from "./global";
3
-
4
- let _defaults = {
5
- duration: 200, // ms
6
- dist: -100, // zoom scale TODO: make this more intuitive as an option
7
- shift: 0, // spacing for center image
8
- padding: 0, // Padding between non center items
9
- numVisible: 5, // Number of visible items in carousel
10
- fullWidth: false, // Change to full width styles
11
- indicators: false, // Toggle indicators
12
- noWrap: false, // Don't wrap around and cycle through items.
13
- onCycleTo: null // Callback for when a new slide is cycled to.
14
- };
15
-
16
- export class Carousel extends Component {
17
- el: HTMLElement;
18
- hasMultipleSlides: boolean;
19
- showIndicators: boolean;
20
- noWrap: any;
21
- pressed: boolean;
22
- dragged: boolean;
23
- offset: number;
24
- target: number;
25
- images: HTMLElement[];
26
- itemWidth: any;
27
- itemHeight: any;
28
- dim: number;
29
- _autoScrollBound: any;
30
- _trackBound: any;
31
- _indicators: any;
32
- count: number;
33
- xform: string;
34
- private _handleCarouselTapBound: any;
35
- private _handleCarouselDragBound: any;
36
- private _handleCarouselReleaseBound: any;
37
- private _handleCarouselClickBound: any;
38
- _handleIndicatorClickBound: any;
39
- _handleThrottledResizeBound: any;
40
- verticalDragged: boolean;
41
- reference: any;
42
- referenceY: any;
43
- velocity: number;
44
- frame: number;
45
- timestamp: number;
46
- ticker: NodeJS.Timer;
47
- amplitude: number;
48
- center: number = 0;
49
- imageHeight: any;
50
- scrollingTimeout: any;
51
- oneTimeCallback: any;
52
-
53
- constructor(el: Element, options: Object) {
54
- super(Carousel, el, options);
55
- (this.el as any).M_Carousel = this;
56
- this.options = {...Carousel.defaults, ...options};
57
-
58
- // Setup
59
- this.hasMultipleSlides = this.el.querySelectorAll('.carousel-item').length > 1;
60
- this.showIndicators = this.options.indicators && this.hasMultipleSlides;
61
- this.noWrap = this.options.noWrap || !this.hasMultipleSlides;
62
- this.pressed = false;
63
- this.dragged = false;
64
- this.offset = this.target = 0;
65
- this.images = [];
66
- this.itemWidth = this.el.querySelector('.carousel-item').clientWidth;
67
- this.itemHeight = this.el.querySelector('.carousel-item').clientHeight;
68
- this.dim = this.itemWidth * 2 + this.options.padding || 1; // Make sure dim is non zero for divisions.
69
- this._autoScrollBound = this._autoScroll.bind(this);
70
- this._trackBound = this._track.bind(this);
1
+ import { Utils } from "./utils";
2
+ import { Component, BaseOptions, InitElements, MElement } from "./component";
3
+
4
+ export interface CarouselOptions extends BaseOptions{
5
+ /**
6
+ * Transition duration in milliseconds.
7
+ * @default 200
8
+ */
9
+ duration: number;
10
+ /**
11
+ * Perspective zoom. If 0, all items are the same size.
12
+ * @default -100
13
+ */
14
+ dist: number;
15
+ /**
16
+ * Set the spacing of the center item.
17
+ * @default 0
18
+ */
19
+ shift: number;
20
+ /**
21
+ * Set the padding between non center items.
22
+ * @default 0
23
+ */
24
+ padding: number;
25
+ /**
26
+ * Set the number of visible items.
27
+ * @default 5
28
+ */
29
+ numVisible: number;
30
+ /**
31
+ * Make the carousel a full width slider like the second example.
32
+ * @default false
33
+ */
34
+ fullWidth: boolean;
35
+ /**
36
+ * Set to true to show indicators.
37
+ * @default false
38
+ */
39
+ indicators: boolean;
40
+ /**
41
+ * Don't wrap around and cycle through items.
42
+ * @default false
43
+ */
44
+ noWrap: boolean;
45
+ /**
46
+ * Callback for when a new slide is cycled to.
47
+ * @default null
48
+ */
49
+ onCycleTo: (current: Element, dragged: boolean) => void;
50
+ }
51
+
52
+ let _defaults: CarouselOptions = {
53
+ duration: 200, // ms
54
+ dist: -100, // zoom scale TODO: make this more intuitive as an option
55
+ shift: 0, // spacing for center image
56
+ padding: 0, // Padding between non center items
57
+ numVisible: 5, // Number of visible items in carousel
58
+ fullWidth: false, // Change to full width styles
59
+ indicators: false, // Toggle indicators
60
+ noWrap: false, // Don't wrap around and cycle through items.
61
+ onCycleTo: null // Callback for when a new slide is cycled to.
62
+ };
63
+
64
+ export class Carousel extends Component<CarouselOptions> {
65
+ hasMultipleSlides: boolean;
66
+ showIndicators: boolean;
67
+ noWrap: boolean;
68
+ /** If the carousel is being clicked or tapped. */
69
+ pressed: boolean;
70
+ /** If the carousel is currently being dragged. */
71
+ dragged: boolean;
72
+ offset: number;
73
+ target: number;
74
+ images: HTMLElement[];
75
+ itemWidth: any;
76
+ itemHeight: any;
77
+ dim: number;
78
+ _indicators: any;
79
+ count: number;
80
+ xform: string;
81
+ verticalDragged: boolean;
82
+ reference: any;
83
+ referenceY: any;
84
+ velocity: number;
85
+ frame: number;
86
+ timestamp: number;
87
+ ticker: NodeJS.Timer;
88
+ amplitude: number;
89
+ /** The index of the center carousel item. */
90
+ center: number = 0;
91
+ imageHeight: any;
92
+ scrollingTimeout: any;
93
+ oneTimeCallback: any;
94
+
95
+ constructor(el: HTMLElement, options: Partial<CarouselOptions>) {
96
+ super(el, options, Carousel);
97
+ (this.el as any).M_Carousel = this;
98
+
99
+ this.options = {
100
+ ...Carousel.defaults,
101
+ ...options
102
+ };
103
+
104
+ // Setup
105
+ this.hasMultipleSlides = this.el.querySelectorAll('.carousel-item').length > 1;
106
+ this.showIndicators = this.options.indicators && this.hasMultipleSlides;
107
+ this.noWrap = this.options.noWrap || !this.hasMultipleSlides;
108
+ this.pressed = false;
109
+ this.dragged = false;
110
+ this.offset = this.target = 0;
111
+ this.images = [];
112
+ this.itemWidth = this.el.querySelector('.carousel-item').clientWidth;
113
+ this.itemHeight = this.el.querySelector('.carousel-item').clientHeight;
114
+ this.dim = this.itemWidth * 2 + this.options.padding || 1; // Make sure dim is non zero for divisions.
115
+
116
+ // Full Width carousel setup
117
+ if (this.options.fullWidth) {
118
+ this.options.dist = 0;
119
+ this._setCarouselHeight();
120
+
121
+ // Offset fixed items when indicators.
122
+ if (this.showIndicators) {
123
+ this.el.querySelector('.carousel-fixed-item')?.classList.add('with-indicators');
124
+ }
125
+ }
71
126
 
72
- // Full Width carousel setup
73
- if (this.options.fullWidth) {
74
- this.options.dist = 0;
75
- this._setCarouselHeight();
127
+ // Iterate through slides
128
+ this._indicators = document.createElement('ul');
129
+ this._indicators.classList.add('indicators');
76
130
 
77
- // Offset fixed items when indicators.
78
- if (this.showIndicators) {
79
- this.el.querySelector('.carousel-fixed-item')?.classList.add('with-indicators');
131
+ this.el.querySelectorAll('.carousel-item').forEach((item: HTMLElement, i) => {
132
+ this.images.push(item);
133
+ if (this.showIndicators) {
134
+ const indicator = document.createElement('li');
135
+ indicator.classList.add('indicator-item');
136
+ if (i === 0) {
137
+ indicator.classList.add('active');
80
138
  }
139
+ this._indicators.appendChild(indicator);
81
140
  }
141
+ });
82
142
 
83
- // Iterate through slides
84
- this._indicators = document.createElement('ul');
85
- this._indicators.classList.add('indicators');
86
-
87
- this.el.querySelectorAll('.carousel-item').forEach((item: HTMLElement, i) => {
88
- this.images.push(item);
89
- if (this.showIndicators) {
90
- const indicator = document.createElement('li');
91
- indicator.classList.add('indicator-item');
92
- if (i === 0) {
93
- indicator.classList.add('active');
94
- }
95
- this._indicators.appendChild(indicator);
96
- }
97
- });
98
-
99
- if (this.showIndicators)
100
- this.el.appendChild(this._indicators);
143
+ if (this.showIndicators)
144
+ this.el.appendChild(this._indicators);
101
145
 
102
- this.count = this.images.length;
146
+ this.count = this.images.length;
103
147
 
104
- // Cap numVisible at count
105
- this.options.numVisible = Math.min(this.count, this.options.numVisible);
148
+ // Cap numVisible at count
149
+ this.options.numVisible = Math.min(this.count, this.options.numVisible);
106
150
 
107
- // Setup cross browser string
108
- this.xform = 'transform';
109
- ['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
110
- var e = prefix + 'Transform';
111
- if (typeof document.body.style[e] !== 'undefined') {
112
- this.xform = e;
113
- return false;
114
- }
115
- return true;
116
- });
117
-
118
- this._setupEventHandlers();
119
- this._scroll(this.offset);
120
- }
121
-
122
- static get defaults() {
123
- return _defaults;
151
+ // Setup cross browser string
152
+ this.xform = 'transform';
153
+ ['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
154
+ var e = prefix + 'Transform';
155
+ if (typeof document.body.style[e] !== 'undefined') {
156
+ this.xform = e;
157
+ return false;
158
+ }
159
+ return true;
160
+ });
161
+
162
+ this._setupEventHandlers();
163
+ this._scroll(this.offset);
164
+ }
165
+
166
+ static get defaults(): CarouselOptions {
167
+ return _defaults;
168
+ }
169
+
170
+ /**
171
+ * Initializes instance of Carousel.
172
+ * @param el HTML element.
173
+ * @param options Component options.
174
+ */
175
+ static init(el: HTMLElement, options?: Partial<CarouselOptions>): Carousel;
176
+ /**
177
+ * Initializes instances of Carousel.
178
+ * @param els HTML elements.
179
+ * @param options Component options.
180
+ */
181
+ static init(els: InitElements<MElement>, options?: Partial<CarouselOptions>): Carousel[];
182
+ /**
183
+ * Initializes instances of Carousel.
184
+ * @param els HTML elements.
185
+ * @param options Component options.
186
+ */
187
+ static init(els: HTMLElement | InitElements<MElement>, options: Partial<CarouselOptions> = {}): Carousel | Carousel[] {
188
+ return super.init(els, options, Carousel);
189
+ }
190
+
191
+ static getInstance(el: HTMLElement): Carousel {
192
+ return (el as any).M_Carousel;
193
+ }
194
+
195
+ destroy() {
196
+ this._removeEventHandlers();
197
+ (this.el as any).M_Carousel = undefined;
198
+ }
199
+
200
+ _setupEventHandlers() {
201
+ if (typeof window.ontouchstart !== 'undefined') {
202
+ this.el.addEventListener('touchstart', this._handleCarouselTap);
203
+ this.el.addEventListener('touchmove', this._handleCarouselDrag);
204
+ this.el.addEventListener('touchend', this._handleCarouselRelease);
124
205
  }
125
-
126
- static init(els, options) {
127
- return super.init(this, els, options);
206
+ this.el.addEventListener('mousedown', this._handleCarouselTap);
207
+ this.el.addEventListener('mousemove', this._handleCarouselDrag);
208
+ this.el.addEventListener('mouseup', this._handleCarouselRelease);
209
+ this.el.addEventListener('mouseleave', this._handleCarouselRelease);
210
+ this.el.addEventListener('click', this._handleCarouselClick);
211
+ if (this.showIndicators && this._indicators) {
212
+ this._indicators.querySelectorAll('.indicator-item').forEach((el) => {
213
+ el.addEventListener('click', this._handleIndicatorClick);
214
+ });
128
215
  }
129
-
130
- static getInstance(el) {
131
- let domElem = !!el.jquery ? el[0] : el;
132
- return domElem.M_Carousel;
216
+ // Resize
217
+ window.addEventListener('resize', this._handleThrottledResize);
218
+ }
219
+
220
+ _removeEventHandlers() {
221
+ if (typeof window.ontouchstart !== 'undefined') {
222
+ this.el.removeEventListener('touchstart', this._handleCarouselTap);
223
+ this.el.removeEventListener('touchmove', this._handleCarouselDrag);
224
+ this.el.removeEventListener('touchend', this._handleCarouselRelease);
133
225
  }
134
-
135
- destroy() {
136
- this._removeEventHandlers();
137
- (this.el as any).M_Carousel = undefined;
226
+ this.el.removeEventListener('mousedown', this._handleCarouselTap);
227
+ this.el.removeEventListener('mousemove', this._handleCarouselDrag);
228
+ this.el.removeEventListener('mouseup', this._handleCarouselRelease);
229
+ this.el.removeEventListener('mouseleave', this._handleCarouselRelease);
230
+ this.el.removeEventListener('click', this._handleCarouselClick);
231
+ if (this.showIndicators && this._indicators) {
232
+ this._indicators.querySelectorAll('.indicator-item').forEach((el) => {
233
+ el.removeEventListener('click', this._handleIndicatorClick);
234
+ });
138
235
  }
236
+ window.removeEventListener('resize', this._handleThrottledResize);
237
+ }
139
238
 
140
- _setupEventHandlers() {
141
- this._handleCarouselTapBound = this._handleCarouselTap.bind(this);
142
- this._handleCarouselDragBound = this._handleCarouselDrag.bind(this);
143
- this._handleCarouselReleaseBound = this._handleCarouselRelease.bind(this);
144
- this._handleCarouselClickBound = this._handleCarouselClick.bind(this);
145
- if (typeof window.ontouchstart !== 'undefined') {
146
- this.el.addEventListener('touchstart', this._handleCarouselTapBound);
147
- this.el.addEventListener('touchmove', this._handleCarouselDragBound);
148
- this.el.addEventListener('touchend', this._handleCarouselReleaseBound);
149
- }
150
- this.el.addEventListener('mousedown', this._handleCarouselTapBound);
151
- this.el.addEventListener('mousemove', this._handleCarouselDragBound);
152
- this.el.addEventListener('mouseup', this._handleCarouselReleaseBound);
153
- this.el.addEventListener('mouseleave', this._handleCarouselReleaseBound);
154
- this.el.addEventListener('click', this._handleCarouselClickBound);
155
- if (this.showIndicators && this._indicators) {
156
- this._handleIndicatorClickBound = this._handleIndicatorClick.bind(this);
157
- this._indicators.querySelectorAll('.indicator-item').forEach((el) => {
158
- el.addEventListener('click', this._handleIndicatorClickBound);
159
- });
160
- }
161
- // Resize
162
- let throttledResize = M.throttle(this._handleResize, 200, null);
163
- this._handleThrottledResizeBound = throttledResize.bind(this);
164
- window.addEventListener('resize', this._handleThrottledResizeBound);
165
- }
239
+ _handleThrottledResize: () => void = Utils.throttle(function(){ this._handleResize(); }, 200, null).bind(this);
166
240
 
167
- _removeEventHandlers() {
168
- if (typeof window.ontouchstart !== 'undefined') {
169
- this.el.removeEventListener('touchstart', this._handleCarouselTapBound);
170
- this.el.removeEventListener('touchmove', this._handleCarouselDragBound);
171
- this.el.removeEventListener('touchend', this._handleCarouselReleaseBound);
172
- }
173
- this.el.removeEventListener('mousedown', this._handleCarouselTapBound);
174
- this.el.removeEventListener('mousemove', this._handleCarouselDragBound);
175
- this.el.removeEventListener('mouseup', this._handleCarouselReleaseBound);
176
- this.el.removeEventListener('mouseleave', this._handleCarouselReleaseBound);
177
- this.el.removeEventListener('click', this._handleCarouselClickBound);
178
- if (this.showIndicators && this._indicators) {
179
- this._indicators.querySelectorAll('.indicator-item').forEach((el) => {
180
- el.removeEventListener('click', this._handleIndicatorClickBound);
181
- });
182
- }
183
- window.removeEventListener('resize', this._handleThrottledResizeBound);
241
+ _handleCarouselTap = (e: MouseEvent | TouchEvent) => {
242
+ // Fixes firefox draggable image bug
243
+ if (e.type === 'mousedown' && (<HTMLElement>e.target).tagName === 'IMG') {
244
+ e.preventDefault();
184
245
  }
185
-
186
- _handleCarouselTap(e) {
187
- // Fixes firefox draggable image bug
188
- if (e.type === 'mousedown' && (<HTMLElement>e.target).tagName === 'IMG') {
189
- e.preventDefault();
190
- }
191
- this.pressed = true;
192
- this.dragged = false;
193
- this.verticalDragged = false;
194
- this.reference = this._xpos(e);
195
- this.referenceY = this._ypos(e);
196
-
197
- this.velocity = this.amplitude = 0;
198
- this.frame = this.offset;
199
- this.timestamp = Date.now();
200
- clearInterval(this.ticker);
201
- this.ticker = setInterval(this._trackBound, 100);
202
- }
203
-
204
- _handleCarouselDrag(e) {
205
- let x, y, delta, deltaY;
206
- if (this.pressed) {
207
- x = this._xpos(e);
208
- y = this._ypos(e);
209
- delta = this.reference - x;
210
- deltaY = Math.abs(this.referenceY - y);
211
- if (deltaY < 30 && !this.verticalDragged) {
212
- // If vertical scrolling don't allow dragging.
213
- if (delta > 2 || delta < -2) {
214
- this.dragged = true;
215
- this.reference = x;
216
- this._scroll(this.offset + delta);
217
- }
218
- } else if (this.dragged) {
219
- // If dragging don't allow vertical scroll.
220
- e.preventDefault();
221
- e.stopPropagation();
222
- return false;
223
- } else {
224
- // Vertical scrolling.
225
- this.verticalDragged = true;
246
+ this.pressed = true;
247
+ this.dragged = false;
248
+ this.verticalDragged = false;
249
+ this.reference = this._xpos(e);
250
+ this.referenceY = this._ypos(e);
251
+
252
+ this.velocity = this.amplitude = 0;
253
+ this.frame = this.offset;
254
+ this.timestamp = Date.now();
255
+ clearInterval(this.ticker);
256
+ this.ticker = setInterval(this._track, 100);
257
+ }
258
+
259
+ _handleCarouselDrag = (e: MouseEvent | TouchEvent) => {
260
+ let x: number, y: number, delta: number, deltaY: number;
261
+ if (this.pressed) {
262
+ x = this._xpos(e);
263
+ y = this._ypos(e);
264
+ delta = this.reference - x;
265
+ deltaY = Math.abs(this.referenceY - y);
266
+ if (deltaY < 30 && !this.verticalDragged) {
267
+ // If vertical scrolling don't allow dragging.
268
+ if (delta > 2 || delta < -2) {
269
+ this.dragged = true;
270
+ this.reference = x;
271
+ this._scroll(this.offset + delta);
226
272
  }
227
- }
228
- if (this.dragged) {
273
+ } else if (this.dragged) {
229
274
  // If dragging don't allow vertical scroll.
230
275
  e.preventDefault();
231
276
  e.stopPropagation();
232
277
  return false;
278
+ } else {
279
+ // Vertical scrolling.
280
+ this.verticalDragged = true;
233
281
  }
234
282
  }
283
+ if (this.dragged) {
284
+ // If dragging don't allow vertical scroll.
285
+ e.preventDefault();
286
+ e.stopPropagation();
287
+ return false;
288
+ }
289
+ }
235
290
 
236
- _handleCarouselRelease(e) {
237
- if (this.pressed) {
238
- this.pressed = false;
239
- } else {
240
- return;
241
- }
242
- clearInterval(this.ticker);
243
- this.target = this.offset;
244
- if (this.velocity > 10 || this.velocity < -10) {
245
- this.amplitude = 0.9 * this.velocity;
246
- this.target = this.offset + this.amplitude;
247
- }
248
- this.target = Math.round(this.target / this.dim) * this.dim;
249
- // No wrap of items.
250
- if (this.noWrap) {
251
- if (this.target >= this.dim * (this.count - 1)) {
252
- this.target = this.dim * (this.count - 1);
253
- } else if (this.target < 0) {
254
- this.target = 0;
255
- }
256
- }
257
- this.amplitude = this.target - this.offset;
258
- this.timestamp = Date.now();
259
- requestAnimationFrame(this._autoScrollBound);
260
- if (this.dragged) {
261
- e.preventDefault();
262
- e.stopPropagation();
291
+ _handleCarouselRelease = (e: MouseEvent | TouchEvent) => {
292
+ if (this.pressed) {
293
+ this.pressed = false;
294
+ } else {
295
+ return;
296
+ }
297
+ clearInterval(this.ticker);
298
+ this.target = this.offset;
299
+ if (this.velocity > 10 || this.velocity < -10) {
300
+ this.amplitude = 0.9 * this.velocity;
301
+ this.target = this.offset + this.amplitude;
302
+ }
303
+ this.target = Math.round(this.target / this.dim) * this.dim;
304
+ // No wrap of items.
305
+ if (this.noWrap) {
306
+ if (this.target >= this.dim * (this.count - 1)) {
307
+ this.target = this.dim * (this.count - 1);
308
+ } else if (this.target < 0) {
309
+ this.target = 0;
263
310
  }
264
- return false;
265
311
  }
312
+ this.amplitude = this.target - this.offset;
313
+ this.timestamp = Date.now();
314
+ requestAnimationFrame(this._autoScroll);
315
+ if (this.dragged) {
316
+ e.preventDefault();
317
+ e.stopPropagation();
318
+ }
319
+ return false;
320
+ }
266
321
 
267
- _handleCarouselClick(e) {
268
- // Disable clicks if carousel was dragged.
269
- if (this.dragged) {
322
+ _handleCarouselClick = (e: MouseEvent | TouchEvent) => {
323
+ // Disable clicks if carousel was dragged.
324
+ if (this.dragged) {
325
+ e.preventDefault();
326
+ e.stopPropagation();
327
+ return false;
328
+ }
329
+ else if (!this.options.fullWidth) {
330
+ const clickedElem = (<HTMLElement>e.target).closest('.carousel-item');
331
+ if (!clickedElem) return;
332
+ const clickedIndex = [...clickedElem.parentNode.children].indexOf(clickedElem);
333
+ const diff = this._wrap(this.center) - clickedIndex;
334
+ // Disable clicks if carousel was shifted by click
335
+ if (diff !== 0) {
270
336
  e.preventDefault();
271
337
  e.stopPropagation();
272
- return false;
273
338
  }
274
- else if (!this.options.fullWidth) {
275
- const clickedElem = (<HTMLElement>e.target).closest('.carousel-item');
276
- const clickedIndex = [...clickedElem.parentNode.children].indexOf(clickedElem);
277
- const diff = this._wrap(this.center) - clickedIndex;
278
- // Disable clicks if carousel was shifted by click
279
- if (diff !== 0) {
280
- e.preventDefault();
281
- e.stopPropagation();
282
- }
283
- // fixes https://github.com/materializecss/materialize/issues/180
284
- if (clickedIndex < 0) {
285
- // relative X position > center of carousel = clicked at the right part of the carousel
286
- if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
287
- this.next();
288
- } else {
289
- this.prev();
290
- }
339
+ // fixes https://github.com/materializecss/materialize/issues/180
340
+ if (clickedIndex < 0) {
341
+ // relative X position > center of carousel = clicked at the right part of the carousel
342
+ if ((e as MouseEvent).clientX - (e.target as HTMLElement).getBoundingClientRect().left > this.el.clientWidth / 2) {
343
+ this.next();
291
344
  } else {
292
- this._cycleTo(clickedIndex);
345
+ this.prev();
293
346
  }
347
+ } else {
348
+ this._cycleTo(clickedIndex);
294
349
  }
295
350
  }
351
+ }
296
352
 
297
- _handleIndicatorClick(e: Event) {
298
- e.stopPropagation();
299
- const indicator = (<HTMLElement>e.target).closest('.indicator-item');
300
- if (indicator) {
301
- const index = [...indicator.parentNode.children].indexOf(indicator);
302
- this._cycleTo(index);
303
- }
353
+ _handleIndicatorClick = (e: Event) => {
354
+ e.stopPropagation();
355
+ const indicator = (<HTMLElement>e.target).closest('.indicator-item');
356
+ if (indicator) {
357
+ const index = [...indicator.parentNode.children].indexOf(indicator);
358
+ this._cycleTo(index);
304
359
  }
360
+ }
305
361
 
306
- _handleResize(e) {
307
- if (this.options.fullWidth) {
308
- this.itemWidth = this.el.querySelector('.carousel-item').clientWidth;
309
- this.imageHeight = this.el.querySelector('.carousel-item.active').clientHeight;
310
- this.dim = this.itemWidth * 2 + this.options.padding;
311
- this.offset = this.center * 2 * this.itemWidth;
312
- this.target = this.offset;
313
- this._setCarouselHeight(true);
314
- }
315
- else {
316
- this._scroll();
317
- }
362
+ _handleResize = () => {
363
+ if (this.options.fullWidth) {
364
+ this.itemWidth = this.el.querySelector('.carousel-item').clientWidth;
365
+ this.imageHeight = this.el.querySelector('.carousel-item.active').clientHeight;
366
+ this.dim = this.itemWidth * 2 + this.options.padding;
367
+ this.offset = this.center * 2 * this.itemWidth;
368
+ this.target = this.offset;
369
+ this._setCarouselHeight(true);
318
370
  }
319
-
320
- _setCarouselHeight(imageOnly: boolean = false) {
321
- const firstSlide = this.el.querySelector('.carousel-item.active')
322
- ? this.el.querySelector('.carousel-item.active')
323
- : this.el.querySelector('.carousel-item');
324
-
325
- const firstImage = firstSlide.querySelector('img');
326
- if (firstImage) {
327
- if (firstImage.complete) {
328
- // If image won't trigger the load event
329
- const imageHeight = firstImage.clientHeight;
330
- if (imageHeight > 0) {
331
- this.el.style.height = imageHeight+'px';
332
- }
333
- else {
334
- // If image still has no height, use the natural dimensions to calculate
335
- const naturalWidth = firstImage.naturalWidth;
336
- const naturalHeight = firstImage.naturalHeight;
337
- const adjustedHeight = (this.el.clientWidth / naturalWidth) * naturalHeight;
338
- this.el.style.height = adjustedHeight+'px';
339
- }
340
- } else {
341
- // Get height when image is loaded normally
342
- firstImage.addEventListener('load', () => {
343
- this.el.style.height = firstImage.offsetHeight+'px';
344
- });
371
+ else {
372
+ this._scroll();
373
+ }
374
+ }
375
+
376
+ _setCarouselHeight(imageOnly: boolean = false) {
377
+ const firstSlide = this.el.querySelector('.carousel-item.active')
378
+ ? this.el.querySelector('.carousel-item.active')
379
+ : this.el.querySelector('.carousel-item');
380
+
381
+ const firstImage = firstSlide.querySelector('img');
382
+ if (firstImage) {
383
+ if (firstImage.complete) {
384
+ // If image won't trigger the load event
385
+ const imageHeight = firstImage.clientHeight;
386
+ if (imageHeight > 0) {
387
+ this.el.style.height = imageHeight+'px';
345
388
  }
389
+ else {
390
+ // If image still has no height, use the natural dimensions to calculate
391
+ const naturalWidth = firstImage.naturalWidth;
392
+ const naturalHeight = firstImage.naturalHeight;
393
+ const adjustedHeight = (this.el.clientWidth / naturalWidth) * naturalHeight;
394
+ this.el.style.height = adjustedHeight+'px';
395
+ }
396
+ } else {
397
+ // Get height when image is loaded normally
398
+ firstImage.addEventListener('load', () => {
399
+ this.el.style.height = firstImage.offsetHeight+'px';
400
+ });
346
401
  }
347
- else if (!imageOnly) {
348
- const slideHeight = firstSlide.clientHeight;
349
- this.el.style.height = slideHeight+'px';
350
- }
351
402
  }
403
+ else if (!imageOnly) {
404
+ const slideHeight = firstSlide.clientHeight;
405
+ this.el.style.height = slideHeight+'px';
406
+ }
407
+ }
352
408
 
353
- _xpos(e) {
354
- // touch event
355
- if (e.targetTouches && e.targetTouches.length >= 1) {
356
- return e.targetTouches[0].clientX;
409
+ _xpos(e: MouseEvent | TouchEvent) {
410
+ // touch event
411
+ if (e.type.startsWith("touch") && (e as TouchEvent).targetTouches.length >= 1) {
412
+ return (e as TouchEvent).targetTouches[0].clientX;
413
+ }
414
+ // mouse event
415
+ return (e as MouseEvent).clientX;
416
+ }
417
+
418
+ _ypos(e: MouseEvent | TouchEvent) {
419
+ // touch event
420
+ if (e.type.startsWith("touch") && (e as TouchEvent).targetTouches.length >= 1) {
421
+ return (e as TouchEvent).targetTouches[0].clientY;
422
+ }
423
+ // mouse event
424
+ return (e as MouseEvent).clientY;
425
+ }
426
+
427
+ _wrap(x: number) {
428
+ return x >= this.count
429
+ ? x % this.count
430
+ : x < 0
431
+ ? this._wrap(this.count + (x % this.count))
432
+ : x;
433
+ }
434
+
435
+ _track = () => {
436
+ let now: number, elapsed: number, delta: number, v: number;
437
+ now = Date.now();
438
+ elapsed = now - this.timestamp;
439
+ this.timestamp = now;
440
+ delta = this.offset - this.frame;
441
+ this.frame = this.offset;
442
+ v = (1000 * delta) / (1 + elapsed);
443
+ this.velocity = 0.8 * v + 0.2 * this.velocity;
444
+ }
445
+
446
+ _autoScroll = () => {
447
+ let elapsed: number, delta: number;
448
+ if (this.amplitude) {
449
+ elapsed = Date.now() - this.timestamp;
450
+ delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
451
+ if (delta > 2 || delta < -2) {
452
+ this._scroll(this.target - delta);
453
+ requestAnimationFrame(this._autoScroll);
454
+ } else {
455
+ this._scroll(this.target);
357
456
  }
358
- // mouse event
359
- return e.clientX;
360
457
  }
458
+ }
361
459
 
362
- _ypos(e) {
363
- // touch event
364
- if (e.targetTouches && e.targetTouches.length >= 1) {
365
- return e.targetTouches[0].clientY;
366
- }
367
- // mouse event
368
- return e.clientY;
369
- }
370
-
371
- _wrap(x: number) {
372
- return x >= this.count
373
- ? x % this.count
374
- : x < 0
375
- ? this._wrap(this.count + (x % this.count))
376
- : x;
377
- }
378
-
379
- _track() {
380
- let now, elapsed, delta, v;
381
- now = Date.now();
382
- elapsed = now - this.timestamp;
383
- this.timestamp = now;
384
- delta = this.offset - this.frame;
385
- this.frame = this.offset;
386
- v = (1000 * delta) / (1 + elapsed);
387
- this.velocity = 0.8 * v + 0.2 * this.velocity;
388
- }
389
-
390
- _autoScroll() {
391
- let elapsed, delta;
392
- if (this.amplitude) {
393
- elapsed = Date.now() - this.timestamp;
394
- delta = this.amplitude * Math.exp(-elapsed / this.options.duration);
395
- if (delta > 2 || delta < -2) {
396
- this._scroll(this.target - delta);
397
- requestAnimationFrame(this._autoScrollBound);
398
- } else {
399
- this._scroll(this.target);
400
- }
401
- }
460
+ _scroll(x: number = 0) {
461
+ // Track scrolling state
462
+ if (!this.el.classList.contains('scrolling')) {
463
+ this.el.classList.add('scrolling');
464
+ }
465
+ if (this.scrollingTimeout != null) {
466
+ window.clearTimeout(this.scrollingTimeout);
467
+ }
468
+ this.scrollingTimeout = window.setTimeout(() => {
469
+ this.el.classList.remove('scrolling');
470
+ }, this.options.duration);
471
+
472
+ // Start actual scroll
473
+ let i: number,
474
+ half: number,
475
+ delta: number,
476
+ dir: number,
477
+ tween: number,
478
+ el: HTMLElement,
479
+ alignment: string,
480
+ zTranslation: number,
481
+ tweenedOpacity: number,
482
+ centerTweenedOpacity: number;
483
+ let lastCenter = this.center;
484
+ let numVisibleOffset = 1 / this.options.numVisible;
485
+
486
+ this.offset = typeof x === 'number' ? x : this.offset;
487
+ this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
488
+
489
+ delta = this.offset - this.center * this.dim;
490
+ dir = delta < 0 ? 1 : -1;
491
+ tween = (-dir * delta * 2) / this.dim;
492
+ half = this.count >> 1;
493
+
494
+ if (this.options.fullWidth) {
495
+ alignment = 'translateX(0)';
496
+ centerTweenedOpacity = 1;
497
+ }
498
+ else {
499
+ alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
500
+ alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
501
+ centerTweenedOpacity = 1 - numVisibleOffset * tween;
402
502
  }
403
503
 
404
- _scroll(x: number = 0) {
405
- // Track scrolling state
406
- if (!this.el.classList.contains('scrolling')) {
407
- this.el.classList.add('scrolling');
504
+ // Set indicator active
505
+ if (this.showIndicators) {
506
+ const diff = this.center % this.count;
507
+ const activeIndicator = this._indicators.querySelector('.indicator-item.active');
508
+ const activeIndicatorIndex = [...activeIndicator.parentNode.children].indexOf(activeIndicator);
509
+ if (activeIndicatorIndex !== diff) {
510
+ activeIndicator.classList.remove('active');
511
+ const pos = diff < 0 ? this.count + diff : diff;
512
+ this._indicators.querySelectorAll('.indicator-item')[pos].classList.add('active');
408
513
  }
409
- if (this.scrollingTimeout != null) {
410
- window.clearTimeout(this.scrollingTimeout);
411
- }
412
- this.scrollingTimeout = window.setTimeout(() => {
413
- this.el.classList.remove('scrolling');
414
- }, this.options.duration);
415
-
416
- // Start actual scroll
417
- let i,
418
- half,
419
- delta,
420
- dir,
421
- tween,
422
- el,
423
- alignment,
424
- zTranslation,
425
- tweenedOpacity,
426
- centerTweenedOpacity;
427
- let lastCenter = this.center;
428
- let numVisibleOffset = 1 / this.options.numVisible;
429
-
430
- this.offset = typeof x === 'number' ? x : this.offset;
431
- this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
432
-
433
- delta = this.offset - this.center * this.dim;
434
- dir = delta < 0 ? 1 : -1;
435
- tween = (-dir * delta * 2) / this.dim;
436
- half = this.count >> 1;
514
+ }
437
515
 
438
- if (this.options.fullWidth) {
439
- alignment = 'translateX(0)';
440
- centerTweenedOpacity = 1;
441
- }
442
- else {
443
- alignment = 'translateX(' + (this.el.clientWidth - this.itemWidth) / 2 + 'px) ';
444
- alignment += 'translateY(' + (this.el.clientHeight - this.itemHeight) / 2 + 'px)';
445
- centerTweenedOpacity = 1 - numVisibleOffset * tween;
446
- }
516
+ // center
517
+ // Don't show wrapped items.
518
+ if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
519
+ el = this.images[this._wrap(this.center)];
447
520
 
448
- // Set indicator active
449
- if (this.showIndicators) {
450
- const diff = this.center % this.count;
451
- const activeIndicator = this._indicators.querySelector('.indicator-item.active');
452
- const activeIndicatorIndex = [...activeIndicator.parentNode.children].indexOf(activeIndicator);
453
- if (activeIndicatorIndex !== diff) {
454
- activeIndicator.classList.remove('active');
455
- const pos = diff < 0 ? this.count + diff : diff;
456
- this._indicators.querySelectorAll('.indicator-item')[pos].classList.add('active');
457
- }
521
+ // Add active class to center item.
522
+ if (!el.classList.contains('active')) {
523
+ this.el.querySelector('.carousel-item').classList.remove('active');
524
+ el.classList.add('active');
458
525
  }
459
526
 
460
- // center
461
- // Don't show wrapped items.
462
- if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
463
- el = this.images[this._wrap(this.center)];
464
-
465
- // Add active class to center item.
466
- if (!el.classList.contains('active')) {
467
- this.el.querySelector('.carousel-item').classList.remove('active');
468
- el.classList.add('active');
469
- }
470
-
471
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
472
- this.options.shift *
473
- tween *
474
- i}px) translateZ(${this.options.dist * tween}px)`;
475
- this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
476
- }
527
+ let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
528
+ this.options.shift *
529
+ tween *
530
+ i}px) translateZ(${this.options.dist * tween}px)`;
531
+ this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
532
+ }
477
533
 
478
- for (i = 1; i <= half; ++i) {
479
- // right side
480
- if (this.options.fullWidth) {
481
- zTranslation = this.options.dist;
482
- tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
483
- } else {
484
- zTranslation = this.options.dist * (i * 2 + tween * dir);
485
- tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
486
- }
487
- // Don't show wrapped items.
488
- if (!this.noWrap || this.center + i < this.count) {
489
- el = this.images[this._wrap(this.center + i)];
490
- let transformString = `${alignment} translateX(${this.options.shift +
491
- (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
492
- this._updateItemStyle(el, tweenedOpacity, -i, transformString);
493
- }
494
- // left side
495
- if (this.options.fullWidth) {
496
- zTranslation = this.options.dist;
497
- tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
498
- } else {
499
- zTranslation = this.options.dist * (i * 2 - tween * dir);
500
- tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
501
- }
502
- // Don't show wrapped items.
503
- if (!this.noWrap || this.center - i >= 0) {
504
- el = this.images[this._wrap(this.center - i)];
505
- let transformString = `${alignment} translateX(${-this.options.shift +
506
- (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
507
- this._updateItemStyle(el, tweenedOpacity, -i, transformString);
508
- }
534
+ for (i = 1; i <= half; ++i) {
535
+ // right side
536
+ if (this.options.fullWidth) {
537
+ zTranslation = this.options.dist;
538
+ tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
539
+ } else {
540
+ zTranslation = this.options.dist * (i * 2 + tween * dir);
541
+ tweenedOpacity = 1 - numVisibleOffset * (i * 2 + tween * dir);
509
542
  }
510
- // center
511
543
  // Don't show wrapped items.
512
- if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
513
- el = this.images[this._wrap(this.center)];
514
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
515
- this.options.shift *
516
- tween}px) translateZ(${this.options.dist * tween}px)`;
517
- this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
544
+ if (!this.noWrap || this.center + i < this.count) {
545
+ el = this.images[this._wrap(this.center + i)];
546
+ let transformString = `${alignment} translateX(${this.options.shift +
547
+ (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
548
+ this._updateItemStyle(el, tweenedOpacity, -i, transformString);
518
549
  }
519
- // onCycleTo callback
520
- const _currItem = this.el.querySelectorAll('.carousel-item')[this._wrap(this.center)];
521
-
522
- if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
523
- this.options.onCycleTo.call(this, _currItem, this.dragged);
550
+ // left side
551
+ if (this.options.fullWidth) {
552
+ zTranslation = this.options.dist;
553
+ tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
554
+ } else {
555
+ zTranslation = this.options.dist * (i * 2 - tween * dir);
556
+ tweenedOpacity = 1 - numVisibleOffset * (i * 2 - tween * dir);
524
557
  }
525
- // One time callback
526
- if (typeof this.oneTimeCallback === 'function') {
527
- this.oneTimeCallback.call(this, _currItem, this.dragged);
528
- this.oneTimeCallback = null;
558
+ // Don't show wrapped items.
559
+ if (!this.noWrap || this.center - i >= 0) {
560
+ el = this.images[this._wrap(this.center - i)];
561
+ let transformString = `${alignment} translateX(${-this.options.shift +
562
+ (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
563
+ this._updateItemStyle(el, tweenedOpacity, -i, transformString);
529
564
  }
530
565
  }
566
+ // center
567
+ // Don't show wrapped items.
568
+ if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
569
+ el = this.images[this._wrap(this.center)];
570
+ let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
571
+ this.options.shift *
572
+ tween}px) translateZ(${this.options.dist * tween}px)`;
573
+ this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
574
+ }
575
+ // onCycleTo callback
576
+ const _currItem = this.el.querySelectorAll('.carousel-item')[this._wrap(this.center)];
531
577
 
532
- _updateItemStyle(el: HTMLElement, opacity: number, zIndex: number, transform: string) {
533
- el.style[this.xform] = transform;
534
- el.style.zIndex = zIndex.toString();
535
- el.style.opacity = opacity.toString();
536
- el.style.visibility = 'visible';
537
- }
538
-
539
- _cycleTo(n: number, callback: Function = null) {
540
- let diff = (this.center % this.count) - n;
541
- // Account for wraparound.
542
- if (!this.noWrap) {
543
- if (diff < 0) {
544
- if (Math.abs(diff + this.count) < Math.abs(diff)) {
545
- diff += this.count;
546
- }
547
- } else if (diff > 0) {
548
- if (Math.abs(diff - this.count) < diff) {
549
- diff -= this.count;
550
- }
551
- }
552
- }
553
- this.target = this.dim * Math.round(this.offset / this.dim);
554
- // Next
578
+ if (lastCenter !== this.center && typeof this.options.onCycleTo === 'function') {
579
+ this.options.onCycleTo.call(this, _currItem, this.dragged);
580
+ }
581
+ // One time callback
582
+ if (typeof this.oneTimeCallback === 'function') {
583
+ this.oneTimeCallback.call(this, _currItem, this.dragged);
584
+ this.oneTimeCallback = null;
585
+ }
586
+ }
587
+
588
+ _updateItemStyle(el: HTMLElement, opacity: number, zIndex: number, transform: string) {
589
+ el.style[this.xform] = transform;
590
+ el.style.zIndex = zIndex.toString();
591
+ el.style.opacity = opacity.toString();
592
+ el.style.visibility = 'visible';
593
+ }
594
+
595
+ _cycleTo(n: number, callback: CarouselOptions["onCycleTo"] = null) {
596
+ let diff = (this.center % this.count) - n;
597
+ // Account for wraparound.
598
+ if (!this.noWrap) {
555
599
  if (diff < 0) {
556
- this.target += this.dim * Math.abs(diff);
557
- } // Prev
558
- else if (diff > 0) {
559
- this.target -= this.dim * diff;
560
- }
561
- // Set one time callback
562
- if (typeof callback === 'function') {
563
- this.oneTimeCallback = callback;
564
- }
565
- // Scroll
566
- if (this.offset !== this.target) {
567
- this.amplitude = this.target - this.offset;
568
- this.timestamp = Date.now();
569
- requestAnimationFrame(this._autoScrollBound);
600
+ if (Math.abs(diff + this.count) < Math.abs(diff)) {
601
+ diff += this.count;
602
+ }
603
+ } else if (diff > 0) {
604
+ if (Math.abs(diff - this.count) < diff) {
605
+ diff -= this.count;
606
+ }
570
607
  }
571
608
  }
572
-
573
- next(n: number = 1) {
574
- if (n === undefined || isNaN(n)) {
575
- n = 1;
576
- }
577
- let index = this.center + n;
578
- if (index >= this.count || index < 0) {
579
- if (this.noWrap) return;
580
- index = this._wrap(index);
581
- }
582
- this._cycleTo(index);
609
+ this.target = this.dim * Math.round(this.offset / this.dim);
610
+ // Next
611
+ if (diff < 0) {
612
+ this.target += this.dim * Math.abs(diff);
613
+ } // Prev
614
+ else if (diff > 0) {
615
+ this.target -= this.dim * diff;
583
616
  }
584
-
585
- prev(n: number = 1) {
586
- if (n === undefined || isNaN(n)) {
587
- n = 1;
588
- }
589
- let index = this.center - n;
590
- if (index >= this.count || index < 0) {
591
- if (this.noWrap) return;
592
- index = this._wrap(index);
593
- }
594
- this._cycleTo(index);
617
+ // Set one time callback
618
+ if (typeof callback === 'function') {
619
+ this.oneTimeCallback = callback;
595
620
  }
596
-
597
- set(n: number, callback: Function) {
598
- if (n === undefined || isNaN(n)) {
599
- n = 0;
600
- }
601
- if (n > this.count || n < 0) {
602
- if (this.noWrap) return;
603
- n = this._wrap(n);
604
- }
605
- this._cycleTo(n, callback);
621
+ // Scroll
622
+ if (this.offset !== this.target) {
623
+ this.amplitude = this.target - this.offset;
624
+ this.timestamp = Date.now();
625
+ requestAnimationFrame(this._autoScroll);
626
+ }
627
+ }
628
+
629
+ /**
630
+ * Move carousel to next slide or go forward a given amount of slides.
631
+ * @param n How many times the carousel slides.
632
+ */
633
+ next(n: number = 1) {
634
+ if (n === undefined || isNaN(n)) {
635
+ n = 1;
636
+ }
637
+ let index = this.center + n;
638
+ if (index >= this.count || index < 0) {
639
+ if (this.noWrap) return;
640
+ index = this._wrap(index);
641
+ }
642
+ this._cycleTo(index);
643
+ }
644
+
645
+ /**
646
+ * Move carousel to previous slide or go back a given amount of slides.
647
+ * @param n How many times the carousel slides.
648
+ */
649
+ prev(n: number = 1) {
650
+ if (n === undefined || isNaN(n)) {
651
+ n = 1;
652
+ }
653
+ let index = this.center - n;
654
+ if (index >= this.count || index < 0) {
655
+ if (this.noWrap) return;
656
+ index = this._wrap(index);
657
+ }
658
+ this._cycleTo(index);
659
+ }
660
+
661
+ /**
662
+ * Move carousel to nth slide.
663
+ * @param n Index of slide.
664
+ * @param callback "onCycleTo" optional callback.
665
+ */
666
+ set(n: number, callback?: CarouselOptions["onCycleTo"]) {
667
+ if (n === undefined || isNaN(n)) {
668
+ n = 0;
669
+ }
670
+ if (n > this.count || n < 0) {
671
+ if (this.noWrap) return;
672
+ n = this._wrap(n);
606
673
  }
607
- }
674
+ this._cycleTo(n, callback);
675
+ }
676
+ }