@materializecss/materialize 2.1.1 → 2.2.1

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Materialize v2.1.1 (https://materializeweb.com)
2
+ * Materialize v2.2.1 (https://materializeweb.com)
3
3
  * Copyright 2014-2024 Materialize
4
4
  * MIT License (https://raw.githubusercontent.com/materializecss/materialize/master/LICENSE)
5
5
  */
@@ -25,7 +25,7 @@ class Utils {
25
25
  ARROW_DOWN: ['ArrowDown', 'Down'],
26
26
  ARROW_LEFT: ['ArrowLeft', 'Left'],
27
27
  ARROW_RIGHT: ['ArrowRight', 'Right'],
28
- DELETE: ['Delete', 'Del'],
28
+ DELETE: ['Delete', 'Del']
29
29
  };
30
30
  /**
31
31
  * Detects when a key is pressed.
@@ -51,6 +51,8 @@ class Utils {
51
51
  * Detects when document is focused.
52
52
  * @param e Event instance.
53
53
  */
54
+ /* eslint-disabled as of required event type condition check */
55
+ /* eslint-disable-next-line */
54
56
  static docHandleFocus(e) {
55
57
  if (Utils.keyDown) {
56
58
  document.body.classList.add('keyboard-focused');
@@ -60,6 +62,8 @@ class Utils {
60
62
  * Detects when document is not focused.
61
63
  * @param e Event instance.
62
64
  */
65
+ /* eslint-disabled as of required event type condition check */
66
+ /* eslint-disable-next-line */
63
67
  static docHandleBlur(e) {
64
68
  document.body.classList.remove('keyboard-focused');
65
69
  }
@@ -81,21 +85,21 @@ class Utils {
81
85
  * @param offset Element offset.
82
86
  */
83
87
  static checkWithinContainer(container, bounding, offset) {
84
- let edges = {
88
+ const edges = {
85
89
  top: false,
86
90
  right: false,
87
91
  bottom: false,
88
92
  left: false
89
93
  };
90
- let containerRect = container.getBoundingClientRect();
94
+ const containerRect = container.getBoundingClientRect();
91
95
  // If body element is smaller than viewport, use viewport height instead.
92
- let containerBottom = container === document.body
96
+ const containerBottom = container === document.body
93
97
  ? Math.max(containerRect.bottom, window.innerHeight)
94
98
  : containerRect.bottom;
95
- let scrollLeft = container.scrollLeft;
96
- let scrollTop = container.scrollTop;
97
- let scrolledX = bounding.left - scrollLeft;
98
- let scrolledY = bounding.top - scrollTop;
99
+ const scrollLeft = container.scrollLeft;
100
+ const scrollTop = container.scrollTop;
101
+ const scrolledX = bounding.left - scrollLeft;
102
+ const scrolledY = bounding.top - scrollTop;
99
103
  // Check for container and viewport for each edge
100
104
  if (scrolledX < containerRect.left + offset || scrolledX < offset) {
101
105
  edges.left = true;
@@ -121,7 +125,7 @@ class Utils {
121
125
  * @param offset Element offset.
122
126
  */
123
127
  static checkPossibleAlignments(el, container, bounding, offset) {
124
- let canAlign = {
128
+ const canAlign = {
125
129
  top: true,
126
130
  right: true,
127
131
  bottom: true,
@@ -131,16 +135,16 @@ class Utils {
131
135
  spaceOnBottom: null,
132
136
  spaceOnLeft: null
133
137
  };
134
- let containerAllowsOverflow = getComputedStyle(container).overflow === 'visible';
135
- let containerRect = container.getBoundingClientRect();
136
- let containerHeight = Math.min(containerRect.height, window.innerHeight);
137
- let containerWidth = Math.min(containerRect.width, window.innerWidth);
138
- let elOffsetRect = el.getBoundingClientRect();
139
- let scrollLeft = container.scrollLeft;
140
- let scrollTop = container.scrollTop;
141
- let scrolledX = bounding.left - scrollLeft;
142
- let scrolledYTopEdge = bounding.top - scrollTop;
143
- let scrolledYBottomEdge = bounding.top + elOffsetRect.height - scrollTop;
138
+ const containerAllowsOverflow = getComputedStyle(container).overflow === 'visible';
139
+ const containerRect = container.getBoundingClientRect();
140
+ const containerHeight = Math.min(containerRect.height, window.innerHeight);
141
+ const containerWidth = Math.min(containerRect.width, window.innerWidth);
142
+ const elOffsetRect = el.getBoundingClientRect();
143
+ const scrollLeft = container.scrollLeft;
144
+ const scrollTop = container.scrollTop;
145
+ const scrolledX = bounding.left - scrollLeft;
146
+ const scrolledYTopEdge = bounding.top - scrollTop;
147
+ const scrolledYBottomEdge = bounding.top + elOffsetRect.height - scrollTop;
144
148
  // Check for container and viewport for left
145
149
  canAlign.spaceOnRight = !containerAllowsOverflow
146
150
  ? containerWidth - (scrolledX + bounding.width)
@@ -189,7 +193,6 @@ class Utils {
189
193
  static getDocumentScrollTop() {
190
194
  return window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0;
191
195
  }
192
- ;
193
196
  /**
194
197
  * Retrieves document scroll postion from left.
195
198
  */
@@ -202,24 +205,20 @@ class Utils {
202
205
  * @param wait Wait time.
203
206
  * @param options Additional options.
204
207
  */
205
- static throttle(func, wait, options = null) {
206
- let context, args, result;
207
- let timeout = null;
208
- let previous = 0;
209
- options || (options = {});
210
- let later = function () {
208
+ static throttle(func, wait, options = {}) {
209
+ let context, args, result, timeout = null, previous = 0;
210
+ const later = () => {
211
211
  previous = options.leading === false ? 0 : new Date().getTime();
212
212
  timeout = null;
213
213
  result = func.apply(context, args);
214
214
  context = args = null;
215
215
  };
216
- return function () {
217
- let now = new Date().getTime();
216
+ return (...args) => {
217
+ const now = new Date().getTime();
218
218
  if (!previous && options.leading === false)
219
219
  previous = now;
220
- let remaining = wait - (now - previous);
220
+ const remaining = wait - (now - previous);
221
221
  context = this;
222
- args = arguments;
223
222
  if (remaining <= 0) {
224
223
  clearTimeout(timeout);
225
224
  timeout = null;
@@ -256,7 +255,7 @@ class Component {
256
255
  console.error(Error(el + ' is not an HTML Element'));
257
256
  }
258
257
  // If exists, destroy and reinitialize in child
259
- let ins = classDef.getInstance(el);
258
+ const ins = classDef.getInstance(el);
260
259
  if (!!ins) {
261
260
  ins.destroy();
262
261
  }
@@ -284,21 +283,26 @@ class Component {
284
283
  /**
285
284
  * @returns default options for component instance.
286
285
  */
287
- static get defaults() { return {}; }
286
+ static get defaults() {
287
+ return {};
288
+ }
288
289
  /**
289
290
  * Retrieves component instance for the given element.
290
291
  * @param el Associated HTML Element.
291
292
  */
293
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
292
294
  static getInstance(el) {
293
- throw new Error("This method must be implemented.");
295
+ throw new Error('This method must be implemented.');
294
296
  }
295
297
  /**
296
298
  * Destroy plugin instance and teardown.
297
299
  */
298
- destroy() { throw new Error("This method must be implemented."); }
300
+ destroy() {
301
+ throw new Error('This method must be implemented.');
302
+ }
299
303
  }
300
304
 
301
- const _defaults$l = {
305
+ const _defaults$m = {
302
306
  alignment: 'left',
303
307
  autoFocus: true,
304
308
  constrainWidth: true,
@@ -331,7 +335,7 @@ class Dropdown extends Component {
331
335
  filterTimeout;
332
336
  constructor(el, options) {
333
337
  super(el, options, Dropdown);
334
- this.el.M_Dropdown = this;
338
+ this.el['M_Dropdown'] = this;
335
339
  Dropdown._dropdowns.push(this);
336
340
  this.id = Utils.getIdFromTrigger(el);
337
341
  this.dropdownEl = document.getElementById(this.id);
@@ -344,13 +348,14 @@ class Dropdown extends Component {
344
348
  this.isTouchMoving = false;
345
349
  this.focusedIndex = -1;
346
350
  this.filterQuery = [];
351
+ this.el.ariaExpanded = 'false';
347
352
  // Move dropdown-content after dropdown-trigger
348
353
  this._moveDropdown();
349
354
  this._makeDropdownFocusable();
350
355
  this._setupEventHandlers();
351
356
  }
352
357
  static get defaults() {
353
- return _defaults$l;
358
+ return _defaults$m;
354
359
  }
355
360
  /**
356
361
  * Initializes instances of Dropdown.
@@ -361,13 +366,13 @@ class Dropdown extends Component {
361
366
  return super.init(els, options, Dropdown);
362
367
  }
363
368
  static getInstance(el) {
364
- return el.M_Dropdown;
369
+ return el['M_Dropdown'];
365
370
  }
366
371
  destroy() {
367
372
  this._resetDropdownStyles();
368
373
  this._removeEventHandlers();
369
374
  Dropdown._dropdowns.splice(Dropdown._dropdowns.indexOf(this), 1);
370
- this.el.M_Dropdown = undefined;
375
+ this.el['M_Dropdown'] = undefined;
371
376
  }
372
377
  _setupEventHandlers() {
373
378
  // Trigger keydown handler
@@ -411,6 +416,7 @@ class Dropdown extends Component {
411
416
  }
412
417
  _handleClick = (e) => {
413
418
  e.preventDefault();
419
+ this._moveDropdown(e.target.closest('li'));
414
420
  if (this.isOpen) {
415
421
  this.close();
416
422
  }
@@ -418,7 +424,8 @@ class Dropdown extends Component {
418
424
  this.open();
419
425
  }
420
426
  };
421
- _handleMouseEnter = () => {
427
+ _handleMouseEnter = (e) => {
428
+ this._moveDropdown(e.target.closest('li'));
422
429
  this.open();
423
430
  };
424
431
  _handleMouseLeave = (e) => {
@@ -426,9 +433,7 @@ class Dropdown extends Component {
426
433
  const leaveToDropdownContent = !!toEl.closest('.dropdown-content');
427
434
  let leaveToActiveDropdownTrigger = false;
428
435
  const closestTrigger = toEl.closest('.dropdown-trigger');
429
- if (closestTrigger &&
430
- !!closestTrigger.M_Dropdown &&
431
- closestTrigger.M_Dropdown.isOpen) {
436
+ if (closestTrigger && !!closestTrigger['M_Dropdown'] && closestTrigger['M_Dropdown'].isOpen) {
432
437
  leaveToActiveDropdownTrigger = true;
433
438
  }
434
439
  // Close hover dropdown if mouse did not leave to either active dropdown-trigger or dropdown-content
@@ -438,9 +443,7 @@ class Dropdown extends Component {
438
443
  };
439
444
  _handleDocumentClick = (e) => {
440
445
  const target = e.target;
441
- if (this.options.closeOnClick &&
442
- target.closest('.dropdown-content') &&
443
- !this.isTouchMoving) {
446
+ if (this.options.closeOnClick && target.closest('.dropdown-content') && !this.isTouchMoving) {
444
447
  // isTouchMoving to check if scrolling on mobile.
445
448
  this.close();
446
449
  }
@@ -527,12 +530,17 @@ class Dropdown extends Component {
527
530
  // CASE WHEN USER TYPE LTTERS
528
531
  const keyText = e.key.toLowerCase();
529
532
  const isLetter = /[a-zA-Z0-9-_]/.test(keyText);
530
- const specialKeys = [...Utils.keys.ARROW_DOWN, ...Utils.keys.ARROW_UP, ...Utils.keys.ENTER, ...Utils.keys.ESC, ...Utils.keys.TAB];
533
+ const specialKeys = [
534
+ ...Utils.keys.ARROW_DOWN,
535
+ ...Utils.keys.ARROW_UP,
536
+ ...Utils.keys.ENTER,
537
+ ...Utils.keys.ESC,
538
+ ...Utils.keys.TAB
539
+ ];
531
540
  if (isLetter && !specialKeys.includes(e.key)) {
532
541
  this.filterQuery.push(keyText);
533
542
  const string = this.filterQuery.join('');
534
- const newOptionEl = Array.from(this.dropdownEl.querySelectorAll('li'))
535
- .find((el) => el.innerText.toLowerCase().indexOf(string) === 0);
543
+ const newOptionEl = Array.from(this.dropdownEl.querySelectorAll('li')).find((el) => el.innerText.toLowerCase().indexOf(string) === 0);
536
544
  if (newOptionEl) {
537
545
  this.focusedIndex = [...newOptionEl.parentNode.children].indexOf(newOptionEl);
538
546
  this._focusFocusedItem();
@@ -540,7 +548,7 @@ class Dropdown extends Component {
540
548
  }
541
549
  this.filterTimeout = setTimeout(this._resetFilterQuery, 1000);
542
550
  };
543
- _handleWindowResize = (e) => {
551
+ _handleWindowResize = () => {
544
552
  // Only re-place the dropdown if it's still visible
545
553
  // Accounts for elements hiding via media queries
546
554
  if (this.el.offsetParent) {
@@ -552,13 +560,16 @@ class Dropdown extends Component {
552
560
  };
553
561
  _resetDropdownStyles() {
554
562
  this.dropdownEl.style.display = '';
563
+ this._resetDropdownPositioningStyles();
564
+ this.dropdownEl.style.transform = '';
565
+ this.dropdownEl.style.opacity = '';
566
+ }
567
+ _resetDropdownPositioningStyles() {
555
568
  this.dropdownEl.style.width = '';
556
569
  this.dropdownEl.style.height = '';
557
570
  this.dropdownEl.style.left = '';
558
571
  this.dropdownEl.style.top = '';
559
572
  this.dropdownEl.style.transformOrigin = '';
560
- this.dropdownEl.style.transform = '';
561
- this.dropdownEl.style.opacity = '';
562
573
  }
563
574
  // Move dropdown after container or trigger
564
575
  _moveDropdown(containerEl = null) {
@@ -577,7 +588,7 @@ class Dropdown extends Component {
577
588
  _makeDropdownFocusable() {
578
589
  if (!this.dropdownEl)
579
590
  return;
580
- this.dropdownEl.popover = "";
591
+ this.dropdownEl.popover = '';
581
592
  // Needed for arrow key navigation
582
593
  this.dropdownEl.tabIndex = 0;
583
594
  // Only set tabindex if it hasn't been set by user
@@ -601,7 +612,7 @@ class Dropdown extends Component {
601
612
  }
602
613
  }
603
614
  _getDropdownPosition(closestOverflowParent) {
604
- this.el.offsetParent.getBoundingClientRect();
615
+ // const offsetParentBRect = this.el.offsetParent.getBoundingClientRect();
605
616
  const triggerBRect = this.el.getBoundingClientRect();
606
617
  const dropdownBRect = this.dropdownEl.getBoundingClientRect();
607
618
  let idealHeight = dropdownBRect.height;
@@ -685,7 +696,7 @@ class Dropdown extends Component {
685
696
  this.dropdownEl.style.opacity = '0';
686
697
  this.dropdownEl.style.transform = 'scale(0.3, 0.3)';
687
698
  setTimeout(() => {
688
- // easeOutQuad (opacity) & easeOutQuint
699
+ // easeOutQuad (opacity) & easeOutQuint
689
700
  this.dropdownEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
690
701
  // to
691
702
  this.dropdownEl.style.opacity = '1';
@@ -700,7 +711,7 @@ class Dropdown extends Component {
700
711
  }
701
712
  _animateOut() {
702
713
  const duration = this.options.outDuration;
703
- // easeOutQuad (opacity) & easeOutQuint
714
+ // easeOutQuad (opacity) & easeOutQuint
704
715
  this.dropdownEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
705
716
  // to
706
717
  this.dropdownEl.style.opacity = '0';
@@ -721,17 +732,15 @@ class Dropdown extends Component {
721
732
  }
722
733
  return null;
723
734
  }
724
- ;
725
735
  _placeDropdown() {
726
736
  // Container here will be closest ancestor with overflow: hidden
727
737
  let closestOverflowParent = this._getClosestAncestor(this.dropdownEl, (ancestor) => {
728
- return !['HTML', 'BODY'].includes(ancestor.tagName) && getComputedStyle(ancestor).overflow !== 'visible';
738
+ return (!['HTML', 'BODY'].includes(ancestor.tagName) &&
739
+ getComputedStyle(ancestor).overflow !== 'visible');
729
740
  });
730
741
  // Fallback
731
742
  if (!closestOverflowParent) {
732
- closestOverflowParent = (!!this.dropdownEl.offsetParent
733
- ? this.dropdownEl.offsetParent
734
- : this.dropdownEl.parentNode);
743
+ closestOverflowParent = ((!!this.dropdownEl.offsetParent ? this.dropdownEl.offsetParent : this.dropdownEl.parentNode));
735
744
  }
736
745
  if (getComputedStyle(closestOverflowParent).position === 'static')
737
746
  closestOverflowParent.style.position = 'relative';
@@ -767,6 +776,7 @@ class Dropdown extends Component {
767
776
  // Do this one frame later so that we don't bind an event handler that's immediately
768
777
  // called when the event bubbles up to the document and closes the dropdown
769
778
  setTimeout(() => this._setupTemporaryEventHandlers(), 0);
779
+ this.el.ariaExpanded = 'true';
770
780
  };
771
781
  /**
772
782
  * Close dropdown.
@@ -785,23 +795,20 @@ class Dropdown extends Component {
785
795
  if (this.options.autoFocus) {
786
796
  this.el.focus();
787
797
  }
798
+ this.el.ariaExpanded = 'false';
788
799
  };
789
800
  /**
790
801
  * While dropdown is open, you can recalculate its dimensions if its contents have changed.
791
802
  */
792
803
  recalculateDimensions = () => {
793
804
  if (this.isOpen) {
794
- this.dropdownEl.style.width = '';
795
- this.dropdownEl.style.height = '';
796
- this.dropdownEl.style.left = '';
797
- this.dropdownEl.style.top = '';
798
- this.dropdownEl.style.transformOrigin = '';
805
+ this._resetDropdownPositioningStyles();
799
806
  this._placeDropdown();
800
807
  }
801
808
  };
802
809
  }
803
810
 
804
- let _defaults$k = {
811
+ const _defaults$l = {
805
812
  data: [], // Autocomplete data set
806
813
  onAutocomplete: null, // Callback for when autocompleted
807
814
  dropdownOptions: {
@@ -814,8 +821,8 @@ let _defaults$k = {
814
821
  isMultiSelect: false,
815
822
  onSearch: (text, autocomplete) => {
816
823
  const normSearch = text.toLocaleLowerCase();
817
- autocomplete.setMenuItems(autocomplete.options.data.filter((option) => option.id.toString().toLocaleLowerCase().includes(normSearch)
818
- || option.text?.toLocaleLowerCase().includes(normSearch)));
824
+ autocomplete.setMenuItems(autocomplete.options.data.filter((option) => option.id.toString().toLocaleLowerCase().includes(normSearch) ||
825
+ option.text?.toLocaleLowerCase().includes(normSearch)));
819
826
  },
820
827
  maxDropDownHeight: '300px',
821
828
  allowUnsafeHTML: false
@@ -838,7 +845,7 @@ class Autocomplete extends Component {
838
845
  menuItems;
839
846
  constructor(el, options) {
840
847
  super(el, options, Autocomplete);
841
- this.el.M_Autocomplete = this;
848
+ this.el['M_Autocomplete'] = this;
842
849
  this.options = {
843
850
  ...Autocomplete.defaults,
844
851
  ...options
@@ -846,7 +853,7 @@ class Autocomplete extends Component {
846
853
  this.isOpen = false;
847
854
  this.count = 0;
848
855
  this.activeIndex = -1;
849
- this.oldVal = "";
856
+ this.oldVal = '';
850
857
  this.selectedValues = [];
851
858
  this.menuItems = this.options.data || [];
852
859
  this.$active = null;
@@ -855,7 +862,7 @@ class Autocomplete extends Component {
855
862
  this._setupEventHandlers();
856
863
  }
857
864
  static get defaults() {
858
- return _defaults$k;
865
+ return _defaults$l;
859
866
  }
860
867
  /**
861
868
  * Initializes instances of Autocomplete.
@@ -866,17 +873,17 @@ class Autocomplete extends Component {
866
873
  return super.init(els, options, Autocomplete);
867
874
  }
868
875
  static getInstance(el) {
869
- return el.M_Autocomplete;
876
+ return el['M_Autocomplete'];
870
877
  }
871
878
  destroy() {
872
879
  this._removeEventHandlers();
873
880
  this._removeDropdown();
874
- this.el.M_Autocomplete = undefined;
881
+ this.el['M_Autocomplete'] = undefined;
875
882
  }
876
883
  _setupEventHandlers() {
877
884
  this.el.addEventListener('blur', this._handleInputBlur);
878
- this.el.addEventListener('keyup', this._handleInputKeyupAndFocus);
879
- this.el.addEventListener('focus', this._handleInputKeyupAndFocus);
885
+ this.el.addEventListener('keyup', this._handleInputKeyup);
886
+ this.el.addEventListener('focus', this._handleInputFocus);
880
887
  this.el.addEventListener('keydown', this._handleInputKeydown);
881
888
  this.el.addEventListener('click', this._handleInputClick);
882
889
  this.container.addEventListener('mousedown', this._handleContainerMousedownAndTouchstart);
@@ -888,8 +895,8 @@ class Autocomplete extends Component {
888
895
  }
889
896
  _removeEventHandlers() {
890
897
  this.el.removeEventListener('blur', this._handleInputBlur);
891
- this.el.removeEventListener('keyup', this._handleInputKeyupAndFocus);
892
- this.el.removeEventListener('focus', this._handleInputKeyupAndFocus);
898
+ this.el.removeEventListener('keyup', this._handleInputKeyup);
899
+ this.el.removeEventListener('focus', this._handleInputFocus);
893
900
  this.el.removeEventListener('keydown', this._handleInputKeydown);
894
901
  this.el.removeEventListener('click', this._handleInputClick);
895
902
  this.container.removeEventListener('mousedown', this._handleContainerMousedownAndTouchstart);
@@ -905,18 +912,19 @@ class Autocomplete extends Component {
905
912
  this.container.id = `autocomplete-options-${Utils.guid()}`;
906
913
  this.container.classList.add('autocomplete-content', 'dropdown-content');
907
914
  this.el.setAttribute('data-target', this.container.id);
908
- this.menuItems.forEach(menuItem => {
915
+ this.menuItems.forEach((menuItem) => {
909
916
  const itemElement = this._createDropdownItem(menuItem);
910
917
  this.container.append(itemElement);
911
918
  });
912
919
  // ! Issue in Component Dropdown: _placeDropdown moves dom-position
913
920
  this.el.parentElement.appendChild(this.container);
914
921
  // Initialize dropdown
915
- let dropdownOptions = {
922
+ const dropdownOptions = {
916
923
  ...Autocomplete.defaults.dropdownOptions,
917
924
  ...this.options.dropdownOptions
918
925
  };
919
- let userOnItemClick = dropdownOptions.onItemClick;
926
+ // @todo shouldn't we conditionally check if dropdownOptions.onItemClick is set in first place?
927
+ const userOnItemClick = dropdownOptions.onItemClick;
920
928
  // Ensuring the select Option call when user passes custom onItemClick function to dropdown
921
929
  dropdownOptions.onItemClick = (li) => {
922
930
  if (!li)
@@ -954,21 +962,31 @@ class Autocomplete extends Component {
954
962
  this._resetAutocomplete();
955
963
  }
956
964
  };
957
- _handleInputKeyupAndFocus = (e) => {
965
+ _handleInputKeyup = (e) => {
958
966
  if (e.type === 'keyup')
959
967
  Autocomplete._keydown = false;
960
968
  this.count = 0;
961
969
  const actualValue = this.el.value.toLocaleLowerCase();
962
970
  // Don't capture enter or arrow key usage.
963
- if (Utils.keys.ENTER.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key))
971
+ if (Utils.keys.ENTER.includes(e.key) ||
972
+ Utils.keys.ARROW_UP.includes(e.key) ||
973
+ Utils.keys.ARROW_DOWN.includes(e.key))
964
974
  return;
965
975
  // Check if the input isn't empty
966
976
  // Check if focus triggered by tab
967
- if (this.oldVal !== actualValue && (Utils.tabPressed || e.type !== 'focus')) {
977
+ if (this.oldVal !== actualValue && Utils.tabPressed) {
968
978
  this.open();
969
979
  }
980
+ this._inputChangeDetection(actualValue);
981
+ };
982
+ _handleInputFocus = () => {
983
+ this.count = 0;
984
+ const actualValue = this.el.value.toLocaleLowerCase();
985
+ this._inputChangeDetection(actualValue);
986
+ };
987
+ _inputChangeDetection = (value) => {
970
988
  // Value has changed!
971
- if (this.oldVal !== actualValue) {
989
+ if (this.oldVal !== value) {
972
990
  this._setStatusLoading();
973
991
  this.options.onSearch(this.el.value, this);
974
992
  }
@@ -977,7 +995,7 @@ class Autocomplete extends Component {
977
995
  this.selectedValues = [];
978
996
  this._triggerChanged();
979
997
  }
980
- this.oldVal = actualValue;
998
+ this.oldVal = value;
981
999
  };
982
1000
  _handleInputKeydown = (e) => {
983
1001
  Autocomplete._keydown = true;
@@ -1083,7 +1101,8 @@ class Autocomplete extends Component {
1083
1101
  item.appendChild(itemText);
1084
1102
  item.querySelector('.item-text').appendChild(div);
1085
1103
  // Description
1086
- if (typeof entry.description === 'string' || (typeof entry.description === 'number' && !isNaN(entry.description))) {
1104
+ if (typeof entry.description === 'string' ||
1105
+ (typeof entry.description === 'number' && !isNaN(entry.description))) {
1087
1106
  const description = document.createElement('small');
1088
1107
  description.setAttribute('style', 'line-height:1.3;color:grey;white-space:nowrap;text-overflow:ellipsis;display:block;width:90%;overflow:hidden;');
1089
1108
  description.innerText = entry.description;
@@ -1115,7 +1134,8 @@ class Autocomplete extends Component {
1115
1134
  }
1116
1135
  }
1117
1136
  _setStatusLoading() {
1118
- this.el.parentElement.querySelector('.status-info').innerHTML = `<div style="height:100%;width:50px;"><svg version="1.1" id="L4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
1137
+ this.el.parentElement.querySelector('.status-info').innerHTML =
1138
+ `<div style="height:100%;width:50px;"><svg version="1.1" id="L4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
1119
1139
  <circle fill="#888c" stroke="none" cx="6" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.1"/></circle>
1120
1140
  <circle fill="#888c" stroke="none" cx="26" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.2"/></circle>
1121
1141
  <circle fill="#888c" stroke="none" cx="46" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.3"/></circle>
@@ -1221,7 +1241,7 @@ class Autocomplete extends Component {
1221
1241
  }
1222
1242
  }
1223
1243
 
1224
- let _defaults$j = {
1244
+ const _defaults$k = {
1225
1245
  direction: 'top',
1226
1246
  hoverEnabled: true,
1227
1247
  toolbarEnabled: false
@@ -1242,7 +1262,7 @@ class FloatingActionButton extends Component {
1242
1262
  btnWidth;
1243
1263
  constructor(el, options) {
1244
1264
  super(el, options, FloatingActionButton);
1245
- this.el.M_FloatingActionButton = this;
1265
+ this.el['M_FloatingActionButton'] = this;
1246
1266
  this.options = {
1247
1267
  ...FloatingActionButton.defaults,
1248
1268
  ...options
@@ -1266,7 +1286,7 @@ class FloatingActionButton extends Component {
1266
1286
  this._setupEventHandlers();
1267
1287
  }
1268
1288
  static get defaults() {
1269
- return _defaults$j;
1289
+ return _defaults$k;
1270
1290
  }
1271
1291
  /**
1272
1292
  * Initializes instances of FloatingActionButton.
@@ -1277,11 +1297,11 @@ class FloatingActionButton extends Component {
1277
1297
  return super.init(els, options, FloatingActionButton);
1278
1298
  }
1279
1299
  static getInstance(el) {
1280
- return el.M_FloatingActionButton;
1300
+ return el['M_FloatingActionButton'];
1281
1301
  }
1282
1302
  destroy() {
1283
1303
  this._removeEventHandlers();
1284
- this.el.M_FloatingActionButton = undefined;
1304
+ this.el['M_FloatingActionButton'] = undefined;
1285
1305
  }
1286
1306
  _setupEventHandlers() {
1287
1307
  if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
@@ -1312,7 +1332,7 @@ class FloatingActionButton extends Component {
1312
1332
  _handleDocumentClick = (e) => {
1313
1333
  const elem = e.target;
1314
1334
  if (elem !== this._menu)
1315
- this.close;
1335
+ this.close();
1316
1336
  };
1317
1337
  /**
1318
1338
  * Open FAB.
@@ -1374,17 +1394,15 @@ class FloatingActionButton extends Component {
1374
1394
  });
1375
1395
  }
1376
1396
  _animateInToolbar() {
1377
- let scaleFactor;
1378
- let windowWidth = window.innerWidth;
1379
- let windowHeight = window.innerHeight;
1380
- let btnRect = this.el.getBoundingClientRect();
1381
- const backdrop = document.createElement('div');
1397
+ const windowWidth = window.innerWidth;
1398
+ const windowHeight = window.innerHeight;
1399
+ const btnRect = this.el.getBoundingClientRect();
1400
+ const backdrop = document.createElement('div'), scaleFactor = windowWidth / backdrop[0].clientWidth, fabColor = getComputedStyle(this._anchor).backgroundColor; // css('background-color');
1382
1401
  backdrop.classList.add('fab-backdrop'); // $('<div class="fab-backdrop"></div>');
1383
- const fabColor = getComputedStyle(this._anchor).backgroundColor; // css('background-color');
1402
+ backdrop.style.backgroundColor = fabColor;
1384
1403
  this._anchor.append(backdrop);
1385
1404
  this.offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
1386
1405
  this.offsetY = windowHeight - btnRect.bottom;
1387
- scaleFactor = windowWidth / backdrop[0].clientWidth;
1388
1406
  this.btnBottom = btnRect.bottom;
1389
1407
  this.btnLeft = btnRect.left;
1390
1408
  this.btnWidth = btnRect.width;
@@ -1398,10 +1416,10 @@ class FloatingActionButton extends Component {
1398
1416
  this.el.style.transition = 'none';
1399
1417
  this._anchor.style.transform = `translateY(${this.offsetY}px`;
1400
1418
  this._anchor.style.transition = 'none';
1401
- backdrop.style.backgroundColor = fabColor;
1402
1419
  setTimeout(() => {
1403
1420
  this.el.style.transform = '';
1404
- this.el.style.transition = 'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s';
1421
+ this.el.style.transition =
1422
+ 'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s';
1405
1423
  this._anchor.style.overflow = 'visible';
1406
1424
  this._anchor.style.transform = '';
1407
1425
  this._anchor.style.transition = 'transform .2s';
@@ -1410,7 +1428,9 @@ class FloatingActionButton extends Component {
1410
1428
  this.el.style.backgroundColor = fabColor;
1411
1429
  backdrop.style.transform = 'scale(' + scaleFactor + ')';
1412
1430
  backdrop.style.transition = 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)';
1413
- this._menu.querySelectorAll('li > a').forEach((a) => a.style.opacity = '1');
1431
+ this._menu
1432
+ .querySelectorAll('li > a')
1433
+ .forEach((a) => (a.style.opacity = '1'));
1414
1434
  // Scroll to close.
1415
1435
  window.addEventListener('scroll', this.close, true);
1416
1436
  document.body.addEventListener('click', this._handleDocumentClick, true);
@@ -1419,49 +1439,143 @@ class FloatingActionButton extends Component {
1419
1439
  }
1420
1440
  }
1421
1441
 
1422
- class Cards {
1423
- static Init() {
1424
- if (typeof document !== 'undefined')
1425
- document.addEventListener("DOMContentLoaded", () => {
1426
- document.body.addEventListener('click', e => {
1427
- const trigger = e.target;
1428
- const card = trigger.closest('.card');
1429
- if (!card)
1430
- return;
1431
- const cardReveal = Array.from(card.children).find(elem => elem.classList.contains('card-reveal'));
1432
- if (!cardReveal)
1433
- return;
1434
- const initialOverflow = getComputedStyle(card).overflow;
1435
- // Close Card
1436
- const closeArea = cardReveal.querySelector('.card-reveal .card-title');
1437
- if (trigger === closeArea || closeArea.contains(trigger)) {
1438
- const duration = 225;
1439
- cardReveal.style.transition = `transform ${duration}ms ease`; //easeInOutQuad
1440
- cardReveal.style.transform = 'translateY(0)';
1441
- setTimeout(() => {
1442
- cardReveal.style.display = 'none';
1443
- card.style.overflow = initialOverflow;
1444
- }, duration);
1445
- }
1446
- // Reveal Card
1447
- const activators = card.querySelectorAll('.activator');
1448
- activators.forEach(activator => {
1449
- if (trigger === activator || activator.contains(trigger)) {
1450
- card.style.overflow = 'hidden';
1451
- cardReveal.style.display = 'block';
1452
- setTimeout(() => {
1453
- const duration = 300;
1454
- cardReveal.style.transition = `transform ${duration}ms ease`; //easeInOutQuad
1455
- cardReveal.style.transform = 'translateY(-100%)';
1456
- }, 1);
1457
- }
1458
- });
1459
- });
1442
+ const _defaults$j = {
1443
+ onOpen: null,
1444
+ onClose: null,
1445
+ inDuration: 225,
1446
+ outDuration: 300
1447
+ };
1448
+ class Cards extends Component {
1449
+ isOpen = false;
1450
+ cardReveal;
1451
+ initialOverflow;
1452
+ _activators;
1453
+ cardRevealClose;
1454
+ constructor(el, options) {
1455
+ super(el, options, Cards);
1456
+ this.el['M_Cards'] = this;
1457
+ this.options = {
1458
+ ...Cards.defaults,
1459
+ ...options
1460
+ };
1461
+ this.cardReveal = this.el.querySelector('.card-reveal');
1462
+ if (this.cardReveal) {
1463
+ this.initialOverflow = getComputedStyle(this.el).overflow;
1464
+ this._activators = Array.from(this.el.querySelectorAll('.activator'));
1465
+ this._activators.forEach((el) => {
1466
+ if (el)
1467
+ el.tabIndex = 0;
1460
1468
  });
1469
+ this.cardRevealClose = this.cardReveal?.querySelector('.card-title');
1470
+ if (this.cardRevealClose)
1471
+ this.cardRevealClose.tabIndex = -1;
1472
+ this.cardReveal.ariaExpanded = 'false';
1473
+ this._setupEventHandlers();
1474
+ }
1475
+ }
1476
+ static get defaults() {
1477
+ return _defaults$j;
1478
+ }
1479
+ /**
1480
+ * Initializes instances of Cards.
1481
+ * @param els HTML elements.
1482
+ * @param options Component options.
1483
+ */
1484
+ static init(els, options) {
1485
+ return super.init(els, options, Cards);
1486
+ }
1487
+ static getInstance(el) {
1488
+ return el['M_Cards'];
1461
1489
  }
1490
+ /**
1491
+ * {@inheritDoc}
1492
+ */
1493
+ destroy() {
1494
+ this._removeEventHandlers();
1495
+ this._activators = [];
1496
+ }
1497
+ _setupEventHandlers = () => {
1498
+ this._activators.forEach((el) => {
1499
+ el.addEventListener('click', this._handleClickInteraction);
1500
+ el.addEventListener('keypress', this._handleKeypressEvent);
1501
+ });
1502
+ };
1503
+ _removeEventHandlers = () => {
1504
+ this._activators.forEach((el) => {
1505
+ el.removeEventListener('click', this._handleClickInteraction);
1506
+ el.removeEventListener('keypress', this._handleKeypressEvent);
1507
+ });
1508
+ };
1509
+ _handleClickInteraction = () => {
1510
+ this._handleRevealEvent();
1511
+ };
1512
+ _handleKeypressEvent = (e) => {
1513
+ if (Utils.keys.ENTER.includes(e.key)) {
1514
+ this._handleRevealEvent();
1515
+ }
1516
+ };
1517
+ _handleRevealEvent = () => {
1518
+ // Reveal Card
1519
+ this._activators.forEach((el) => (el.tabIndex = -1));
1520
+ this.open();
1521
+ };
1522
+ _setupRevealCloseEventHandlers = () => {
1523
+ this.cardRevealClose.addEventListener('click', this.close);
1524
+ this.cardRevealClose.addEventListener('keypress', this._handleKeypressCloseEvent);
1525
+ };
1526
+ _removeRevealCloseEventHandlers = () => {
1527
+ this.cardRevealClose.addEventListener('click', this.close);
1528
+ this.cardRevealClose.addEventListener('keypress', this._handleKeypressCloseEvent);
1529
+ };
1530
+ _handleKeypressCloseEvent = (e) => {
1531
+ if (Utils.keys.ENTER.includes(e.key)) {
1532
+ this.close();
1533
+ }
1534
+ };
1535
+ /**
1536
+ * Show card reveal.
1537
+ */
1538
+ open = () => {
1539
+ if (this.isOpen)
1540
+ return;
1541
+ this.isOpen = true;
1542
+ this.el.style.overflow = 'hidden';
1543
+ this.cardReveal.style.display = 'block';
1544
+ this.cardReveal.ariaExpanded = 'true';
1545
+ this.cardRevealClose.tabIndex = 0;
1546
+ setTimeout(() => {
1547
+ this.cardReveal.style.transition = `transform ${this.options.outDuration}ms ease`; //easeInOutQuad
1548
+ this.cardReveal.style.transform = 'translateY(-100%)';
1549
+ }, 1);
1550
+ if (typeof this.options.onOpen === 'function') {
1551
+ this.options.onOpen.call(this);
1552
+ }
1553
+ this._setupRevealCloseEventHandlers();
1554
+ };
1555
+ /**
1556
+ * Hide card reveal.
1557
+ */
1558
+ close = () => {
1559
+ if (!this.isOpen)
1560
+ return;
1561
+ this.isOpen = false;
1562
+ this.cardReveal.style.transition = `transform ${this.options.inDuration}ms ease`; //easeInOutQuad
1563
+ this.cardReveal.style.transform = 'translateY(0)';
1564
+ setTimeout(() => {
1565
+ this.cardReveal.style.display = 'none';
1566
+ this.cardReveal.ariaExpanded = 'false';
1567
+ this._activators.forEach((el) => (el.tabIndex = 0));
1568
+ this.cardRevealClose.tabIndex = -1;
1569
+ this.el.style.overflow = this.initialOverflow;
1570
+ }, this.options.inDuration);
1571
+ if (typeof this.options.onClose === 'function') {
1572
+ this.options.onClose.call(this);
1573
+ }
1574
+ this._removeRevealCloseEventHandlers();
1575
+ };
1462
1576
  }
1463
1577
 
1464
- let _defaults$i = {
1578
+ const _defaults$i = {
1465
1579
  duration: 200, // ms
1466
1580
  dist: -100, // zoom scale TODO: make this more intuitive as an option
1467
1581
  shift: 0, // spacing for center image
@@ -1504,7 +1618,7 @@ class Carousel extends Component {
1504
1618
  oneTimeCallback;
1505
1619
  constructor(el, options) {
1506
1620
  super(el, options, Carousel);
1507
- this.el.M_Carousel = this;
1621
+ this.el['M_Carousel'] = this;
1508
1622
  this.options = {
1509
1623
  ...Carousel.defaults,
1510
1624
  ...options
@@ -1537,6 +1651,7 @@ class Carousel extends Component {
1537
1651
  if (this.showIndicators) {
1538
1652
  const indicator = document.createElement('li');
1539
1653
  indicator.classList.add('indicator-item');
1654
+ indicator.tabIndex = 0;
1540
1655
  if (i === 0) {
1541
1656
  indicator.classList.add('active');
1542
1657
  }
@@ -1551,7 +1666,7 @@ class Carousel extends Component {
1551
1666
  // Setup cross browser string
1552
1667
  this.xform = 'transform';
1553
1668
  ['webkit', 'Moz', 'O', 'ms'].every((prefix) => {
1554
- var e = prefix + 'Transform';
1669
+ const e = prefix + 'Transform';
1555
1670
  if (typeof document.body.style[e] !== 'undefined') {
1556
1671
  this.xform = e;
1557
1672
  return false;
@@ -1573,11 +1688,11 @@ class Carousel extends Component {
1573
1688
  return super.init(els, options, Carousel);
1574
1689
  }
1575
1690
  static getInstance(el) {
1576
- return el.M_Carousel;
1691
+ return el['M_Carousel'];
1577
1692
  }
1578
1693
  destroy() {
1579
1694
  this._removeEventHandlers();
1580
- this.el.M_Carousel = undefined;
1695
+ this.el['M_Carousel'] = undefined;
1581
1696
  }
1582
1697
  _setupEventHandlers() {
1583
1698
  if (typeof window.ontouchstart !== 'undefined') {
@@ -1593,6 +1708,7 @@ class Carousel extends Component {
1593
1708
  if (this.showIndicators && this._indicators) {
1594
1709
  this._indicators.querySelectorAll('.indicator-item').forEach((el) => {
1595
1710
  el.addEventListener('click', this._handleIndicatorClick);
1711
+ el.addEventListener('keypress', this._handleIndicatorKeyPress);
1596
1712
  });
1597
1713
  }
1598
1714
  // Resize
@@ -1616,7 +1732,9 @@ class Carousel extends Component {
1616
1732
  }
1617
1733
  window.removeEventListener('resize', this._handleThrottledResize);
1618
1734
  }
1619
- _handleThrottledResize = Utils.throttle(function () { this._handleResize(); }, 200, null).bind(this);
1735
+ _handleThrottledResize = Utils.throttle(function () {
1736
+ this._handleResize();
1737
+ }, 200, null).bind(this);
1620
1738
  _handleCarouselTap = (e) => {
1621
1739
  // Fixes firefox draggable image bug
1622
1740
  if (e.type === 'mousedown' && e.target.tagName === 'IMG') {
@@ -1719,7 +1837,8 @@ class Carousel extends Component {
1719
1837
  // fixes https://github.com/materializecss/materialize/issues/180
1720
1838
  if (clickedIndex < 0) {
1721
1839
  // relative X position > center of carousel = clicked at the right part of the carousel
1722
- if (e.clientX - e.target.getBoundingClientRect().left > this.el.clientWidth / 2) {
1840
+ if (e.clientX - e.target.getBoundingClientRect().left >
1841
+ this.el.clientWidth / 2) {
1723
1842
  this.next();
1724
1843
  }
1725
1844
  else {
@@ -1733,6 +1852,15 @@ class Carousel extends Component {
1733
1852
  };
1734
1853
  _handleIndicatorClick = (e) => {
1735
1854
  e.stopPropagation();
1855
+ this._handleIndicatorInteraction(e);
1856
+ };
1857
+ _handleIndicatorKeyPress = (e) => {
1858
+ e.stopPropagation();
1859
+ if (Utils.keys.ENTER.includes(e.key)) {
1860
+ this._handleIndicatorInteraction(e);
1861
+ }
1862
+ };
1863
+ _handleIndicatorInteraction = (e) => {
1736
1864
  const indicator = e.target.closest('.indicator-item');
1737
1865
  if (indicator) {
1738
1866
  const index = [...indicator.parentNode.children].indexOf(indicator);
@@ -1786,7 +1914,7 @@ class Carousel extends Component {
1786
1914
  }
1787
1915
  _xpos(e) {
1788
1916
  // touch event
1789
- if (e.type.startsWith("touch") && e.targetTouches.length >= 1) {
1917
+ if (e.type.startsWith('touch') && e.targetTouches.length >= 1) {
1790
1918
  return e.targetTouches[0].clientX;
1791
1919
  }
1792
1920
  // mouse event
@@ -1794,27 +1922,23 @@ class Carousel extends Component {
1794
1922
  }
1795
1923
  _ypos(e) {
1796
1924
  // touch event
1797
- if (e.type.startsWith("touch") && e.targetTouches.length >= 1) {
1925
+ if (e.type.startsWith('touch') && e.targetTouches.length >= 1) {
1798
1926
  return e.targetTouches[0].clientY;
1799
1927
  }
1800
1928
  // mouse event
1801
1929
  return e.clientY;
1802
1930
  }
1803
1931
  _wrap(x) {
1804
- return x >= this.count
1805
- ? x % this.count
1806
- : x < 0
1807
- ? this._wrap(this.count + (x % this.count))
1808
- : x;
1932
+ return x >= this.count ? x % this.count : x < 0 ? this._wrap(this.count + (x % this.count)) : x;
1809
1933
  }
1810
1934
  _track = () => {
1811
- let now, elapsed, delta, v;
1812
- now = Date.now();
1813
- elapsed = now - this.timestamp;
1935
+ const now = Date.now(), elapsed = now - this.timestamp, delta = this.offset - this.frame, v = (1000 * delta) / (1 + elapsed);
1936
+ // now = Date.now();
1937
+ // elapsed = now - this.timestamp;
1814
1938
  this.timestamp = now;
1815
- delta = this.offset - this.frame;
1939
+ // delta = this.offset - this.frame;
1816
1940
  this.frame = this.offset;
1817
- v = (1000 * delta) / (1 + elapsed);
1941
+ // v = (1000 * delta) / (1 + elapsed);
1818
1942
  this.velocity = 0.8 * v + 0.2 * this.velocity;
1819
1943
  };
1820
1944
  _autoScroll = () => {
@@ -1837,21 +1961,22 @@ class Carousel extends Component {
1837
1961
  this.el.classList.add('scrolling');
1838
1962
  }
1839
1963
  if (this.scrollingTimeout != null) {
1840
- window.clearTimeout(this.scrollingTimeout);
1964
+ clearTimeout(this.scrollingTimeout);
1841
1965
  }
1842
- this.scrollingTimeout = window.setTimeout(() => {
1966
+ this.scrollingTimeout = setTimeout(() => {
1843
1967
  this.el.classList.remove('scrolling');
1844
1968
  }, this.options.duration);
1845
1969
  // Start actual scroll
1846
- let i, half, delta, dir, tween, el, alignment, zTranslation, tweenedOpacity, centerTweenedOpacity;
1847
- let lastCenter = this.center;
1848
- let numVisibleOffset = 1 / this.options.numVisible;
1849
1970
  this.offset = typeof x === 'number' ? x : this.offset;
1850
1971
  this.center = Math.floor((this.offset + this.dim / 2) / this.dim);
1851
- delta = this.offset - this.center * this.dim;
1852
- dir = delta < 0 ? 1 : -1;
1853
- tween = (-dir * delta * 2) / this.dim;
1854
- half = this.count >> 1;
1972
+ const half = this.count >> 1, delta = this.offset - this.center * this.dim, dir = delta < 0 ? 1 : -1, tween = (-dir * delta * 2) / this.dim;
1973
+ let i, el, alignment, zTranslation, tweenedOpacity, centerTweenedOpacity;
1974
+ const lastCenter = this.center;
1975
+ const numVisibleOffset = 1 / this.options.numVisible;
1976
+ // delta = this.offset - this.center * this.dim;
1977
+ // dir = delta < 0 ? 1 : -1;
1978
+ // tween = (-dir * delta * 2) / this.dim;
1979
+ // half = this.count >> 1;
1855
1980
  if (this.options.fullWidth) {
1856
1981
  alignment = 'translateX(0)';
1857
1982
  centerTweenedOpacity = 1;
@@ -1881,10 +2006,7 @@ class Carousel extends Component {
1881
2006
  this.el.querySelector('.carousel-item').classList.remove('active');
1882
2007
  el.classList.add('active');
1883
2008
  }
1884
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
1885
- this.options.shift *
1886
- tween *
1887
- i}px) translateZ(${this.options.dist * tween}px)`;
2009
+ const transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir * this.options.shift * tween * i}px) translateZ(${this.options.dist * tween}px)`;
1888
2010
  this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
1889
2011
  }
1890
2012
  for (i = 1; i <= half; ++i) {
@@ -1900,8 +2022,7 @@ class Carousel extends Component {
1900
2022
  // Don't show wrapped items.
1901
2023
  if (!this.noWrap || this.center + i < this.count) {
1902
2024
  el = this.images[this._wrap(this.center + i)];
1903
- let transformString = `${alignment} translateX(${this.options.shift +
1904
- (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
2025
+ const transformString = `${alignment} translateX(${this.options.shift + (this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
1905
2026
  this._updateItemStyle(el, tweenedOpacity, -i, transformString);
1906
2027
  }
1907
2028
  // left side
@@ -1916,8 +2037,7 @@ class Carousel extends Component {
1916
2037
  // Don't show wrapped items.
1917
2038
  if (!this.noWrap || this.center - i >= 0) {
1918
2039
  el = this.images[this._wrap(this.center - i)];
1919
- let transformString = `${alignment} translateX(${-this.options.shift +
1920
- (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
2040
+ const transformString = `${alignment} translateX(${-this.options.shift + (-this.dim * i - delta) / 2}px) translateZ(${zTranslation}px)`;
1921
2041
  this._updateItemStyle(el, tweenedOpacity, -i, transformString);
1922
2042
  }
1923
2043
  }
@@ -1925,9 +2045,7 @@ class Carousel extends Component {
1925
2045
  // Don't show wrapped items.
1926
2046
  if (!this.noWrap || (this.center >= 0 && this.center < this.count)) {
1927
2047
  el = this.images[this._wrap(this.center)];
1928
- let transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir *
1929
- this.options.shift *
1930
- tween}px) translateZ(${this.options.dist * tween}px)`;
2048
+ const transformString = `${alignment} translateX(${-delta / 2}px) translateX(${dir * this.options.shift * tween}px) translateZ(${this.options.dist * tween}px)`;
1931
2049
  this._updateItemStyle(el, centerTweenedOpacity, 0, transformString);
1932
2050
  }
1933
2051
  // onCycleTo callback
@@ -2031,7 +2149,7 @@ class Carousel extends Component {
2031
2149
  }
2032
2150
  }
2033
2151
 
2034
- let _defaults$h = {
2152
+ const _defaults$h = {
2035
2153
  data: [],
2036
2154
  placeholder: '',
2037
2155
  secondaryPlaceholder: '',
@@ -2039,6 +2157,7 @@ let _defaults$h = {
2039
2157
  autocompleteOptions: {},
2040
2158
  autocompleteOnly: false,
2041
2159
  limit: Infinity,
2160
+ allowUserInput: false,
2042
2161
  onChipAdd: null,
2043
2162
  onChipSelect: null,
2044
2163
  onChipDelete: null
@@ -2060,30 +2179,28 @@ class Chips extends Component {
2060
2179
  _selectedChip;
2061
2180
  constructor(el, options) {
2062
2181
  super(el, options, Chips);
2063
- this.el.M_Chips = this;
2182
+ this.el['M_Chips'] = this;
2064
2183
  this.options = {
2065
2184
  ...Chips.defaults,
2066
2185
  ...options
2067
2186
  };
2068
- this.el.classList.add('chips', 'input-field');
2187
+ this.el.classList.add('chips');
2069
2188
  this.chipsData = [];
2070
2189
  this._chips = [];
2071
- this._setupInput();
2072
- this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;
2073
- // Set input id
2074
- if (!this._input.getAttribute('id'))
2075
- this._input.setAttribute('id', Utils.guid());
2076
2190
  // Render initial chips
2077
2191
  if (this.options.data.length) {
2078
2192
  this.chipsData = this.options.data;
2079
2193
  this._renderChips();
2080
2194
  }
2081
- // Setup autocomplete if needed
2082
- if (this.hasAutocomplete)
2083
- this._setupAutocomplete();
2084
- this._setPlaceholder();
2085
2195
  this._setupLabel();
2086
- this._setupEventHandlers();
2196
+ // Render input element, setup event handlers
2197
+ if (this.options.allowUserInput) {
2198
+ this.el.classList.add('input-field');
2199
+ this._setupInput();
2200
+ this._setupEventHandlers();
2201
+ // move input to end
2202
+ this.el.append(this._input);
2203
+ }
2087
2204
  }
2088
2205
  static get defaults() {
2089
2206
  return _defaults$h;
@@ -2097,19 +2214,22 @@ class Chips extends Component {
2097
2214
  return super.init(els, options, Chips);
2098
2215
  }
2099
2216
  static getInstance(el) {
2100
- return el.M_Chips;
2217
+ return el['M_Chips'];
2101
2218
  }
2102
2219
  getData() {
2103
2220
  return this.chipsData;
2104
2221
  }
2105
2222
  destroy() {
2106
- this._removeEventHandlers();
2107
- this._chips.forEach(c => c.remove());
2223
+ if (this.options.allowUserInput) {
2224
+ this._removeEventHandlers();
2225
+ }
2226
+ this._chips.forEach((c) => c.remove());
2108
2227
  this._chips = [];
2109
- this.el.M_Chips = undefined;
2228
+ this.el['M_Chips'] = undefined;
2110
2229
  }
2111
2230
  _setupEventHandlers() {
2112
2231
  this.el.addEventListener('click', this._handleChipClick);
2232
+ // @todo why do we need this as document event listener, shouldn't we apply it to the element wrapper itself?
2113
2233
  document.addEventListener('keydown', Chips._handleChipsKeydown);
2114
2234
  document.addEventListener('keyup', Chips._handleChipsKeyup);
2115
2235
  this.el.addEventListener('blur', Chips._handleChipsBlur, true);
@@ -2152,7 +2272,7 @@ class Chips extends Component {
2152
2272
  const tag = e.target.tagName;
2153
2273
  if (tag === 'INPUT' || tag === 'TEXTAREA' || !chipsKeydown)
2154
2274
  return;
2155
- const currChips = chips.M_Chips;
2275
+ const currChips = chips['M_Chips'];
2156
2276
  if (Utils.keys.BACKSPACE.includes(e.key) || Utils.keys.DELETE.includes(e.key)) {
2157
2277
  e.preventDefault();
2158
2278
  let selectIndex = currChips.chipsData.length;
@@ -2186,13 +2306,13 @@ class Chips extends Component {
2186
2306
  }
2187
2307
  }
2188
2308
  }
2189
- static _handleChipsKeyup(e) {
2309
+ static _handleChipsKeyup() {
2190
2310
  Chips._keydown = false;
2191
2311
  }
2192
2312
  static _handleChipsBlur(e) {
2193
2313
  if (!Chips._keydown && document.hidden) {
2194
2314
  const chips = e.target.closest('.chips');
2195
- const currChips = chips.M_Chips;
2315
+ const currChips = chips['M_Chips'];
2196
2316
  currChips._selectedChip = null;
2197
2317
  }
2198
2318
  }
@@ -2228,17 +2348,19 @@ class Chips extends Component {
2228
2348
  const renderedChip = document.createElement('div');
2229
2349
  renderedChip.classList.add('chip');
2230
2350
  renderedChip.innerText = chip.text || chip.id;
2231
- renderedChip.setAttribute('tabindex', "0");
2232
- const closeIcon = document.createElement('i');
2233
- closeIcon.classList.add(this.options.closeIconClass, 'close');
2234
- closeIcon.innerText = 'close';
2235
2351
  // attach image if needed
2236
2352
  if (chip.image) {
2237
2353
  const img = document.createElement('img');
2238
2354
  img.setAttribute('src', chip.image);
2239
2355
  renderedChip.insertBefore(img, renderedChip.firstChild);
2240
2356
  }
2241
- renderedChip.appendChild(closeIcon);
2357
+ if (this.options.allowUserInput) {
2358
+ renderedChip.setAttribute('tabindex', '0');
2359
+ const closeIcon = document.createElement('i');
2360
+ closeIcon.classList.add(this.options.closeIconClass, 'close');
2361
+ closeIcon.innerText = 'close';
2362
+ renderedChip.appendChild(closeIcon);
2363
+ }
2242
2364
  return renderedChip;
2243
2365
  }
2244
2366
  _renderChips() {
@@ -2248,8 +2370,6 @@ class Chips extends Component {
2248
2370
  this.el.appendChild(chipElem);
2249
2371
  this._chips.push(chipElem);
2250
2372
  }
2251
- // move input to end
2252
- this.el.append(this._input);
2253
2373
  }
2254
2374
  _setupAutocomplete() {
2255
2375
  this.options.autocompleteOptions.onAutocomplete = (items) => {
@@ -2271,6 +2391,14 @@ class Chips extends Component {
2271
2391
  this.el.append(this._input);
2272
2392
  }
2273
2393
  this._input.classList.add('input');
2394
+ this.hasAutocomplete = Object.keys(this.options.autocompleteOptions).length > 0;
2395
+ // Setup autocomplete if needed
2396
+ if (this.hasAutocomplete)
2397
+ this._setupAutocomplete();
2398
+ this._setPlaceholder();
2399
+ // Set input id
2400
+ if (!this._input.getAttribute('id'))
2401
+ this._input.setAttribute('id', Utils.guid());
2274
2402
  }
2275
2403
  _setupLabel() {
2276
2404
  this._label = this.el.querySelector('label');
@@ -2288,7 +2416,7 @@ class Chips extends Component {
2288
2416
  }
2289
2417
  _isValidAndNotExist(chip) {
2290
2418
  const isValid = !!chip.id;
2291
- const doesNotExist = !this.chipsData.some(item => item.id == chip.id);
2419
+ const doesNotExist = !this.chipsData.some((item) => item.id == chip.id);
2292
2420
  return isValid && doesNotExist;
2293
2421
  }
2294
2422
  /**
@@ -2339,15 +2467,18 @@ class Chips extends Component {
2339
2467
  }
2340
2468
  static Init() {
2341
2469
  if (typeof document !== 'undefined')
2342
- document.addEventListener("DOMContentLoaded", () => {
2343
- // Handle removal of static chips.
2344
- document.body.addEventListener('click', e => {
2345
- if (e.target.closest('.chip .close')) {
2346
- const chips = e.target.closest('.chips');
2347
- if (chips && chips.M_Chips == undefined)
2348
- return;
2349
- e.target.closest('.chip').remove();
2350
- }
2470
+ // Handle removal of static chips.
2471
+ document.addEventListener('DOMContentLoaded', () => {
2472
+ const chips = document.querySelectorAll('.chips');
2473
+ chips.forEach((el) => {
2474
+ // if (el && (el['M_Chips == undefined) return;
2475
+ el.addEventListener('click', (e) => {
2476
+ if (e.target.classList.contains('close')) {
2477
+ const chip = e.target.closest('.chip');
2478
+ if (chip)
2479
+ chip.remove();
2480
+ }
2481
+ });
2351
2482
  });
2352
2483
  });
2353
2484
  }
@@ -2369,14 +2500,14 @@ class Collapsible extends Component {
2369
2500
  _headers;
2370
2501
  constructor(el, options) {
2371
2502
  super(el, options, Collapsible);
2372
- this.el.M_Collapsible = this;
2503
+ this.el['M_Collapsible'] = this;
2373
2504
  this.options = {
2374
2505
  ...Collapsible.defaults,
2375
2506
  ...options
2376
2507
  };
2377
2508
  // Setup tab indices
2378
2509
  this._headers = Array.from(this.el.querySelectorAll('li > .collapsible-header'));
2379
- this._headers.forEach(el => el.tabIndex = 0);
2510
+ this._headers.forEach((el) => (el.tabIndex = 0));
2380
2511
  this._setupEventHandlers();
2381
2512
  // Open active
2382
2513
  const activeBodies = Array.from(this.el.querySelectorAll('li.active > .collapsible-body'));
@@ -2388,7 +2519,7 @@ class Collapsible extends Component {
2388
2519
  }
2389
2520
  else {
2390
2521
  // Expandables => all active
2391
- activeBodies.forEach(el => this._setExpanded(el));
2522
+ activeBodies.forEach((el) => this._setExpanded(el));
2392
2523
  }
2393
2524
  }
2394
2525
  static get defaults() {
@@ -2403,19 +2534,19 @@ class Collapsible extends Component {
2403
2534
  return super.init(els, options, Collapsible);
2404
2535
  }
2405
2536
  static getInstance(el) {
2406
- return el.M_Collapsible;
2537
+ return el['M_Collapsible'];
2407
2538
  }
2408
2539
  destroy() {
2409
2540
  this._removeEventHandlers();
2410
- this.el.M_Collapsible = undefined;
2541
+ this.el['M_Collapsible'] = undefined;
2411
2542
  }
2412
2543
  _setupEventHandlers() {
2413
2544
  this.el.addEventListener('click', this._handleCollapsibleClick);
2414
- this._headers.forEach(header => header.addEventListener('keydown', this._handleCollapsibleKeydown));
2545
+ this._headers.forEach((header) => header.addEventListener('keydown', this._handleCollapsibleKeydown));
2415
2546
  }
2416
2547
  _removeEventHandlers() {
2417
2548
  this.el.removeEventListener('click', this._handleCollapsibleClick);
2418
- this._headers.forEach(header => header.removeEventListener('keydown', this._handleCollapsibleKeydown));
2549
+ this._headers.forEach((header) => header.removeEventListener('keydown', this._handleCollapsibleKeydown));
2419
2550
  }
2420
2551
  _handleCollapsibleClick = (e) => {
2421
2552
  const header = e.target.closest('.collapsible-header');
@@ -2438,7 +2569,7 @@ class Collapsible extends Component {
2438
2569
  }
2439
2570
  };
2440
2571
  _setExpanded(li) {
2441
- li.style.maxHeight = li.scrollHeight + "px";
2572
+ li.style.maxHeight = li.scrollHeight + 'px';
2442
2573
  }
2443
2574
  _animateIn(index) {
2444
2575
  const li = this.el.children[index];
@@ -2461,7 +2592,7 @@ class Collapsible extends Component {
2461
2592
  const body = li.querySelector('.collapsible-body');
2462
2593
  const duration = this.options.outDuration; // easeInOutCubic
2463
2594
  body.style.transition = `max-height ${duration}ms ease-out`;
2464
- body.style.maxHeight = "0";
2595
+ body.style.maxHeight = '0';
2465
2596
  setTimeout(() => {
2466
2597
  if (typeof this.options.onCloseEnd === 'function') {
2467
2598
  this.options.onCloseEnd.call(this, li);
@@ -2473,7 +2604,7 @@ class Collapsible extends Component {
2473
2604
  * @param n Nth section to open.
2474
2605
  */
2475
2606
  open = (index) => {
2476
- const listItems = Array.from(this.el.children).filter(c => c.tagName === 'LI');
2607
+ const listItems = Array.from(this.el.children).filter((c) => c.tagName === 'LI');
2477
2608
  const li = listItems[index];
2478
2609
  if (li && !li.classList.contains('active')) {
2479
2610
  // onOpenStart callback
@@ -2482,8 +2613,8 @@ class Collapsible extends Component {
2482
2613
  }
2483
2614
  // Handle accordion behavior
2484
2615
  if (this.options.accordion) {
2485
- const activeLis = listItems.filter(li => li.classList.contains('active'));
2486
- activeLis.forEach(activeLi => {
2616
+ const activeLis = listItems.filter((li) => li.classList.contains('active'));
2617
+ activeLis.forEach((activeLi) => {
2487
2618
  const index = listItems.indexOf(activeLi);
2488
2619
  this.close(index);
2489
2620
  });
@@ -2498,7 +2629,7 @@ class Collapsible extends Component {
2498
2629
  * @param n Nth section to close.
2499
2630
  */
2500
2631
  close = (index) => {
2501
- const li = Array.from(this.el.children).filter(c => c.tagName === 'LI')[index];
2632
+ const li = Array.from(this.el.children).filter((c) => c.tagName === 'LI')[index];
2502
2633
  if (li && li.classList.contains('active')) {
2503
2634
  // onCloseStart callback
2504
2635
  if (typeof this.options.onCloseStart === 'function') {
@@ -2512,271 +2643,6 @@ class Collapsible extends Component {
2512
2643
  }
2513
2644
 
2514
2645
  const _defaults$f = {
2515
- opacity: 0.5,
2516
- inDuration: 250,
2517
- outDuration: 250,
2518
- onOpenStart: null,
2519
- onOpenEnd: null,
2520
- onCloseStart: null,
2521
- onCloseEnd: null,
2522
- preventScrolling: true,
2523
- dismissible: true,
2524
- startingTop: '4%',
2525
- endingTop: '10%'
2526
- };
2527
- class Modal extends Component {
2528
- static _modalsOpen;
2529
- static _count;
2530
- /**
2531
- * ID of the modal element.
2532
- */
2533
- id;
2534
- /**
2535
- * If the modal is open.
2536
- */
2537
- isOpen;
2538
- _openingTrigger;
2539
- _overlay;
2540
- _nthModalOpened;
2541
- constructor(el, options) {
2542
- super(el, options, Modal);
2543
- this.el.M_Modal = this;
2544
- this.options = {
2545
- ...Modal.defaults,
2546
- ...options
2547
- };
2548
- this.isOpen = false;
2549
- this.id = this.el.id;
2550
- this._openingTrigger = undefined;
2551
- this._overlay = document.createElement('div');
2552
- this._overlay.classList.add('modal-overlay');
2553
- this.el.tabIndex = 0;
2554
- this._nthModalOpened = 0;
2555
- Modal._count++;
2556
- this._setupEventHandlers();
2557
- }
2558
- static get defaults() {
2559
- return _defaults$f;
2560
- }
2561
- /**
2562
- * Initializes instances of Modal.
2563
- * @param els HTML elements.
2564
- * @param options Component options.
2565
- * @returns {Modal | Modal[]}
2566
- */
2567
- static init(els, options = {}) {
2568
- return super.init(els, options, Modal);
2569
- }
2570
- static getInstance(el) {
2571
- return el.M_Modal;
2572
- }
2573
- destroy() {
2574
- Modal._count--;
2575
- this._removeEventHandlers();
2576
- this.el.removeAttribute('style');
2577
- this._overlay.remove();
2578
- this.el.M_Modal = undefined;
2579
- }
2580
- _setupEventHandlers() {
2581
- if (Modal._count === 1) {
2582
- document.body.addEventListener('click', this._handleTriggerClick);
2583
- }
2584
- this._overlay.addEventListener('click', this._handleOverlayClick);
2585
- this.el.addEventListener('click', this._handleModalCloseClick);
2586
- }
2587
- _removeEventHandlers() {
2588
- if (Modal._count === 0) {
2589
- document.body.removeEventListener('click', this._handleTriggerClick);
2590
- }
2591
- this._overlay.removeEventListener('click', this._handleOverlayClick);
2592
- this.el.removeEventListener('click', this._handleModalCloseClick);
2593
- }
2594
- _handleTriggerClick = (e) => {
2595
- const trigger = e.target.closest('.modal-trigger');
2596
- if (!trigger)
2597
- return;
2598
- const modalId = Utils.getIdFromTrigger(trigger);
2599
- const modalInstance = document.getElementById(modalId).M_Modal;
2600
- if (modalInstance)
2601
- modalInstance.open(trigger);
2602
- e.preventDefault();
2603
- };
2604
- _handleOverlayClick = () => {
2605
- if (this.options.dismissible)
2606
- this.close();
2607
- };
2608
- _handleModalCloseClick = (e) => {
2609
- const closeTrigger = e.target.closest('.modal-close');
2610
- if (closeTrigger)
2611
- this.close();
2612
- };
2613
- _handleKeydown = (e) => {
2614
- if (Utils.keys.ESC.includes(e.key) && this.options.dismissible)
2615
- this.close();
2616
- };
2617
- _handleFocus = (e) => {
2618
- // Only trap focus if this modal is the last model opened (prevents loops in nested modals).
2619
- if (!this.el.contains(e.target) && this._nthModalOpened === Modal._modalsOpen) {
2620
- this.el.focus();
2621
- }
2622
- };
2623
- _animateIn() {
2624
- // Set initial styles
2625
- this._overlay.style.display = 'block';
2626
- this._overlay.style.opacity = '0';
2627
- this.el.style.display = 'block';
2628
- this.el.style.opacity = '0';
2629
- const duration = this.options.inDuration;
2630
- const isBottomSheet = this.el.classList.contains('bottom-sheet');
2631
- if (!isBottomSheet) {
2632
- this.el.style.top = this.options.startingTop;
2633
- this.el.style.transform = 'scaleX(0.9) scaleY(0.9)';
2634
- }
2635
- // Overlay
2636
- this._overlay.style.transition = `opacity ${duration}ms ease-out`; // v1: easeOutQuad
2637
- // Modal
2638
- this.el.style.transition = `
2639
- top ${duration}ms ease-out,
2640
- bottom ${duration}ms ease-out,
2641
- opacity ${duration}ms ease-out,
2642
- transform ${duration}ms ease-out
2643
- `;
2644
- setTimeout(() => {
2645
- this._overlay.style.opacity = this.options.opacity.toString();
2646
- this.el.style.opacity = '1';
2647
- if (isBottomSheet) {
2648
- this.el.style.bottom = '0';
2649
- }
2650
- else {
2651
- this.el.style.top = this.options.endingTop;
2652
- this.el.style.transform = 'scaleX(1) scaleY(1)';
2653
- }
2654
- setTimeout(() => {
2655
- if (typeof this.options.onOpenEnd === 'function') {
2656
- this.options.onOpenEnd.call(this, this.el, this._openingTrigger);
2657
- }
2658
- }, duration);
2659
- }, 1);
2660
- }
2661
- _animateOut() {
2662
- const duration = this.options.outDuration;
2663
- const isBottomSheet = this.el.classList.contains('bottom-sheet');
2664
- if (!isBottomSheet) {
2665
- this.el.style.top = this.options.endingTop;
2666
- }
2667
- // Overlay
2668
- this._overlay.style.transition = `opacity ${duration}ms ease-out`; // v1: easeOutQuart
2669
- // Modal // easeOutCubic
2670
- this.el.style.transition = `
2671
- top ${duration}ms ease-out,
2672
- bottom ${duration}ms ease-out,
2673
- opacity ${duration}ms ease-out,
2674
- transform ${duration}ms ease-out
2675
- `;
2676
- setTimeout(() => {
2677
- this._overlay.style.opacity = '0';
2678
- this.el.style.opacity = '0';
2679
- if (isBottomSheet) {
2680
- this.el.style.bottom = '-100%';
2681
- }
2682
- else {
2683
- this.el.style.top = this.options.startingTop;
2684
- this.el.style.transform = 'scaleX(0.9) scaleY(0.9)';
2685
- }
2686
- setTimeout(() => {
2687
- this.el.style.display = 'none';
2688
- this._overlay.remove();
2689
- if (typeof this.options.onCloseEnd === 'function') {
2690
- this.options.onCloseEnd.call(this, this.el);
2691
- }
2692
- }, duration);
2693
- }, 1);
2694
- }
2695
- /**
2696
- * Open modal.
2697
- */
2698
- open = (trigger) => {
2699
- if (this.isOpen)
2700
- return;
2701
- this.isOpen = true;
2702
- Modal._modalsOpen++;
2703
- this._nthModalOpened = Modal._modalsOpen;
2704
- // Set Z-Index based on number of currently open modals
2705
- this._overlay.style.zIndex = (1000 + Modal._modalsOpen * 2).toString();
2706
- this.el.style.zIndex = (1000 + Modal._modalsOpen * 2 + 1).toString();
2707
- // Set opening trigger, undefined indicates modal was opened by javascript
2708
- this._openingTrigger = !!trigger ? trigger : undefined;
2709
- // onOpenStart callback
2710
- if (typeof this.options.onOpenStart === 'function') {
2711
- this.options.onOpenStart.call(this, this.el, this._openingTrigger);
2712
- }
2713
- if (this.options.preventScrolling) {
2714
- const hasVerticalScrollBar = document.documentElement.scrollHeight > document.documentElement.clientHeight;
2715
- if (hasVerticalScrollBar) {
2716
- const scrollTop = document.documentElement.scrollTop;
2717
- document.documentElement.style.top = '-' + scrollTop + "px";
2718
- document.documentElement.classList.add('noscroll');
2719
- }
2720
- }
2721
- this.el.classList.add('open');
2722
- this.el.insertAdjacentElement('afterend', this._overlay);
2723
- if (this.options.dismissible) {
2724
- document.addEventListener('keydown', this._handleKeydown);
2725
- document.addEventListener('focus', this._handleFocus, true);
2726
- }
2727
- this._animateIn();
2728
- // Focus modal
2729
- this.el.focus();
2730
- return this;
2731
- };
2732
- /**
2733
- * Close modal.
2734
- */
2735
- close = () => {
2736
- if (!this.isOpen)
2737
- return;
2738
- this.isOpen = false;
2739
- Modal._modalsOpen--;
2740
- this._nthModalOpened = 0;
2741
- // Call onCloseStart callback
2742
- if (typeof this.options.onCloseStart === 'function') {
2743
- this.options.onCloseStart.call(this, this.el);
2744
- }
2745
- this.el.classList.remove('open');
2746
- // Enable body scrolling only if there are no more modals open.
2747
- if (Modal._modalsOpen === 0) {
2748
- const scrollTop = -parseInt(document.documentElement.style.top);
2749
- document.documentElement.style.removeProperty("top");
2750
- document.documentElement.classList.remove('noscroll');
2751
- document.documentElement.scrollTop = scrollTop;
2752
- }
2753
- if (this.options.dismissible) {
2754
- document.removeEventListener('keydown', this._handleKeydown);
2755
- document.removeEventListener('focus', this._handleFocus, true);
2756
- }
2757
- this._animateOut();
2758
- return this;
2759
- };
2760
- // Experimental!
2761
- // also note: https://stackoverflow.com/a/35385518/8830502
2762
- static create(children = '') {
2763
- return `<dialog id="modal1" class="modal">
2764
- <div class="modal-content">
2765
- <h4>${children}</h4>
2766
- <p>A bunch of text</p>
2767
- </div>
2768
- <div class="modal-footer">
2769
- <a href="#!" class="modal-close waves-effect btn-flat">Agree</a>
2770
- </div>
2771
- </dialog>`;
2772
- }
2773
- static {
2774
- Modal._modalsOpen = 0;
2775
- Modal._count = 0;
2776
- }
2777
- }
2778
-
2779
- let _defaults$e = {
2780
2646
  classes: '',
2781
2647
  dropdownOptions: {}
2782
2648
  };
@@ -2802,7 +2668,7 @@ class FormSelect extends Component {
2802
2668
  super(el, options, FormSelect);
2803
2669
  if (this.el.classList.contains('browser-default'))
2804
2670
  return;
2805
- this.el.M_FormSelect = this;
2671
+ this.el['M_FormSelect'] = this;
2806
2672
  this.options = {
2807
2673
  ...FormSelect.defaults,
2808
2674
  ...options
@@ -2814,7 +2680,7 @@ class FormSelect extends Component {
2814
2680
  this._setupEventHandlers();
2815
2681
  }
2816
2682
  static get defaults() {
2817
- return _defaults$e;
2683
+ return _defaults$f;
2818
2684
  }
2819
2685
  /**
2820
2686
  * Initializes instances of FormSelect.
@@ -2825,18 +2691,18 @@ class FormSelect extends Component {
2825
2691
  return super.init(els, options, FormSelect);
2826
2692
  }
2827
2693
  static getInstance(el) {
2828
- return el.M_FormSelect;
2694
+ return el['M_FormSelect'];
2829
2695
  }
2830
2696
  destroy() {
2831
2697
  this._removeEventHandlers();
2832
2698
  this._removeDropdown();
2833
- this.el.M_FormSelect = undefined;
2699
+ this.el['M_FormSelect'] = undefined;
2834
2700
  }
2835
2701
  _setupEventHandlers() {
2836
2702
  this.dropdownOptions.querySelectorAll('li:not(.optgroup)').forEach((el) => {
2837
2703
  el.addEventListener('click', this._handleOptionClick);
2838
2704
  el.addEventListener('keydown', (e) => {
2839
- if (e.key === " " || e.key === "Enter")
2705
+ if (e.key === ' ' || e.key === 'Enter')
2840
2706
  this._handleOptionClick(e);
2841
2707
  });
2842
2708
  });
@@ -2872,7 +2738,8 @@ class FormSelect extends Component {
2872
2738
  return true;
2873
2739
  }
2874
2740
  _selectOptionElement(virtualOption) {
2875
- if (!virtualOption.classList.contains('disabled') && !virtualOption.classList.contains('optgroup')) {
2741
+ if (!virtualOption.classList.contains('disabled') &&
2742
+ !virtualOption.classList.contains('optgroup')) {
2876
2743
  const value = this._values.find((value) => value.optionEl === virtualOption);
2877
2744
  const previousSelectedValues = this.getSelectedValues();
2878
2745
  if (this.isMultiple) {
@@ -2918,7 +2785,7 @@ class FormSelect extends Component {
2918
2785
  hiddenDiv.appendChild(this.el);
2919
2786
  if (this.el.disabled)
2920
2787
  this.wrapper.classList.add('disabled');
2921
- this.selectOptions = Array.from(this.el.children).filter(el => ['OPTION', 'OPTGROUP'].includes(el.tagName));
2788
+ this.selectOptions = (Array.from(this.el.children).filter((el) => ['OPTION', 'OPTGROUP'].includes(el.tagName)));
2922
2789
  // Create dropdown
2923
2790
  this.dropdownOptions = document.createElement('ul');
2924
2791
  this.dropdownOptions.id = `select-options-${Utils.guid()}`;
@@ -2937,7 +2804,7 @@ class FormSelect extends Component {
2937
2804
  }
2938
2805
  else if (realOption.tagName === 'OPTGROUP') {
2939
2806
  // Optgroup
2940
- const groupId = "opt-group-" + Utils.guid();
2807
+ const groupId = 'opt-group-' + Utils.guid();
2941
2808
  const groupParent = document.createElement('li');
2942
2809
  groupParent.classList.add('optgroup');
2943
2810
  groupParent.tabIndex = -1;
@@ -2946,42 +2813,42 @@ class FormSelect extends Component {
2946
2813
  groupParent.innerHTML = `<span id="${groupId}" role="presentation">${realOption.getAttribute('label')}</span>`;
2947
2814
  this.dropdownOptions.append(groupParent);
2948
2815
  const groupChildren = [];
2949
- const selectOptions = Array.from(realOption.children).filter(el => el.tagName === 'OPTION');
2950
- selectOptions.forEach(realOption => {
2816
+ const selectOptions = (Array.from(realOption.children).filter((el) => el.tagName === 'OPTION'));
2817
+ selectOptions.forEach((realOption) => {
2951
2818
  const virtualOption = this._createAndAppendOptionWithIcon(realOption, 'optgroup-option');
2952
- const childId = "opt-child-" + Utils.guid();
2819
+ const childId = 'opt-child-' + Utils.guid();
2953
2820
  virtualOption.id = childId;
2954
2821
  groupChildren.push(childId);
2955
2822
  this._addOptionToValues(realOption, virtualOption);
2956
2823
  });
2957
- groupParent.setAttribute("aria-owns", groupChildren.join(" "));
2824
+ groupParent.setAttribute('aria-owns', groupChildren.join(' '));
2958
2825
  }
2959
2826
  });
2960
2827
  }
2961
2828
  this.wrapper.append(this.dropdownOptions);
2962
2829
  // Add input dropdown
2963
2830
  this.input = document.createElement('input');
2964
- this.input.id = "m_select-input-" + Utils.guid();
2831
+ this.input.id = 'm_select-input-' + Utils.guid();
2965
2832
  this.input.classList.add('select-dropdown', 'dropdown-trigger');
2966
2833
  this.input.type = 'text';
2967
2834
  this.input.readOnly = true;
2968
2835
  this.input.setAttribute('data-target', this.dropdownOptions.id);
2969
2836
  this.input.ariaReadOnly = 'true';
2970
- this.input.ariaRequired = this.el.hasAttribute("required").toString(); //setAttribute("aria-required", this.el.hasAttribute("required"));
2837
+ this.input.ariaRequired = this.el.hasAttribute('required').toString(); //setAttribute("aria-required", this.el.hasAttribute("required"));
2971
2838
  if (this.el.disabled)
2972
2839
  this.input.disabled = true; // 'true');
2973
2840
  const attrs = this.el.attributes;
2974
2841
  for (let i = 0; i < attrs.length; ++i) {
2975
2842
  const attr = attrs[i];
2976
- if (attr.name.startsWith("aria-"))
2843
+ if (attr.name.startsWith('aria-'))
2977
2844
  this.input.setAttribute(attr.name, attr.value);
2978
2845
  }
2979
2846
  // Adds aria-attributes to input element
2980
2847
  this.input.setAttribute('role', 'combobox');
2981
2848
  this.input.ariaExpanded = 'false';
2982
- this.input.setAttribute("aria-owns", this.dropdownOptions.id);
2983
- this.input.setAttribute("aria-controls", this.dropdownOptions.id);
2984
- this.input.placeholder = " ";
2849
+ this.input.setAttribute('aria-owns', this.dropdownOptions.id);
2850
+ this.input.setAttribute('aria-controls', this.dropdownOptions.id);
2851
+ this.input.placeholder = ' ';
2985
2852
  this.wrapper.prepend(this.input);
2986
2853
  this._setValueToInput();
2987
2854
  // Add caret
@@ -3000,7 +2867,7 @@ class FormSelect extends Component {
3000
2867
  const userOnOpenEnd = dropdownOptions.onOpenEnd;
3001
2868
  const userOnCloseEnd = dropdownOptions.onCloseEnd;
3002
2869
  // Add callback for centering selected option when dropdown content is scrollable
3003
- dropdownOptions.onOpenEnd = (el) => {
2870
+ dropdownOptions.onOpenEnd = () => {
3004
2871
  const selectedOption = this.dropdownOptions.querySelector('.selected');
3005
2872
  if (selectedOption) {
3006
2873
  // Focus selected option in dropdown
@@ -3022,7 +2889,7 @@ class FormSelect extends Component {
3022
2889
  userOnOpenEnd.call(this.dropdown, this.el);
3023
2890
  };
3024
2891
  // Add callback for reseting "expanded" state
3025
- dropdownOptions.onCloseEnd = (el) => {
2892
+ dropdownOptions.onCloseEnd = () => {
3026
2893
  this.input.ariaExpanded = 'false';
3027
2894
  // Handle user declared onOpenEnd if needed
3028
2895
  if (userOnCloseEnd && typeof userOnCloseEnd === 'function')
@@ -3100,7 +2967,7 @@ class FormSelect extends Component {
3100
2967
  checkbox.checked = false;
3101
2968
  }
3102
2969
  _deselectAll() {
3103
- this._values.forEach(value => this._deselectValue(value));
2970
+ this._values.forEach((value) => this._deselectValue(value));
3104
2971
  }
3105
2972
  _isValueSelected(value) {
3106
2973
  const realValues = this.getSelectedValues();
@@ -3120,7 +2987,7 @@ class FormSelect extends Component {
3120
2987
  const selectedRealOptions = this._getSelectedOptions();
3121
2988
  const selectedOptionPairs = this._values.filter((value) => selectedRealOptions.indexOf(value.el) >= 0);
3122
2989
  // Filter not disabled
3123
- const notDisabledOptionPairs = selectedOptionPairs.filter(op => !op.el.disabled);
2990
+ const notDisabledOptionPairs = selectedOptionPairs.filter((op) => !op.el.disabled);
3124
2991
  const texts = notDisabledOptionPairs.map((value) => value.optionEl.querySelector('span').innerText.trim());
3125
2992
  // Set input-text to first Option with empty value which indicates a description like "choose your option"
3126
2993
  if (texts.length === 0) {
@@ -3151,7 +3018,7 @@ class FormSelect extends Component {
3151
3018
  if (!li)
3152
3019
  return;
3153
3020
  if (!this.isMultiple)
3154
- ul.querySelectorAll('li.selected').forEach(li => li.classList.remove('selected'));
3021
+ ul.querySelectorAll('li.selected').forEach((li) => li.classList.remove('selected'));
3155
3022
  li.classList.add('selected');
3156
3023
  li.ariaSelected = 'true';
3157
3024
  }
@@ -3160,17 +3027,23 @@ class FormSelect extends Component {
3160
3027
  }
3161
3028
  }
3162
3029
 
3163
- let _defaults$d = {
3164
- // Close when date is selected
3165
- autoClose: false,
3030
+ const _defaults$e = {
3166
3031
  // the default output format for the input field value
3167
3032
  format: 'mmm dd, yyyy',
3168
3033
  // Used to create date object from current input string
3169
3034
  parse: null,
3035
+ // The initial condition if the datepicker is based on date range
3036
+ isDateRange: false,
3037
+ // The initial condition if the datepicker is based on multiple date selection
3038
+ isMultipleSelection: false,
3170
3039
  // The initial date to view when first opened
3171
3040
  defaultDate: null,
3041
+ // The initial end date to view when first opened
3042
+ defaultEndDate: null,
3172
3043
  // Make the `defaultDate` the initial selected value
3173
3044
  setDefaultDate: false,
3045
+ // Make the `defaultEndDate` the initial selected value
3046
+ setDefaultEndDate: false,
3174
3047
  disableWeekends: false,
3175
3048
  disableDayFn: null,
3176
3049
  // First day of week (0: Sunday, 1: Monday etc)
@@ -3241,15 +3114,11 @@ let _defaults$d = {
3241
3114
  events: [],
3242
3115
  // callback function
3243
3116
  onSelect: null,
3244
- onOpen: null,
3245
- onClose: null,
3246
3117
  onDraw: null
3247
3118
  };
3248
3119
  class Datepicker extends Component {
3249
3120
  id;
3250
- /** If the picker is open. */
3251
- isOpen;
3252
- modal;
3121
+ multiple = false;
3253
3122
  calendarEl;
3254
3123
  /** CLEAR button instance. */
3255
3124
  clearBtn;
@@ -3259,8 +3128,12 @@ class Datepicker extends Component {
3259
3128
  modalEl;
3260
3129
  yearTextEl;
3261
3130
  dateTextEl;
3131
+ endDateEl;
3132
+ dateEls;
3262
3133
  /** The selected Date. */
3263
3134
  date;
3135
+ endDate;
3136
+ dates;
3264
3137
  formats;
3265
3138
  calendars;
3266
3139
  _y;
@@ -3268,7 +3141,7 @@ class Datepicker extends Component {
3268
3141
  static _template;
3269
3142
  constructor(el, options) {
3270
3143
  super(el, options, Datepicker);
3271
- this.el.M_Datepicker = this;
3144
+ this.el['M_Datepicker'] = this;
3272
3145
  this.options = {
3273
3146
  ...Datepicker.defaults,
3274
3147
  ...options
@@ -3285,16 +3158,15 @@ class Datepicker extends Component {
3285
3158
  this.id = Utils.guid();
3286
3159
  this._setupVariables();
3287
3160
  this._insertHTMLIntoDOM();
3288
- this._setupModal();
3289
3161
  this._setupEventHandlers();
3290
3162
  if (!this.options.defaultDate) {
3291
3163
  this.options.defaultDate = new Date(Date.parse(this.el.value));
3292
3164
  }
3293
- let defDate = this.options.defaultDate;
3165
+ const defDate = this.options.defaultDate;
3294
3166
  if (Datepicker._isDate(defDate)) {
3295
3167
  if (this.options.setDefaultDate) {
3296
3168
  this.setDate(defDate, true);
3297
- this.setInputValue();
3169
+ this.setInputValue(this.el, defDate);
3298
3170
  }
3299
3171
  else {
3300
3172
  this.gotoDate(defDate);
@@ -3303,10 +3175,25 @@ class Datepicker extends Component {
3303
3175
  else {
3304
3176
  this.gotoDate(new Date());
3305
3177
  }
3306
- this.isOpen = false;
3178
+ if (this.options.isDateRange) {
3179
+ this.multiple = true;
3180
+ const defEndDate = this.options.defaultEndDate;
3181
+ if (Datepicker._isDate(defEndDate)) {
3182
+ if (this.options.setDefaultEndDate) {
3183
+ this.setDate(defEndDate, true, true);
3184
+ this.setInputValue(this.endDateEl, defEndDate);
3185
+ }
3186
+ }
3187
+ }
3188
+ if (this.options.isMultipleSelection) {
3189
+ this.multiple = true;
3190
+ this.dates = [];
3191
+ this.dateEls = [];
3192
+ this.dateEls.push(el);
3193
+ }
3307
3194
  }
3308
3195
  static get defaults() {
3309
- return _defaults$d;
3196
+ return _defaults$e;
3310
3197
  }
3311
3198
  /**
3312
3199
  * Initializes instances of Datepicker.
@@ -3320,9 +3207,12 @@ class Datepicker extends Component {
3320
3207
  return /Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
3321
3208
  }
3322
3209
  static _isWeekend(date) {
3323
- let day = date.getDay();
3210
+ const day = date.getDay();
3324
3211
  return day === 0 || day === 6;
3325
3212
  }
3213
+ /**
3214
+ * @deprecated as this function has no effect without any return statement or global parameter setter.
3215
+ */
3326
3216
  static _setToStartOfDay(date) {
3327
3217
  if (Datepicker._isDate(date))
3328
3218
  date.setHours(0, 0, 0, 0);
@@ -3338,27 +3228,40 @@ class Datepicker extends Component {
3338
3228
  // weak date comparison (use setToStartOfDay(date) to ensure correct result)
3339
3229
  return a.getTime() === b.getTime();
3340
3230
  }
3231
+ static _compareWithinRange(day, date, dateEnd) {
3232
+ return day.getTime() > date.getTime() && day.getTime() < dateEnd.getTime();
3233
+ }
3234
+ static _comparePastDate(a, b) {
3235
+ return a.getTime() < b.getTime();
3236
+ }
3341
3237
  static getInstance(el) {
3342
- return el.M_Datepicker;
3238
+ return el['M_Datepicker'];
3343
3239
  }
3344
3240
  destroy() {
3345
3241
  this._removeEventHandlers();
3346
- this.modal.destroy();
3347
3242
  this.modalEl.remove();
3348
3243
  this.destroySelects();
3349
- this.el.M_Datepicker = undefined;
3244
+ this.el['M_Datepicker'] = undefined;
3350
3245
  }
3351
3246
  destroySelects() {
3352
- let oldYearSelect = this.calendarEl.querySelector('.orig-select-year');
3247
+ const oldYearSelect = this.calendarEl.querySelector('.orig-select-year');
3353
3248
  if (oldYearSelect) {
3354
3249
  FormSelect.getInstance(oldYearSelect).destroy();
3355
3250
  }
3356
- let oldMonthSelect = this.calendarEl.querySelector('.orig-select-month');
3251
+ const oldMonthSelect = this.calendarEl.querySelector('.orig-select-month');
3357
3252
  if (oldMonthSelect) {
3358
3253
  FormSelect.getInstance(oldMonthSelect).destroy();
3359
3254
  }
3360
3255
  }
3361
3256
  _insertHTMLIntoDOM() {
3257
+ // HTML5 input date field support
3258
+ if (this.el.type == 'date') {
3259
+ this.el.classList.add('datepicker-date-input');
3260
+ }
3261
+ if (this.options.isDateRange) {
3262
+ this.endDateEl = this.createDateInput();
3263
+ this.endDateEl.classList.add('datepicker-end-date');
3264
+ }
3362
3265
  if (this.options.showClearBtn) {
3363
3266
  this.clearBtn.style.visibility = '';
3364
3267
  this.clearBtn.innerText = this.options.i18n.clear;
@@ -3376,39 +3279,59 @@ class Datepicker extends Component {
3376
3279
  this.el.parentElement.appendChild(this.modalEl);
3377
3280
  }
3378
3281
  }
3379
- _setupModal() {
3380
- this.modalEl.id = 'modal-' + this.id;
3381
- this.modal = Modal.init(this.modalEl, {
3382
- onCloseEnd: () => {
3383
- this.isOpen = false;
3384
- }
3385
- });
3386
- }
3387
3282
  /**
3388
- * Gets a string representation of the selected date.
3283
+ * Gets a string representation of the given date.
3389
3284
  */
3390
- toString(format = null) {
3285
+ toString(date = this.date, format = null) {
3391
3286
  format = format || this.options.format;
3392
3287
  if (typeof format === 'function')
3393
- return format(this.date);
3394
- if (!Datepicker._isDate(this.date))
3288
+ return format(date);
3289
+ if (!Datepicker._isDate(date))
3395
3290
  return '';
3396
3291
  // String Format
3292
+ return this.formatDate(date, format);
3293
+ }
3294
+ /**
3295
+ * Returns the formatted date.
3296
+ */
3297
+ formatDate(date, format) {
3397
3298
  const formatArray = format.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
3398
- const formattedDate = formatArray
3399
- .map(label => this.formats[label] ? this.formats[label]() : label)
3299
+ return formatArray
3300
+ .map((label) => (this.formats[label] ? this.formats[label](date) : label))
3400
3301
  .join('');
3401
- return formattedDate;
3302
+ }
3303
+ /**
3304
+ * Sets date from input field.
3305
+ */
3306
+ setDateFromInput(el) {
3307
+ const date = new Date(Date.parse(el.value));
3308
+ this.setDate(date, false, el == this.endDateEl, true);
3402
3309
  }
3403
3310
  /**
3404
3311
  * Set a date on the datepicker.
3405
3312
  * @param date Date to set on the datepicker.
3406
3313
  * @param preventOnSelect Undocumented as of 5 March 2018.
3314
+ * @param isEndDate
3315
+ * @param fromUserInput
3407
3316
  */
3408
- setDate(date = null, preventOnSelect = false) {
3317
+ setDate(date = null, preventOnSelect = false, isEndDate = false, fromUserInput = false) {
3318
+ const selectedDate = this.validateDate(date);
3319
+ if (!selectedDate) {
3320
+ return;
3321
+ }
3322
+ if (!this.options.isMultipleSelection)
3323
+ this.setSingleDate(selectedDate, isEndDate);
3324
+ else if (!fromUserInput)
3325
+ this.setMultiDate(selectedDate);
3326
+ Datepicker._setToStartOfDay(selectedDate);
3327
+ this.gotoDate(selectedDate);
3328
+ if (!preventOnSelect && typeof this.options.onSelect === 'function') {
3329
+ this.options.onSelect.call(this, selectedDate);
3330
+ }
3331
+ }
3332
+ validateDate(date) {
3409
3333
  if (!date) {
3410
- this.date = null;
3411
- this._renderDateDisplay();
3334
+ this._renderDateDisplay(date);
3412
3335
  return this.draw();
3413
3336
  }
3414
3337
  if (typeof date === 'string') {
@@ -3417,36 +3340,114 @@ class Datepicker extends Component {
3417
3340
  if (!Datepicker._isDate(date)) {
3418
3341
  return;
3419
3342
  }
3420
- let min = this.options.minDate, max = this.options.maxDate;
3343
+ const min = this.options.minDate, max = this.options.maxDate;
3421
3344
  if (Datepicker._isDate(min) && date < min) {
3422
3345
  date = min;
3423
3346
  }
3424
3347
  else if (Datepicker._isDate(max) && date > max) {
3425
3348
  date = max;
3426
3349
  }
3427
- this.date = new Date(date.getTime());
3428
- this._renderDateDisplay();
3429
- Datepicker._setToStartOfDay(this.date);
3430
- this.gotoDate(this.date);
3431
- if (!preventOnSelect && typeof this.options.onSelect === 'function') {
3432
- this.options.onSelect.call(this, this.date);
3350
+ return new Date(date.getTime());
3351
+ }
3352
+ /**
3353
+ * Set a single date on the datepicker.
3354
+ * @param date Date to set on the datepicker.
3355
+ * @param isEndDate
3356
+ */
3357
+ setSingleDate(date, isEndDate) {
3358
+ if (!isEndDate) {
3359
+ this.date = date;
3360
+ }
3361
+ else if (isEndDate) {
3362
+ this.endDate = date;
3363
+ }
3364
+ }
3365
+ /**
3366
+ * Set a multi date on the datepicker.
3367
+ * @param date Date to set on the datepicker.
3368
+ */
3369
+ setMultiDate(date) {
3370
+ const selectedDate = this.dates?.find((item) => {
3371
+ return item.getTime() === date.getTime() ? item : false;
3372
+ });
3373
+ if (!selectedDate) {
3374
+ this.dates.push(date);
3375
+ }
3376
+ else {
3377
+ this.dates.splice(this.dates.indexOf(selectedDate), 1);
3378
+ }
3379
+ this.dates.sort((a, b) => (a.getTime() < b.getTime() ? -1 : 0));
3380
+ }
3381
+ /**
3382
+ * Sets the data-date attribute on the date input field
3383
+ */
3384
+ setDataDate(el, date) {
3385
+ el.setAttribute('data-date', this.toString(date));
3386
+ }
3387
+ /**
3388
+ * Sets dates on the input values.
3389
+ */
3390
+ setInputValues() {
3391
+ if (!this.options?.isMultipleSelection) {
3392
+ this.setInputValue(this.el, this.date);
3393
+ if (this.options?.isDateRange) {
3394
+ this.setInputValue(this.endDateEl, this.endDate);
3395
+ }
3396
+ return;
3433
3397
  }
3398
+ this.setMultipleSelectionInputValues();
3399
+ }
3400
+ setMultipleSelectionInputValues() {
3401
+ const dateElsArr = Array.from(this.dateEls).filter((el, index) => {
3402
+ if (index > this.dates.length - 1)
3403
+ return el;
3404
+ });
3405
+ dateElsArr.forEach((el) => {
3406
+ el.remove();
3407
+ });
3408
+ this.dates.forEach((date, index) => {
3409
+ if (Array.from(this.dateEls)[index]) {
3410
+ this.setInputValue(this.dateEls[index], date);
3411
+ return;
3412
+ }
3413
+ const dateEl = this.createDateInput();
3414
+ this.setInputValue(dateEl, date);
3415
+ this.dateEls.push(dateEl);
3416
+ });
3434
3417
  }
3435
3418
  /**
3436
- * Sets current date as the input value.
3419
+ * Sets given date as the input value on the given element.
3437
3420
  */
3438
- setInputValue() {
3439
- this.el.value = this.toString();
3440
- this.el.dispatchEvent(new CustomEvent('change', { bubbles: true, cancelable: true, composed: true, detail: { firedBy: this } }));
3441
- }
3442
- _renderDateDisplay() {
3443
- let displayDate = Datepicker._isDate(this.date) ? this.date : new Date();
3444
- let i18n = this.options.i18n;
3445
- let day = i18n.weekdaysShort[displayDate.getDay()];
3446
- let month = i18n.monthsShort[displayDate.getMonth()];
3447
- let date = displayDate.getDate();
3448
- this.yearTextEl.innerHTML = displayDate.getFullYear().toString();
3449
- this.dateTextEl.innerHTML = `${day}, ${month} ${date}`;
3421
+ setInputValue(el, date) {
3422
+ console.log('setinputvalue');
3423
+ if (el.type == 'date') {
3424
+ this.setDataDate(el, date);
3425
+ el.value = this.formatDate(date, 'yyyy-mm-dd');
3426
+ }
3427
+ else {
3428
+ el.value = this.toString(date);
3429
+ }
3430
+ this.el.dispatchEvent(new CustomEvent('change', {
3431
+ bubbles: true,
3432
+ cancelable: true,
3433
+ composed: true,
3434
+ detail: { firedBy: this }
3435
+ }));
3436
+ }
3437
+ /**
3438
+ * Renders the date in the modal head section.
3439
+ */
3440
+ _renderDateDisplay(date, endDate = null) {
3441
+ const displayDate = Datepicker._isDate(date) ? date : new Date();
3442
+ // this.yearTextEl.innerHTML = displayDate.getFullYear().toString();
3443
+ // @todo should we include an option for date formatting by component options?
3444
+ if (!this.options.isDateRange) {
3445
+ this.dateTextEl.innerHTML = this.formatDate(displayDate, 'ddd, mmm d');
3446
+ }
3447
+ else {
3448
+ const displayEndDate = Datepicker._isDate(endDate) ? endDate : new Date();
3449
+ this.dateTextEl.innerHTML = `${this.formatDate(displayDate, 'mmm d')} - ${this.formatDate(displayEndDate, 'mmm d')}`;
3450
+ }
3450
3451
  }
3451
3452
  /**
3452
3453
  * Change date view to a specific date on the datepicker.
@@ -3458,7 +3459,7 @@ class Datepicker extends Component {
3458
3459
  return;
3459
3460
  }
3460
3461
  if (this.calendars) {
3461
- let firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), lastVisibleDate = new Date(this.calendars[this.calendars.length - 1].year, this.calendars[this.calendars.length - 1].month, 1), visibleDate = date.getTime();
3462
+ const firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), lastVisibleDate = new Date(this.calendars[this.calendars.length - 1].year, this.calendars[this.calendars.length - 1].month, 1), visibleDate = date.getTime();
3462
3463
  // get the end of the month
3463
3464
  lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1);
3464
3465
  lastVisibleDate.setDate(lastVisibleDate.getDate() - 1);
@@ -3499,15 +3500,16 @@ class Datepicker extends Component {
3499
3500
  this.adjustCalendars();
3500
3501
  }
3501
3502
  render(year, month, randId) {
3502
- let opts = this.options, now = new Date(), days = Datepicker._getDaysInMonth(year, month), before = new Date(year, month, 1).getDay(), data = [], row = [];
3503
+ const now = new Date(), days = Datepicker._getDaysInMonth(year, month), data = [];
3504
+ let before = new Date(year, month, 1).getDay(), row = [];
3503
3505
  Datepicker._setToStartOfDay(now);
3504
- if (opts.firstDay > 0) {
3505
- before -= opts.firstDay;
3506
+ if (this.options.firstDay > 0) {
3507
+ before -= this.options.firstDay;
3506
3508
  if (before < 0) {
3507
3509
  before += 7;
3508
3510
  }
3509
3511
  }
3510
- let previousMonth = month === 0 ? 11 : month - 1, nextMonth = month === 11 ? 0 : month + 1, yearOfPreviousMonth = month === 0 ? year - 1 : year, yearOfNextMonth = month === 11 ? year + 1 : year, daysInPreviousMonth = Datepicker._getDaysInMonth(yearOfPreviousMonth, previousMonth);
3512
+ const previousMonth = month === 0 ? 11 : month - 1, nextMonth = month === 11 ? 0 : month + 1, yearOfPreviousMonth = month === 0 ? year - 1 : year, yearOfNextMonth = month === 11 ? year + 1 : year, daysInPreviousMonth = Datepicker._getDaysInMonth(yearOfPreviousMonth, previousMonth);
3511
3513
  let cells = days + before, after = cells;
3512
3514
  while (after > 7) {
3513
3515
  after -= 7;
@@ -3515,12 +3517,27 @@ class Datepicker extends Component {
3515
3517
  cells += 7 - after;
3516
3518
  let isWeekSelected = false;
3517
3519
  for (let i = 0, r = 0; i < cells; i++) {
3518
- let day = new Date(year, month, 1 + (i - before)), isSelected = Datepicker._isDate(this.date)
3519
- ? Datepicker._compareDates(day, this.date)
3520
- : false, isToday = Datepicker._compareDates(day, now), hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false, isEmpty = i < before || i >= days + before, dayNumber = 1 + (i - before), monthNumber = month, yearNumber = year, isStartRange = opts.startRange && Datepicker._compareDates(opts.startRange, day), isEndRange = opts.endRange && Datepicker._compareDates(opts.endRange, day), isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange, isDisabled = (opts.minDate && day < opts.minDate) ||
3521
- (opts.maxDate && day > opts.maxDate) ||
3522
- (opts.disableWeekends && Datepicker._isWeekend(day)) ||
3523
- (opts.disableDayFn && opts.disableDayFn(day));
3520
+ const day = new Date(year, month, 1 + (i - before)), isToday = Datepicker._compareDates(day, now), hasEvent = this.options.events.indexOf(day.toDateString()) !== -1, isEmpty = i < before || i >= days + before, isStartRange = this.options.startRange && Datepicker._compareDates(this.options.startRange, day), isEndRange = this.options.endRange && Datepicker._compareDates(this.options.endRange, day), isInRange = this.options.startRange &&
3521
+ this.options.endRange &&
3522
+ this.options.startRange < day &&
3523
+ day < this.options.endRange, isDisabled = (this.options.minDate && day < this.options.minDate) ||
3524
+ (this.options.maxDate && day > this.options.maxDate) ||
3525
+ (this.options.disableWeekends && Datepicker._isWeekend(day)) ||
3526
+ (this.options.disableDayFn && this.options.disableDayFn(day)), isDateRange = this.options.isDateRange &&
3527
+ Datepicker._isDate(this.endDate) &&
3528
+ Datepicker._compareWithinRange(day, this.date, this.endDate);
3529
+ let dayNumber = 1 + (i - before), monthNumber = month, yearNumber = year;
3530
+ let isSelected = false;
3531
+ if (Datepicker._isDate(this.date)) {
3532
+ isSelected = Datepicker._compareDates(day, this.date);
3533
+ }
3534
+ if (!isSelected && Datepicker._isDate(this.endDate)) {
3535
+ isSelected = Datepicker._compareDates(day, this.endDate);
3536
+ }
3537
+ if (this.options.isMultipleSelection &&
3538
+ this.dates?.some((item) => item.getTime() === day.getTime())) {
3539
+ isSelected = true;
3540
+ }
3524
3541
  if (isEmpty) {
3525
3542
  if (i < before) {
3526
3543
  dayNumber = daysInPreviousMonth + dayNumber;
@@ -3533,7 +3550,7 @@ class Datepicker extends Component {
3533
3550
  yearNumber = yearOfNextMonth;
3534
3551
  }
3535
3552
  }
3536
- let dayConfig = {
3553
+ const dayConfig = {
3537
3554
  day: dayNumber,
3538
3555
  month: monthNumber,
3539
3556
  year: yearNumber,
@@ -3545,20 +3562,21 @@ class Datepicker extends Component {
3545
3562
  isStartRange: isStartRange,
3546
3563
  isEndRange: isEndRange,
3547
3564
  isInRange: isInRange,
3548
- showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths
3565
+ showDaysInNextAndPreviousMonths: this.options.showDaysInNextAndPreviousMonths,
3566
+ isDateRange: isDateRange
3549
3567
  };
3550
3568
  row.push(this.renderDay(dayConfig));
3551
3569
  if (++r === 7) {
3552
- data.push(this.renderRow(row, opts.isRTL, isWeekSelected));
3570
+ data.push(this.renderRow(row, this.options.isRTL, isWeekSelected));
3553
3571
  row = [];
3554
3572
  r = 0;
3555
3573
  isWeekSelected = false;
3556
3574
  }
3557
3575
  }
3558
- return this.renderTable(opts, data, randId);
3576
+ return this.renderTable(this.options, data, randId);
3559
3577
  }
3560
3578
  renderDay(opts) {
3561
- let arr = [];
3579
+ const arr = [];
3562
3580
  let ariaSelected = 'false';
3563
3581
  if (opts.isEmpty) {
3564
3582
  if (opts.showDaysInNextAndPreviousMonths) {
@@ -3569,6 +3587,7 @@ class Datepicker extends Component {
3569
3587
  return '<td class="is-empty"></td>';
3570
3588
  }
3571
3589
  }
3590
+ // @todo wouldn't it be better defining opts class mapping and looping trough opts?
3572
3591
  if (opts.isDisabled) {
3573
3592
  arr.push('is-disabled');
3574
3593
  }
@@ -3579,18 +3598,26 @@ class Datepicker extends Component {
3579
3598
  arr.push('is-selected');
3580
3599
  ariaSelected = 'true';
3581
3600
  }
3601
+ // @todo should we create this additional css class?
3582
3602
  if (opts.hasEvent) {
3583
3603
  arr.push('has-event');
3584
3604
  }
3605
+ // @todo should we create this additional css class?
3585
3606
  if (opts.isInRange) {
3586
3607
  arr.push('is-inrange');
3587
3608
  }
3609
+ // @todo should we create this additional css class?
3588
3610
  if (opts.isStartRange) {
3589
3611
  arr.push('is-startrange');
3590
3612
  }
3613
+ // @todo should we create this additional css class?
3591
3614
  if (opts.isEndRange) {
3592
3615
  arr.push('is-endrange');
3593
3616
  }
3617
+ // @todo create additional css class
3618
+ if (opts.isDateRange) {
3619
+ arr.push('is-daterange');
3620
+ }
3594
3621
  return (`<td data-day="${opts.day}" class="${arr.join(' ')}" aria-selected="${ariaSelected}">` +
3595
3622
  `<button class="datepicker-day-button" type="button" data-year="${opts.year}" data-month="${opts.month}" data-day="${opts.day}">${opts.day}</button>` +
3596
3623
  '</td>');
@@ -3611,7 +3638,8 @@ class Datepicker extends Component {
3611
3638
  '</table></div>');
3612
3639
  }
3613
3640
  renderHead(opts) {
3614
- let i, arr = [];
3641
+ const arr = [];
3642
+ let i;
3615
3643
  for (i = 0; i < 7; i++) {
3616
3644
  arr.push(`<th scope="col"><abbr title="${this.renderDayName(opts, i)}">${this.renderDayName(opts, i, true)}</abbr></th>`);
3617
3645
  }
@@ -3621,10 +3649,11 @@ class Datepicker extends Component {
3621
3649
  return '<tbody>' + rows.join('') + '</tbody>';
3622
3650
  }
3623
3651
  renderTitle(instance, c, year, month, refYear, randId) {
3624
- let i, j, arr, opts = this.options, isMinYear = year === opts.minYear, isMaxYear = year === opts.maxYear, html = '<div id="' +
3652
+ const opts = this.options, isMinYear = year === opts.minYear, isMaxYear = year === opts.maxYear;
3653
+ let i, j, arr = [], html = '<div id="' +
3625
3654
  randId +
3626
- '" class="datepicker-controls" role="heading" aria-live="assertive">', monthHtml, yearHtml, prev = true, next = true;
3627
- for (arr = [], i = 0; i < 12; i++) {
3655
+ '" class="datepicker-controls" role="heading" aria-live="assertive">', prev = true, next = true;
3656
+ for (i = 0; i < 12; i++) {
3628
3657
  arr.push('<option value="' +
3629
3658
  (year === refYear ? i - c : 12 + i - c) +
3630
3659
  '"' +
@@ -3636,7 +3665,9 @@ class Datepicker extends Component {
3636
3665
  opts.i18n.months[i] +
3637
3666
  '</option>');
3638
3667
  }
3639
- monthHtml = '<select class="datepicker-select orig-select-month" tabindex="-1">' + arr.join('') + '</select>';
3668
+ const monthHtml = '<select class="datepicker-select orig-select-month" tabindex="-1">' +
3669
+ arr.join('') +
3670
+ '</select>';
3640
3671
  if (Array.isArray(opts.yearRange)) {
3641
3672
  i = opts.yearRange[0];
3642
3673
  j = opts.yearRange[1] + 1;
@@ -3652,8 +3683,8 @@ class Datepicker extends Component {
3652
3683
  }
3653
3684
  if (opts.yearRangeReverse)
3654
3685
  arr.reverse();
3655
- yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join('')}</select>`;
3656
- let leftArrow = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/><path d="M0-.5h24v24H0z" fill="none"/></svg>';
3686
+ const yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join('')}</select>`;
3687
+ const leftArrow = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/><path d="M0-.5h24v24H0z" fill="none"/></svg>';
3657
3688
  html += `<button class="month-prev${prev ? '' : ' is-disabled'} btn-flat" type="button">${leftArrow}</button>`;
3658
3689
  html += '<div class="selects-container">';
3659
3690
  if (opts.showMonthAfterYear) {
@@ -3669,15 +3700,14 @@ class Datepicker extends Component {
3669
3700
  if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
3670
3701
  next = false;
3671
3702
  }
3672
- let rightArrow = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/><path d="M0-.25h24v24H0z" fill="none"/></svg>';
3703
+ const rightArrow = '<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/><path d="M0-.25h24v24H0z" fill="none"/></svg>';
3673
3704
  html += `<button class="month-next${next ? '' : ' is-disabled'} btn-flat" type="button">${rightArrow}</button>`;
3674
3705
  return (html += '</div>');
3675
3706
  }
3676
3707
  // refresh HTML
3677
- draw(force = false) {
3678
- if (!this.isOpen && !force)
3679
- return;
3680
- let opts = this.options, minYear = opts.minYear, maxYear = opts.maxYear, minMonth = opts.minMonth, maxMonth = opts.maxMonth, html = '', randId;
3708
+ draw() {
3709
+ const opts = this.options, minYear = opts.minYear, maxYear = opts.maxYear, minMonth = opts.minMonth, maxMonth = opts.maxMonth;
3710
+ let html = '';
3681
3711
  if (this._y <= minYear) {
3682
3712
  this._y = minYear;
3683
3713
  if (!isNaN(minMonth) && this._m < minMonth) {
@@ -3690,22 +3720,26 @@ class Datepicker extends Component {
3690
3720
  this._m = maxMonth;
3691
3721
  }
3692
3722
  }
3693
- randId =
3694
- 'datepicker-title-' +
3695
- Math.random()
3696
- .toString(36)
3697
- .replace(/[^a-z]+/g, '')
3698
- .substr(0, 2);
3723
+ const randId = 'datepicker-title-' +
3724
+ Math.random()
3725
+ .toString(36)
3726
+ .replace(/[^a-z]+/g, '')
3727
+ .substr(0, 2);
3699
3728
  for (let c = 0; c < 1; c++) {
3700
- this._renderDateDisplay();
3729
+ if (!this.options.isDateRange) {
3730
+ this._renderDateDisplay(this.date);
3731
+ }
3732
+ else {
3733
+ this._renderDateDisplay(this.date, this.endDate);
3734
+ }
3701
3735
  html +=
3702
3736
  this.renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId);
3703
3737
  }
3704
3738
  this.destroySelects();
3705
3739
  this.calendarEl.innerHTML = html;
3706
3740
  // Init Materialize Select
3707
- let yearSelect = this.calendarEl.querySelector('.orig-select-year');
3708
- let monthSelect = this.calendarEl.querySelector('.orig-select-month');
3741
+ const yearSelect = this.calendarEl.querySelector('.orig-select-year');
3742
+ const monthSelect = this.calendarEl.querySelector('.orig-select-month');
3709
3743
  FormSelect.init(yearSelect, {
3710
3744
  classes: 'select-year',
3711
3745
  dropdownOptions: { container: document.body, constrainWidth: false }
@@ -3726,7 +3760,7 @@ class Datepicker extends Component {
3726
3760
  this.el.addEventListener('keydown', this._handleInputKeydown);
3727
3761
  this.el.addEventListener('change', this._handleInputChange);
3728
3762
  this.calendarEl.addEventListener('click', this._handleCalendarClick);
3729
- this.doneBtn.addEventListener('click', this._finishSelection);
3763
+ this.doneBtn.addEventListener('click', () => this.setInputValues());
3730
3764
  this.cancelBtn.addEventListener('click', this.close);
3731
3765
  if (this.options.showClearBtn) {
3732
3766
  this.clearBtn.addEventListener('click', this._handleClearClick);
@@ -3742,40 +3776,41 @@ class Datepicker extends Component {
3742
3776
  if (this.options.showClearBtn) {
3743
3777
  this.clearBtn = this.modalEl.querySelector('.datepicker-clear');
3744
3778
  }
3779
+ // TODO: This should not be part of the datepicker
3745
3780
  this.doneBtn = this.modalEl.querySelector('.datepicker-done');
3746
3781
  this.cancelBtn = this.modalEl.querySelector('.datepicker-cancel');
3747
3782
  this.formats = {
3748
- d: () => {
3749
- return this.date.getDate();
3783
+ d: (date) => {
3784
+ return date.getDate();
3750
3785
  },
3751
- dd: () => {
3752
- let d = this.date.getDate();
3786
+ dd: (date) => {
3787
+ const d = date.getDate();
3753
3788
  return (d < 10 ? '0' : '') + d;
3754
3789
  },
3755
- ddd: () => {
3756
- return this.options.i18n.weekdaysShort[this.date.getDay()];
3790
+ ddd: (date) => {
3791
+ return this.options.i18n.weekdaysShort[date.getDay()];
3757
3792
  },
3758
- dddd: () => {
3759
- return this.options.i18n.weekdays[this.date.getDay()];
3793
+ dddd: (date) => {
3794
+ return this.options.i18n.weekdays[date.getDay()];
3760
3795
  },
3761
- m: () => {
3762
- return this.date.getMonth() + 1;
3796
+ m: (date) => {
3797
+ return date.getMonth() + 1;
3763
3798
  },
3764
- mm: () => {
3765
- let m = this.date.getMonth() + 1;
3799
+ mm: (date) => {
3800
+ const m = date.getMonth() + 1;
3766
3801
  return (m < 10 ? '0' : '') + m;
3767
3802
  },
3768
- mmm: () => {
3769
- return this.options.i18n.monthsShort[this.date.getMonth()];
3803
+ mmm: (date) => {
3804
+ return this.options.i18n.monthsShort[date.getMonth()];
3770
3805
  },
3771
- mmmm: () => {
3772
- return this.options.i18n.months[this.date.getMonth()];
3806
+ mmmm: (date) => {
3807
+ return this.options.i18n.months[date.getMonth()];
3773
3808
  },
3774
- yy: () => {
3775
- return ('' + this.date.getFullYear()).slice(2);
3809
+ yy: (date) => {
3810
+ return ('' + date.getFullYear()).slice(2);
3776
3811
  },
3777
- yyyy: () => {
3778
- return this.date.getFullYear();
3812
+ yyyy: (date) => {
3813
+ return date.getFullYear();
3779
3814
  }
3780
3815
  };
3781
3816
  }
@@ -3784,28 +3819,42 @@ class Datepicker extends Component {
3784
3819
  this.el.removeEventListener('keydown', this._handleInputKeydown);
3785
3820
  this.el.removeEventListener('change', this._handleInputChange);
3786
3821
  this.calendarEl.removeEventListener('click', this._handleCalendarClick);
3822
+ if (this.options.isDateRange) {
3823
+ this.endDateEl.removeEventListener('click', this._handleInputClick);
3824
+ this.endDateEl.removeEventListener('keypress', this._handleInputKeydown);
3825
+ this.endDateEl.removeEventListener('change', this._handleInputChange);
3826
+ }
3787
3827
  }
3788
- _handleInputClick = () => {
3789
- this.open();
3828
+ _handleInputClick = (e) => {
3829
+ // Prevents default browser datepicker modal rendering
3830
+ if (e.type == 'date') {
3831
+ e.preventDefault();
3832
+ }
3833
+ this.setDateFromInput(e.target);
3834
+ this.draw();
3835
+ this.gotoDate(e.target === this.el ? this.date : this.endDate);
3790
3836
  };
3791
3837
  _handleInputKeydown = (e) => {
3792
3838
  if (Utils.keys.ENTER.includes(e.key)) {
3793
3839
  e.preventDefault();
3794
- this.open();
3840
+ this.setDateFromInput(e.target);
3841
+ this.draw();
3795
3842
  }
3796
3843
  };
3797
3844
  _handleCalendarClick = (e) => {
3798
- if (!this.isOpen)
3799
- return;
3800
- const target = (e.target);
3845
+ const target = e.target;
3801
3846
  if (!target.classList.contains('is-disabled')) {
3802
3847
  if (target.classList.contains('datepicker-day-button') &&
3803
3848
  !target.classList.contains('is-empty') &&
3804
3849
  !target.parentElement.classList.contains('is-disabled')) {
3805
- this.setDate(new Date(e.target.getAttribute('data-year'), e.target.getAttribute('data-month'), e.target.getAttribute('data-day')));
3806
- if (this.options.autoClose) {
3807
- this._finishSelection();
3850
+ const selectedDate = new Date(e.target.getAttribute('data-year'), e.target.getAttribute('data-month'), e.target.getAttribute('data-day'));
3851
+ if (!this.multiple || (this.multiple && this.options.isMultipleSelection)) {
3852
+ this.setDate(selectedDate);
3808
3853
  }
3854
+ if (this.options.isDateRange) {
3855
+ this._handleDateRangeCalendarClick(selectedDate);
3856
+ }
3857
+ this._finishSelection();
3809
3858
  }
3810
3859
  else if (target.closest('.month-prev')) {
3811
3860
  this.prevMonth();
@@ -3815,10 +3864,24 @@ class Datepicker extends Component {
3815
3864
  }
3816
3865
  }
3817
3866
  };
3867
+ _handleDateRangeCalendarClick = (date) => {
3868
+ if (this.endDate == null || !Datepicker._compareDates(date, this.endDate)) {
3869
+ if (Datepicker._isDate(this.date) && Datepicker._comparePastDate(date, this.date)) {
3870
+ return;
3871
+ }
3872
+ this.setDate(date, false, Datepicker._isDate(this.date));
3873
+ return;
3874
+ }
3875
+ this._clearDates();
3876
+ this.draw();
3877
+ };
3818
3878
  _handleClearClick = () => {
3879
+ this._clearDates();
3880
+ this.setInputValues();
3881
+ };
3882
+ _clearDates = () => {
3819
3883
  this.date = null;
3820
- this.setInputValue();
3821
- this.close();
3884
+ this.endDate = null;
3822
3885
  };
3823
3886
  _handleMonthChange = (e) => {
3824
3887
  this.gotoMonth(e.target.value);
@@ -3842,19 +3905,28 @@ class Datepicker extends Component {
3842
3905
  }
3843
3906
  _handleInputChange = (e) => {
3844
3907
  let date;
3908
+ const el = e.target;
3845
3909
  // Prevent change event from being fired when triggered by the plugin
3846
3910
  if (e['detail']?.firedBy === this)
3847
3911
  return;
3912
+ // Prevent change event from being fired if an end date is set without a start date
3913
+ if (el == this.endDateEl && !this.date)
3914
+ return;
3848
3915
  if (this.options.parse) {
3849
- date = this.options.parse(this.el.value, typeof this.options.format === "function"
3916
+ date = this.options.parse(e.target.value, typeof this.options.format === 'function'
3850
3917
  ? this.options.format(new Date(this.el.value))
3851
3918
  : this.options.format);
3852
3919
  }
3853
3920
  else {
3854
- date = new Date(Date.parse(this.el.value));
3921
+ date = new Date(Date.parse(e.target.value));
3922
+ }
3923
+ if (Datepicker._isDate(date)) {
3924
+ this.setDate(date, false, el == this.endDateEl, true);
3925
+ if (e.type == 'date') {
3926
+ this.setDataDate(e, date);
3927
+ this.setInputValues();
3928
+ }
3855
3929
  }
3856
- if (Datepicker._isDate(date))
3857
- this.setDate(date);
3858
3930
  };
3859
3931
  renderDayName(opts, day, abbr = false) {
3860
3932
  day += opts.firstDay;
@@ -3863,41 +3935,31 @@ class Datepicker extends Component {
3863
3935
  }
3864
3936
  return abbr ? opts.i18n.weekdaysAbbrev[day] : opts.i18n.weekdays[day];
3865
3937
  }
3938
+ createDateInput() {
3939
+ const dateInput = this.el.cloneNode(true);
3940
+ dateInput.addEventListener('click', this._handleInputClick);
3941
+ dateInput.addEventListener('keypress', this._handleInputKeydown);
3942
+ dateInput.addEventListener('change', this._handleInputChange);
3943
+ this.el.parentElement.appendChild(dateInput);
3944
+ return dateInput;
3945
+ }
3866
3946
  // Set input value to the selected date and close Datepicker
3867
3947
  _finishSelection = () => {
3868
- this.setInputValue();
3948
+ this.setInputValues();
3869
3949
  this.close();
3870
3950
  };
3871
- /**
3872
- * Open datepicker.
3873
- */
3874
- open = () => {
3875
- if (this.isOpen)
3876
- return;
3877
- this.isOpen = true;
3878
- if (typeof this.options.onOpen === 'function') {
3879
- this.options.onOpen.call(this);
3880
- }
3881
- this.draw();
3882
- this.modal.open(undefined);
3951
+ // deprecated
3952
+ open() {
3953
+ console.warn('Datepicker.open() is deprecated. Remove this method and wrap in modal yourself.');
3883
3954
  return this;
3884
- };
3885
- /**
3886
- * Close datepicker.
3887
- */
3888
- close = () => {
3889
- if (!this.isOpen)
3890
- return;
3891
- this.isOpen = false;
3892
- if (typeof this.options.onClose === 'function') {
3893
- this.options.onClose.call(this);
3894
- }
3895
- this.modal.close();
3955
+ }
3956
+ close() {
3957
+ console.warn('Datepicker.close() is deprecated. Remove this method and wrap in modal yourself.');
3896
3958
  return this;
3897
- };
3959
+ }
3898
3960
  static {
3899
3961
  Datepicker._template = `
3900
- <div class="modal datepicker-modal">
3962
+ <div class="datepicker-modal">
3901
3963
  <div class="modal-content datepicker-container">
3902
3964
  <div class="datepicker-date-display">
3903
3965
  <span class="year-text"></span>
@@ -3920,15 +3982,46 @@ class Datepicker extends Component {
3920
3982
 
3921
3983
  class Forms {
3922
3984
  /**
3923
- * Resizes the given TextArea after updating the
3924
- * value content dynamically.
3925
- * @param textarea TextArea to be resized
3985
+ * Checks if the label has validation and apply
3986
+ * the correct class and styles
3987
+ * @param textfield
3926
3988
  */
3927
- static textareaAutoResize(textarea) {
3928
- if (!textarea) {
3929
- console.error('No textarea element found');
3989
+ static validateField(textfield) {
3990
+ if (!textfield) {
3991
+ console.error('No text field element found');
3930
3992
  return;
3931
3993
  }
3994
+ const hasLength = textfield.getAttribute('data-length') !== null;
3995
+ const lenAttr = parseInt(textfield.getAttribute('data-length'));
3996
+ const len = textfield.value.length;
3997
+ if (len === 0 &&
3998
+ textfield.validity.badInput === false &&
3999
+ !textfield.required &&
4000
+ textfield.classList.contains('validate')) {
4001
+ textfield.classList.remove('invalid');
4002
+ }
4003
+ else if (textfield.classList.contains('validate')) {
4004
+ // Check for character counter attributes
4005
+ if ((textfield.validity.valid && hasLength && len <= lenAttr) ||
4006
+ (textfield.validity.valid && !hasLength)) {
4007
+ textfield.classList.remove('invalid');
4008
+ }
4009
+ else {
4010
+ textfield.classList.add('invalid');
4011
+ }
4012
+ }
4013
+ }
4014
+ /**
4015
+ * Resizes the given TextArea after updating the
4016
+ * value content dynamically.
4017
+ * @param e EventTarget
4018
+ */
4019
+ static textareaAutoResize(e) {
4020
+ const textarea = e;
4021
+ // if (!textarea) {
4022
+ // console.error('No textarea element found');
4023
+ // return;
4024
+ // }
3932
4025
  // Textarea Auto Resize
3933
4026
  let hiddenDiv = document.querySelector('.hiddendiv');
3934
4027
  if (!hiddenDiv) {
@@ -3968,15 +4061,14 @@ class Forms {
3968
4061
  hiddenDiv.style.whiteSpace = 'pre'; //.css('white-space', 'pre');
3969
4062
  }
3970
4063
  hiddenDiv.innerText = textarea.value + '\n';
3971
- const content = hiddenDiv.innerHTML.replace(/\n/g, '<br>');
3972
- hiddenDiv.innerHTML = content;
4064
+ hiddenDiv.innerHTML = hiddenDiv.innerHTML.replace(/\n/g, '<br>');
3973
4065
  // When textarea is hidden, width goes crazy.
3974
4066
  // Approximate with half of window size
3975
4067
  if (textarea.offsetWidth > 0 && textarea.offsetHeight > 0) {
3976
4068
  hiddenDiv.style.width = textarea.getBoundingClientRect().width + 'px'; // ('width', textarea.width() + 'px');
3977
4069
  }
3978
4070
  else {
3979
- hiddenDiv.style.width = (window.innerWidth / 2) + 'px'; //css('width', window.innerWidth / 2 + 'px');
4071
+ hiddenDiv.style.width = window.innerWidth / 2 + 'px'; //css('width', window.innerWidth / 2 + 'px');
3980
4072
  }
3981
4073
  // Resize if the new height is greater than the
3982
4074
  // original height of the textarea
@@ -3995,10 +4087,22 @@ class Forms {
3995
4087
  }
3996
4088
  textarea.setAttribute('previous-length', textarea.value.length.toString());
3997
4089
  }
3998
- ;
3999
4090
  static Init() {
4000
4091
  if (typeof document !== 'undefined')
4001
- document?.addEventListener("DOMContentLoaded", () => {
4092
+ document?.addEventListener('DOMContentLoaded', () => {
4093
+ document.addEventListener('change', (e) => {
4094
+ const target = e.target;
4095
+ if (target instanceof HTMLInputElement) {
4096
+ if (target.value.length !== 0 || target.getAttribute('placeholder') !== null) {
4097
+ for (const child of target.parentNode.children) {
4098
+ if (child.tagName == 'label') {
4099
+ child.classList.add('active');
4100
+ }
4101
+ }
4102
+ }
4103
+ Forms.validateField(target);
4104
+ }
4105
+ });
4002
4106
  document.addEventListener('keyup', (e) => {
4003
4107
  const target = e.target;
4004
4108
  // Radio and Checkbox focus class
@@ -4006,15 +4110,21 @@ class Forms {
4006
4110
  // TAB, check if tabbing to radio or checkbox.
4007
4111
  if (Utils.keys.TAB.includes(e.key)) {
4008
4112
  target.classList.add('tabbed');
4009
- target.addEventListener('blur', e => target.classList.remove('tabbed'), { once: true });
4113
+ target.addEventListener('blur', () => target.classList.remove('tabbed'), {
4114
+ once: true
4115
+ });
4010
4116
  }
4011
4117
  }
4012
4118
  });
4013
- document.querySelectorAll('.materialize-textarea').forEach((textArea) => {
4119
+ document
4120
+ .querySelectorAll('.materialize-textarea')
4121
+ .forEach((textArea) => {
4014
4122
  Forms.InitTextarea(textArea);
4015
4123
  });
4016
4124
  // File Input Path
4017
- document.querySelectorAll('.file-field input[type="file"]').forEach((fileInput) => {
4125
+ document
4126
+ .querySelectorAll('.file-field input[type="file"]')
4127
+ .forEach((fileInput) => {
4018
4128
  Forms.InitFileInputPath(fileInput);
4019
4129
  });
4020
4130
  });
@@ -4024,11 +4134,11 @@ class Forms {
4024
4134
  textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());
4025
4135
  textarea.setAttribute('previous-length', textarea.value.length.toString());
4026
4136
  Forms.textareaAutoResize(textarea);
4027
- textarea.addEventListener('keyup', e => Forms.textareaAutoResize(textarea));
4028
- textarea.addEventListener('keydown', e => Forms.textareaAutoResize(textarea));
4137
+ textarea.addEventListener('keyup', (e) => Forms.textareaAutoResize(e.target));
4138
+ textarea.addEventListener('keydown', (e) => Forms.textareaAutoResize(e.target));
4029
4139
  }
4030
4140
  static InitFileInputPath(fileInput) {
4031
- fileInput.addEventListener('change', e => {
4141
+ fileInput.addEventListener('change', () => {
4032
4142
  const fileField = fileInput.closest('.file-field');
4033
4143
  const pathInput = fileField.querySelector('input.file-path');
4034
4144
  const files = fileInput.files;
@@ -4042,7 +4152,7 @@ class Forms {
4042
4152
  }
4043
4153
  }
4044
4154
 
4045
- const _defaults$c = {
4155
+ const _defaults$d = {
4046
4156
  inDuration: 275,
4047
4157
  outDuration: 200,
4048
4158
  onOpenStart: null,
@@ -4074,7 +4184,7 @@ class Materialbox extends Component {
4074
4184
  _photoCaption;
4075
4185
  constructor(el, options) {
4076
4186
  super(el, options, Materialbox);
4077
- this.el.M_Materialbox = this;
4187
+ this.el['M_Materialbox'] = this;
4078
4188
  this.options = {
4079
4189
  ...Materialbox.defaults,
4080
4190
  ...options
@@ -4087,13 +4197,14 @@ class Materialbox extends Component {
4087
4197
  this.originalHeight = 0;
4088
4198
  this.originInlineStyles = this.el.getAttribute('style');
4089
4199
  this.caption = this.el.getAttribute('data-caption') || '';
4200
+ this.el.tabIndex = 0;
4090
4201
  // Wrap
4091
4202
  this.el.before(this.placeholder);
4092
4203
  this.placeholder.append(this.el);
4093
4204
  this._setupEventHandlers();
4094
4205
  }
4095
4206
  static get defaults() {
4096
- return _defaults$c;
4207
+ return _defaults$d;
4097
4208
  }
4098
4209
  /**
4099
4210
  * Initializes instances of MaterialBox.
@@ -4104,11 +4215,11 @@ class Materialbox extends Component {
4104
4215
  return super.init(els, options, Materialbox);
4105
4216
  }
4106
4217
  static getInstance(el) {
4107
- return el.M_Materialbox;
4218
+ return el['M_Materialbox'];
4108
4219
  }
4109
4220
  destroy() {
4110
4221
  this._removeEventHandlers();
4111
- this.el.M_Materialbox = undefined;
4222
+ this.el['M_Materialbox'] = undefined;
4112
4223
  // Unwrap image
4113
4224
  //this.placeholder.after(this.el).remove();
4114
4225
  this.placeholder.remove();
@@ -4116,11 +4227,21 @@ class Materialbox extends Component {
4116
4227
  }
4117
4228
  _setupEventHandlers() {
4118
4229
  this.el.addEventListener('click', this._handleMaterialboxClick);
4230
+ this.el.addEventListener('keypress', this._handleMaterialboxKeypress);
4119
4231
  }
4120
4232
  _removeEventHandlers() {
4121
4233
  this.el.removeEventListener('click', this._handleMaterialboxClick);
4234
+ this.el.removeEventListener('keypress', this._handleMaterialboxKeypress);
4122
4235
  }
4123
4236
  _handleMaterialboxClick = () => {
4237
+ this._handleMaterialboxToggle();
4238
+ };
4239
+ _handleMaterialboxKeypress = (e) => {
4240
+ if (Utils.keys.ENTER.includes(e.key)) {
4241
+ this._handleMaterialboxToggle();
4242
+ }
4243
+ };
4244
+ _handleMaterialboxToggle = () => {
4124
4245
  // If already modal, return to original
4125
4246
  if (this.doneAnimating === false || (this.overlayActive && this.doneAnimating))
4126
4247
  this.close();
@@ -4155,8 +4276,8 @@ class Materialbox extends Component {
4155
4276
  const box = el.getBoundingClientRect();
4156
4277
  const docElem = document.documentElement;
4157
4278
  return {
4158
- top: box.top + window.pageYOffset - docElem.clientTop,
4159
- left: box.left + window.pageXOffset - docElem.clientLeft
4279
+ top: box.top + window.scrollY - docElem.clientTop,
4280
+ left: box.left + window.scrollX - docElem.clientLeft
4160
4281
  };
4161
4282
  }
4162
4283
  _updateVars() {
@@ -4183,14 +4304,18 @@ class Materialbox extends Component {
4183
4304
  // to
4184
4305
  this.el.style.height = this.newHeight + 'px';
4185
4306
  this.el.style.width = this.newWidth + 'px';
4186
- this.el.style.left = (Utils.getDocumentScrollLeft() +
4187
- this.windowWidth / 2 -
4188
- this._offset(this.placeholder).left -
4189
- this.newWidth / 2) + 'px';
4190
- this.el.style.top = (Utils.getDocumentScrollTop() +
4191
- this.windowHeight / 2 -
4192
- this._offset(this.placeholder).top -
4193
- this.newHeight / 2) + 'px';
4307
+ this.el.style.left =
4308
+ Utils.getDocumentScrollLeft() +
4309
+ this.windowWidth / 2 -
4310
+ this._offset(this.placeholder).left -
4311
+ this.newWidth / 2 +
4312
+ 'px';
4313
+ this.el.style.top =
4314
+ Utils.getDocumentScrollTop() +
4315
+ this.windowHeight / 2 -
4316
+ this._offset(this.placeholder).top -
4317
+ this.newHeight / 2 +
4318
+ 'px';
4194
4319
  }, 1);
4195
4320
  setTimeout(() => {
4196
4321
  this.doneAnimating = true;
@@ -4247,12 +4372,13 @@ class Materialbox extends Component {
4247
4372
  if (this.attrHeight)
4248
4373
  this.el.setAttribute('height', this.attrHeight.toString());
4249
4374
  this.el.removeAttribute('style');
4250
- this.originInlineStyles && this.el.setAttribute('style', this.originInlineStyles);
4375
+ if (this.originInlineStyles)
4376
+ this.el.setAttribute('style', this.originInlineStyles);
4251
4377
  // Remove class
4252
4378
  this.el.classList.remove('active');
4253
4379
  this.doneAnimating = true;
4254
4380
  // Remove overflow overrides on ancestors
4255
- this._changedAncestorList.forEach(anchestor => anchestor.style.overflow = '');
4381
+ this._changedAncestorList.forEach((anchestor) => (anchestor.style.overflow = ''));
4256
4382
  // onCloseEnd callback
4257
4383
  if (typeof this.options.onCloseEnd === 'function')
4258
4384
  this.options.onCloseEnd.call(this, this.el);
@@ -4286,7 +4412,7 @@ class Materialbox extends Component {
4286
4412
  _addOverlay() {
4287
4413
  this._overlay = document.createElement('div');
4288
4414
  this._overlay.id = 'materialbox-overlay';
4289
- this._overlay.addEventListener('click', e => {
4415
+ this._overlay.addEventListener('click', () => {
4290
4416
  if (this.doneAnimating)
4291
4417
  this.close();
4292
4418
  }, { once: true });
@@ -4402,7 +4528,75 @@ class Materialbox extends Component {
4402
4528
  };
4403
4529
  }
4404
4530
 
4405
- let _defaults$b = {
4531
+ const _defaults$c = {
4532
+ opacity: 0.5,
4533
+ inDuration: 250,
4534
+ outDuration: 250,
4535
+ onOpenStart: null,
4536
+ onOpenEnd: null,
4537
+ onCloseStart: null,
4538
+ onCloseEnd: null,
4539
+ preventScrolling: true,
4540
+ dismissible: true,
4541
+ startingTop: '4%',
4542
+ endingTop: '10%'
4543
+ };
4544
+ class Modal extends Component {
4545
+ constructor(el, options) {
4546
+ super(el, options, Modal);
4547
+ this.el['M_Modal'] = this;
4548
+ this.options = {
4549
+ ...Modal.defaults,
4550
+ ...options
4551
+ };
4552
+ this.el.tabIndex = 0;
4553
+ this._setupEventHandlers();
4554
+ }
4555
+ static get defaults() {
4556
+ return _defaults$c;
4557
+ }
4558
+ static init(els, options = {}) {
4559
+ return super.init(els, options, Modal);
4560
+ }
4561
+ static getInstance(el) {
4562
+ return el['M_Modal'];
4563
+ }
4564
+ destroy() { }
4565
+ _setupEventHandlers() { }
4566
+ _removeEventHandlers() { }
4567
+ _handleTriggerClick() { }
4568
+ _handleOverlayClick() { }
4569
+ _handleModalCloseClick() { }
4570
+ _handleKeydown() { }
4571
+ _handleFocus() { }
4572
+ open() {
4573
+ return this;
4574
+ }
4575
+ close() {
4576
+ return this;
4577
+ }
4578
+ // Experimental!
4579
+ static #createHtml(config) {
4580
+ return `<dialog id="modal1" class="modal">
4581
+ ${config.header ? '<div class="modal-header">' + config.header + '</div>' : ''}
4582
+ <div class="modal-content">
4583
+ ${config.content}
4584
+ </div>
4585
+ ${config.header ? '<div class="modal-footer">' + config.footer + '</div>' : ''}
4586
+ </dialog>`;
4587
+ }
4588
+ static #createHtmlElement(config) {
4589
+ const dialog = document.createElement('dialog');
4590
+ dialog.id = config.id;
4591
+ return dialog;
4592
+ }
4593
+ static create(config) {
4594
+ return this.#createHtmlElement(config);
4595
+ }
4596
+ static { }
4597
+ }
4598
+
4599
+ const _defaults$b = {
4406
4600
  responsiveThreshold: 0 // breakpoint for swipeable
4407
4601
  };
4408
4602
  class Parallax extends Component {
@@ -4413,7 +4607,7 @@ class Parallax extends Component {
4413
4607
  static _handleWindowResizeThrottled;
4414
4608
  constructor(el, options) {
4415
4609
  super(el, options, Parallax);
4416
- this.el.M_Parallax = this;
4610
+ this.el['M_Parallax'] = this;
4417
4611
  this.options = {
4418
4612
  ...Parallax.defaults,
4419
4613
  ...options
@@ -4437,25 +4631,24 @@ class Parallax extends Component {
4437
4631
  return super.init(els, options, Parallax);
4438
4632
  }
4439
4633
  static getInstance(el) {
4440
- return el.M_Parallax;
4634
+ return el['M_Parallax'];
4441
4635
  }
4442
4636
  destroy() {
4443
4637
  Parallax._parallaxes.splice(Parallax._parallaxes.indexOf(this), 1);
4444
4638
  this._img.style.transform = '';
4445
4639
  this._removeEventHandlers();
4446
- this.el.M_Parallax = undefined;
4640
+ this.el['M_Parallax'] = undefined;
4447
4641
  }
4448
4642
  static _handleScroll() {
4449
4643
  for (let i = 0; i < Parallax._parallaxes.length; i++) {
4450
- let parallaxInstance = Parallax._parallaxes[i];
4644
+ const parallaxInstance = Parallax._parallaxes[i];
4451
4645
  parallaxInstance._updateParallax.call(parallaxInstance);
4452
4646
  }
4453
4647
  }
4454
4648
  static _handleWindowResize() {
4455
4649
  for (let i = 0; i < Parallax._parallaxes.length; i++) {
4456
- let parallaxInstance = Parallax._parallaxes[i];
4457
- parallaxInstance._enabled =
4458
- window.innerWidth > parallaxInstance.options.responsiveThreshold;
4650
+ const parallaxInstance = Parallax._parallaxes[i];
4651
+ parallaxInstance._enabled = window.innerWidth > parallaxInstance.options.responsiveThreshold;
4459
4652
  }
4460
4653
  }
4461
4654
  _setupEventHandlers() {
@@ -4488,12 +4681,12 @@ class Parallax extends Component {
4488
4681
  const box = el.getBoundingClientRect();
4489
4682
  const docElem = document.documentElement;
4490
4683
  return {
4491
- top: box.top + window.pageYOffset - docElem.clientTop,
4492
- left: box.left + window.pageXOffset - docElem.clientLeft
4684
+ top: box.top + window.scrollY - docElem.clientTop,
4685
+ left: box.left + window.scrollX - docElem.clientLeft
4493
4686
  };
4494
4687
  }
4495
4688
  _updateParallax() {
4496
- const containerHeight = this.el.getBoundingClientRect().height > 0 ? this.el.parentNode.offsetHeight : 500;
4689
+ const containerHeight = this.el.getBoundingClientRect().height > 0 ? this.el.parentElement.offsetHeight : 500;
4497
4690
  const imgHeight = this._img.offsetHeight;
4498
4691
  const parallaxDist = imgHeight - containerHeight;
4499
4692
  const bottom = this._offset(this.el).top + containerHeight;
@@ -4512,7 +4705,7 @@ class Parallax extends Component {
4512
4705
  }
4513
4706
  }
4514
4707
 
4515
- let _defaults$a = {
4708
+ const _defaults$a = {
4516
4709
  top: 0,
4517
4710
  bottom: Infinity,
4518
4711
  offset: 0,
@@ -4523,7 +4716,7 @@ class Pushpin extends Component {
4523
4716
  originalOffset;
4524
4717
  constructor(el, options) {
4525
4718
  super(el, options, Pushpin);
4526
- this.el.M_Pushpin = this;
4719
+ this.el['M_Pushpin'] = this;
4527
4720
  this.options = {
4528
4721
  ...Pushpin.defaults,
4529
4722
  ...options
@@ -4545,22 +4738,22 @@ class Pushpin extends Component {
4545
4738
  return super.init(els, options, Pushpin);
4546
4739
  }
4547
4740
  static getInstance(el) {
4548
- return el.M_Pushpin;
4741
+ return el['M_Pushpin'];
4549
4742
  }
4550
4743
  destroy() {
4551
4744
  this.el.style.top = null;
4552
4745
  this._removePinClasses();
4553
4746
  // Remove pushpin Inst
4554
- let index = Pushpin._pushpins.indexOf(this);
4747
+ const index = Pushpin._pushpins.indexOf(this);
4555
4748
  Pushpin._pushpins.splice(index, 1);
4556
4749
  if (Pushpin._pushpins.length === 0) {
4557
4750
  this._removeEventHandlers();
4558
4751
  }
4559
- this.el.M_Pushpin = undefined;
4752
+ this.el['M_Pushpin'] = undefined;
4560
4753
  }
4561
4754
  static _updateElements() {
4562
- for (let elIndex in Pushpin._pushpins) {
4563
- let pInstance = Pushpin._pushpins[elIndex];
4755
+ for (const elIndex in Pushpin._pushpins) {
4756
+ const pInstance = Pushpin._pushpins[elIndex];
4564
4757
  pInstance._updatePosition();
4565
4758
  }
4566
4759
  }
@@ -4571,7 +4764,7 @@ class Pushpin extends Component {
4571
4764
  document.removeEventListener('scroll', Pushpin._updateElements);
4572
4765
  }
4573
4766
  _updatePosition() {
4574
- let scrolled = Utils.getDocumentScrollTop() + this.options.offset;
4767
+ const scrolled = Utils.getDocumentScrollTop() + this.options.offset;
4575
4768
  if (this.options.top <= scrolled &&
4576
4769
  this.options.bottom >= scrolled &&
4577
4770
  !this.el.classList.contains('pinned')) {
@@ -4615,24 +4808,29 @@ class Pushpin extends Component {
4615
4808
  }
4616
4809
  }
4617
4810
 
4618
- let _defaults$9 = {
4811
+ const _defaults$9 = {
4619
4812
  throttle: 100,
4620
4813
  scrollOffset: 200, // offset - 200 allows elements near bottom of page to scroll
4621
4814
  activeClass: 'active',
4622
- getActiveElement: (id) => { return 'a[href="#' + id + '"]'; }
4815
+ getActiveElement: (id) => {
4816
+ return 'a[href="#' + id + '"]';
4817
+ },
4818
+ keepTopElementActive: false,
4819
+ animationDuration: null
4623
4820
  };
4624
4821
  class ScrollSpy extends Component {
4625
4822
  static _elements;
4626
4823
  static _count;
4627
4824
  static _increment;
4628
- tickId;
4629
- id;
4630
4825
  static _elementsInView;
4631
4826
  static _visibleElements;
4632
4827
  static _ticks;
4828
+ static _keptTopActiveElement = null;
4829
+ tickId;
4830
+ id;
4633
4831
  constructor(el, options) {
4634
4832
  super(el, options, ScrollSpy);
4635
- this.el.M_ScrollSpy = this;
4833
+ this.el['M_ScrollSpy'] = this;
4636
4834
  this.options = {
4637
4835
  ...ScrollSpy.defaults,
4638
4836
  ...options
@@ -4641,7 +4839,7 @@ class ScrollSpy extends Component {
4641
4839
  ScrollSpy._count++;
4642
4840
  ScrollSpy._increment++;
4643
4841
  this.tickId = -1;
4644
- this.id = ScrollSpy._increment;
4842
+ this.id = ScrollSpy._increment.toString();
4645
4843
  this._setupEventHandlers();
4646
4844
  this._handleWindowScroll();
4647
4845
  }
@@ -4657,7 +4855,7 @@ class ScrollSpy extends Component {
4657
4855
  return super.init(els, options, ScrollSpy);
4658
4856
  }
4659
4857
  static getInstance(el) {
4660
- return el.M_ScrollSpy;
4858
+ return el['M_ScrollSpy'];
4661
4859
  }
4662
4860
  destroy() {
4663
4861
  ScrollSpy._elements.splice(ScrollSpy._elements.indexOf(this), 1);
@@ -4667,7 +4865,7 @@ class ScrollSpy extends Component {
4667
4865
  this._removeEventHandlers();
4668
4866
  const actElem = document.querySelector(this.options.getActiveElement(this.el.id));
4669
4867
  actElem.classList.remove(this.options.activeClass);
4670
- this.el.M_ScrollSpy = undefined;
4868
+ this.el['M_ScrollSpy'] = undefined;
4671
4869
  }
4672
4870
  _setupEventHandlers() {
4673
4871
  if (ScrollSpy._count === 1) {
@@ -4683,7 +4881,9 @@ class ScrollSpy extends Component {
4683
4881
  document.body.removeEventListener('click', this._handleTriggerClick);
4684
4882
  }
4685
4883
  }
4686
- _handleThrottledResize = Utils.throttle(function () { this._handleWindowScroll(); }, 200).bind(this);
4884
+ _handleThrottledResize = Utils.throttle(function () {
4885
+ this._handleWindowScroll();
4886
+ }, 200).bind(this);
4687
4887
  _handleTriggerClick = (e) => {
4688
4888
  const trigger = e.target;
4689
4889
  for (let i = ScrollSpy._elements.length - 1; i >= 0; i--) {
@@ -4691,7 +4891,12 @@ class ScrollSpy extends Component {
4691
4891
  const x = document.querySelector('a[href="#' + scrollspy.el.id + '"]');
4692
4892
  if (trigger === x) {
4693
4893
  e.preventDefault();
4694
- scrollspy.el.scrollIntoView({ behavior: 'smooth' });
4894
+ if (scrollspy.el['M_ScrollSpy'].options.animationDuration) {
4895
+ ScrollSpy._smoothScrollIntoView(scrollspy.el, scrollspy.el['M_ScrollSpy'].options.animationDuration);
4896
+ }
4897
+ else {
4898
+ scrollspy.el.scrollIntoView({ behavior: 'smooth' });
4899
+ }
4695
4900
  break;
4696
4901
  }
4697
4902
  }
@@ -4700,12 +4905,12 @@ class ScrollSpy extends Component {
4700
4905
  // unique tick id
4701
4906
  ScrollSpy._ticks++;
4702
4907
  // viewport rectangle
4703
- let top = Utils.getDocumentScrollTop(), left = Utils.getDocumentScrollLeft(), right = left + window.innerWidth, bottom = top + window.innerHeight;
4908
+ const top = Utils.getDocumentScrollTop(), left = Utils.getDocumentScrollLeft(), right = left + window.innerWidth, bottom = top + window.innerHeight;
4704
4909
  // determine which elements are in view
4705
- let intersections = ScrollSpy._findElements(top, right, bottom, left);
4910
+ const intersections = ScrollSpy._findElements(top, right, bottom, left);
4706
4911
  for (let i = 0; i < intersections.length; i++) {
4707
- let scrollspy = intersections[i];
4708
- let lastTick = scrollspy.tickId;
4912
+ const scrollspy = intersections[i];
4913
+ const lastTick = scrollspy.tickId;
4709
4914
  if (lastTick < 0) {
4710
4915
  // entered into view
4711
4916
  scrollspy._enter();
@@ -4714,8 +4919,8 @@ class ScrollSpy extends Component {
4714
4919
  scrollspy.tickId = ScrollSpy._ticks;
4715
4920
  }
4716
4921
  for (let i = 0; i < ScrollSpy._elementsInView.length; i++) {
4717
- let scrollspy = ScrollSpy._elementsInView[i];
4718
- let lastTick = scrollspy.tickId;
4922
+ const scrollspy = ScrollSpy._elementsInView[i];
4923
+ const lastTick = scrollspy.tickId;
4719
4924
  if (lastTick >= 0 && lastTick !== ScrollSpy._ticks) {
4720
4925
  // exited from view
4721
4926
  scrollspy._exit();
@@ -4724,6 +4929,29 @@ class ScrollSpy extends Component {
4724
4929
  }
4725
4930
  // remember elements in view for next tick
4726
4931
  ScrollSpy._elementsInView = intersections;
4932
+ if (ScrollSpy._elements.length) {
4933
+ const options = ScrollSpy._elements[0].el['M_ScrollSpy'].options;
4934
+ if (options.keepTopElementActive && ScrollSpy._visibleElements.length === 0) {
4935
+ this._resetKeptTopActiveElementIfNeeded();
4936
+ const topElements = ScrollSpy._elements
4937
+ .filter((value) => ScrollSpy._getDistanceToViewport(value.el) <= 0)
4938
+ .sort((a, b) => {
4939
+ const distanceA = ScrollSpy._getDistanceToViewport(a.el);
4940
+ const distanceB = ScrollSpy._getDistanceToViewport(b.el);
4941
+ if (distanceA < distanceB)
4942
+ return -1;
4943
+ if (distanceA > distanceB)
4944
+ return 1;
4945
+ return 0;
4946
+ });
4947
+ const nearestTopElement = topElements.length
4948
+ ? topElements[topElements.length - 1]
4949
+ : ScrollSpy._elements[0];
4950
+ const actElem = document.querySelector(options.getActiveElement(nearestTopElement.el.id));
4951
+ actElem?.classList.add(options.activeClass);
4952
+ ScrollSpy._keptTopActiveElement = actElem;
4953
+ }
4954
+ }
4727
4955
  };
4728
4956
  static _offset(el) {
4729
4957
  const box = el.getBoundingClientRect();
@@ -4734,13 +4962,13 @@ class ScrollSpy extends Component {
4734
4962
  };
4735
4963
  }
4736
4964
  static _findElements(top, right, bottom, left) {
4737
- let hits = [];
4965
+ const hits = [];
4738
4966
  for (let i = 0; i < ScrollSpy._elements.length; i++) {
4739
- let scrollspy = ScrollSpy._elements[i];
4740
- let currTop = top + scrollspy.options.scrollOffset || 200;
4967
+ const scrollspy = ScrollSpy._elements[i];
4968
+ const currTop = top + scrollspy.options.scrollOffset || 200;
4741
4969
  if (scrollspy.el.getBoundingClientRect().height > 0) {
4742
- let elTop = ScrollSpy._offset(scrollspy.el).top, elLeft = ScrollSpy._offset(scrollspy.el).left, elRight = elLeft + scrollspy.el.getBoundingClientRect().width, elBottom = elTop + scrollspy.el.getBoundingClientRect().height;
4743
- let isIntersect = !(elLeft > right ||
4970
+ const elTop = ScrollSpy._offset(scrollspy.el).top, elLeft = ScrollSpy._offset(scrollspy.el).left, elRight = elLeft + scrollspy.el.getBoundingClientRect().width, elBottom = elTop + scrollspy.el.getBoundingClientRect().height;
4971
+ const isIntersect = !(elLeft > right ||
4744
4972
  elRight < left ||
4745
4973
  elTop > bottom ||
4746
4974
  elBottom < currTop);
@@ -4752,11 +4980,12 @@ class ScrollSpy extends Component {
4752
4980
  return hits;
4753
4981
  }
4754
4982
  _enter() {
4755
- ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter(value => value.getBoundingClientRect().height !== 0);
4983
+ ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter((value) => value.getBoundingClientRect().height !== 0);
4756
4984
  if (ScrollSpy._visibleElements[0]) {
4757
4985
  const actElem = document.querySelector(this.options.getActiveElement(ScrollSpy._visibleElements[0].id));
4758
4986
  actElem?.classList.remove(this.options.activeClass);
4759
- if (ScrollSpy._visibleElements[0].M_ScrollSpy && this.id < ScrollSpy._visibleElements[0].M_ScrollSpy.id) {
4987
+ if (ScrollSpy._visibleElements[0]['M_ScrollSpy'] &&
4988
+ this.id < ScrollSpy._visibleElements[0]['M_ScrollSpy'].id) {
4760
4989
  ScrollSpy._visibleElements.unshift(this.el);
4761
4990
  }
4762
4991
  else {
@@ -4766,11 +4995,12 @@ class ScrollSpy extends Component {
4766
4995
  else {
4767
4996
  ScrollSpy._visibleElements.push(this.el);
4768
4997
  }
4998
+ this._resetKeptTopActiveElementIfNeeded();
4769
4999
  const selector = this.options.getActiveElement(ScrollSpy._visibleElements[0].id);
4770
5000
  document.querySelector(selector)?.classList.add(this.options.activeClass);
4771
5001
  }
4772
5002
  _exit() {
4773
- ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter(value => value.getBoundingClientRect().height !== 0);
5003
+ ScrollSpy._visibleElements = ScrollSpy._visibleElements.filter((value) => value.getBoundingClientRect().height !== 0);
4774
5004
  if (ScrollSpy._visibleElements[0]) {
4775
5005
  const actElem = document.querySelector(this.options.getActiveElement(ScrollSpy._visibleElements[0].id));
4776
5006
  actElem?.classList.remove(this.options.activeClass);
@@ -4779,8 +5009,39 @@ class ScrollSpy extends Component {
4779
5009
  // Check if empty
4780
5010
  const selector = this.options.getActiveElement(ScrollSpy._visibleElements[0].id);
4781
5011
  document.querySelector(selector)?.classList.add(this.options.activeClass);
5012
+ this._resetKeptTopActiveElementIfNeeded();
5013
+ }
5014
+ }
5015
+ }
5016
+ _resetKeptTopActiveElementIfNeeded() {
5017
+ if (ScrollSpy._keptTopActiveElement) {
5018
+ ScrollSpy._keptTopActiveElement.classList.remove(this.options.activeClass);
5019
+ ScrollSpy._keptTopActiveElement = null;
5020
+ }
5021
+ }
5022
+ static _getDistanceToViewport(element) {
5023
+ const rect = element.getBoundingClientRect();
5024
+ const distance = rect.top;
5025
+ return distance;
5026
+ }
5027
+ static _smoothScrollIntoView(element, duration = 300) {
5028
+ const targetPosition = element.getBoundingClientRect().top + (window.scrollY || window.pageYOffset);
5029
+ const startPosition = window.scrollY || window.pageYOffset;
5030
+ const distance = targetPosition - startPosition;
5031
+ const startTime = performance.now();
5032
+ function scrollStep(currentTime) {
5033
+ const elapsed = currentTime - startTime;
5034
+ const progress = Math.min(elapsed / duration, 1);
5035
+ const scrollY = startPosition + distance * progress;
5036
+ if (progress < 1) {
5037
+ window.scrollTo(0, scrollY);
5038
+ requestAnimationFrame(scrollStep);
5039
+ }
5040
+ else {
5041
+ window.scrollTo(0, targetPosition);
4782
5042
  }
4783
5043
  }
5044
+ requestAnimationFrame(scrollStep);
4784
5045
  }
4785
5046
  static {
4786
5047
  ScrollSpy._elements = [];
@@ -4828,7 +5089,7 @@ class Sidenav extends Component {
4828
5089
  percentOpen;
4829
5090
  constructor(el, options) {
4830
5091
  super(el, options, Sidenav);
4831
- this.el.M_Sidenav = this;
5092
+ this.el['M_Sidenav'] = this;
4832
5093
  this.options = {
4833
5094
  ...Sidenav.defaults,
4834
5095
  ...options
@@ -4859,14 +5120,14 @@ class Sidenav extends Component {
4859
5120
  return super.init(els, options, Sidenav);
4860
5121
  }
4861
5122
  static getInstance(el) {
4862
- return el.M_Sidenav;
5123
+ return el['M_Sidenav'];
4863
5124
  }
4864
5125
  destroy() {
4865
5126
  this._removeEventHandlers();
4866
5127
  this._enableBodyScrolling();
4867
5128
  this._overlay.parentNode.removeChild(this._overlay);
4868
5129
  this.dragTarget.parentNode.removeChild(this.dragTarget);
4869
- this.el.M_Sidenav = undefined;
5130
+ this.el['M_Sidenav'] = undefined;
4870
5131
  this.el.style.transform = '';
4871
5132
  const index = Sidenav._sidenavs.indexOf(this);
4872
5133
  if (index >= 0) {
@@ -4883,18 +5144,21 @@ class Sidenav extends Component {
4883
5144
  if (Sidenav._sidenavs.length === 0) {
4884
5145
  document.body.addEventListener('click', this._handleTriggerClick);
4885
5146
  }
4886
- var passiveIfSupported = null;
5147
+ const passiveIfSupported = null;
4887
5148
  this.dragTarget.addEventListener('touchmove', this._handleDragTargetDrag, passiveIfSupported);
4888
5149
  this.dragTarget.addEventListener('touchend', this._handleDragTargetRelease);
4889
5150
  this._overlay.addEventListener('touchmove', this._handleCloseDrag, passiveIfSupported);
4890
5151
  this._overlay.addEventListener('touchend', this._handleCloseRelease);
4891
- this.el.addEventListener('touchmove', this._handleCloseDrag, passiveIfSupported);
5152
+ this.el.addEventListener('touchmove', this._handleCloseDrag); // , passiveIfSupported);
4892
5153
  this.el.addEventListener('touchend', this._handleCloseRelease);
4893
5154
  this.el.addEventListener('click', this._handleCloseTriggerClick);
4894
5155
  // Add resize for side nav fixed
4895
5156
  if (this.isFixed) {
4896
5157
  window.addEventListener('resize', this._handleWindowResize);
4897
5158
  }
5159
+ /* Set aria-hidden state */
5160
+ this._setAriaHidden();
5161
+ this._setTabIndex();
4898
5162
  }
4899
5163
  _removeEventHandlers() {
4900
5164
  if (Sidenav._sidenavs.length === 1) {
@@ -4916,9 +5180,9 @@ class Sidenav extends Component {
4916
5180
  const trigger = e.target.closest('.sidenav-trigger');
4917
5181
  if (e.target && trigger) {
4918
5182
  const sidenavId = Utils.getIdFromTrigger(trigger);
4919
- const sidenavInstance = document.getElementById(sidenavId).M_Sidenav;
5183
+ const sidenavInstance = document.getElementById(sidenavId)['M_Sidenav'];
4920
5184
  if (sidenavInstance) {
4921
- sidenavInstance.open(trigger);
5185
+ sidenavInstance.open();
4922
5186
  }
4923
5187
  e.preventDefault();
4924
5188
  }
@@ -4949,18 +5213,9 @@ class Sidenav extends Component {
4949
5213
  }
4950
5214
  _handleDragTargetDrag = (e) => {
4951
5215
  // Check if draggable
4952
- if (!this.options.draggable || this._isCurrentlyFixed() || this._verticallyScrolling) {
5216
+ if (!this._isDraggable())
4953
5217
  return;
4954
- }
4955
- // If not being dragged, set initial drag start variables
4956
- if (!this.isDragged) {
4957
- this._startDrag(e);
4958
- }
4959
- // Run touchmove updates
4960
- this._dragMoveUpdate(e);
4961
- // Calculate raw deltaX
4962
- let totalDeltaX = this._xPos - this._startingXpos;
4963
- // dragDirection is the attempted user drag direction
5218
+ let totalDeltaX = this._calculateDelta(e);
4964
5219
  const dragDirection = totalDeltaX > 0 ? 'right' : 'left';
4965
5220
  // Don't allow totalDeltaX to exceed Sidenav width or be dragged in the opposite direction
4966
5221
  totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
@@ -4997,36 +5252,35 @@ class Sidenav extends Component {
4997
5252
  }
4998
5253
  };
4999
5254
  _handleCloseDrag = (e) => {
5000
- if (this.isOpen) {
5001
- // Check if draggable
5002
- if (!this.options.draggable || this._isCurrentlyFixed() || this._verticallyScrolling) {
5003
- return;
5004
- }
5005
- // If not being dragged, set initial drag start variables
5006
- if (!this.isDragged) {
5007
- this._startDrag(e);
5008
- }
5009
- // Run touchmove updates
5010
- this._dragMoveUpdate(e);
5011
- // Calculate raw deltaX
5012
- let totalDeltaX = this._xPos - this._startingXpos;
5013
- // dragDirection is the attempted user drag direction
5014
- let dragDirection = totalDeltaX > 0 ? 'right' : 'left';
5015
- // Don't allow totalDeltaX to exceed Sidenav width or be dragged in the opposite direction
5016
- totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
5017
- if (this.options.edge !== dragDirection) {
5018
- totalDeltaX = 0;
5019
- }
5020
- let transformX = -totalDeltaX;
5021
- if (this.options.edge === 'right') {
5022
- transformX = -transformX;
5023
- }
5024
- // Calculate open/close percentage of sidenav, with open = 1 and close = 0
5025
- this.percentOpen = Math.min(1, 1 - totalDeltaX / this._width);
5026
- // Set transform and opacity styles
5027
- this.el.style.transform = `translateX(${transformX}px)`;
5028
- this._overlay.style.opacity = this.percentOpen.toString();
5255
+ // Check if open and draggable
5256
+ if (!this.isOpen || !this._isDraggable())
5257
+ return;
5258
+ let totalDeltaX = this._calculateDelta(e);
5259
+ // dragDirection is the attempted user drag direction
5260
+ const dragDirection = totalDeltaX > 0 ? 'right' : 'left';
5261
+ totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
5262
+ if (this.options.edge !== dragDirection) {
5263
+ totalDeltaX = 0;
5264
+ }
5265
+ let transformX = -totalDeltaX;
5266
+ if (this.options.edge === 'right') {
5267
+ transformX = -transformX;
5268
+ }
5269
+ // Calculate open/close percentage of sidenav, with open = 1 and close = 0
5270
+ this.percentOpen = Math.min(1, 1 - totalDeltaX / this._width);
5271
+ // Set transform and opacity styles
5272
+ this.el.style.transform = `translateX(${transformX}px)`;
5273
+ this._overlay.style.opacity = this.percentOpen.toString();
5274
+ };
5275
+ _calculateDelta = (e) => {
5276
+ // If not being dragged, set initial drag start variables
5277
+ if (!this.isDragged) {
5278
+ this._startDrag(e);
5029
5279
  }
5280
+ // Run touchmove updates
5281
+ this._dragMoveUpdate(e);
5282
+ // Calculate raw deltaX
5283
+ return this._xPos - this._startingXpos;
5030
5284
  };
5031
5285
  _handleCloseRelease = () => {
5032
5286
  if (this.isOpen && this.isDragged) {
@@ -5074,6 +5328,9 @@ class Sidenav extends Component {
5074
5328
  if (this._isCurrentlyFixed())
5075
5329
  this.open();
5076
5330
  }
5331
+ _isDraggable() {
5332
+ return this.options.draggable && !this._isCurrentlyFixed() && !this._verticallyScrolling;
5333
+ }
5077
5334
  _isCurrentlyFixed() {
5078
5335
  return this.isFixed && window.innerWidth > 992;
5079
5336
  }
@@ -5114,6 +5371,9 @@ class Sidenav extends Component {
5114
5371
  this._preventBodyScrolling();
5115
5372
  if (!this.isDragged || this.percentOpen != 1)
5116
5373
  this._animateIn();
5374
+ /* Set aria-hidden state */
5375
+ this._setAriaHidden();
5376
+ this._setTabIndex();
5117
5377
  }
5118
5378
  };
5119
5379
  /**
@@ -5141,6 +5401,9 @@ class Sidenav extends Component {
5141
5401
  else {
5142
5402
  this._overlay.style.display = 'none';
5143
5403
  }
5404
+ /* Set aria-hidden state */
5405
+ this._setAriaHidden();
5406
+ this._setTabIndex();
5144
5407
  }
5145
5408
  };
5146
5409
  _animateIn() {
@@ -5162,7 +5425,7 @@ class Sidenav extends Component {
5162
5425
  const duration = this.options.inDuration;
5163
5426
  // from
5164
5427
  this.el.style.transition = 'none';
5165
- this.el.style.transform = 'translateX(' + (slideOutPercent * 100) + '%)';
5428
+ this.el.style.transform = 'translateX(' + slideOutPercent * 100 + '%)';
5166
5429
  setTimeout(() => {
5167
5430
  this.el.style.transition = `transform ${duration}ms ease`; // easeOutQuad
5168
5431
  // to
@@ -5175,15 +5438,18 @@ class Sidenav extends Component {
5175
5438
  }
5176
5439
  _animateSidenavOut() {
5177
5440
  const endPercent = this.options.edge === 'left' ? -1 : 1;
5178
- if (this.isDragged) {
5179
- this.options.edge === 'left'
5180
- ? endPercent + this.percentOpen
5181
- : endPercent - this.percentOpen;
5182
- }
5441
+ // let slideOutPercent = 0;
5442
+ // if (this.isDragged) {
5443
+ // // @todo unused variable
5444
+ // slideOutPercent =
5445
+ // this.options.edge === 'left'
5446
+ // ? endPercent + this.percentOpen
5447
+ // : endPercent - this.percentOpen;
5448
+ // }
5183
5449
  const duration = this.options.outDuration;
5184
5450
  this.el.style.transition = `transform ${duration}ms ease`; // easeOutQuad
5185
5451
  // to
5186
- this.el.style.transform = 'translateX(' + (endPercent * 100) + '%)';
5452
+ this.el.style.transform = 'translateX(' + endPercent * 100 + '%)';
5187
5453
  setTimeout(() => {
5188
5454
  if (typeof this.options.onCloseEnd === 'function')
5189
5455
  this.options.onCloseEnd.call(this, this.el);
@@ -5217,12 +5483,30 @@ class Sidenav extends Component {
5217
5483
  this._overlay.style.display = 'none';
5218
5484
  }, duration);
5219
5485
  }
5486
+ _setAriaHidden = () => {
5487
+ this.el.ariaHidden = this.isOpen ? 'false' : 'true';
5488
+ const navWrapper = document.querySelector('.nav-wrapper ul');
5489
+ if (navWrapper)
5490
+ navWrapper.ariaHidden = this.isOpen.toString();
5491
+ };
5492
+ _setTabIndex = () => {
5493
+ const navLinks = document.querySelectorAll('.nav-wrapper ul li a');
5494
+ const sideNavLinks = document.querySelectorAll('.sidenav li a');
5495
+ if (navLinks)
5496
+ navLinks.forEach((navLink) => {
5497
+ navLink.tabIndex = this.isOpen ? -1 : 0;
5498
+ });
5499
+ if (sideNavLinks)
5500
+ sideNavLinks.forEach((sideNavLink) => {
5501
+ sideNavLink.tabIndex = this.isOpen ? 0 : -1;
5502
+ });
5503
+ };
5220
5504
  static {
5221
5505
  Sidenav._sidenavs = [];
5222
5506
  }
5223
5507
  }
5224
5508
 
5225
- let _defaults$7 = {
5509
+ const _defaults$7 = {
5226
5510
  duration: 300,
5227
5511
  onShow: null,
5228
5512
  swipeable: false,
@@ -5239,7 +5523,7 @@ class Tabs extends Component {
5239
5523
  _content;
5240
5524
  constructor(el, options) {
5241
5525
  super(el, options, Tabs);
5242
- this.el.M_Tabs = this;
5526
+ this.el['M_Tabs'] = this;
5243
5527
  this.options = {
5244
5528
  ...Tabs.defaults,
5245
5529
  ...options
@@ -5270,7 +5554,7 @@ class Tabs extends Component {
5270
5554
  return super.init(els, options, Tabs);
5271
5555
  }
5272
5556
  static getInstance(el) {
5273
- return el.M_Tabs;
5557
+ return el['M_Tabs'];
5274
5558
  }
5275
5559
  destroy() {
5276
5560
  this._removeEventHandlers();
@@ -5281,12 +5565,14 @@ class Tabs extends Component {
5281
5565
  else {
5282
5566
  this._teardownNormalTabs();
5283
5567
  }
5284
- this.el.M_Tabs = undefined;
5568
+ this.el['M_Tabs'] = undefined;
5285
5569
  }
5286
5570
  /**
5287
5571
  * The index of tab that is currently shown.
5288
5572
  */
5289
- get index() { return this._index; }
5573
+ get index() {
5574
+ return this._index;
5575
+ }
5290
5576
  _setupEventHandlers() {
5291
5577
  window.addEventListener('resize', this._handleWindowResize);
5292
5578
  this.el.addEventListener('click', this._handleTabClick);
@@ -5303,8 +5589,14 @@ class Tabs extends Component {
5303
5589
  }
5304
5590
  };
5305
5591
  _handleTabClick = (e) => {
5306
- const tabLink = e.target;
5307
- const tab = tabLink.parentElement;
5592
+ let tabLink = e.target;
5593
+ if (!tabLink)
5594
+ return;
5595
+ let tab = tabLink.parentElement;
5596
+ while (tab && !tab.classList.contains('tab')) {
5597
+ tabLink = tabLink.parentElement;
5598
+ tab = tab.parentElement;
5599
+ }
5308
5600
  // Handle click on tab link only
5309
5601
  if (!tabLink || !tab.classList.contains('tab'))
5310
5602
  return;
@@ -5367,10 +5659,11 @@ class Tabs extends Component {
5367
5659
  this._activeTabLink = Array.from(this._tabLinks).find((a) => a.getAttribute('href') === location.hash);
5368
5660
  // If no match is found, use the first link or any with class 'active' as the initial active tab.
5369
5661
  if (!this._activeTabLink) {
5370
- this._activeTabLink = this.el.querySelector('li.tab a.active');
5371
- }
5372
- if (this._activeTabLink.length === 0) {
5373
- this._activeTabLink = this.el.querySelector('li.tab a');
5662
+ let activeTabLink = this.el.querySelector('li.tab a.active');
5663
+ if (!activeTabLink) {
5664
+ activeTabLink = this.el.querySelector('li.tab a');
5665
+ }
5666
+ this._activeTabLink = activeTabLink;
5374
5667
  }
5375
5668
  Array.from(this._tabLinks).forEach((a) => a.classList.remove('active'));
5376
5669
  this._activeTabLink.classList.add('active');
@@ -5386,7 +5679,7 @@ class Tabs extends Component {
5386
5679
  if (window.innerWidth > this.options.responsiveThreshold)
5387
5680
  this.options.swipeable = false;
5388
5681
  const tabsContent = [];
5389
- this._tabLinks.forEach(a => {
5682
+ this._tabLinks.forEach((a) => {
5390
5683
  if (a.hash) {
5391
5684
  const currContent = document.querySelector(a.hash);
5392
5685
  currContent.classList.add('carousel-item');
@@ -5398,7 +5691,7 @@ class Tabs extends Component {
5398
5691
  tabsWrapper.classList.add('tabs-content', 'carousel', 'carousel-slider');
5399
5692
  // Wrap around
5400
5693
  tabsContent[0].parentElement.insertBefore(tabsWrapper, tabsContent[0]);
5401
- tabsContent.forEach(tabContent => {
5694
+ tabsContent.forEach((tabContent) => {
5402
5695
  tabsWrapper.appendChild(tabContent);
5403
5696
  tabContent.style.display = '';
5404
5697
  });
@@ -5426,7 +5719,7 @@ class Tabs extends Component {
5426
5719
  const tabsWrapper = this._tabsCarousel.el;
5427
5720
  this._tabsCarousel.destroy();
5428
5721
  // Unwrap
5429
- tabsWrapper.after(tabsWrapper.children);
5722
+ tabsWrapper.append(tabsWrapper.parentElement);
5430
5723
  tabsWrapper.remove();
5431
5724
  }
5432
5725
  _setupNormalTabs() {
@@ -5471,7 +5764,7 @@ class Tabs extends Component {
5471
5764
  }
5472
5765
  _animateIndicator(prevIndex) {
5473
5766
  let leftDelay = 0, rightDelay = 0;
5474
- const isMovingLeftOrStaying = (this._index - prevIndex >= 0);
5767
+ const isMovingLeftOrStaying = this._index - prevIndex >= 0;
5475
5768
  if (isMovingLeftOrStaying)
5476
5769
  leftDelay = 90;
5477
5770
  else
@@ -5494,7 +5787,7 @@ class Tabs extends Component {
5494
5787
  }
5495
5788
  }
5496
5789
 
5497
- let _defaults$6 = {
5790
+ const _defaults$6 = {
5498
5791
  onOpen: null,
5499
5792
  onClose: null
5500
5793
  };
@@ -5503,24 +5796,27 @@ class TapTarget extends Component {
5503
5796
  * If the tap target is open.
5504
5797
  */
5505
5798
  isOpen;
5799
+ static _taptargets;
5506
5800
  wrapper;
5507
- _origin;
5801
+ // private _origin: HTMLElement;
5508
5802
  originEl;
5509
5803
  waveEl;
5510
5804
  contentEl;
5511
5805
  constructor(el, options) {
5512
5806
  super(el, options, TapTarget);
5513
- this.el.M_TapTarget = this;
5807
+ this.el['M_TapTarget'] = this;
5514
5808
  this.options = {
5515
5809
  ...TapTarget.defaults,
5516
5810
  ...options
5517
5811
  };
5518
5812
  this.isOpen = false;
5519
5813
  // setup
5520
- this._origin = document.querySelector(`#${el.dataset.target}`);
5814
+ this.originEl = document.querySelector(`#${el.dataset.target}`);
5815
+ this.originEl.tabIndex = 0;
5521
5816
  this._setup();
5522
5817
  this._calculatePositioning();
5523
5818
  this._setupEventHandlers();
5819
+ TapTarget._taptargets.push(this);
5524
5820
  }
5525
5821
  static get defaults() {
5526
5822
  return _defaults$6;
@@ -5534,45 +5830,64 @@ class TapTarget extends Component {
5534
5830
  return super.init(els, options, TapTarget);
5535
5831
  }
5536
5832
  static getInstance(el) {
5537
- return el.M_TapTarget;
5833
+ return el['M_TapTarget'];
5538
5834
  }
5539
5835
  destroy() {
5540
5836
  this._removeEventHandlers();
5541
- this.el.TapTarget = undefined;
5837
+ this.el['M_TapTarget'] = undefined;
5838
+ const index = TapTarget._taptargets.indexOf(this);
5839
+ if (index >= 0) {
5840
+ TapTarget._taptargets.splice(index, 1);
5841
+ }
5542
5842
  }
5543
5843
  _setupEventHandlers() {
5544
- this.el.addEventListener('click', this._handleTargetClick);
5545
- this.originEl.addEventListener('click', this._handleOriginClick);
5844
+ this.originEl.addEventListener('click', this._handleTargetToggle);
5845
+ this.originEl.addEventListener('keypress', this._handleKeyboardInteraction, true);
5846
+ // this.originEl.addEventListener('click', this._handleOriginClick);
5546
5847
  // Resize
5547
5848
  window.addEventListener('resize', this._handleThrottledResize);
5548
5849
  }
5549
5850
  _removeEventHandlers() {
5550
- this.el.removeEventListener('click', this._handleTargetClick);
5551
- this.originEl.removeEventListener('click', this._handleOriginClick);
5851
+ this.originEl.removeEventListener('click', this._handleTargetToggle);
5852
+ this.originEl.removeEventListener('keypress', this._handleKeyboardInteraction, true);
5853
+ // this.originEl.removeEventListener('click', this._handleOriginClick);
5552
5854
  window.removeEventListener('resize', this._handleThrottledResize);
5553
5855
  }
5554
- _handleThrottledResize = Utils.throttle(function () { this._handleResize(); }, 200).bind(this);
5555
- _handleTargetClick = () => {
5556
- this.open();
5856
+ _handleThrottledResize = Utils.throttle(function () {
5857
+ this._handleResize();
5858
+ }, 200).bind(this);
5859
+ _handleKeyboardInteraction = (e) => {
5860
+ if (Utils.keys.ENTER.includes(e.key)) {
5861
+ this._handleTargetToggle();
5862
+ }
5557
5863
  };
5558
- _handleOriginClick = () => {
5559
- this.close();
5864
+ _handleTargetToggle = () => {
5865
+ if (!this.isOpen)
5866
+ this.open();
5867
+ else
5868
+ this.close();
5560
5869
  };
5870
+ /*_handleOriginClick = () => {
5871
+ this.close();
5872
+ }*/
5561
5873
  _handleResize = () => {
5562
5874
  this._calculatePositioning();
5563
5875
  };
5564
5876
  _handleDocumentClick = (e) => {
5565
- if (!e.target.closest('.tap-target-wrapper')) {
5877
+ if (e.target.closest(`#${this.el.dataset.target}`) !== this.originEl &&
5878
+ !e.target.closest('.tap-target-wrapper')) {
5566
5879
  this.close();
5567
- e.preventDefault();
5568
- e.stopPropagation();
5880
+ // e.preventDefault();
5881
+ // e.stopPropagation();
5569
5882
  }
5570
5883
  };
5571
5884
  _setup() {
5572
5885
  // Creating tap target
5573
5886
  this.wrapper = this.el.parentElement;
5574
5887
  this.waveEl = this.wrapper.querySelector('.tap-target-wave');
5575
- this.originEl = this.wrapper.querySelector('.tap-target-origin');
5888
+ this.el.parentElement.ariaExpanded = 'false';
5889
+ this.originEl.style.zIndex = '1002';
5890
+ // this.originEl = this.wrapper.querySelector('.tap-target-origin');
5576
5891
  this.contentEl = this.el.querySelector('.tap-target-content');
5577
5892
  // Creating wrapper
5578
5893
  if (!this.wrapper.classList.contains('.tap-target-wrapper')) {
@@ -5592,13 +5907,13 @@ class TapTarget extends Component {
5592
5907
  this.waveEl = document.createElement('div');
5593
5908
  this.waveEl.classList.add('tap-target-wave');
5594
5909
  // Creating origin
5595
- if (!this.originEl) {
5596
- this.originEl = this._origin.cloneNode(true); // .clone(true, true);
5597
- this.originEl.classList.add('tap-target-origin');
5598
- this.originEl.removeAttribute('id');
5599
- this.originEl.removeAttribute('style');
5600
- this.waveEl.append(this.originEl);
5601
- }
5910
+ /*if (!this.originEl) {
5911
+ this.originEl = <HTMLElement>this._origin.cloneNode(true); // .clone(true, true);
5912
+ this.originEl.classList.add('tap-target-origin');
5913
+ this.originEl.removeAttribute('id');
5914
+ this.originEl.removeAttribute('style');
5915
+ this.waveEl.append(this.originEl);
5916
+ }*/
5602
5917
  this.wrapper.append(this.waveEl);
5603
5918
  }
5604
5919
  }
@@ -5612,9 +5927,10 @@ class TapTarget extends Component {
5612
5927
  }
5613
5928
  _calculatePositioning() {
5614
5929
  // Element or parent is fixed position?
5615
- let isFixed = getComputedStyle(this._origin).position === 'fixed';
5930
+ let isFixed = getComputedStyle(this.originEl).position === 'fixed';
5616
5931
  if (!isFixed) {
5617
- let currentElem = this._origin;
5932
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5933
+ let currentElem = this.originEl;
5618
5934
  const parents = [];
5619
5935
  while ((currentElem = currentElem.parentNode) && currentElem !== document)
5620
5936
  parents.push(currentElem);
@@ -5625,10 +5941,14 @@ class TapTarget extends Component {
5625
5941
  }
5626
5942
  }
5627
5943
  // Calculating origin
5628
- const originWidth = this._origin.offsetWidth;
5629
- const originHeight = this._origin.offsetHeight;
5630
- const originTop = isFixed ? this._offset(this._origin).top - Utils.getDocumentScrollTop() : this._offset(this._origin).top;
5631
- const originLeft = isFixed ? this._offset(this._origin).left - Utils.getDocumentScrollLeft() : this._offset(this._origin).left;
5944
+ const originWidth = this.originEl.offsetWidth;
5945
+ const originHeight = this.originEl.offsetHeight;
5946
+ const originTop = isFixed
5947
+ ? this._offset(this.originEl).top - Utils.getDocumentScrollTop()
5948
+ : this._offset(this.originEl).top;
5949
+ const originLeft = isFixed
5950
+ ? this._offset(this.originEl).left - Utils.getDocumentScrollLeft()
5951
+ : this._offset(this.originEl).left;
5632
5952
  // Calculating screen
5633
5953
  const windowWidth = window.innerWidth;
5634
5954
  const windowHeight = window.innerHeight;
@@ -5662,8 +5982,12 @@ class TapTarget extends Component {
5662
5982
  const tapTargetWaveLeft = tapTargetWidth / 2 - tapTargetWaveWidth / 2;
5663
5983
  // Setting tap target
5664
5984
  this.wrapper.style.top = isTop ? tapTargetTop + 'px' : '';
5665
- this.wrapper.style.right = isRight ? windowWidth - tapTargetLeft - tapTargetWidth - scrollBarWidth + 'px' : '';
5666
- this.wrapper.style.bottom = isBottom ? windowHeight - tapTargetTop - tapTargetHeight + 'px' : '';
5985
+ this.wrapper.style.right = isRight
5986
+ ? windowWidth - tapTargetLeft - tapTargetWidth - scrollBarWidth + 'px'
5987
+ : '';
5988
+ this.wrapper.style.bottom = isBottom
5989
+ ? windowHeight - tapTargetTop - tapTargetHeight + 'px'
5990
+ : '';
5667
5991
  this.wrapper.style.left = isLeft ? tapTargetLeft + 'px' : '';
5668
5992
  this.wrapper.style.position = tapTargetPosition;
5669
5993
  // Setting content
@@ -5689,11 +6013,13 @@ class TapTarget extends Component {
5689
6013
  return;
5690
6014
  // onOpen callback
5691
6015
  if (typeof this.options.onOpen === 'function') {
5692
- this.options.onOpen.call(this, this._origin);
6016
+ this.options.onOpen.call(this, this.originEl);
5693
6017
  }
5694
6018
  this.isOpen = true;
5695
6019
  this.wrapper.classList.add('open');
6020
+ this.wrapper.ariaExpanded = 'true';
5696
6021
  document.body.addEventListener('click', this._handleDocumentClick, true);
6022
+ document.body.addEventListener('keypress', this._handleDocumentClick, true);
5697
6023
  document.body.addEventListener('touchend', this._handleDocumentClick);
5698
6024
  };
5699
6025
  /**
@@ -5704,16 +6030,21 @@ class TapTarget extends Component {
5704
6030
  return;
5705
6031
  // onClose callback
5706
6032
  if (typeof this.options.onClose === 'function') {
5707
- this.options.onClose.call(this, this._origin);
6033
+ this.options.onClose.call(this, this.originEl);
5708
6034
  }
5709
6035
  this.isOpen = false;
5710
6036
  this.wrapper.classList.remove('open');
6037
+ this.wrapper.ariaExpanded = 'false';
5711
6038
  document.body.removeEventListener('click', this._handleDocumentClick, true);
6039
+ document.body.removeEventListener('keypress', this._handleDocumentClick, true);
5712
6040
  document.body.removeEventListener('touchend', this._handleDocumentClick);
5713
6041
  };
6042
+ static {
6043
+ TapTarget._taptargets = [];
6044
+ }
5714
6045
  }
5715
6046
 
5716
- let _defaults$5 = {
6047
+ const _defaults$5 = {
5717
6048
  dialRadius: 135,
5718
6049
  outerRadius: 105,
5719
6050
  innerRadius: 70,
@@ -5729,19 +6060,13 @@ let _defaults$5 = {
5729
6060
  clear: 'Clear',
5730
6061
  done: 'Ok'
5731
6062
  },
5732
- autoClose: false, // auto close when minute is selected
5733
6063
  twelveHour: true, // change to 12 hour AM/PM clock from 24 hour
5734
6064
  vibrate: true, // vibrate the device when dragging clock hand
5735
6065
  // Callbacks
5736
- onOpenStart: null,
5737
- onOpenEnd: null,
5738
- onCloseStart: null,
5739
- onCloseEnd: null,
5740
6066
  onSelect: null
5741
6067
  };
5742
6068
  class Timepicker extends Component {
5743
6069
  id;
5744
- modal;
5745
6070
  modalEl;
5746
6071
  plate;
5747
6072
  digitalClock;
@@ -5769,8 +6094,6 @@ class Timepicker extends Component {
5769
6094
  */
5770
6095
  amOrPm;
5771
6096
  static _template;
5772
- /** If the picker is open. */
5773
- isOpen;
5774
6097
  /** Vibrate device when dragging clock hand. */
5775
6098
  vibrate;
5776
6099
  _canvas;
@@ -5783,18 +6106,16 @@ class Timepicker extends Component {
5783
6106
  bearing;
5784
6107
  g;
5785
6108
  toggleViewTimer;
5786
- canvas;
5787
6109
  vibrateTimer;
5788
6110
  constructor(el, options) {
5789
6111
  super(el, options, Timepicker);
5790
- this.el.M_Timepicker = this;
6112
+ this.el['M_Timepicker'] = this;
5791
6113
  this.options = {
5792
6114
  ...Timepicker.defaults,
5793
6115
  ...options
5794
6116
  };
5795
6117
  this.id = Utils.guid();
5796
6118
  this._insertHTMLIntoDOM();
5797
- this._setupModal();
5798
6119
  this._setupVariables();
5799
6120
  this._setupEventHandlers();
5800
6121
  this._clockSetup();
@@ -5815,24 +6136,26 @@ class Timepicker extends Component {
5815
6136
  return (num < 10 ? '0' : '') + num;
5816
6137
  }
5817
6138
  static _createSVGEl(name) {
5818
- let svgNS = 'http://www.w3.org/2000/svg';
6139
+ const svgNS = 'http://www.w3.org/2000/svg';
5819
6140
  return document.createElementNS(svgNS, name);
5820
6141
  }
5821
6142
  static _Pos(e) {
5822
- if (e.type.startsWith("touch") && e.targetTouches.length >= 1) {
5823
- return { x: e.targetTouches[0].clientX, y: e.targetTouches[0].clientY };
6143
+ if (e.type.startsWith('touch') && e.targetTouches.length >= 1) {
6144
+ return {
6145
+ x: e.targetTouches[0].clientX,
6146
+ y: e.targetTouches[0].clientY
6147
+ };
5824
6148
  }
5825
6149
  // mouse event
5826
6150
  return { x: e.clientX, y: e.clientY };
5827
6151
  }
5828
6152
  static getInstance(el) {
5829
- return el.M_Timepicker;
6153
+ return el['M_Timepicker'];
5830
6154
  }
5831
6155
  destroy() {
5832
6156
  this._removeEventHandlers();
5833
- this.modal.destroy();
5834
6157
  this.modalEl.remove();
5835
- this.el.M_Timepicker = undefined;
6158
+ this.el['M_Timepicker'] = undefined;
5836
6159
  }
5837
6160
  _setupEventHandlers() {
5838
6161
  this.el.addEventListener('click', this._handleInputClick);
@@ -5840,8 +6163,10 @@ class Timepicker extends Component {
5840
6163
  this.plate.addEventListener('mousedown', this._handleClockClickStart);
5841
6164
  this.plate.addEventListener('touchstart', this._handleClockClickStart);
5842
6165
  this.digitalClock.addEventListener('keyup', this._inputFromTextField);
5843
- this.inputHours.addEventListener('click', () => this.showView('hours'));
5844
- this.inputMinutes.addEventListener('click', () => this.showView('minutes'));
6166
+ this.inputHours.addEventListener('focus', () => this.showView('hours'));
6167
+ this.inputHours.addEventListener('focusout', () => this.formatHours());
6168
+ this.inputMinutes.addEventListener('focus', () => this.showView('minutes'));
6169
+ this.inputMinutes.addEventListener('focusout', () => this.formatMinutes());
5845
6170
  }
5846
6171
  _removeEventHandlers() {
5847
6172
  this.el.removeEventListener('click', this._handleInputClick);
@@ -5864,12 +6189,12 @@ class Timepicker extends Component {
5864
6189
  };
5865
6190
  _handleClockClickStart = (e) => {
5866
6191
  e.preventDefault();
5867
- let clockPlateBR = this.plate.getBoundingClientRect();
5868
- let offset = { x: clockPlateBR.left, y: clockPlateBR.top };
6192
+ const clockPlateBR = this.plate.getBoundingClientRect();
6193
+ const offset = { x: clockPlateBR.left, y: clockPlateBR.top };
5869
6194
  this.x0 = offset.x + this.options.dialRadius;
5870
6195
  this.y0 = offset.y + this.options.dialRadius;
5871
6196
  this.moved = false;
5872
- let clickPos = Timepicker._Pos(e);
6197
+ const clickPos = Timepicker._Pos(e);
5873
6198
  this.dx = clickPos.x - this.x0;
5874
6199
  this.dy = clickPos.y - this.y0;
5875
6200
  // Set clock hands
@@ -5883,9 +6208,9 @@ class Timepicker extends Component {
5883
6208
  };
5884
6209
  _handleDocumentClickMove = (e) => {
5885
6210
  e.preventDefault();
5886
- let clickPos = Timepicker._Pos(e);
5887
- let x = clickPos.x - this.x0;
5888
- let y = clickPos.y - this.y0;
6211
+ const clickPos = Timepicker._Pos(e);
6212
+ const x = clickPos.x - this.x0;
6213
+ const y = clickPos.y - this.y0;
5889
6214
  this.moved = true;
5890
6215
  this.setHand(x, y, false);
5891
6216
  };
@@ -5893,16 +6218,16 @@ class Timepicker extends Component {
5893
6218
  e.preventDefault();
5894
6219
  document.removeEventListener('mouseup', this._handleDocumentClickEnd);
5895
6220
  document.removeEventListener('touchend', this._handleDocumentClickEnd);
5896
- let clickPos = Timepicker._Pos(e);
5897
- let x = clickPos.x - this.x0;
5898
- let y = clickPos.y - this.y0;
6221
+ const clickPos = Timepicker._Pos(e);
6222
+ const x = clickPos.x - this.x0;
6223
+ const y = clickPos.y - this.y0;
5899
6224
  if (this.moved && x === this.dx && y === this.dy) {
5900
6225
  this.setHand(x, y);
5901
6226
  }
5902
6227
  if (this.currentView === 'hours') {
5903
6228
  this.showView('minutes', this.options.duration / 2);
5904
6229
  }
5905
- else if (this.options.autoClose) {
6230
+ else {
5906
6231
  this.minutesView.classList.add('timepicker-dial-out');
5907
6232
  setTimeout(() => {
5908
6233
  this.done();
@@ -5930,24 +6255,11 @@ class Timepicker extends Component {
5930
6255
  this.el.parentElement.appendChild(this.modalEl);
5931
6256
  }
5932
6257
  }
5933
- _setupModal() {
5934
- this.modal = Modal.init(this.modalEl, {
5935
- onOpenStart: this.options.onOpenStart,
5936
- onOpenEnd: this.options.onOpenEnd,
5937
- onCloseStart: this.options.onCloseStart,
5938
- onCloseEnd: () => {
5939
- if (typeof this.options.onCloseEnd === 'function') {
5940
- this.options.onCloseEnd.call(this);
5941
- }
5942
- this.isOpen = false;
5943
- }
5944
- });
5945
- }
5946
6258
  _setupVariables() {
5947
6259
  this.currentView = 'hours';
5948
6260
  this.vibrate = navigator.vibrate
5949
6261
  ? 'vibrate'
5950
- : navigator.webkitVibrate
6262
+ : navigator['webkitVibrate']
5951
6263
  ? 'webkitVibrate'
5952
6264
  : null;
5953
6265
  this._canvas = this.modalEl.querySelector('.timepicker-canvas');
@@ -5963,10 +6275,10 @@ class Timepicker extends Component {
5963
6275
  }
5964
6276
  _createButton(text, visibility) {
5965
6277
  const button = document.createElement('button');
5966
- button.classList.add('btn-flat', 'waves-effect');
6278
+ button.classList.add('btn', 'btn-flat', 'waves-effect', 'text');
5967
6279
  button.style.visibility = visibility;
5968
6280
  button.type = 'button';
5969
- button.tabIndex = this.options.twelveHour ? 3 : 1;
6281
+ button.tabIndex = -1;
5970
6282
  button.innerText = text;
5971
6283
  return button;
5972
6284
  }
@@ -5984,20 +6296,20 @@ class Timepicker extends Component {
5984
6296
  confirmationBtnsContainer.appendChild(cancelButton);
5985
6297
  const doneButton = this._createButton(this.options.i18n.done, '');
5986
6298
  doneButton.classList.add('timepicker-close');
5987
- doneButton.addEventListener('click', this.done);
6299
+ //doneButton.addEventListener('click', this._finishSelection);
5988
6300
  confirmationBtnsContainer.appendChild(doneButton);
5989
6301
  }
5990
6302
  _clockSetup() {
5991
6303
  if (this.options.twelveHour) {
5992
6304
  // AM Button
5993
6305
  this._amBtn = document.createElement('div');
5994
- this._amBtn.classList.add('am-btn');
6306
+ this._amBtn.classList.add('am-btn', 'btn');
5995
6307
  this._amBtn.innerText = 'AM';
5996
6308
  this._amBtn.addEventListener('click', this._handleAmPmClick);
5997
6309
  this.spanAmPm.appendChild(this._amBtn);
5998
6310
  // PM Button
5999
6311
  this._pmBtn = document.createElement('div');
6000
- this._pmBtn.classList.add('pm-btn');
6312
+ this._pmBtn.classList.add('pm-btn', 'btn');
6001
6313
  this._pmBtn.innerText = 'PM';
6002
6314
  this._pmBtn.addEventListener('click', this._handleAmPmClick);
6003
6315
  this.spanAmPm.appendChild(this._pmBtn);
@@ -6008,24 +6320,24 @@ class Timepicker extends Component {
6008
6320
  }
6009
6321
  _buildSVGClock() {
6010
6322
  // Draw clock hands and others
6011
- let dialRadius = this.options.dialRadius;
6012
- let tickRadius = this.options.tickRadius;
6013
- let diameter = dialRadius * 2;
6014
- let svg = Timepicker._createSVGEl('svg');
6323
+ const dialRadius = this.options.dialRadius;
6324
+ const tickRadius = this.options.tickRadius;
6325
+ const diameter = dialRadius * 2;
6326
+ const svg = Timepicker._createSVGEl('svg');
6015
6327
  svg.setAttribute('class', 'timepicker-svg');
6016
6328
  svg.setAttribute('width', diameter.toString());
6017
6329
  svg.setAttribute('height', diameter.toString());
6018
- let g = Timepicker._createSVGEl('g');
6330
+ const g = Timepicker._createSVGEl('g');
6019
6331
  g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
6020
- let bearing = Timepicker._createSVGEl('circle');
6332
+ const bearing = Timepicker._createSVGEl('circle');
6021
6333
  bearing.setAttribute('class', 'timepicker-canvas-bearing');
6022
6334
  bearing.setAttribute('cx', '0');
6023
6335
  bearing.setAttribute('cy', '0');
6024
6336
  bearing.setAttribute('r', '4');
6025
- let hand = Timepicker._createSVGEl('line');
6337
+ const hand = Timepicker._createSVGEl('line');
6026
6338
  hand.setAttribute('x1', '0');
6027
6339
  hand.setAttribute('y1', '0');
6028
- let bg = Timepicker._createSVGEl('circle');
6340
+ const bg = Timepicker._createSVGEl('circle');
6029
6341
  bg.setAttribute('class', 'timepicker-canvas-bg');
6030
6342
  bg.setAttribute('r', tickRadius.toString());
6031
6343
  g.appendChild(hand);
@@ -6039,35 +6351,37 @@ class Timepicker extends Component {
6039
6351
  this.g = g;
6040
6352
  }
6041
6353
  _buildHoursView() {
6042
- const $tick = document.createElement('div');
6043
- $tick.classList.add('timepicker-tick');
6354
+ // const $tick = document.createElement('div');
6355
+ // $tick.classList.add('timepicker-tick');
6044
6356
  // Hours view
6045
6357
  if (this.options.twelveHour) {
6046
6358
  for (let i = 1; i < 13; i += 1) {
6047
- const tick = $tick.cloneNode(true);
6359
+ // const tick = <HTMLElement>$tick.cloneNode(true);
6048
6360
  const radian = (i / 6) * Math.PI;
6049
6361
  const radius = this.options.outerRadius;
6050
- tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
6051
- tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
6052
- tick.innerHTML = i === 0 ? '00' : i.toString();
6053
- this.hoursView.appendChild(tick);
6054
- // tick.on(mousedownEvent, mousedown);
6362
+ this._buildHoursTick(i, radian, radius);
6055
6363
  }
6056
6364
  }
6057
6365
  else {
6058
6366
  for (let i = 0; i < 24; i += 1) {
6059
- const tick = $tick.cloneNode(true);
6367
+ // const tick = <HTMLElement>$tick.cloneNode(true);
6060
6368
  const radian = (i / 6) * Math.PI;
6061
6369
  const inner = i > 0 && i < 13;
6062
6370
  const radius = inner ? this.options.innerRadius : this.options.outerRadius;
6063
- tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
6064
- tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
6065
- tick.innerHTML = i === 0 ? '00' : i.toString();
6066
- this.hoursView.appendChild(tick);
6067
- // tick.on(mousedownEvent, mousedown);
6371
+ this._buildHoursTick(i, radian, radius);
6068
6372
  }
6069
6373
  }
6070
6374
  }
6375
+ _buildHoursTick(i, radian, radius) {
6376
+ const tick = document.createElement('div');
6377
+ tick.classList.add('timepicker-tick');
6378
+ tick.style.left =
6379
+ this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
6380
+ tick.style.top =
6381
+ this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
6382
+ tick.innerHTML = i === 0 ? '00' : i.toString();
6383
+ this.hoursView.appendChild(tick);
6384
+ }
6071
6385
  _buildMinutesView() {
6072
6386
  const _tick = document.createElement('div');
6073
6387
  _tick.classList.add('timepicker-tick');
@@ -6097,12 +6411,12 @@ class Timepicker extends Component {
6097
6411
  _updateAmPmView() {
6098
6412
  if (this.options.twelveHour) {
6099
6413
  if (this.amOrPm === 'PM') {
6100
- this._amBtn.classList.remove('text-primary');
6101
- this._pmBtn.classList.add('text-primary');
6414
+ this._amBtn.classList.remove('filled');
6415
+ this._pmBtn.classList.add('filled');
6102
6416
  }
6103
6417
  else if (this.amOrPm === 'AM') {
6104
- this._amBtn.classList.add('text-primary');
6105
- this._pmBtn.classList.remove('text-primary');
6418
+ this._amBtn.classList.add('filled');
6419
+ this._pmBtn.classList.remove('filled');
6106
6420
  }
6107
6421
  }
6108
6422
  }
@@ -6119,7 +6433,7 @@ class Timepicker extends Component {
6119
6433
  value[1] = value[1].replace('AM', '').replace('PM', '');
6120
6434
  }
6121
6435
  if (value[0] === 'now') {
6122
- let now = new Date(+new Date() + this.options.fromNow);
6436
+ const now = new Date(+new Date() + this.options.fromNow);
6123
6437
  value = [now.getHours().toString(), now.getMinutes().toString()];
6124
6438
  if (this.options.twelveHour) {
6125
6439
  this.amOrPm = parseInt(value[0]) >= 12 && parseInt(value[0]) < 24 ? 'PM' : 'AM';
@@ -6127,17 +6441,18 @@ class Timepicker extends Component {
6127
6441
  }
6128
6442
  this.hours = +value[0] || 0;
6129
6443
  this.minutes = +value[1] || 0;
6130
- this.inputHours.value = this.hours;
6444
+ this.inputHours.value = Timepicker._addLeadingZero(this.hours);
6131
6445
  this.inputMinutes.value = Timepicker._addLeadingZero(this.minutes);
6132
6446
  this._updateAmPmView();
6133
6447
  }
6134
6448
  /**
6135
6449
  * Show hours or minutes view on timepicker.
6136
6450
  * @param view The name of the view you want to switch to, 'hours' or 'minutes'.
6451
+ * @param delay
6137
6452
  */
6138
6453
  showView = (view, delay = null) => {
6139
6454
  if (view === 'minutes' && getComputedStyle(this.hoursView).visibility === 'visible') ;
6140
- let isHours = view === 'hours', nextView = isHours ? this.hoursView : this.minutesView, hideView = isHours ? this.minutesView : this.hoursView;
6455
+ const isHours = view === 'hours', nextView = isHours ? this.hoursView : this.minutesView, hideView = isHours ? this.minutesView : this.hoursView;
6141
6456
  this.currentView = view;
6142
6457
  if (isHours) {
6143
6458
  this.inputHours.classList.add('text-primary');
@@ -6160,12 +6475,12 @@ class Timepicker extends Component {
6160
6475
  }, this.options.duration);
6161
6476
  };
6162
6477
  resetClock(delay) {
6163
- let view = this.currentView, value = this[view], isHours = view === 'hours', unit = Math.PI / (isHours ? 6 : 30), radian = value * unit, radius = isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius, x = Math.sin(radian) * radius, y = -Math.cos(radian) * radius, self = this;
6478
+ const view = this.currentView, value = this[view], isHours = view === 'hours', unit = Math.PI / (isHours ? 6 : 30), radian = value * unit, radius = isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius, x = Math.sin(radian) * radius, y = -Math.cos(radian) * radius;
6164
6479
  if (delay) {
6165
- this.canvas?.classList.add('timepicker-canvas-out');
6480
+ this._canvas?.classList.add('timepicker-canvas-out');
6166
6481
  setTimeout(() => {
6167
- self.canvas?.classList.remove('timepicker-canvas-out');
6168
- self.setHand(x, y);
6482
+ this._canvas?.classList.remove('timepicker-canvas-out');
6483
+ this.setHand(x, y);
6169
6484
  }, delay);
6170
6485
  }
6171
6486
  else {
@@ -6174,31 +6489,26 @@ class Timepicker extends Component {
6174
6489
  }
6175
6490
  _inputFromTextField = () => {
6176
6491
  const isHours = this.currentView === 'hours';
6177
- if (isHours) {
6492
+ if (isHours && this.inputHours.value !== '') {
6178
6493
  const value = parseInt(this.inputHours.value);
6179
- if (value > 0 && value < 13) {
6180
- this.drawClockFromTimeInput(value, isHours);
6181
- this.showView('minutes', this.options.duration / 2);
6494
+ if (value > 0 && value < (this.options.twelveHour ? 13 : 24)) {
6182
6495
  this.hours = value;
6183
- this.inputMinutes.focus();
6184
6496
  }
6185
6497
  else {
6186
- const hour = new Date().getHours();
6187
- this.inputHours.value = (hour % 12).toString();
6498
+ this.setHoursDefault();
6188
6499
  }
6500
+ this.drawClockFromTimeInput(this.hours, isHours);
6189
6501
  }
6190
- else {
6502
+ else if (!isHours && this.inputMinutes.value !== '') {
6191
6503
  const value = parseInt(this.inputMinutes.value);
6192
6504
  if (value >= 0 && value < 60) {
6193
- this.inputMinutes.value = Timepicker._addLeadingZero(value);
6194
- this.drawClockFromTimeInput(value, isHours);
6195
6505
  this.minutes = value;
6196
- this.modalEl.querySelector('.confirmation-btns :nth-child(2)').focus();
6197
6506
  }
6198
6507
  else {
6199
- const minutes = new Date().getMinutes();
6200
- this.inputMinutes.value = Timepicker._addLeadingZero(minutes);
6508
+ this.minutes = new Date().getMinutes();
6509
+ this.inputMinutes.value = this.minutes.toString();
6201
6510
  }
6511
+ this.drawClockFromTimeInput(this.minutes, isHours);
6202
6512
  }
6203
6513
  };
6204
6514
  drawClockFromTimeInput(value, isHours) {
@@ -6208,14 +6518,15 @@ class Timepicker extends Component {
6208
6518
  if (this.options.twelveHour) {
6209
6519
  radius = this.options.outerRadius;
6210
6520
  }
6211
- let cx1 = Math.sin(radian) * (radius - this.options.tickRadius), cy1 = -Math.cos(radian) * (radius - this.options.tickRadius), cx2 = Math.sin(radian) * radius, cy2 = -Math.cos(radian) * radius;
6212
- this.hand.setAttribute('x2', cx1.toString());
6213
- this.hand.setAttribute('y2', cy1.toString());
6214
- this.bg.setAttribute('cx', cx2.toString());
6215
- this.bg.setAttribute('cy', cy2.toString());
6521
+ else {
6522
+ radius =
6523
+ isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius;
6524
+ }
6525
+ this.setClockAttributes(radian, radius);
6216
6526
  }
6217
6527
  setHand(x, y, roundBy5 = false) {
6218
- let radian = Math.atan2(x, -y), isHours = this.currentView === 'hours', unit = Math.PI / (isHours || roundBy5 ? 6 : 30), z = Math.sqrt(x * x + y * y), inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2, radius = inner ? this.options.innerRadius : this.options.outerRadius;
6528
+ const isHours = this.currentView === 'hours', unit = Math.PI / (isHours || roundBy5 ? 6 : 30), z = Math.sqrt(x * x + y * y), inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2;
6529
+ let radian = Math.atan2(x, -y), radius = inner ? this.options.innerRadius : this.options.outerRadius;
6219
6530
  if (this.options.twelveHour) {
6220
6531
  radius = this.options.outerRadius;
6221
6532
  }
@@ -6270,41 +6581,39 @@ class Timepicker extends Component {
6270
6581
  }
6271
6582
  this[this.currentView] = value;
6272
6583
  if (isHours) {
6273
- this.inputHours.value = value.toString();
6584
+ this.inputHours.value = Timepicker._addLeadingZero(value);
6274
6585
  }
6275
6586
  else {
6276
6587
  this.inputMinutes.value = Timepicker._addLeadingZero(value);
6277
6588
  }
6278
6589
  // Set clock hand and others' position
6279
- let cx1 = Math.sin(radian) * (radius - this.options.tickRadius), cy1 = -Math.cos(radian) * (radius - this.options.tickRadius), cx2 = Math.sin(radian) * radius, cy2 = -Math.cos(radian) * radius;
6590
+ this.setClockAttributes(radian, radius);
6591
+ }
6592
+ setClockAttributes(radian, radius) {
6593
+ const cx1 = Math.sin(radian) * (radius - this.options.tickRadius), cy1 = -Math.cos(radian) * (radius - this.options.tickRadius), cx2 = Math.sin(radian) * radius, cy2 = -Math.cos(radian) * radius;
6280
6594
  this.hand.setAttribute('x2', cx1.toString());
6281
6595
  this.hand.setAttribute('y2', cy1.toString());
6282
6596
  this.bg.setAttribute('cx', cx2.toString());
6283
6597
  this.bg.setAttribute('cy', cy2.toString());
6284
6598
  }
6285
- /**
6286
- * Open timepicker.
6287
- */
6288
- open = () => {
6289
- if (this.isOpen)
6290
- return;
6291
- this.isOpen = true;
6292
- this._updateTimeFromInput();
6293
- this.showView('hours');
6294
- this.modal.open(undefined);
6295
- };
6296
- /**
6297
- * Close timepicker.
6298
- */
6299
- close = () => {
6300
- if (!this.isOpen)
6301
- return;
6302
- this.isOpen = false;
6303
- this.modal.close();
6304
- };
6599
+ formatHours() {
6600
+ if (this.inputHours.value == '')
6601
+ this.setHoursDefault();
6602
+ this.inputHours.value = Timepicker._addLeadingZero(Number(this.inputHours.value));
6603
+ }
6604
+ formatMinutes() {
6605
+ if (this.inputMinutes.value == '')
6606
+ this.minutes = new Date().getMinutes();
6607
+ this.inputMinutes.value = Timepicker._addLeadingZero(Number(this.inputMinutes.value));
6608
+ }
6609
+ setHoursDefault() {
6610
+ this.hours = new Date().getHours();
6611
+ this.inputHours.value = (this.hours % (this.options.twelveHour ? 12 : 24)).toString();
6612
+ }
6613
+ // todo: remove e
6305
6614
  done = (e = null, clearValue = null) => {
6306
6615
  // Set input value
6307
- let last = this.el.value;
6616
+ const last = this.el.value;
6308
6617
  let value = clearValue
6309
6618
  ? ''
6310
6619
  : Timepicker._addLeadingZero(this.hours) + ':' + Timepicker._addLeadingZero(this.minutes);
@@ -6317,12 +6626,23 @@ class Timepicker extends Component {
6317
6626
  if (value !== last) {
6318
6627
  this.el.dispatchEvent(new Event('change', { bubbles: true, cancelable: true, composed: true }));
6319
6628
  }
6320
- this.close();
6321
- this.el.focus();
6629
+ //this.el.focus();
6630
+ return e; // just for passing linter, can be removed
6322
6631
  };
6323
6632
  clear = () => {
6324
6633
  this.done(null, true);
6325
6634
  };
6635
+ // deprecated
6636
+ open() {
6637
+ // this._updateTimeFromInput();
6638
+ // this.showView('hours');
6639
+ console.warn('Timepicker.close() is deprecated. Remove this method and wrap in modal yourself.');
6640
+ return this;
6641
+ }
6642
+ close() {
6643
+ console.warn('Timepicker.close() is deprecated. Remove this method and wrap in modal yourself.');
6644
+ return this;
6645
+ }
6326
6646
  static {
6327
6647
  Timepicker._template = `
6328
6648
  <div class="modal timepicker-modal">
@@ -6330,9 +6650,15 @@ class Timepicker extends Component {
6330
6650
  <div class="timepicker-digital-display">
6331
6651
  <div class="timepicker-text-container">
6332
6652
  <div class="timepicker-display-column">
6333
- <input type="text" maxlength="2" autofocus class="timepicker-input-hours text-primary" />
6334
- :
6335
- <input type="text" maxlength="2" class="timepicker-input-minutes" />
6653
+ <div class="timepicker-input-hours-wrapper">
6654
+ <input type="text" maxlength="2" autofocus class="timepicker-input-hours text-primary" />
6655
+ </div>
6656
+ <div class="timepicker-input-divider-wrapper">
6657
+ <span class="timepicker-input-divider">:</span>
6658
+ </div>
6659
+ <div class="timepicker-input-minutes-wrapper">
6660
+ <input type="text" maxlength="2" class="timepicker-input-minutes" />
6661
+ </div>
6336
6662
  </div>
6337
6663
  <div class="timepicker-display-column timepicker-display-am-pm">
6338
6664
  <div class="timepicker-span-am-pm"></div>
@@ -6348,7 +6674,7 @@ class Timepicker extends Component {
6348
6674
  <div class="timepicker-footer"></div>
6349
6675
  </div>
6350
6676
  </div>
6351
- </div`;
6677
+ </div>`;
6352
6678
  }
6353
6679
  }
6354
6680
 
@@ -6383,7 +6709,7 @@ class Tooltip extends Component {
6383
6709
  yMovement;
6384
6710
  constructor(el, options) {
6385
6711
  super(el, options, Tooltip);
6386
- this.el.M_Tooltip = this;
6712
+ this.el['M_Tooltip'] = this;
6387
6713
  this.options = {
6388
6714
  ...Tooltip.defaults,
6389
6715
  ...this._getAttributeOptions(),
@@ -6407,12 +6733,12 @@ class Tooltip extends Component {
6407
6733
  return super.init(els, options, Tooltip);
6408
6734
  }
6409
6735
  static getInstance(el) {
6410
- return el.M_Tooltip;
6736
+ return el['M_Tooltip'];
6411
6737
  }
6412
6738
  destroy() {
6413
6739
  this.tooltipEl.remove();
6414
6740
  this._removeEventHandlers();
6415
- this.el.M_Tooltip = undefined;
6741
+ this.el['M_Tooltip'] = undefined;
6416
6742
  }
6417
6743
  _appendTooltipEl() {
6418
6744
  this.tooltipEl = document.createElement('div');
@@ -6421,7 +6747,7 @@ class Tooltip extends Component {
6421
6747
  ? document.getElementById(this.options.tooltipId)
6422
6748
  : document.createElement('div');
6423
6749
  this.tooltipEl.append(tooltipContentEl);
6424
- tooltipContentEl.style.display = "";
6750
+ tooltipContentEl.style.display = '';
6425
6751
  tooltipContentEl.classList.add('tooltip-content');
6426
6752
  this._setTooltipContent(tooltipContentEl);
6427
6753
  this.tooltipEl.appendChild(tooltipContentEl);
@@ -6490,7 +6816,8 @@ class Tooltip extends Component {
6490
6816
  _positionTooltip() {
6491
6817
  const tooltip = this.tooltipEl;
6492
6818
  const origin = this.el, originHeight = origin.offsetHeight, originWidth = origin.offsetWidth, tooltipHeight = tooltip.offsetHeight, tooltipWidth = tooltip.offsetWidth, margin = this.options.margin;
6493
- (this.xMovement = 0), (this.yMovement = 0);
6819
+ this.xMovement = 0;
6820
+ this.yMovement = 0;
6494
6821
  let targetTop = origin.getBoundingClientRect().top + Utils.getDocumentScrollTop();
6495
6822
  let targetLeft = origin.getBoundingClientRect().left + Utils.getDocumentScrollLeft();
6496
6823
  if (this.options.position === 'top') {
@@ -6603,7 +6930,7 @@ class Tooltip extends Component {
6603
6930
  this.close();
6604
6931
  };
6605
6932
  _getAttributeOptions() {
6606
- let attributeOptions = {};
6933
+ const attributeOptions = {};
6607
6934
  const tooltipTextOption = this.el.getAttribute('data-tooltip');
6608
6935
  const tooltipId = this.el.getAttribute('data-tooltip-id');
6609
6936
  const positionOption = this.el.getAttribute('data-position');
@@ -6640,11 +6967,22 @@ class Waves {
6640
6967
  }
6641
6968
  const frame = timestamp - animationStart;
6642
6969
  if (frame < duration) {
6643
- const easing = (frame / duration) * (2 - (frame / duration));
6644
- const circle = isCentered ? 'circle at 50% 50%' : `circle at ${position.x}px ${position.y}px`;
6970
+ const easing = (frame / duration) * (2 - frame / duration);
6971
+ const circle = isCentered
6972
+ ? 'circle at 50% 50%'
6973
+ : `circle at ${position.x}px ${position.y}px`;
6645
6974
  const waveColor = `rgba(${color?.r || 0}, ${color?.g || 0}, ${color?.b || 0}, ${0.3 * (1 - easing)})`;
6646
- const stop = 90 * easing + "%";
6647
- targetElement.style.backgroundImage = "radial-gradient(" + circle + ", " + waveColor + " " + stop + ", transparent " + stop + ")";
6975
+ const stop = 90 * easing + '%';
6976
+ targetElement.style.backgroundImage =
6977
+ 'radial-gradient(' +
6978
+ circle +
6979
+ ', ' +
6980
+ waveColor +
6981
+ ' ' +
6982
+ stop +
6983
+ ', transparent ' +
6984
+ stop +
6985
+ ')';
6648
6986
  animationFrame = window.requestAnimationFrame(animationStep);
6649
6987
  }
6650
6988
  else {
@@ -6656,8 +6994,8 @@ class Waves {
6656
6994
  }
6657
6995
  static Init() {
6658
6996
  if (typeof document !== 'undefined')
6659
- document?.addEventListener("DOMContentLoaded", () => {
6660
- document.body.addEventListener('click', e => {
6997
+ document?.addEventListener('DOMContentLoaded', () => {
6998
+ document.body.addEventListener('click', (e) => {
6661
6999
  const trigger = e.target;
6662
7000
  const el = trigger.closest('.waves-effect');
6663
7001
  if (el && el.contains(trigger)) {
@@ -6682,7 +7020,7 @@ class Range extends Component {
6682
7020
  thumb;
6683
7021
  constructor(el, options) {
6684
7022
  super(el, options, Range);
6685
- this.el.M_Range = this;
7023
+ this.el['M_Range'] = this;
6686
7024
  this.options = {
6687
7025
  ...Range.defaults,
6688
7026
  ...options
@@ -6703,12 +7041,12 @@ class Range extends Component {
6703
7041
  return super.init(els, options, Range);
6704
7042
  }
6705
7043
  static getInstance(el) {
6706
- return el.M_Range;
7044
+ return el['M_Range'];
6707
7045
  }
6708
7046
  destroy() {
6709
7047
  this._removeEventHandlers();
6710
7048
  this._removeThumb();
6711
- this.el.M_Range = undefined;
7049
+ this.el['M_Range'] = undefined;
6712
7050
  }
6713
7051
  _setupEventHandlers() {
6714
7052
  this.el.addEventListener('change', this._handleRangeChange);
@@ -6789,7 +7127,7 @@ class Range extends Component {
6789
7127
  top ${duration}ms ease,
6790
7128
  margin ${duration}ms ease
6791
7129
  `;
6792
- // to
7130
+ // to
6793
7131
  this.thumb.style.height = '0';
6794
7132
  this.thumb.style.width = '0';
6795
7133
  this.thumb.style.top = '0';
@@ -6839,7 +7177,7 @@ class Range extends Component {
6839
7177
  */
6840
7178
  static Init() {
6841
7179
  if (typeof document !== 'undefined')
6842
- Range.init((document?.querySelectorAll('input[type=range]')), {});
7180
+ Range.init(document?.querySelectorAll('input[type=range]'), {});
6843
7181
  }
6844
7182
  }
6845
7183
 
@@ -6853,7 +7191,7 @@ class CharacterCounter extends Component {
6853
7191
  isValidLength;
6854
7192
  constructor(el, options) {
6855
7193
  super(el, {}, CharacterCounter);
6856
- this.el.M_CharacterCounter = this;
7194
+ this.el['M_CharacterCounter'] = this;
6857
7195
  this.options = {
6858
7196
  ...CharacterCounter.defaults,
6859
7197
  ...options
@@ -6875,11 +7213,11 @@ class CharacterCounter extends Component {
6875
7213
  return super.init(els, options, CharacterCounter);
6876
7214
  }
6877
7215
  static getInstance(el) {
6878
- return el.M_CharacterCounter;
7216
+ return el['M_CharacterCounter'];
6879
7217
  }
6880
7218
  destroy() {
6881
7219
  this._removeEventHandlers();
6882
- this.el.CharacterCounter = undefined;
7220
+ this.el['CharacterCounter'] = undefined;
6883
7221
  this._removeCounter();
6884
7222
  }
6885
7223
  _setupEventHandlers() {
@@ -6902,7 +7240,7 @@ class CharacterCounter extends Component {
6902
7240
  this.counterEl.remove();
6903
7241
  }
6904
7242
  updateCounter = () => {
6905
- let maxLength = parseInt(this.el.getAttribute('maxlength')), actualLength = this.el.value.length;
7243
+ const maxLength = parseInt(this.el.getAttribute('maxlength')), actualLength = this.el.value.length;
6906
7244
  this.isValidLength = actualLength <= maxLength;
6907
7245
  let counterString = actualLength.toString();
6908
7246
  if (maxLength) {
@@ -6924,7 +7262,7 @@ class CharacterCounter extends Component {
6924
7262
  }
6925
7263
  }
6926
7264
 
6927
- let _defaults$1 = {
7265
+ const _defaults$1 = {
6928
7266
  indicators: true,
6929
7267
  height: 400,
6930
7268
  duration: 500,
@@ -6948,7 +7286,7 @@ class Slider extends Component {
6948
7286
  _sliderId;
6949
7287
  constructor(el, options) {
6950
7288
  super(el, options, Slider);
6951
- this.el.M_Slider = this;
7289
+ this.el['M_Slider'] = this;
6952
7290
  this.options = {
6953
7291
  ...Slider.defaults,
6954
7292
  ...options
@@ -6962,7 +7300,7 @@ class Slider extends Component {
6962
7300
  // setup
6963
7301
  this._slider = this.el.querySelector('.slides');
6964
7302
  this._slides = Array.from(this._slider.querySelectorAll('li'));
6965
- this.activeIndex = this._slides.findIndex(li => li.classList.contains('active'));
7303
+ this.activeIndex = this._slides.findIndex((li) => li.classList.contains('active'));
6966
7304
  if (this.activeIndex !== -1) {
6967
7305
  this._activeSlide = this._slides[this.activeIndex];
6968
7306
  }
@@ -6976,7 +7314,7 @@ class Slider extends Component {
6976
7314
  }
6977
7315
  const placeholderBase64 = 'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
6978
7316
  // Set initial positions of captions
6979
- this._slides.forEach(slide => {
7317
+ this._slides.forEach((slide) => {
6980
7318
  // Caption
6981
7319
  //const caption = <HTMLElement|null>slide.querySelector('.caption');
6982
7320
  //if (caption) this._animateCaptionIn(caption, 0);
@@ -7027,13 +7365,13 @@ class Slider extends Component {
7027
7365
  return super.init(els, options, Slider);
7028
7366
  }
7029
7367
  static getInstance(el) {
7030
- return el.M_Slider;
7368
+ return el['M_Slider'];
7031
7369
  }
7032
7370
  destroy() {
7033
7371
  this.pause();
7034
7372
  this._removeIndicators();
7035
7373
  this._removeEventHandlers();
7036
- this.el.M_Slider = undefined;
7374
+ this.el['M_Slider'] = undefined;
7037
7375
  }
7038
7376
  _setupEventHandlers() {
7039
7377
  if (this.options.pauseOnFocus) {
@@ -7138,7 +7476,7 @@ class Slider extends Component {
7138
7476
  if (!this.el.classList.contains('fullscreen')) {
7139
7477
  if (this.options.indicators) {
7140
7478
  // Add height if indicators are present
7141
- this.el.style.height = (this.options.height + 40) + 'px'; //.css('height', this.options.height + 40 + 'px');
7479
+ this.el.style.height = this.options.height + 40 + 'px'; //.css('height', this.options.height + 40 + 'px');
7142
7480
  }
7143
7481
  else {
7144
7482
  this.el.style.height = this.options.height + 'px';
@@ -7181,11 +7519,11 @@ class Slider extends Component {
7181
7519
  const _caption = this._activeSlide.querySelector('.caption');
7182
7520
  this._activeSlide.classList.remove('active');
7183
7521
  // Enables every slide
7184
- this._slides.forEach(slide => slide.style.visibility = 'visible');
7522
+ this._slides.forEach((slide) => (slide.style.visibility = 'visible'));
7185
7523
  //--- Hide active Slide + Caption
7186
7524
  this._activeSlide.style.opacity = '0';
7187
7525
  setTimeout(() => {
7188
- this._slides.forEach(slide => {
7526
+ this._slides.forEach((slide) => {
7189
7527
  if (slide.classList.contains('active'))
7190
7528
  return;
7191
7529
  slide.style.opacity = '0';
@@ -7203,7 +7541,7 @@ class Slider extends Component {
7203
7541
  const nextIndicator = this._indicators[index].children[0];
7204
7542
  activeIndicator.classList.remove('active');
7205
7543
  nextIndicator.classList.add('active');
7206
- if (typeof this.options.indicatorLabelFunc === "function") {
7544
+ if (typeof this.options.indicatorLabelFunc === 'function') {
7207
7545
  activeIndicator.ariaLabel = this.options.indicatorLabelFunc.call(this, this.activeIndex, false);
7208
7546
  nextIndicator.ariaLabel = this.options.indicatorLabelFunc.call(this, index, true);
7209
7547
  }
@@ -7263,7 +7601,7 @@ class Slider extends Component {
7263
7601
  };
7264
7602
  }
7265
7603
 
7266
- let _defaults = {
7604
+ const _defaults = {
7267
7605
  text: '',
7268
7606
  displayLength: 4000,
7269
7607
  inDuration: 300,
@@ -7309,8 +7647,8 @@ class Toast {
7309
7647
  }
7310
7648
  // Create new toast
7311
7649
  Toast._toasts.push(this);
7312
- let toastElement = this._createToast();
7313
- toastElement.M_Toast = this;
7650
+ const toastElement = this._createToast();
7651
+ toastElement['M_Toast'] = this;
7314
7652
  this.el = toastElement;
7315
7653
  this._animateIn();
7316
7654
  this._setTimer();
@@ -7319,7 +7657,7 @@ class Toast {
7319
7657
  return _defaults;
7320
7658
  }
7321
7659
  static getInstance(el) {
7322
- return el.M_Toast;
7660
+ return el['M_Toast'];
7323
7661
  }
7324
7662
  static _createContainer() {
7325
7663
  const container = document.createElement('div');
@@ -7343,7 +7681,7 @@ class Toast {
7343
7681
  static _onDragStart(e) {
7344
7682
  if (e.target && e.target.closest('.toast')) {
7345
7683
  const toastElem = e.target.closest('.toast');
7346
- const toast = toastElem.M_Toast;
7684
+ const toast = toastElem['M_Toast'];
7347
7685
  toast.panning = true;
7348
7686
  Toast._draggedToast = toast;
7349
7687
  toast.el.classList.add('panning');
@@ -7369,12 +7707,12 @@ class Toast {
7369
7707
  }
7370
7708
  static _onDragEnd() {
7371
7709
  if (!!Toast._draggedToast) {
7372
- let toast = Toast._draggedToast;
7710
+ const toast = Toast._draggedToast;
7373
7711
  toast.panning = false;
7374
7712
  toast.el.classList.remove('panning');
7375
- let totalDeltaX = toast.xPos - toast.startingXPos;
7376
- let activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
7377
- let shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
7713
+ const totalDeltaX = toast.xPos - toast.startingXPos;
7714
+ const activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
7715
+ const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
7378
7716
  // Remove toast
7379
7717
  if (shouldBeDismissed) {
7380
7718
  toast.wasSwiped = true;
@@ -7390,7 +7728,7 @@ class Toast {
7390
7728
  }
7391
7729
  }
7392
7730
  static _xPos(e) {
7393
- if (e.type.startsWith("touch") && e.targetTouches.length >= 1) {
7731
+ if (e.type.startsWith('touch') && e.targetTouches.length >= 1) {
7394
7732
  return e.targetTouches[0].clientX;
7395
7733
  }
7396
7734
  // mouse event
@@ -7400,7 +7738,7 @@ class Toast {
7400
7738
  * dismiss all toasts.
7401
7739
  */
7402
7740
  static dismissAll() {
7403
- for (let toastIndex in Toast._toasts) {
7741
+ for (const toastIndex in Toast._toasts) {
7404
7742
  Toast._toasts[toastIndex].dismiss();
7405
7743
  }
7406
7744
  }
@@ -7427,7 +7765,7 @@ class Toast {
7427
7765
  }
7428
7766
  _animateIn() {
7429
7767
  // Animate toast in
7430
- this.el.style.display = "";
7768
+ this.el.style.display = '';
7431
7769
  this.el.style.opacity = '0';
7432
7770
  // easeOutCubic
7433
7771
  this.el.style.transition = `
@@ -7461,8 +7799,8 @@ class Toast {
7461
7799
  * Dismiss toast with animation.
7462
7800
  */
7463
7801
  dismiss() {
7464
- window.clearInterval(this.counterInterval);
7465
- let activationDistance = this.el.offsetWidth * this.options.activationPercent;
7802
+ clearInterval(this.counterInterval);
7803
+ const activationDistance = this.el.offsetWidth * this.options.activationPercent;
7466
7804
  if (this.wasSwiped) {
7467
7805
  this.el.style.transition = 'transform .05s, opacity .05s';
7468
7806
  this.el.style.transform = `translateX(${activationDistance}px)`;
@@ -7498,20 +7836,17 @@ class Toast {
7498
7836
  }
7499
7837
  }
7500
7838
 
7501
- const version = '2.1.1';
7502
- const Grid = (children = '') => {
7503
- return `<div class="row">${children}</row>`;
7504
- };
7505
- function Button(children = '') {
7506
- return `<button class="btn">${children}</button>`;
7507
- }
7839
+ /* eslint-disable @typescript-eslint/no-unused-vars */
7840
+ const version = '2.2.1';
7508
7841
  /**
7509
7842
  * Automatically initialize components.
7510
7843
  * @param context Root element to initialize. Defaults to `document.body`.
7844
+ * @param options Options for each component.
7511
7845
  */
7512
- function AutoInit(context = document.body) {
7513
- let registry = {
7846
+ function AutoInit(context = document.body, options) {
7847
+ const registry = {
7514
7848
  Autocomplete: context.querySelectorAll('.autocomplete:not(.no-autoinit)'),
7849
+ Cards: context.querySelectorAll('.cards:not(.no-autoinit)'),
7515
7850
  Carousel: context.querySelectorAll('.carousel:not(.no-autoinit)'),
7516
7851
  Chips: context.querySelectorAll('.chips:not(.no-autoinit)'),
7517
7852
  Collapsible: context.querySelectorAll('.collapsible:not(.no-autoinit)'),
@@ -7530,24 +7865,25 @@ function AutoInit(context = document.body) {
7530
7865
  Tooltip: context.querySelectorAll('.tooltipped:not(.no-autoinit)'),
7531
7866
  FloatingActionButton: context.querySelectorAll('.fixed-action-btn:not(.no-autoinit)')
7532
7867
  };
7533
- Autocomplete.init(registry.Autocomplete, {});
7534
- Carousel.init(registry.Carousel, {});
7535
- Chips.init(registry.Chips, {});
7536
- Collapsible.init(registry.Collapsible, {});
7537
- Datepicker.init(registry.Datepicker, {});
7538
- Dropdown.init(registry.Dropdown, {});
7539
- Materialbox.init(registry.Materialbox, {});
7540
- Modal.init(registry.Modal, {});
7541
- Parallax.init(registry.Parallax, {});
7542
- Pushpin.init(registry.Pushpin, {});
7543
- ScrollSpy.init(registry.ScrollSpy, {});
7544
- FormSelect.init(registry.FormSelect, {});
7545
- Sidenav.init(registry.Sidenav, {});
7546
- Tabs.init(registry.Tabs, {});
7547
- TapTarget.init(registry.TapTarget, {});
7548
- Timepicker.init(registry.Timepicker, {});
7549
- Tooltip.init(registry.Tooltip, {});
7550
- FloatingActionButton.init(registry.FloatingActionButton, {});
7868
+ Autocomplete.init(registry.Autocomplete, options?.Autocomplete ?? {});
7869
+ Cards.init(registry.Cards, options?.Cards ?? {});
7870
+ Carousel.init(registry.Carousel, options?.Carousel ?? {});
7871
+ Chips.init(registry.Chips, options?.Chips ?? {});
7872
+ Collapsible.init(registry.Collapsible, options?.Collapsible ?? {});
7873
+ Datepicker.init(registry.Datepicker, options?.Datepicker ?? {});
7874
+ Dropdown.init(registry.Dropdown, options?.Dropdown ?? {});
7875
+ Materialbox.init(registry.Materialbox, options?.Materialbox ?? {});
7876
+ Modal.init(registry.Modal, options?.Modal ?? {});
7877
+ Parallax.init(registry.Parallax, options?.Parallax ?? {});
7878
+ Pushpin.init(registry.Pushpin, options?.Pushpin ?? {});
7879
+ ScrollSpy.init(registry.ScrollSpy, options?.ScrollSpy ?? {});
7880
+ FormSelect.init(registry.FormSelect, options?.FormSelect ?? {});
7881
+ Sidenav.init(registry.Sidenav, options?.Sidenav ?? {});
7882
+ Tabs.init(registry.Tabs, options?.Tabs ?? {});
7883
+ TapTarget.init(registry.TapTarget, options?.TapTarget ?? {});
7884
+ Timepicker.init(registry.Timepicker, options?.Timepicker ?? {});
7885
+ Tooltip.init(registry.Tooltip, options?.Tooltip ?? {});
7886
+ FloatingActionButton.init(registry.FloatingActionButton, options?.FloatingActionButton ?? {});
7551
7887
  }
7552
7888
  // Init
7553
7889
  if (typeof document !== 'undefined') {
@@ -7556,7 +7892,6 @@ if (typeof document !== 'undefined') {
7556
7892
  document.addEventListener('focus', Utils.docHandleFocus, true);
7557
7893
  document.addEventListener('blur', Utils.docHandleBlur, true);
7558
7894
  }
7559
- Cards.Init();
7560
7895
  Forms.Init();
7561
7896
  Chips.Init();
7562
7897
  Waves.Init();
@@ -7564,7 +7899,6 @@ Range.Init();
7564
7899
 
7565
7900
  exports.AutoInit = AutoInit;
7566
7901
  exports.Autocomplete = Autocomplete;
7567
- exports.Button = Button;
7568
7902
  exports.Cards = Cards;
7569
7903
  exports.Carousel = Carousel;
7570
7904
  exports.CharacterCounter = CharacterCounter;
@@ -7575,7 +7909,6 @@ exports.Dropdown = Dropdown;
7575
7909
  exports.FloatingActionButton = FloatingActionButton;
7576
7910
  exports.FormSelect = FormSelect;
7577
7911
  exports.Forms = Forms;
7578
- exports.Grid = Grid;
7579
7912
  exports.Materialbox = Materialbox;
7580
7913
  exports.Modal = Modal;
7581
7914
  exports.Parallax = Parallax;