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