@materializecss/materialize 1.2.2 → 2.0.0-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 (89) hide show
  1. package/Gruntfile.js +68 -313
  2. package/README.md +2 -2
  3. package/dist/css/materialize.css +1009 -1822
  4. package/dist/css/materialize.min.css +2 -8
  5. package/dist/js/materialize.js +8402 -12300
  6. package/dist/js/materialize.min.js +3 -2
  7. package/dist/js/materialize.min.js.map +1 -0
  8. package/package.json +13 -9
  9. package/sass/components/_badges.scss +12 -2
  10. package/sass/components/_buttons.scss +16 -11
  11. package/sass/components/_cards.scss +14 -9
  12. package/sass/components/_carousel.scss +5 -2
  13. package/sass/components/_chips.scss +3 -3
  14. package/sass/components/_collapsible.scss +22 -8
  15. package/sass/components/_collection.scss +14 -6
  16. package/sass/components/_datepicker.scss +30 -11
  17. package/sass/components/_dropdown.scss +6 -4
  18. package/sass/components/_global.scss +132 -111
  19. package/sass/components/_grid.scss +119 -98
  20. package/sass/components/_modal.scss +3 -3
  21. package/sass/components/_navbar.scss +31 -17
  22. package/sass/components/_normalize.scss +26 -124
  23. package/sass/components/_sidenav.scss +21 -20
  24. package/sass/components/_slider.scss +27 -7
  25. package/sass/components/_table_of_contents.scss +12 -12
  26. package/sass/components/_tabs.scss +47 -16
  27. package/sass/components/_tapTarget.scss +6 -6
  28. package/sass/components/_timepicker.scss +54 -46
  29. package/sass/components/_toast.scss +3 -3
  30. package/sass/components/_tooltip.scss +4 -5
  31. package/sass/components/_typography.scss +1 -1
  32. package/sass/components/_variables.scss +185 -120
  33. package/sass/components/forms/_checkboxes.scss +9 -9
  34. package/sass/components/forms/_file-input.scss +9 -7
  35. package/sass/components/forms/_input-fields.scss +173 -234
  36. package/sass/components/forms/_radio-buttons.scss +1 -1
  37. package/sass/components/forms/_range.scss +11 -11
  38. package/sass/components/forms/_select.scss +29 -19
  39. package/sass/components/forms/_switches.scss +22 -18
  40. package/sass/materialize.scss +1 -1
  41. package/src/autocomplete.ts +459 -0
  42. package/src/bounding.ts +6 -0
  43. package/{js/buttons.js → src/buttons.ts} +103 -162
  44. package/src/cards.ts +54 -0
  45. package/{js/carousel.js → src/carousel.ts} +137 -262
  46. package/src/characterCounter.ts +88 -0
  47. package/src/chips.ts +350 -0
  48. package/src/collapsible.ts +184 -0
  49. package/{js/component.js → src/component.ts} +6 -19
  50. package/{js/datepicker.js → src/datepicker.ts} +213 -299
  51. package/{js/dropdown.js → src/dropdown.ts} +140 -254
  52. package/src/edges.ts +6 -0
  53. package/src/forms.ts +120 -0
  54. package/src/global.ts +385 -0
  55. package/src/materialbox.ts +348 -0
  56. package/src/modal.ts +256 -0
  57. package/{js/parallax.js → src/parallax.ts} +47 -60
  58. package/{js/pushpin.js → src/pushpin.ts} +19 -47
  59. package/{js/range.js → src/range.ts} +58 -139
  60. package/{js/scrollspy.js → src/scrollspy.ts} +81 -153
  61. package/src/select.ts +448 -0
  62. package/{js/sidenav.js → src/sidenav.ts} +96 -202
  63. package/src/slider.ts +415 -0
  64. package/src/tabs.ts +290 -0
  65. package/src/tapTarget.ts +240 -0
  66. package/{js/timepicker.js → src/timepicker.ts} +268 -272
  67. package/{js/toasts.js → src/toasts.ts} +75 -134
  68. package/{js/tooltip.js → src/tooltip.ts} +59 -96
  69. package/src/waves.ts +70 -0
  70. package/extras/noUiSlider/nouislider.css +0 -404
  71. package/extras/noUiSlider/nouislider.js +0 -2147
  72. package/extras/noUiSlider/nouislider.min.js +0 -1
  73. package/js/anime.min.js +0 -34
  74. package/js/autocomplete.js +0 -479
  75. package/js/cards.js +0 -40
  76. package/js/cash.js +0 -960
  77. package/js/characterCounter.js +0 -136
  78. package/js/chips.js +0 -486
  79. package/js/collapsible.js +0 -275
  80. package/js/forms.js +0 -285
  81. package/js/global.js +0 -428
  82. package/js/materialbox.js +0 -453
  83. package/js/modal.js +0 -382
  84. package/js/select.js +0 -391
  85. package/js/slider.js +0 -497
  86. package/js/tabs.js +0 -402
  87. package/js/tapTarget.js +0 -315
  88. package/js/waves.js +0 -615
  89. package/sass/components/_waves.scss +0 -187
@@ -0,0 +1,348 @@
1
+ import { Component } from "./component";
2
+ import anim from "animejs";
3
+ import { M } from "./global";
4
+
5
+ const _defaults = {
6
+ inDuration: 275,
7
+ outDuration: 200,
8
+ onOpenStart: null,
9
+ onOpenEnd: null,
10
+ onCloseStart: null,
11
+ onCloseEnd: null
12
+ };
13
+
14
+ export class Materialbox extends Component {
15
+ el: HTMLElement;
16
+ overlayActive: boolean;
17
+ doneAnimating: boolean;
18
+ caption: string;
19
+ originalWidth: number;
20
+ originalHeight: number;
21
+ private originInlineStyles: string;
22
+ private placeholder: HTMLElement;
23
+ private _changedAncestorList: HTMLElement[];
24
+ private newHeight: number;
25
+ private newWidth: number;
26
+ private windowWidth: number;
27
+ private windowHeight: number;
28
+ private attrWidth: string;
29
+ private attrHeight: string;
30
+ private _overlay: HTMLElement;
31
+ private _photoCaption: HTMLElement;
32
+ private _handleMaterialboxClickBound: any;
33
+ private _handleWindowScrollBound: any;
34
+ private _handleWindowResizeBound: any;
35
+ private _handleWindowEscapeBound: any;
36
+
37
+ constructor(el, options) {
38
+ super(Materialbox, el, options);
39
+ (this.el as any).M_Materialbox = this;
40
+ this.options = {...Materialbox.defaults, ...options};
41
+ this.overlayActive = false;
42
+ this.doneAnimating = true;
43
+ this.placeholder = document.createElement('div');
44
+ this.placeholder.classList.add('material-placeholder');
45
+ this.originalWidth = 0;
46
+ this.originalHeight = 0;
47
+ this.originInlineStyles = this.el.getAttribute('style');
48
+ this.caption = this.el.getAttribute('data-caption') || '';
49
+ // Wrap
50
+ this.el.before(this.placeholder);
51
+ this.placeholder.append(this.el);
52
+ this._setupEventHandlers();
53
+ }
54
+
55
+ static get defaults() {
56
+ return _defaults;
57
+ }
58
+
59
+ static init(els, options) {
60
+ return super.init(this, els, options);
61
+ }
62
+
63
+ static getInstance(el) {
64
+ const domElem = !!el.jquery ? el[0] : el;
65
+ return domElem.M_Materialbox;
66
+ }
67
+
68
+ destroy() {
69
+ this._removeEventHandlers();
70
+ (this.el as any).M_Materialbox = undefined;
71
+ // Unwrap image
72
+ //this.placeholder.after(this.el).remove();
73
+ this.placeholder.remove();
74
+ this.el.removeAttribute('style');
75
+ }
76
+
77
+ _setupEventHandlers() {
78
+ this._handleMaterialboxClickBound = this._handleMaterialboxClick.bind(this);
79
+ this.el.addEventListener('click', this._handleMaterialboxClickBound);
80
+ }
81
+
82
+ _removeEventHandlers() {
83
+ this.el.removeEventListener('click', this._handleMaterialboxClickBound);
84
+ }
85
+
86
+ _handleMaterialboxClick(e) {
87
+ // If already modal, return to original
88
+ if (this.doneAnimating === false || (this.overlayActive && this.doneAnimating))
89
+ this.close();
90
+ else
91
+ this.open();
92
+ }
93
+
94
+ _handleWindowScroll() {
95
+ if (this.overlayActive) this.close();
96
+ }
97
+
98
+ _handleWindowResize() {
99
+ if (this.overlayActive) this.close();
100
+ }
101
+
102
+ _handleWindowEscape(e) {
103
+ // ESC key
104
+ if (e.keyCode === 27 && this.doneAnimating && this.overlayActive) this.close();
105
+ }
106
+
107
+ _makeAncestorsOverflowVisible() {
108
+ this._changedAncestorList = [];
109
+ let ancestor = this.placeholder.parentNode;
110
+ while (ancestor !== null && ancestor !== document) {
111
+ const curr = <HTMLElement>ancestor;
112
+ if (curr.style.overflow !== 'visible') {
113
+ curr.style.overflow = 'visible';
114
+ this._changedAncestorList.push(curr);
115
+ }
116
+ ancestor = ancestor.parentNode;
117
+ }
118
+ }
119
+
120
+ private _offset(el) {
121
+ const box = el.getBoundingClientRect();
122
+ const docElem = document.documentElement;
123
+ return {
124
+ top: box.top + window.pageYOffset - docElem.clientTop,
125
+ left: box.left + window.pageXOffset - docElem.clientLeft
126
+ };
127
+ }
128
+
129
+ _animateImageIn() {
130
+ this.el.style.maxHeight = this.newHeight.toString()+'px';
131
+ this.el.style.maxWidth = this.newWidth.toString()+'px';
132
+
133
+ const animOptions = {
134
+ targets: this.el, // image
135
+ height: [this.originalHeight, this.newHeight],
136
+ width: [this.originalWidth, this.newWidth],
137
+ left:
138
+ M.getDocumentScrollLeft() +
139
+ this.windowWidth / 2 -
140
+ this._offset(this.placeholder).left -
141
+ this.newWidth / 2,
142
+ top:
143
+ M.getDocumentScrollTop() +
144
+ this.windowHeight / 2 -
145
+ this._offset(this.placeholder).top -
146
+ this.newHeight / 2,
147
+ duration: this.options.inDuration,
148
+ easing: 'easeOutQuad',
149
+ complete: () => {
150
+ this.doneAnimating = true;
151
+ // onOpenEnd callback
152
+ if (typeof this.options.onOpenEnd === 'function') {
153
+ this.options.onOpenEnd.call(this, this.el);
154
+ }
155
+ }
156
+ };
157
+ // Override max-width or max-height if needed
158
+ //const elStyle = this.el.style;
159
+ //console.log('mh', elStyle.maxHeight, '->', this.newHeight);
160
+ //console.log('mw', elStyle.maxWidth, '->', this.newWidth);
161
+ //if (elStyle.maxWidth !== 'none') animOptions.maxWidth = this.newWidth;
162
+ //if (elStyle.maxHeight !== 'none') animOptions.maxHeight = this.newHeight;
163
+ //console.log('>>> animate');
164
+ //console.log(JSON.stringify(animOptions));
165
+ anim(animOptions);
166
+ }
167
+
168
+ _animateImageOut() {
169
+ const animOptions = {
170
+ targets: this.el,
171
+ width: this.originalWidth,
172
+ height: this.originalHeight,
173
+ left: 0,
174
+ top: 0,
175
+ duration: this.options.outDuration,
176
+ easing: 'easeOutQuad',
177
+ complete: () => {
178
+ this.placeholder.style.height = '';
179
+ this.placeholder.style.width = '';
180
+ this.placeholder.style.position = '';
181
+ this.placeholder.style.top = '';
182
+ this.placeholder.style.left = '';
183
+ // Revert to width or height attribute
184
+ if (this.attrWidth) this.el.setAttribute('width', this.attrWidth.toString());
185
+ if (this.attrHeight) this.el.setAttribute('height', this.attrHeight.toString());
186
+ this.el.removeAttribute('style');
187
+ this.originInlineStyles && this.el.setAttribute('style', this.originInlineStyles);
188
+ // Remove class
189
+ this.el.classList.remove('active');
190
+ this.doneAnimating = true;
191
+ // Remove overflow overrides on ancestors
192
+ this._changedAncestorList.forEach(anchestor => anchestor.style.overflow = '');
193
+ // onCloseEnd callback
194
+ if (typeof this.options.onCloseEnd === 'function') {
195
+ this.options.onCloseEnd.call(this, this.el);
196
+ }
197
+ }
198
+ };
199
+ anim(animOptions);
200
+ }
201
+
202
+ _updateVars() {
203
+ this.windowWidth = window.innerWidth;
204
+ this.windowHeight = window.innerHeight;
205
+ this.caption = this.el.getAttribute('data-caption') || '';
206
+ }
207
+
208
+ open() {
209
+ this._updateVars();
210
+ this.originalWidth = this.el.getBoundingClientRect().width;
211
+ this.originalHeight = this.el.getBoundingClientRect().height;
212
+ // Set states
213
+ this.doneAnimating = false;
214
+ this.el.classList.add('active');
215
+ this.overlayActive = true;
216
+ // onOpenStart callback
217
+ if (typeof this.options.onOpenStart === 'function') {
218
+ this.options.onOpenStart.call(this, this.el);
219
+ }
220
+ // Set positioning for placeholder
221
+ this.placeholder.style.width = this.placeholder.getBoundingClientRect().width+'px';
222
+ this.placeholder.style.height = this.placeholder.getBoundingClientRect().height+'px';
223
+ this.placeholder.style.position = 'relative';
224
+ this.placeholder.style.top = '0';
225
+ this.placeholder.style.left = '0';
226
+ this._makeAncestorsOverflowVisible();
227
+ // Set css on origin
228
+ this.el.style.position = 'absolute';
229
+ this.el.style.zIndex = '1000';
230
+ this.el.style.willChange = 'left, top, width, height';
231
+ // Change from width or height attribute to css
232
+ this.attrWidth = this.el.getAttribute('width');
233
+ this.attrHeight = this.el.getAttribute('height');
234
+ if (this.attrWidth) {
235
+ this.el.style.width = this.attrWidth+'px';
236
+ this.el.removeAttribute('width');
237
+ }
238
+ if (this.attrHeight) {
239
+ this.el.style.width = this.attrHeight+'px';
240
+ this.el.removeAttribute('height');
241
+ }
242
+ // Add overlay
243
+ this._overlay = document.createElement('div');
244
+ this._overlay.id = 'materialbox-overlay';
245
+ this._overlay.style.opacity = '0';
246
+ this._overlay.addEventListener('click', e => {
247
+ if (this.doneAnimating) this.close();
248
+ }, {once: true});
249
+ // Put before in origin image to preserve z-index layering.
250
+ this.el.before(this._overlay);
251
+ // Set dimensions if needed
252
+ const overlayOffset = this._overlay.getBoundingClientRect();
253
+ this._overlay.style.width = this.windowWidth+'px';
254
+ this._overlay.style.height = this.windowHeight+'px';
255
+ this._overlay.style.left = -1 * overlayOffset.left+'px';
256
+ this._overlay.style.top = -1 * overlayOffset.top+'px';
257
+ anim.remove(this.el);
258
+ anim.remove(this._overlay);
259
+ // Animate Overlay
260
+ anim({
261
+ targets: this._overlay,
262
+ opacity: 1,
263
+ duration: this.options.inDuration,
264
+ easing: 'easeOutQuad'
265
+ });
266
+ // Add and animate caption if it exists
267
+ if (this.caption !== '') {
268
+ if (this._photoCaption) anim.remove(this._photoCaption);
269
+ this._photoCaption = document.createElement('div');
270
+ this._photoCaption.classList.add('materialbox-caption');
271
+ this._photoCaption.innerText = this.caption;
272
+ document.body.append(this._photoCaption);
273
+ this._photoCaption.style.display = 'inline';
274
+ anim({
275
+ targets: this._photoCaption,
276
+ opacity: 1,
277
+ duration: this.options.inDuration,
278
+ easing: 'easeOutQuad'
279
+ });
280
+ }
281
+
282
+ // Resize Image
283
+ const widthPercent = this.originalWidth / this.windowWidth;
284
+ const heightPercent = this.originalHeight / this.windowHeight;
285
+ this.newWidth = 0;
286
+ this.newHeight = 0;
287
+ if (widthPercent > heightPercent) {
288
+ // Width first
289
+ const ratio = this.originalHeight / this.originalWidth;
290
+ this.newWidth = this.windowWidth * 0.9;
291
+ this.newHeight = this.windowWidth * 0.9 * ratio;
292
+ }
293
+ else {
294
+ // Height first
295
+ const ratio = this.originalWidth / this.originalHeight;
296
+ this.newWidth = this.windowHeight * 0.9 * ratio;
297
+ this.newHeight = this.windowHeight * 0.9;
298
+ }
299
+ this._animateImageIn();
300
+
301
+ // Handle Exit triggers
302
+ this._handleWindowScrollBound = this._handleWindowScroll.bind(this);
303
+ this._handleWindowResizeBound = this._handleWindowResize.bind(this);
304
+ this._handleWindowEscapeBound = this._handleWindowEscape.bind(this);
305
+ window.addEventListener('scroll', this._handleWindowScrollBound);
306
+ window.addEventListener('resize', this._handleWindowResizeBound);
307
+ window.addEventListener('keyup', this._handleWindowEscapeBound);
308
+ }
309
+
310
+ close() {
311
+ this._updateVars();
312
+ this.doneAnimating = false;
313
+ // onCloseStart callback
314
+ if (typeof this.options.onCloseStart === 'function') {
315
+ this.options.onCloseStart.call(this, this.el);
316
+ }
317
+ anim.remove(this.el);
318
+ anim.remove(this._overlay);
319
+ if (this.caption !== '') anim.remove(this._photoCaption);
320
+ // disable exit handlers
321
+ window.removeEventListener('scroll', this._handleWindowScrollBound);
322
+ window.removeEventListener('resize', this._handleWindowResizeBound);
323
+ window.removeEventListener('keyup', this._handleWindowEscapeBound);
324
+ anim({
325
+ targets: this._overlay,
326
+ opacity: 0,
327
+ duration: this.options.outDuration,
328
+ easing: 'easeOutQuad',
329
+ complete: () => {
330
+ this.overlayActive = false;
331
+ this._overlay.remove();
332
+ }
333
+ });
334
+ this._animateImageOut();
335
+ // Remove Caption + reset css settings on image
336
+ if (this.caption !== '') {
337
+ anim({
338
+ targets: this._photoCaption,
339
+ opacity: 0,
340
+ duration: this.options.outDuration,
341
+ easing: 'easeOutQuad',
342
+ complete: () => {
343
+ this._photoCaption.remove();
344
+ }
345
+ });
346
+ }
347
+ }
348
+ }
package/src/modal.ts ADDED
@@ -0,0 +1,256 @@
1
+ import { Component } from "./component";
2
+ import anim from "animejs";
3
+ import { M } from "./global";
4
+
5
+ const _defaults = {
6
+ opacity: 0.5,
7
+ inDuration: 250,
8
+ outDuration: 250,
9
+ onOpenStart: null,
10
+ onOpenEnd: null,
11
+ onCloseStart: null,
12
+ onCloseEnd: null,
13
+ preventScrolling: true,
14
+ dismissible: true,
15
+ startingTop: '4%',
16
+ endingTop: '10%'
17
+ };
18
+
19
+ export class Modal extends Component {
20
+ el: HTMLElement;
21
+ static _modalsOpen: number;
22
+ static _count: number;
23
+ isOpen: boolean;
24
+ id: string;
25
+ private _openingTrigger: any;
26
+ private _overlay: HTMLElement;
27
+ private _nthModalOpened: number;
28
+ private _handleOverlayClickBound: any;
29
+ private _handleModalCloseClickBound: any;
30
+ private _handleKeydownBound: any;
31
+ private _handleFocusBound: any;
32
+
33
+ constructor(el, options) {
34
+ super(Modal, el, options);
35
+ (this.el as any).M_Modal = this;
36
+ this.options = {...Modal.defaults, ...options};
37
+ this.isOpen = false;
38
+ this.id = this.el.id;
39
+ this._openingTrigger = undefined;
40
+ this._overlay = document.createElement('div');
41
+ this._overlay.classList.add('modal-overlay');
42
+ this.el.tabIndex = 0;
43
+ this._nthModalOpened = 0;
44
+ Modal._count++;
45
+ this._setupEventHandlers();
46
+ }
47
+
48
+ static get defaults() {
49
+ return _defaults;
50
+ }
51
+
52
+ static init(els, options) {
53
+ return super.init(this, els, options);
54
+ }
55
+
56
+ static getInstance(el) {
57
+ const domElem = !!el.jquery ? el[0] : el;
58
+ return domElem.M_Modal;
59
+ }
60
+
61
+ destroy() {
62
+ Modal._count--;
63
+ this._removeEventHandlers();
64
+ this.el.removeAttribute('style');
65
+ this._overlay.remove();
66
+ (this.el as any).M_Modal = undefined;
67
+ }
68
+
69
+ _setupEventHandlers() {
70
+ this._handleOverlayClickBound = this._handleOverlayClick.bind(this);
71
+ this._handleModalCloseClickBound = this._handleModalCloseClick.bind(this);
72
+ if (Modal._count === 1) {
73
+ document.body.addEventListener('click', this._handleTriggerClick);
74
+ }
75
+ this._overlay.addEventListener('click', this._handleOverlayClickBound);
76
+ this.el.addEventListener('click', this._handleModalCloseClickBound);
77
+ }
78
+
79
+ _removeEventHandlers() {
80
+ if (Modal._count === 0) {
81
+ document.body.removeEventListener('click', this._handleTriggerClick);
82
+ }
83
+ this._overlay.removeEventListener('click', this._handleOverlayClickBound);
84
+ this.el.removeEventListener('click', this._handleModalCloseClickBound);
85
+ }
86
+
87
+ _handleTriggerClick(e) {
88
+ const trigger = e.target.closest('.modal-trigger');
89
+ if (!trigger) return;
90
+ const modalId = M.getIdFromTrigger(trigger);
91
+ const modalInstance = (document.getElementById(modalId) as any).M_Modal;
92
+ if (modalInstance) modalInstance.open(trigger);
93
+ e.preventDefault();
94
+ }
95
+
96
+ _handleOverlayClick() {
97
+ if (this.options.dismissible) this.close();
98
+ }
99
+
100
+ _handleModalCloseClick(e) {
101
+ const closeTrigger = e.target.closest('.modal-close');
102
+ if (closeTrigger) this.close();
103
+ }
104
+
105
+ _handleKeydown(e) {
106
+ // ESC key
107
+ if (e.keyCode === 27 && this.options.dismissible) this.close();
108
+ }
109
+
110
+ _handleFocus(e) {
111
+ // Only trap focus if this modal is the last model opened (prevents loops in nested modals).
112
+ if (!this.el.contains(e.target) && this._nthModalOpened === Modal._modalsOpen) {
113
+ this.el.focus();
114
+ }
115
+ }
116
+
117
+ _animateIn() {
118
+ // Set initial styles
119
+ this.el.style.display = 'block';
120
+ this.el.style.opacity = '0';
121
+ this._overlay.style.display = 'block';
122
+ this._overlay.style.opacity = '0';
123
+ // Animate overlay
124
+ anim({
125
+ targets: this._overlay,
126
+ opacity: this.options.opacity,
127
+ duration: this.options.inDuration,
128
+ easing: 'easeOutQuad'
129
+ });
130
+ // Define modal animation options
131
+ const enterAnimOptions = {
132
+ targets: this.el,
133
+ duration: this.options.inDuration,
134
+ easing: 'easeOutCubic',
135
+ // Handle modal onOpenEnd callback
136
+ complete: () => {
137
+ if (typeof this.options.onOpenEnd === 'function') {
138
+ this.options.onOpenEnd.call(this, this.el, this._openingTrigger);
139
+ }
140
+ }
141
+ };
142
+ // Bottom sheet animation
143
+ if (this.el.classList.contains('bottom-sheet')) {
144
+ enterAnimOptions['bottom'] = 0;
145
+ enterAnimOptions['opacity'] = 1;
146
+ }
147
+ // Normal modal animation
148
+ else {
149
+ enterAnimOptions['top'] = [this.options.startingTop, this.options.endingTop];
150
+ enterAnimOptions['opacity'] = 1;
151
+ enterAnimOptions['scaleX'] = [0.8, 1];
152
+ enterAnimOptions['scaleY'] = [0.8, 1];
153
+ }
154
+ anim(enterAnimOptions);
155
+ }
156
+
157
+ _animateOut() {
158
+ // Animate overlay
159
+ anim({
160
+ targets: this._overlay,
161
+ opacity: 0,
162
+ duration: this.options.outDuration,
163
+ easing: 'easeOutQuart'
164
+ });
165
+ // Define modal animation options
166
+ const exitAnimOptions = {
167
+ targets: this.el,
168
+ duration: this.options.outDuration,
169
+ easing: 'easeOutCubic',
170
+ // Handle modal ready callback
171
+ complete: () => {
172
+ this.el.style.display = 'none';
173
+ this._overlay.remove();
174
+ // Call onCloseEnd callback
175
+ if (typeof this.options.onCloseEnd === 'function') {
176
+ this.options.onCloseEnd.call(this, this.el);
177
+ }
178
+ }
179
+ };
180
+ // Bottom sheet animation
181
+ if (this.el.classList.contains('bottom-sheet')) {
182
+ exitAnimOptions['bottom'] = '-100%';
183
+ exitAnimOptions['opacity'] = 0;
184
+ }
185
+ // Normal modal animation
186
+ else {
187
+ exitAnimOptions['top'] = [this.options.endingTop, this.options.startingTop];
188
+ exitAnimOptions['opacity'] = 0;
189
+ exitAnimOptions['scaleX'] = 0.8;
190
+ exitAnimOptions['scaleY'] = 0.8;
191
+ }
192
+ anim(exitAnimOptions);
193
+ }
194
+
195
+ open(trigger: HTMLElement|undefined): Modal {
196
+ if (this.isOpen) return;
197
+ this.isOpen = true;
198
+ Modal._modalsOpen++;
199
+ this._nthModalOpened = Modal._modalsOpen;
200
+ // Set Z-Index based on number of currently open modals
201
+ this._overlay.style.zIndex = (1000 + Modal._modalsOpen * 2).toString();
202
+ this.el.style.zIndex = (1000 + Modal._modalsOpen * 2 + 1).toString();
203
+ // Set opening trigger, undefined indicates modal was opened by javascript
204
+ this._openingTrigger = !!trigger ? trigger : undefined;
205
+ // onOpenStart callback
206
+ if (typeof this.options.onOpenStart === 'function') {
207
+ this.options.onOpenStart.call(this, this.el, this._openingTrigger);
208
+ }
209
+ if (this.options.preventScrolling) {
210
+ document.body.style.overflow = 'hidden';
211
+ }
212
+ this.el.classList.add('open');
213
+ this.el.insertAdjacentElement('afterend', this._overlay);
214
+ if (this.options.dismissible) {
215
+ this._handleKeydownBound = this._handleKeydown.bind(this);
216
+ this._handleFocusBound = this._handleFocus.bind(this);
217
+ document.addEventListener('keydown', this._handleKeydownBound);
218
+ document.addEventListener('focus', this._handleFocusBound, true);
219
+ }
220
+ anim.remove(this.el);
221
+ anim.remove(this._overlay);
222
+ this._animateIn();
223
+ // Focus modal
224
+ this.el.focus();
225
+ return this;
226
+ }
227
+
228
+ close() {
229
+ if (!this.isOpen) return;
230
+ this.isOpen = false;
231
+ Modal._modalsOpen--;
232
+ this._nthModalOpened = 0;
233
+ // Call onCloseStart callback
234
+ if (typeof this.options.onCloseStart === 'function') {
235
+ this.options.onCloseStart.call(this, this.el);
236
+ }
237
+ this.el.classList.remove('open');
238
+ // Enable body scrolling only if there are no more modals open.
239
+ if (Modal._modalsOpen === 0) {
240
+ document.body.style.overflow = '';
241
+ }
242
+ if (this.options.dismissible) {
243
+ document.removeEventListener('keydown', this._handleKeydownBound);
244
+ document.removeEventListener('focus', this._handleFocusBound, true);
245
+ }
246
+ anim.remove(this.el);
247
+ anim.remove(this._overlay);
248
+ this._animateOut();
249
+ return this;
250
+ }
251
+
252
+ static{
253
+ Modal._modalsOpen = 0;
254
+ Modal._count = 0;
255
+ }
256
+ }