@expressivecss/expressive 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +1 -1
  2. package/dist/css/expressive.css +1011 -1339
  3. package/dist/css/expressive.css.map +1 -1
  4. package/dist/css/expressive.min.css +1 -1
  5. package/dist/css/expressive.min.css.map +1 -1
  6. package/dist/js/expressive.cjs +701 -853
  7. package/dist/js/expressive.cjs.map +4 -4
  8. package/dist/js/expressive.js +701 -853
  9. package/dist/js/expressive.js.map +4 -4
  10. package/dist/js/expressive.min.js +10 -20
  11. package/dist/js/expressive.min.js.map +4 -4
  12. package/dist/js/expressive.mjs +701 -854
  13. package/dist/js/expressive.mjs.map +4 -4
  14. package/dist/types/components/autocomplete.d.ts +2 -9
  15. package/dist/types/components/buttons.d.ts +2 -2
  16. package/dist/types/components/cards.d.ts +3 -6
  17. package/dist/types/components/carousel.d.ts +3 -3
  18. package/dist/types/components/characterCounter.d.ts +3 -5
  19. package/dist/types/components/chips.d.ts +2 -2
  20. package/dist/types/components/collapsible.d.ts +6 -23
  21. package/dist/types/components/datepicker.d.ts +2 -8
  22. package/dist/types/components/dropdown.d.ts +11 -2
  23. package/dist/types/components/index.d.ts +0 -1
  24. package/dist/types/components/lightbox.d.ts +2 -2
  25. package/dist/types/components/parallax.d.ts +2 -8
  26. package/dist/types/components/pushpin.d.ts +2 -2
  27. package/dist/types/components/range.d.ts +2 -2
  28. package/dist/types/components/registry.d.ts +0 -4
  29. package/dist/types/components/scrollspy.d.ts +26 -50
  30. package/dist/types/components/select.d.ts +20 -6
  31. package/dist/types/components/sidenav.d.ts +40 -55
  32. package/dist/types/components/slider.d.ts +2 -2
  33. package/dist/types/components/tabs.d.ts +2 -2
  34. package/dist/types/components/tapTarget.d.ts +2 -2
  35. package/dist/types/components/timepicker.d.ts +2 -4
  36. package/dist/types/components/tooltip.d.ts +2 -2
  37. package/dist/types/core/component.d.ts +4 -4
  38. package/dist/types/index.d.ts +1 -1
  39. package/package.json +2 -2
  40. package/src/sass/README.md +2 -6
  41. package/src/sass/abstracts/_breakpoints.scss +0 -16
  42. package/src/sass/abstracts/_variables.scss +0 -21
  43. package/src/sass/base/_grid.scss +0 -19
  44. package/src/sass/components/_badges.scss +1 -1
  45. package/src/sass/components/_buttons.scss +22 -54
  46. package/src/sass/components/_cards.scss +50 -123
  47. package/src/sass/components/_carousel.scss +4 -6
  48. package/src/sass/components/_collapsible.scss +13 -15
  49. package/src/sass/components/_collection.scss +9 -27
  50. package/src/sass/components/_datepicker.scss +1 -15
  51. package/src/sass/components/_dropdown.scss +110 -14
  52. package/src/sass/components/_index.scss +1 -0
  53. package/src/sass/components/_modal.scss +13 -31
  54. package/src/sass/components/_navbar.scss +9 -6
  55. package/src/sass/components/_page-footer.scss +134 -15
  56. package/src/sass/components/_parallax.scss +7 -28
  57. package/src/sass/components/_preloader.scss +145 -300
  58. package/src/sass/components/_scrollspy.scss +18 -0
  59. package/src/sass/components/_sidenav.scss +226 -120
  60. package/src/sass/components/_table_of_contents.scss +30 -14
  61. package/src/sass/components/_tabs.scss +54 -35
  62. package/src/sass/components/_tapTarget.scss +2 -6
  63. package/src/sass/components/_toast.scss +10 -11
  64. package/src/sass/components/_toolbar.scss +2 -2
  65. package/src/sass/components/_tooltip.scss +4 -9
  66. package/src/sass/components/_transitions.scss +0 -5
  67. package/src/sass/components/forms/_index.scss +0 -5
  68. package/src/sass/components/forms/_input-fields.scss +49 -52
  69. package/src/sass/components/forms/_select.scss +175 -60
  70. package/src/sass/components/forms/_switches.scss +21 -8
  71. package/src/sass/utilities/_helpers.scss +1 -3
  72. package/src/sass/utilities/_typescale.scss +0 -5
  73. package/src/sass/utilities/_visibility.scss +2 -2
  74. package/dist/types/components/modal.d.ts +0 -45
@@ -1,10 +1,3 @@
1
- var __typeError = (msg) => {
2
- throw TypeError(msg);
3
- };
4
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
6
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
7
-
8
1
  // src/ts/core/utils.ts
9
2
  var _Utils = class _Utils {
10
3
  /**
@@ -220,7 +213,7 @@ var _Utils = class _Utils {
220
213
  * Renders a button with optional callback function
221
214
  */
222
215
  static createButton(container, text, className = [], visibility = true, callback = null) {
223
- className = className.concat(["btn", "waves-effect", "text"]);
216
+ className = className.concat(["waves-effect", "text"]);
224
217
  const button = document.createElement("button");
225
218
  button.className = className.join(" ");
226
219
  button.style.visibility = visibility ? "visible" : "hidden";
@@ -399,11 +392,9 @@ var Component = class {
399
392
  // src/ts/components/cards.ts
400
393
  var _defaults = {
401
394
  onOpen: null,
402
- onClose: null,
403
- inDuration: 225,
404
- outDuration: 300
395
+ onClose: null
405
396
  };
406
- var CARDS_SELECTOR = ".card, article:has(> aside), article:has(.card-reveal)";
397
+ var CARDS_SELECTOR = "article:has(> aside)";
407
398
  var Cards = class _Cards extends Component {
408
399
  constructor(el, options) {
409
400
  super(el, options, _Cards);
@@ -449,16 +440,10 @@ var Cards = class _Cards extends Component {
449
440
  * Show card reveal.
450
441
  */
451
442
  this.open = () => {
452
- if (this.isOpen) return;
443
+ if (this.isOpen || !this.cardReveal) return;
453
444
  this.isOpen = true;
454
- this.el.style.overflow = "hidden";
455
- this.cardReveal.style.display = "block";
456
445
  this.cardReveal.ariaExpanded = "true";
457
446
  if (this.cardRevealClose) this.cardRevealClose.tabIndex = 0;
458
- setTimeout(() => {
459
- this.cardReveal.style.transition = `transform ${this.options.outDuration}ms ease`;
460
- this.cardReveal.style.transform = "translateY(-100%)";
461
- }, 1);
462
447
  if (typeof this.options.onOpen === "function") {
463
448
  this.options.onOpen.call(this);
464
449
  }
@@ -468,17 +453,11 @@ var Cards = class _Cards extends Component {
468
453
  * Hide card reveal.
469
454
  */
470
455
  this.close = () => {
471
- if (!this.isOpen) return;
456
+ if (!this.isOpen || !this.cardReveal) return;
472
457
  this.isOpen = false;
473
- this.cardReveal.style.transition = `transform ${this.options.inDuration}ms ease`;
474
- this.cardReveal.style.transform = "translateY(0)";
475
- setTimeout(() => {
476
- this.cardReveal.style.display = "none";
477
- this.cardReveal.ariaExpanded = "false";
478
- this._activators.forEach((el) => el.tabIndex = 0);
479
- if (this.cardRevealClose) this.cardRevealClose.tabIndex = -1;
480
- this.el.style.overflow = this.initialOverflow;
481
- }, this.options.inDuration);
458
+ this.cardReveal.ariaExpanded = "false";
459
+ this._activators.forEach((el) => el.tabIndex = 0);
460
+ if (this.cardRevealClose) this.cardRevealClose.tabIndex = -1;
482
461
  if (typeof this.options.onClose === "function") {
483
462
  this.options.onClose.call(this);
484
463
  }
@@ -490,15 +469,14 @@ var Cards = class _Cards extends Component {
490
469
  ...options
491
470
  };
492
471
  this._activators = [];
493
- this.cardReveal = this.el.querySelector(":scope > aside, .card-reveal");
472
+ this.cardReveal = this.el.querySelector(":scope > aside");
494
473
  if (this.cardReveal) {
495
- this.initialOverflow = getComputedStyle(this.el).overflow;
496
474
  this._activators = Array.from(this.el.querySelectorAll(".activator"));
497
475
  this._activators.forEach((el2) => {
498
476
  if (el2) el2.tabIndex = 0;
499
477
  });
500
478
  this.cardRevealClose = this.cardReveal.querySelector(
501
- ".card-title, :scope > :is(h1, h2, h3, h4, h5, h6)"
479
+ ":scope > :is(h1, h2, h3, h4, h5, h6)"
502
480
  );
503
481
  if (this.cardRevealClose) this.cardRevealClose.tabIndex = -1;
504
482
  this.cardReveal.ariaExpanded = "false";
@@ -575,7 +553,7 @@ var _Dropdown = class _Dropdown extends Component {
575
553
  this.close();
576
554
  return;
577
555
  }
578
- const leaveToDropdownContent = !!toEl.closest(".dropdown-content, menu");
556
+ const leaveToDropdownContent = !!(this.dropdownEl && toEl && this.dropdownEl.contains(toEl));
579
557
  let leaveToActiveDropdownTrigger = false;
580
558
  const closestTrigger = toEl.closest(".dropdown-trigger");
581
559
  if (closestTrigger && !!closestTrigger["Expressive_Dropdown"] && closestTrigger["Expressive_Dropdown"].isOpen) {
@@ -587,9 +565,10 @@ var _Dropdown = class _Dropdown extends Component {
587
565
  };
588
566
  this._handleDocumentClick = (e) => {
589
567
  const target = e.target;
590
- if (this.options.closeOnClick && target.closest(".dropdown-content, menu") && !this.isTouchMoving) {
568
+ if (this._isSubmenuTriggerClick(target)) return;
569
+ if (this.options.closeOnClick && this.dropdownEl?.contains(target) && !this.isTouchMoving) {
591
570
  this.close();
592
- } else if (!target.closest(".dropdown-content, menu")) {
571
+ } else if (!this.dropdownEl?.contains(target)) {
593
572
  setTimeout(() => {
594
573
  if (this.isOpen) {
595
574
  this.close();
@@ -607,14 +586,29 @@ var _Dropdown = class _Dropdown extends Component {
607
586
  };
608
587
  this._handleDocumentTouchmove = (e) => {
609
588
  const target = e.target;
610
- if (target.closest(".dropdown-content, menu")) {
589
+ if (this.dropdownEl?.contains(target)) {
611
590
  this.isTouchMoving = true;
612
591
  }
613
592
  };
614
593
  this._handleDropdownClick = (e) => {
594
+ const target = e.target;
595
+ const li = target.closest("li");
596
+ if (li && this._isSubmenuTriggerClick(target)) {
597
+ e.preventDefault();
598
+ e.stopPropagation();
599
+ this._toggleSubmenu(li);
600
+ return;
601
+ }
615
602
  if (typeof this.options.onItemClick === "function") {
616
- const itemEl = e.target.closest("li");
617
- this.options.onItemClick.call(this, itemEl);
603
+ this.options.onItemClick.call(this, li);
604
+ }
605
+ };
606
+ this._handleSubmenuAlign = (e) => {
607
+ const target = e.target;
608
+ if (!(target instanceof Element)) return;
609
+ const li = target.closest("li");
610
+ if (li?.querySelector(":scope > menu") && this.dropdownEl?.contains(li)) {
611
+ this._alignSubmenu(li);
618
612
  }
619
613
  };
620
614
  this._handleDropdownKeydown = (e) => {
@@ -622,37 +616,70 @@ var _Dropdown = class _Dropdown extends Component {
622
616
  if (Utils.keys.TAB.includes(e.key)) {
623
617
  e.preventDefault();
624
618
  this.close();
619
+ } else if (Utils.keys.ARROW_RIGHT.includes(e.key) && this.isOpen) {
620
+ const li = this._focusedRow(e);
621
+ if (li?.querySelector(":scope > menu")) {
622
+ e.preventDefault();
623
+ li.classList.add("open");
624
+ this._alignSubmenu(li);
625
+ this._syncSubmenuAria(li, true);
626
+ const first = li.querySelector(":scope > menu > li");
627
+ first?.focus();
628
+ }
629
+ } else if (Utils.keys.ARROW_LEFT.includes(e.key) && this.isOpen) {
630
+ const submenu = this._containingSubmenu(e);
631
+ if (submenu) {
632
+ e.preventDefault();
633
+ const parentLi = submenu.parentElement;
634
+ parentLi.classList.remove("open", "submenu-start");
635
+ this._syncSubmenuAria(parentLi, false);
636
+ parentLi.focus();
637
+ }
625
638
  } else if (arrowUpOrDown && this.isOpen) {
626
639
  e.preventDefault();
627
640
  const direction = Utils.keys.ARROW_DOWN.includes(e.key) ? 1 : -1;
641
+ const list = this._containingSubmenu(e) ?? this.dropdownEl;
628
642
  let newFocusedIndex = this.focusedIndex;
629
643
  let hasFoundNewIndex = false;
630
644
  do {
631
645
  newFocusedIndex = newFocusedIndex + direction;
632
- if (!!this.dropdownEl.children[newFocusedIndex] && this.dropdownEl.children[newFocusedIndex].tabIndex !== -1) {
646
+ if (!!list.children[newFocusedIndex] && list.children[newFocusedIndex].tabIndex !== -1) {
633
647
  hasFoundNewIndex = true;
634
648
  break;
635
649
  }
636
- } while (newFocusedIndex < this.dropdownEl.children.length && newFocusedIndex >= 0);
650
+ } while (newFocusedIndex < list.children.length && newFocusedIndex >= 0);
637
651
  if (hasFoundNewIndex) {
638
652
  if (this.focusedIndex >= 0)
639
- this.dropdownEl.children[this.focusedIndex].classList.remove("active");
653
+ list.children[this.focusedIndex]?.classList.remove("active");
640
654
  this.focusedIndex = newFocusedIndex;
641
- this._focusFocusedItem();
655
+ const item = list.children[this.focusedIndex];
656
+ item.classList.add("active");
657
+ item.focus({ preventScroll: true });
642
658
  }
643
659
  } else if (Utils.keys.ENTER.includes(e.key) && this.isOpen) {
644
- const focusedElement = this.dropdownEl.children[this.focusedIndex];
660
+ const li = this._focusedRow(e);
661
+ if (li?.querySelector(":scope > menu")) {
662
+ e.preventDefault();
663
+ this._toggleSubmenu(li);
664
+ return;
665
+ }
666
+ const focusedElement = li ?? this.dropdownEl.children[this.focusedIndex];
645
667
  const activatableElement = focusedElement?.querySelector("a, button");
646
668
  if (!!activatableElement) {
647
669
  activatableElement.click();
648
- } else if (!!focusedElement) {
649
- if (focusedElement instanceof HTMLElement) {
650
- focusedElement.click();
651
- }
670
+ } else if (focusedElement instanceof HTMLElement) {
671
+ focusedElement.click();
652
672
  }
653
673
  } else if (Utils.keys.ESC.includes(e.key) && this.isOpen) {
654
674
  e.preventDefault();
655
- this.close();
675
+ const openSub = this.dropdownEl.querySelector("li.open");
676
+ if (openSub) {
677
+ openSub.classList.remove("open", "submenu-start");
678
+ this._syncSubmenuAria(openSub, false);
679
+ openSub.focus();
680
+ } else {
681
+ this.close();
682
+ }
656
683
  }
657
684
  const keyText = e.key.toLowerCase();
658
685
  const isLetter = /[a-zA-Z0-9-_]/.test(keyText);
@@ -666,7 +693,8 @@ var _Dropdown = class _Dropdown extends Component {
666
693
  if (isLetter && !specialKeys.includes(e.key)) {
667
694
  this.filterQuery.push(keyText);
668
695
  const string = this.filterQuery.join("");
669
- const newOptionEl = Array.from(this.dropdownEl.querySelectorAll("li")).find(
696
+ const list = this._containingSubmenu(e) ?? this.dropdownEl;
697
+ const newOptionEl = Array.from(list.querySelectorAll(":scope > li")).find(
670
698
  (el) => el.textContent.trim().toLowerCase().indexOf(string) === 0
671
699
  );
672
700
  if (newOptionEl) {
@@ -708,6 +736,7 @@ var _Dropdown = class _Dropdown extends Component {
708
736
  if (!this.isOpen) return;
709
737
  this.isOpen = false;
710
738
  this.focusedIndex = -1;
739
+ this._closeSubmenus();
711
740
  if (typeof this.options.onCloseStart === "function") {
712
741
  this.options.onCloseStart.call(this, this.el);
713
742
  }
@@ -731,7 +760,6 @@ var _Dropdown = class _Dropdown extends Component {
731
760
  _Dropdown._dropdowns.push(this);
732
761
  this.id = Utils.getIdFromTrigger(el);
733
762
  this.dropdownEl = document.getElementById(this.id);
734
- this.dropdownEl?.classList.add("dropdown-content");
735
763
  this.options = {
736
764
  ..._Dropdown.defaults,
737
765
  ...options
@@ -744,6 +772,7 @@ var _Dropdown = class _Dropdown extends Component {
744
772
  this.el.ariaExpanded = "false";
745
773
  this._moveDropdownToElement();
746
774
  this._makeDropdownFocusable();
775
+ this._setupSubmenus();
747
776
  this._setupEventHandlers();
748
777
  }
749
778
  static get defaults() {
@@ -772,6 +801,9 @@ var _Dropdown = class _Dropdown extends Component {
772
801
  _setupEventHandlers() {
773
802
  this.el.addEventListener("keydown", this._handleTriggerKeydown);
774
803
  this.dropdownEl?.addEventListener("click", this._handleDropdownClick);
804
+ if (this.dropdownEl?.querySelector(":scope > li > menu")) {
805
+ this.dropdownEl.addEventListener("mouseover", this._handleSubmenuAlign);
806
+ }
775
807
  if (this.options.hover) {
776
808
  this.el.addEventListener("mouseenter", this._handleMouseEnter);
777
809
  this.el.addEventListener("mouseleave", this._handleMouseLeave);
@@ -783,6 +815,7 @@ var _Dropdown = class _Dropdown extends Component {
783
815
  _removeEventHandlers() {
784
816
  this.el.removeEventListener("keydown", this._handleTriggerKeydown);
785
817
  this.dropdownEl?.removeEventListener("click", this._handleDropdownClick);
818
+ this.dropdownEl?.removeEventListener("mouseover", this._handleSubmenuAlign);
786
819
  if (this.options.hover) {
787
820
  this.el.removeEventListener("mouseenter", this._handleMouseEnter);
788
821
  this.el.removeEventListener("mouseleave", this._handleMouseLeave);
@@ -803,6 +836,68 @@ var _Dropdown = class _Dropdown extends Component {
803
836
  this.dropdownEl?.removeEventListener("keydown", this._handleDropdownKeydown);
804
837
  window.removeEventListener("resize", this._handleWindowResize);
805
838
  }
839
+ _isSubmenuTriggerClick(target) {
840
+ if (!this.dropdownEl) return false;
841
+ const li = target.closest("li");
842
+ if (!li || !this.dropdownEl.contains(li)) return false;
843
+ const submenu = li.querySelector(":scope > menu");
844
+ if (!submenu) return false;
845
+ return !submenu.contains(target);
846
+ }
847
+ _setupSubmenus() {
848
+ this.dropdownEl?.querySelectorAll("li").forEach((li) => {
849
+ if (!li.querySelector(":scope > menu")) return;
850
+ const trigger = li.querySelector(":scope > a, :scope > button, :scope > span") ?? li;
851
+ trigger.setAttribute("aria-haspopup", "menu");
852
+ trigger.setAttribute("aria-expanded", "false");
853
+ });
854
+ }
855
+ _toggleSubmenu(li) {
856
+ const open = !li.classList.contains("open");
857
+ li.parentElement?.querySelectorAll(":scope > li.open").forEach((other) => {
858
+ if (other !== li) {
859
+ other.classList.remove("open", "submenu-start");
860
+ this._syncSubmenuAria(other, false);
861
+ }
862
+ });
863
+ li.classList.toggle("open", open);
864
+ if (open) this._alignSubmenu(li);
865
+ this._syncSubmenuAria(li, open);
866
+ }
867
+ _syncSubmenuAria(li, open) {
868
+ const trigger = li.querySelector(":scope > a, :scope > button, :scope > span") ?? li;
869
+ trigger.setAttribute("aria-expanded", open ? "true" : "false");
870
+ }
871
+ _alignSubmenu(li) {
872
+ const menu = li.querySelector(":scope > menu");
873
+ if (!menu) return;
874
+ const wasHidden = getComputedStyle(menu).display === "none";
875
+ if (wasHidden) menu.style.display = "block";
876
+ li.classList.remove("submenu-start");
877
+ const rect = menu.getBoundingClientRect();
878
+ if (rect.right > window.innerWidth - 8) li.classList.add("submenu-start");
879
+ if (wasHidden) menu.style.display = "";
880
+ }
881
+ _closeSubmenus() {
882
+ this.dropdownEl?.querySelectorAll("li.open").forEach((li) => {
883
+ li.classList.remove("open", "submenu-start");
884
+ this._syncSubmenuAria(li, false);
885
+ });
886
+ }
887
+ _containingSubmenu(e) {
888
+ const target = e.target;
889
+ if (!(target instanceof Element)) return null;
890
+ const submenu = target.closest("li > menu");
891
+ if (submenu instanceof HTMLElement && this.dropdownEl?.contains(submenu)) return submenu;
892
+ return null;
893
+ }
894
+ _focusedRow(e) {
895
+ const target = e.target;
896
+ if (!(target instanceof Element)) return null;
897
+ const li = target.closest("li");
898
+ if (li instanceof HTMLElement && this.dropdownEl?.contains(li)) return li;
899
+ return null;
900
+ }
806
901
  _resetDropdownStyles() {
807
902
  this.dropdownEl.style.display = "";
808
903
  this._resetDropdownPositioningStyles();
@@ -831,7 +926,7 @@ var _Dropdown = class _Dropdown extends Component {
831
926
  if (!this.dropdownEl) return;
832
927
  this.dropdownEl.popover = "";
833
928
  this.dropdownEl.tabIndex = 0;
834
- Array.from(this.dropdownEl.children).forEach((el) => {
929
+ this.dropdownEl.querySelectorAll(":scope li, :scope > hr").forEach((el) => {
835
930
  if (el instanceof HTMLHRElement || el.classList.contains("divider")) {
836
931
  el.setAttribute("tabindex", "-1");
837
932
  return;
@@ -1179,10 +1274,10 @@ var _Autocomplete = class _Autocomplete extends Component {
1179
1274
  }
1180
1275
  }
1181
1276
  _setupDropdown() {
1182
- this.container = document.createElement("ul");
1277
+ this.container = document.createElement("menu");
1183
1278
  this.container.style.maxHeight = this.options.maxDropDownHeight;
1184
1279
  this.container.id = `autocomplete-options-${Utils.guid()}`;
1185
- this.container.classList.add("autocomplete-content", "dropdown-content");
1280
+ this.container.classList.add("autocomplete-content");
1186
1281
  this.container.ariaExpanded = "true";
1187
1282
  this.el.setAttribute("data-target", this.container.id);
1188
1283
  this.menuItems.forEach((menuItem) => {
@@ -1363,19 +1458,6 @@ var _Autocomplete = class _Autocomplete extends Component {
1363
1458
  this._updateSelectedInfo();
1364
1459
  this._triggerChanged();
1365
1460
  }
1366
- /**
1367
- * Sets selected values.
1368
- * @deprecated @see https://github.com/materializecss/materialize/issues/552
1369
- * @param entries
1370
- */
1371
- setValues(entries) {
1372
- this.selectedValues = entries;
1373
- this._updateSelectedInfo();
1374
- if (!this.options.isMultiSelect) {
1375
- this._refreshInputText();
1376
- }
1377
- this._triggerChanged();
1378
- }
1379
1461
  /**
1380
1462
  * Select a specific autocomplete option via id-property.
1381
1463
  * @param id The id of a data-entry.
@@ -1401,14 +1483,6 @@ var _Autocomplete = class _Autocomplete extends Component {
1401
1483
  this._updateSelectedInfo();
1402
1484
  this._triggerChanged();
1403
1485
  }
1404
- selectOptions(ids) {
1405
- const entries = this.menuItems.filter(
1406
- (item) => !(ids.indexOf(item.id) === -1)
1407
- );
1408
- if (!entries) return;
1409
- this.selectedValues = entries;
1410
- this._renderDropdown();
1411
- }
1412
1486
  };
1413
1487
  /**
1414
1488
  * The three-dot loading indicator, parsed once and cloned thereafter.
@@ -1488,7 +1562,7 @@ var _Chips = class _Chips extends Component {
1488
1562
  this._renderChips();
1489
1563
  }
1490
1564
  if (this.options.allowUserInput) {
1491
- this.el.classList.add("input-field");
1565
+ this.el.classList.add("field");
1492
1566
  this._setupInput();
1493
1567
  this._setupEventHandlers();
1494
1568
  this.el.append(this._input);
@@ -2352,7 +2426,7 @@ var _Carousel = class _Carousel extends Component {
2352
2426
  ..._Carousel.defaults,
2353
2427
  ...options
2354
2428
  };
2355
- this._flat = this.options.fullWidth || this.el.classList.contains("flat") || this.el.classList.contains("carousel-slider");
2429
+ this._flat = this.options.fullWidth || this.el.classList.contains("flat");
2356
2430
  if (this._flat) {
2357
2431
  this.el.classList.add("flat");
2358
2432
  this.options.fullWidth = true;
@@ -2819,9 +2893,7 @@ var _defaults9 = {
2819
2893
  onOpenStart: null,
2820
2894
  onOpenEnd: null,
2821
2895
  onCloseStart: null,
2822
- onCloseEnd: null,
2823
- inDuration: 300,
2824
- outDuration: 300
2896
+ onCloseEnd: null
2825
2897
  };
2826
2898
  var Collapsible = class _Collapsible extends Component {
2827
2899
  constructor(el, options) {
@@ -2852,31 +2924,6 @@ var Collapsible = class _Collapsible extends Component {
2852
2924
  if (!item || !this._isOpen(item)) return;
2853
2925
  this._setOpen(item, false);
2854
2926
  };
2855
- this._handleClick = (e) => {
2856
- const header = e.target.closest(".collapsible-header");
2857
- if (!header || header.closest(".collapsible") !== this.el) return;
2858
- if (header.closest("details")) return;
2859
- const item = header.closest("li");
2860
- if (!item) return;
2861
- const index = this._items.indexOf(item);
2862
- if (index < 0) return;
2863
- if (this._isOpen(item)) this.close(index);
2864
- else this.open(index);
2865
- };
2866
- this._handleKeydown = (e) => {
2867
- if (!Utils.keys.ENTER.includes(e.key) && e.key !== " ") return;
2868
- const header = e.target.closest(".collapsible-header");
2869
- if (!header || header.closest(".collapsible") !== this.el) return;
2870
- if (header.closest("details")) return;
2871
- if (header.matches("a, button")) return;
2872
- e.preventDefault();
2873
- const item = header.closest("li");
2874
- if (!item) return;
2875
- const index = this._items.indexOf(item);
2876
- if (index < 0) return;
2877
- if (this._isOpen(item)) this.close(index);
2878
- else this.open(index);
2879
- };
2880
2927
  this._handleToggle = (e) => {
2881
2928
  const item = e.target;
2882
2929
  if (!(item instanceof HTMLDetailsElement)) return;
@@ -2918,9 +2965,7 @@ var Collapsible = class _Collapsible extends Component {
2918
2965
  this.el["Expressive_Collapsible"] = void 0;
2919
2966
  }
2920
2967
  _collectItems() {
2921
- const details = Array.from(this.el.querySelectorAll(":scope > details"));
2922
- if (details.length) return details;
2923
- return Array.from(this.el.children).filter((c) => c.tagName === "LI");
2968
+ return Array.from(this.el.querySelectorAll(":scope > details"));
2924
2969
  }
2925
2970
  _setupItems() {
2926
2971
  if (this.options.accordion) {
@@ -2934,36 +2979,26 @@ var Collapsible = class _Collapsible extends Component {
2934
2979
  if (this.options.accordion && opened.length > 1) {
2935
2980
  opened.slice(1).forEach((item) => {
2936
2981
  if (item instanceof HTMLDetailsElement) item.open = false;
2937
- else item.classList.remove("active");
2938
2982
  });
2939
2983
  }
2940
- this._items.forEach((item) => this._syncAria(item));
2941
2984
  }
2942
2985
  _isOpen(item) {
2943
- if (item instanceof HTMLDetailsElement) return item.open;
2944
- return item.classList.contains("active");
2986
+ return item instanceof HTMLDetailsElement && item.open;
2945
2987
  }
2946
2988
  _setOpen(item, open) {
2947
- if (item instanceof HTMLDetailsElement) {
2948
- item.open = open;
2949
- return;
2950
- }
2951
- item.classList.toggle("active", open);
2952
- this._syncAria(item);
2953
- this._notify(item, open);
2954
- }
2955
- _headerOf(item) {
2956
- if (item instanceof HTMLDetailsElement) {
2957
- return item.querySelector(":scope > summary");
2958
- }
2959
- return item.querySelector(":scope > .collapsible-header");
2989
+ if (item instanceof HTMLDetailsElement) item.open = open;
2960
2990
  }
2961
2991
  _wrapDetailsBodies() {
2962
2992
  this._items.forEach((item) => {
2963
2993
  if (!(item instanceof HTMLDetailsElement)) return;
2964
- if (item.querySelector(":scope > .collapsible-body")) return;
2994
+ if (item.querySelector(":scope > :not(summary)")) {
2995
+ const already = Array.from(item.children).filter((c) => c.tagName !== "SUMMARY");
2996
+ if (already.length === 1 && already[0].tagName === "DIV") {
2997
+ this._wrappedBodies.push(already[0]);
2998
+ return;
2999
+ }
3000
+ }
2965
3001
  const body = document.createElement("div");
2966
- body.className = "collapsible-body";
2967
3002
  Array.from(item.childNodes).forEach((node) => {
2968
3003
  if (node instanceof HTMLElement && node.tagName === "SUMMARY") return;
2969
3004
  body.appendChild(node);
@@ -2982,31 +3017,12 @@ var Collapsible = class _Collapsible extends Component {
2982
3017
  this._wrappedBodies = [];
2983
3018
  }
2984
3019
  _bodyOf(item) {
2985
- return item.querySelector(":scope > .collapsible-body");
2986
- }
2987
- _syncAria(item) {
2988
- if (item instanceof HTMLDetailsElement) return;
2989
- const header = this._headerOf(item);
2990
- const body = this._bodyOf(item);
2991
- if (!header) return;
2992
- header.setAttribute("aria-expanded", String(this._isOpen(item)));
2993
- if (body) {
2994
- if (!body.id) body.id = `collapsible-body-${Utils.guid()}`;
2995
- header.setAttribute("aria-controls", body.id);
2996
- }
2997
- if (!header.matches("a, button, summary")) {
2998
- header.setAttribute("role", "button");
2999
- if (header.tabIndex < 0) header.tabIndex = 0;
3000
- }
3020
+ return item.querySelector(":scope > :not(summary)");
3001
3021
  }
3002
3022
  _setupEventHandlers() {
3003
- this.el.addEventListener("click", this._handleClick);
3004
- this.el.addEventListener("keydown", this._handleKeydown);
3005
3023
  this.el.addEventListener("toggle", this._handleToggle, true);
3006
3024
  }
3007
3025
  _removeEventHandlers() {
3008
- this.el.removeEventListener("click", this._handleClick);
3009
- this.el.removeEventListener("keydown", this._handleKeydown);
3010
3026
  this.el.removeEventListener("toggle", this._handleToggle, true);
3011
3027
  }
3012
3028
  _notify(item, opening) {
@@ -3061,6 +3077,12 @@ var FormSelect = class _FormSelect extends Component {
3061
3077
  this._selectOptionElement(virtualOption);
3062
3078
  e.stopPropagation();
3063
3079
  };
3080
+ this._handleOptionFocus = (e) => {
3081
+ const target = e.target;
3082
+ if (!(target instanceof Element)) return;
3083
+ const li = target.closest('li[role="option"]');
3084
+ if (li?.id) this.input.setAttribute("aria-activedescendant", li.id);
3085
+ };
3064
3086
  this._handleInputClick = () => {
3065
3087
  if (this.dropdown && this.dropdown.isOpen) {
3066
3088
  this._setValueToInput();
@@ -3077,6 +3099,8 @@ var FormSelect = class _FormSelect extends Component {
3077
3099
  this.nativeTabIndex = this.el.tabIndex ?? -1;
3078
3100
  this.el.tabIndex = -1;
3079
3101
  this._values = [];
3102
+ this._createdWrapper = false;
3103
+ this._originalLabelFor = null;
3080
3104
  this._setupDropdown();
3081
3105
  this._setupEventHandlers();
3082
3106
  }
@@ -3098,6 +3122,7 @@ var FormSelect = class _FormSelect extends Component {
3098
3122
  this._removeEventHandlers();
3099
3123
  this.dropdown?.destroy();
3100
3124
  this._removeDropdown();
3125
+ this.el.tabIndex = this.nativeTabIndex;
3101
3126
  this.el["Expressive_FormSelect"] = void 0;
3102
3127
  }
3103
3128
  /**
@@ -3105,27 +3130,38 @@ var FormSelect = class _FormSelect extends Component {
3105
3130
  *
3106
3131
  * Assigning `select.value` from script fires no `change` event, so nothing
3107
3132
  * else syncs the visible input text or the `.selected` state on the virtual
3108
- * options. Call this after mutating the underlying select programmatically.
3133
+ * options. Adding or removing `<option>`s also requires this — the menu is
3134
+ * rebuilt from the native list, the field and Dropdown instance stay put.
3109
3135
  */
3110
3136
  refresh() {
3137
+ if (!this.dropdownOptions) return;
3138
+ this._rebuildOptions();
3111
3139
  this._setValueToInput();
3112
3140
  this._setSelectedStates();
3113
3141
  }
3114
3142
  _setupEventHandlers() {
3115
- this.dropdownOptions.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3116
- el.addEventListener("click", this._handleOptionClick);
3117
- el.addEventListener("keydown", this._handleOptionKeydown);
3118
- });
3143
+ this._setupOptionHandlers();
3119
3144
  this.el.addEventListener("change", this._handleSelectChange);
3120
3145
  this.input.addEventListener("click", this._handleInputClick);
3146
+ this.dropdownOptions.addEventListener("focusin", this._handleOptionFocus);
3121
3147
  }
3122
3148
  _removeEventHandlers() {
3149
+ this._removeOptionHandlers();
3150
+ this.el.removeEventListener("change", this._handleSelectChange);
3151
+ this.input?.removeEventListener("click", this._handleInputClick);
3152
+ this.dropdownOptions?.removeEventListener("focusin", this._handleOptionFocus);
3153
+ }
3154
+ _setupOptionHandlers() {
3123
3155
  this.dropdownOptions.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3156
+ el.addEventListener("click", this._handleOptionClick);
3157
+ el.addEventListener("keydown", this._handleOptionKeydown);
3158
+ });
3159
+ }
3160
+ _removeOptionHandlers() {
3161
+ this.dropdownOptions?.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3124
3162
  el.removeEventListener("click", this._handleOptionClick);
3125
3163
  el.removeEventListener("keydown", this._handleOptionKeydown);
3126
3164
  });
3127
- this.el.removeEventListener("change", this._handleSelectChange);
3128
- this.input.removeEventListener("click", this._handleInputClick);
3129
3165
  }
3130
3166
  _arraysEqual(a, b) {
3131
3167
  if (a === b) return true;
@@ -3137,6 +3173,7 @@ var FormSelect = class _FormSelect extends Component {
3137
3173
  _selectOptionElement(virtualOption) {
3138
3174
  if (!virtualOption.classList.contains("disabled") && !virtualOption.classList.contains("optgroup")) {
3139
3175
  const value = this._values.find((value2) => value2.optionEl === virtualOption);
3176
+ if (!value) return;
3140
3177
  const previousSelectedValues = this.getSelectedValues();
3141
3178
  if (this.isMultiple) {
3142
3179
  this._toggleEntryFromArray(value);
@@ -3152,70 +3189,54 @@ var FormSelect = class _FormSelect extends Component {
3152
3189
  new Event("change", { bubbles: true, cancelable: true, composed: true })
3153
3190
  );
3154
3191
  }
3155
- if (!this.isMultiple) this.dropdown.close();
3192
+ if (!this.isMultiple) this.dropdown?.close();
3156
3193
  }
3157
3194
  _setupDropdown() {
3158
3195
  this.labelEl = this.el.labels?.[0] ?? null;
3159
- this.wrapper = document.createElement("div");
3160
- this.wrapper.classList.add("select-wrapper", "input-field");
3161
- if (this.options.classes.length > 0) {
3162
- this.wrapper.classList.add(...this.options.classes.split(" ").filter(Boolean));
3163
- }
3164
- this.el.before(this.wrapper);
3165
- const hiddenDiv = document.createElement("div");
3166
- hiddenDiv.classList.add("hide-select");
3167
- this.wrapper.append(hiddenDiv);
3168
- hiddenDiv.appendChild(this.el);
3196
+ this._setupWrapper();
3197
+ this._hideNativeSelect();
3169
3198
  if (this.el.disabled) this.wrapper.classList.add("disabled");
3170
- this.selectOptions = Array.from(this.el.children).filter((el) => ["OPTION", "OPTGROUP"].includes(el.tagName));
3171
- this.dropdownOptions = document.createElement("ul");
3199
+ this.dropdownOptions = document.createElement("menu");
3172
3200
  this.dropdownOptions.id = `select-options-${Utils.guid()}`;
3173
3201
  this.dropdownOptions.setAttribute("popover", "auto");
3174
- this.dropdownOptions.classList.add("dropdown-content", "select-dropdown");
3175
3202
  this.dropdownOptions.setAttribute("role", "listbox");
3176
3203
  this.dropdownOptions.ariaMultiSelectable = this.isMultiple.toString();
3177
3204
  if (this.isMultiple) this.dropdownOptions.classList.add("multiple-select-dropdown");
3178
- if (this.selectOptions.length > 0) {
3179
- this.selectOptions.forEach((realOption) => {
3180
- if (realOption.tagName === "OPTION") {
3181
- const virtualOption = this._createAndAppendOptionWithIcon(
3182
- realOption,
3183
- this.isMultiple ? "multiple" : void 0
3184
- );
3185
- this._addOptionToValues(realOption, virtualOption);
3186
- } else if (realOption.tagName === "OPTGROUP") {
3187
- const groupId = "opt-group-" + Utils.guid();
3188
- const groupParent = document.createElement("li");
3189
- groupParent.classList.add("optgroup");
3190
- groupParent.tabIndex = -1;
3191
- groupParent.setAttribute("role", "group");
3192
- groupParent.setAttribute("aria-labelledby", groupId);
3193
- const groupLabel = document.createElement("span");
3194
- groupLabel.id = groupId;
3195
- groupLabel.setAttribute("role", "presentation");
3196
- groupLabel.textContent = realOption.getAttribute("label") ?? "";
3197
- groupParent.replaceChildren(groupLabel);
3198
- this.dropdownOptions.append(groupParent);
3199
- const groupChildren = [];
3200
- const selectOptions = Array.from(realOption.children).filter((el) => el.tagName === "OPTION");
3201
- selectOptions.forEach((realOption2) => {
3202
- const virtualOption = this._createAndAppendOptionWithIcon(
3203
- realOption2,
3204
- "optgroup-option"
3205
- );
3206
- const childId = "opt-child-" + Utils.guid();
3207
- virtualOption.id = childId;
3208
- groupChildren.push(childId);
3209
- this._addOptionToValues(realOption2, virtualOption);
3210
- });
3211
- groupParent.setAttribute("aria-owns", groupChildren.join(" "));
3212
- }
3213
- });
3214
- }
3205
+ this._buildOptions();
3215
3206
  this.wrapper.append(this.dropdownOptions);
3207
+ this._buildInput();
3208
+ this._buildCaret();
3209
+ this._initDropdown();
3210
+ this._setSelectedStates();
3211
+ if (this.labelEl) this.input.after(this.labelEl);
3212
+ }
3213
+ _setupWrapper() {
3214
+ const parent = this.el.parentElement;
3215
+ const reuse = parent && parent.matches(".field") && !parent.querySelector(":scope > .hide-select") && !parent.querySelector(":scope > input, :scope > textarea");
3216
+ if (reuse) {
3217
+ this.wrapper = parent;
3218
+ this._createdWrapper = false;
3219
+ } else {
3220
+ this.wrapper = document.createElement("div");
3221
+ this.wrapper.classList.add("field");
3222
+ this._createdWrapper = true;
3223
+ this.el.before(this.wrapper);
3224
+ }
3225
+ if (this.options.classes.length > 0) {
3226
+ this.wrapper.classList.add(...this.options.classes.split(" ").filter(Boolean));
3227
+ }
3228
+ }
3229
+ _hideNativeSelect() {
3230
+ const hiddenDiv = document.createElement("div");
3231
+ hiddenDiv.classList.add("hide-select");
3232
+ this.el.before(hiddenDiv);
3233
+ hiddenDiv.appendChild(this.el);
3234
+ this.wrapper.append(hiddenDiv);
3235
+ }
3236
+ _buildInput() {
3216
3237
  this.input = document.createElement("input");
3217
- this.input.id = "m_select-input-" + Utils.guid();
3218
- this.input.classList.add("select-dropdown", "dropdown-trigger");
3238
+ this.input.id = "select-input-" + Utils.guid();
3239
+ this.input.classList.add("dropdown-trigger");
3219
3240
  this.input.type = "text";
3220
3241
  this.input.readOnly = true;
3221
3242
  this.input.setAttribute("data-target", this.dropdownOptions.id);
@@ -3229,71 +3250,131 @@ var FormSelect = class _FormSelect extends Component {
3229
3250
  if (attr.name.startsWith("aria-")) this.input.setAttribute(attr.name, attr.value);
3230
3251
  }
3231
3252
  this.input.setAttribute("role", "combobox");
3253
+ this.input.setAttribute("aria-haspopup", "listbox");
3232
3254
  this.input.ariaExpanded = "false";
3233
- this.input.setAttribute("aria-owns", this.dropdownOptions.id);
3234
3255
  this.input.setAttribute("aria-controls", this.dropdownOptions.id);
3235
3256
  this.input.placeholder = " ";
3257
+ if (this.labelEl) {
3258
+ this._originalLabelFor = this.labelEl.htmlFor;
3259
+ this.labelEl.htmlFor = this.input.id;
3260
+ }
3236
3261
  this.wrapper.prepend(this.input);
3237
3262
  this._setValueToInput();
3238
- const dropdownIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3239
- dropdownIcon.classList.add("caret");
3240
- dropdownIcon.setAttribute("height", "24");
3241
- dropdownIcon.setAttribute("width", "24");
3242
- dropdownIcon.setAttribute("viewBox", "0 0 24 24");
3243
- dropdownIcon.ariaHidden = "true";
3244
- dropdownIcon.innerHTML = `<path d="M7 10l5 5 5-5z"/><path d="M0 0h24v24H0z" fill="none"/>`;
3245
- this.wrapper.prepend(dropdownIcon);
3246
- if (!this.el.disabled) {
3247
- const dropdownOptions = { ...this.options.dropdownOptions };
3248
- dropdownOptions.coverTrigger = false;
3249
- const userOnOpenEnd = dropdownOptions.onOpenEnd;
3250
- const userOnCloseEnd = dropdownOptions.onCloseEnd;
3251
- dropdownOptions.onOpenEnd = () => {
3252
- const selectedOption = this.dropdownOptions.querySelector(".selected");
3253
- if (selectedOption) {
3254
- Utils.keyDown = true;
3255
- this.dropdown.focusedIndex = [...selectedOption.parentNode.children].indexOf(
3256
- selectedOption
3257
- );
3258
- this.dropdown._focusFocusedItem();
3259
- Utils.keyDown = false;
3260
- if (this.dropdown.isScrollable) {
3261
- let scrollOffset = selectedOption.getBoundingClientRect().top - this.dropdownOptions.getBoundingClientRect().top;
3262
- scrollOffset -= this.dropdownOptions.clientHeight / 2;
3263
- this.dropdownOptions.scrollTop = scrollOffset;
3264
- }
3263
+ }
3264
+ _buildCaret() {
3265
+ const caret = document.createElement("span");
3266
+ caret.classList.add("caret");
3267
+ caret.setAttribute("aria-hidden", "true");
3268
+ this.wrapper.prepend(caret);
3269
+ }
3270
+ _initDropdown() {
3271
+ if (this.el.disabled) return;
3272
+ const dropdownOptions = { ...this.options.dropdownOptions };
3273
+ dropdownOptions.coverTrigger = false;
3274
+ const userOnOpenEnd = dropdownOptions.onOpenEnd;
3275
+ const userOnCloseEnd = dropdownOptions.onCloseEnd;
3276
+ dropdownOptions.onOpenEnd = () => {
3277
+ const selectedOption = this.dropdownOptions.querySelector(".selected");
3278
+ if (selectedOption) {
3279
+ Utils.keyDown = true;
3280
+ this.dropdown.focusedIndex = [...selectedOption.parentNode.children].indexOf(selectedOption);
3281
+ this.dropdown._focusFocusedItem();
3282
+ Utils.keyDown = false;
3283
+ if (this.dropdown.isScrollable) {
3284
+ let scrollOffset = selectedOption.getBoundingClientRect().top - this.dropdownOptions.getBoundingClientRect().top;
3285
+ scrollOffset -= this.dropdownOptions.clientHeight / 2;
3286
+ this.dropdownOptions.scrollTop = scrollOffset;
3265
3287
  }
3266
- this.input.ariaExpanded = "true";
3267
- if (userOnOpenEnd && typeof userOnOpenEnd === "function")
3268
- userOnOpenEnd.call(this.dropdown, this.el);
3269
- };
3270
- dropdownOptions.onCloseEnd = () => {
3271
- this.input.ariaExpanded = "false";
3272
- if (userOnCloseEnd && typeof userOnCloseEnd === "function")
3273
- userOnCloseEnd.call(this.dropdown, this.el);
3274
- };
3275
- dropdownOptions.closeOnClick = false;
3276
- this.dropdown = Dropdown.init(this.input, dropdownOptions);
3277
- }
3278
- this._setSelectedStates();
3279
- if (this.labelEl) this.input.after(this.labelEl);
3288
+ if (selectedOption.id) this.input.setAttribute("aria-activedescendant", selectedOption.id);
3289
+ }
3290
+ this.input.ariaExpanded = "true";
3291
+ if (userOnOpenEnd && typeof userOnOpenEnd === "function")
3292
+ userOnOpenEnd.call(this.dropdown, this.el);
3293
+ };
3294
+ dropdownOptions.onCloseEnd = () => {
3295
+ this.input.ariaExpanded = "false";
3296
+ this.input.removeAttribute("aria-activedescendant");
3297
+ if (userOnCloseEnd && typeof userOnCloseEnd === "function")
3298
+ userOnCloseEnd.call(this.dropdown, this.el);
3299
+ };
3300
+ dropdownOptions.closeOnClick = false;
3301
+ this.dropdown = Dropdown.init(this.input, dropdownOptions);
3302
+ }
3303
+ _nativeOptions() {
3304
+ return Array.from(this.el.children).filter((el) => ["OPTION", "OPTGROUP"].includes(el.tagName));
3305
+ }
3306
+ _buildOptions() {
3307
+ this.selectOptions = this._nativeOptions();
3308
+ this._values = [];
3309
+ this.selectOptions.forEach((realOption) => {
3310
+ if (realOption.tagName === "OPTION") {
3311
+ const virtualOption = this._createAndAppendOptionWithIcon(
3312
+ realOption,
3313
+ this.isMultiple ? "multiple" : void 0
3314
+ );
3315
+ this._addOptionToValues(realOption, virtualOption);
3316
+ } else if (realOption.tagName === "OPTGROUP") {
3317
+ const groupId = "opt-group-" + Utils.guid();
3318
+ const groupParent = document.createElement("li");
3319
+ groupParent.classList.add("optgroup");
3320
+ groupParent.tabIndex = -1;
3321
+ groupParent.setAttribute("role", "group");
3322
+ groupParent.setAttribute("aria-labelledby", groupId);
3323
+ const groupLabel = document.createElement("span");
3324
+ groupLabel.id = groupId;
3325
+ groupLabel.setAttribute("role", "presentation");
3326
+ groupLabel.textContent = realOption.getAttribute("label") ?? "";
3327
+ groupParent.replaceChildren(groupLabel);
3328
+ this.dropdownOptions.append(groupParent);
3329
+ const groupChildren = [];
3330
+ const selectOptions = Array.from(realOption.children).filter((el) => el.tagName === "OPTION");
3331
+ selectOptions.forEach((child) => {
3332
+ const virtualOption = this._createAndAppendOptionWithIcon(child, "optgroup-option");
3333
+ groupChildren.push(virtualOption.id);
3334
+ this._addOptionToValues(child, virtualOption);
3335
+ });
3336
+ groupParent.setAttribute("aria-owns", groupChildren.join(" "));
3337
+ }
3338
+ });
3339
+ }
3340
+ _rebuildOptions() {
3341
+ this._removeOptionHandlers();
3342
+ this.dropdownOptions.replaceChildren();
3343
+ this._buildOptions();
3344
+ this._setupOptionHandlers();
3345
+ this.dropdown?._makeDropdownFocusable();
3280
3346
  }
3281
3347
  _addOptionToValues(realOption, virtualOption) {
3282
3348
  this._values.push({ el: realOption, optionEl: virtualOption });
3283
3349
  }
3284
3350
  _removeDropdown() {
3285
- this.wrapper.querySelector(".caret").remove();
3286
- this.input.remove();
3287
- this.dropdownOptions.remove();
3288
- this.wrapper.before(this.el);
3289
- this.wrapper.remove();
3351
+ this.wrapper?.querySelector(":scope > .caret")?.remove();
3352
+ this.input?.remove();
3353
+ this.dropdownOptions?.remove();
3354
+ const hide = this.el.parentElement;
3355
+ if (hide?.classList.contains("hide-select")) hide.replaceWith(this.el);
3356
+ if (this.labelEl && this._originalLabelFor !== null) {
3357
+ this.labelEl.htmlFor = this._originalLabelFor;
3358
+ }
3359
+ if (!this.wrapper) return;
3360
+ if (this._createdWrapper) {
3361
+ this.wrapper.replaceWith(this.el);
3362
+ } else {
3363
+ this.wrapper.classList.remove("disabled");
3364
+ if (this.options.classes.length > 0) {
3365
+ this.wrapper.classList.remove(...this.options.classes.split(" ").filter(Boolean));
3366
+ }
3367
+ }
3290
3368
  }
3291
3369
  _createAndAppendOptionWithIcon(realOption, type) {
3292
3370
  const li = document.createElement("li");
3371
+ li.id = "select-option-" + Utils.guid();
3293
3372
  li.setAttribute("role", "option");
3373
+ li.tabIndex = 0;
3294
3374
  if (realOption.disabled) {
3295
3375
  li.classList.add("disabled");
3296
3376
  li.ariaDisabled = "true";
3377
+ li.tabIndex = -1;
3297
3378
  }
3298
3379
  if (type === "optgroup-option") li.classList.add(type);
3299
3380
  const optionText = realOption.textContent;
@@ -3302,6 +3383,7 @@ var FormSelect = class _FormSelect extends Component {
3302
3383
  const label = document.createElement("label");
3303
3384
  const checkbox = document.createElement("input");
3304
3385
  checkbox.type = "checkbox";
3386
+ checkbox.tabIndex = -1;
3305
3387
  const labelText = document.createElement("span");
3306
3388
  labelText.textContent = optionText;
3307
3389
  label.append(checkbox, labelText);
@@ -3365,7 +3447,7 @@ var FormSelect = class _FormSelect extends Component {
3365
3447
  if (texts.length === 0) {
3366
3448
  const firstDisabledOption = this.el.querySelector("option:disabled");
3367
3449
  if (firstDisabledOption && firstDisabledOption.value === "") {
3368
- this.input.value = firstDisabledOption.innerText;
3450
+ this.input.value = firstDisabledOption.textContent;
3369
3451
  return;
3370
3452
  }
3371
3453
  }
@@ -3387,7 +3469,7 @@ var FormSelect = class _FormSelect extends Component {
3387
3469
  _activateOption(ul, li) {
3388
3470
  if (!li) return;
3389
3471
  if (!this.isMultiple)
3390
- ul.querySelectorAll("li.selected").forEach((li2) => li2.classList.remove("selected"));
3472
+ ul.querySelectorAll("li.selected").forEach((row) => row.classList.remove("selected"));
3391
3473
  li.classList.add("selected");
3392
3474
  li.ariaSelected = "true";
3393
3475
  }
@@ -3673,7 +3755,6 @@ var _Datepicker = class _Datepicker extends Component {
3673
3755
  }
3674
3756
  }
3675
3757
  };
3676
- // Set input value to the selected date and close Datepicker
3677
3758
  this._finishSelection = () => {
3678
3759
  this.setInputValues();
3679
3760
  };
@@ -4229,7 +4310,7 @@ var _Datepicker = class _Datepicker extends Component {
4229
4310
  if (opts.yearRangeReverse) arr.reverse();
4230
4311
  const yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join("")}</select>`;
4231
4312
  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>';
4232
- html += `<button class="month-prev${prev ? "" : " is-disabled"} btn" type="button">${leftArrow}</button>`;
4313
+ html += `<button class="month-prev${prev ? "" : " is-disabled"}" type="button">${leftArrow}</button>`;
4233
4314
  html += '<div class="selects-container">';
4234
4315
  if (opts.showMonthAfterYear) {
4235
4316
  html += yearHtml + monthHtml;
@@ -4238,7 +4319,7 @@ var _Datepicker = class _Datepicker extends Component {
4238
4319
  }
4239
4320
  html += "</div>";
4240
4321
  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>';
4241
- html += `<button class="month-next${next ? "" : " is-disabled"} btn" type="button">${rightArrow}</button>`;
4322
+ html += `<button class="month-next${next ? "" : " is-disabled"}" type="button">${rightArrow}</button>`;
4242
4323
  return html += "</div>";
4243
4324
  }
4244
4325
  /**
@@ -4436,17 +4517,6 @@ var _Datepicker = class _Datepicker extends Component {
4436
4517
  this.el.parentElement.appendChild(dateInput);
4437
4518
  return dateInput;
4438
4519
  }
4439
- // deprecated
4440
- open() {
4441
- console.warn("Datepicker.open() is deprecated. Remove this method and wrap in modal yourself.");
4442
- return this;
4443
- }
4444
- close() {
4445
- console.warn(
4446
- "Datepicker.close() is deprecated. Remove this method and wrap in modal yourself."
4447
- );
4448
- return this;
4449
- }
4450
4520
  };
4451
4521
  _Datepicker._template = `
4452
4522
  <div class="datepicker-container">
@@ -4456,13 +4526,7 @@ _Datepicker._template = `
4456
4526
  </div>
4457
4527
  <div class="datepicker-calendar-container">
4458
4528
  <div class="datepicker-calendar"></div>
4459
- <div class="datepicker-footer">
4460
- <!--<button class="btn-flat datepicker-clear waves-effect" style="visibility: hidden;" type="button"></button>
4461
- <div class="confirmation-btns">
4462
- <button class="btn-flat datepicker-cancel waves-effect" type="button"></button>
4463
- <button class="btn-flat datepicker-done waves-effect" type="button"></button>
4464
- </div>-->
4465
- </div>
4529
+ <div class="datepicker-footer"></div>
4466
4530
  </div>
4467
4531
  </div>`;
4468
4532
  var Datepicker = _Datepicker;
@@ -4751,91 +4815,8 @@ var Lightbox = class _Lightbox extends Component {
4751
4815
  }
4752
4816
  };
4753
4817
 
4754
- // src/ts/components/modal.ts
4755
- var _defaults14 = {
4756
- opacity: 0.5,
4757
- inDuration: 250,
4758
- outDuration: 250,
4759
- onOpenStart: null,
4760
- onOpenEnd: null,
4761
- onCloseStart: null,
4762
- onCloseEnd: null,
4763
- preventScrolling: true,
4764
- dismissible: true,
4765
- startingTop: "4%",
4766
- endingTop: "10%"
4767
- };
4768
- var _Modal_static, createHtml_fn, createHtmlElement_fn;
4769
- var _Modal = class _Modal extends Component {
4770
- constructor(el, options) {
4771
- super(el, options, _Modal);
4772
- this.el["Expressive_Modal"] = this;
4773
- this.options = {
4774
- ..._Modal.defaults,
4775
- ...options
4776
- };
4777
- this.el.tabIndex = 0;
4778
- this._setupEventHandlers();
4779
- }
4780
- static get defaults() {
4781
- return _defaults14;
4782
- }
4783
- static init(els, options = {}) {
4784
- return super.init(els, options, _Modal);
4785
- }
4786
- static getInstance(el) {
4787
- return el["Expressive_Modal"];
4788
- }
4789
- destroy() {
4790
- }
4791
- _setupEventHandlers() {
4792
- }
4793
- _removeEventHandlers() {
4794
- }
4795
- _handleTriggerClick() {
4796
- }
4797
- _handleOverlayClick() {
4798
- }
4799
- _handleModalCloseClick() {
4800
- }
4801
- _handleKeydown() {
4802
- }
4803
- _handleFocus() {
4804
- }
4805
- open() {
4806
- return this;
4807
- }
4808
- close() {
4809
- return this;
4810
- }
4811
- static create(config) {
4812
- const isServer = false;
4813
- if (isServer) return __privateMethod(this, _Modal_static, createHtml_fn).call(this, config);
4814
- return __privateMethod(this, _Modal_static, createHtmlElement_fn).call(this, config);
4815
- }
4816
- };
4817
- _Modal_static = new WeakSet();
4818
- createHtml_fn = function(config) {
4819
- const title = config.header ? `<h2>${typeof config.header === "string" ? config.header : ""}</h2>` : "";
4820
- const actions = config.footer ? `<form method="dialog">${typeof config.footer === "string" ? config.footer : ""}</form>` : "";
4821
- return `<dialog id="${config.id}">
4822
- ${title}
4823
- <div>${typeof config.content === "string" ? config.content : ""}</div>
4824
- ${actions}
4825
- </dialog>`;
4826
- };
4827
- createHtmlElement_fn = function(config) {
4828
- const dialog = document.createElement("dialog");
4829
- dialog.id = config.id;
4830
- return dialog;
4831
- };
4832
- __privateAdd(_Modal, _Modal_static);
4833
- var Modal = _Modal;
4834
-
4835
4818
  // src/ts/components/parallax.ts
4836
- var _defaults15 = {
4837
- responsiveThreshold: 0
4838
- };
4819
+ var _defaults14 = {};
4839
4820
  var Parallax = class _Parallax extends Component {
4840
4821
  constructor(el, options) {
4841
4822
  super(el, options, _Parallax);
@@ -4849,7 +4830,7 @@ var Parallax = class _Parallax extends Component {
4849
4830
  }
4850
4831
  }
4851
4832
  static get defaults() {
4852
- return _defaults15;
4833
+ return _defaults14;
4853
4834
  }
4854
4835
  static init(els, options = {}) {
4855
4836
  return super.init(els, options, _Parallax);
@@ -4863,7 +4844,7 @@ var Parallax = class _Parallax extends Component {
4863
4844
  };
4864
4845
 
4865
4846
  // src/ts/components/pushpin.ts
4866
- var _defaults16 = {
4847
+ var _defaults15 = {
4867
4848
  top: 0,
4868
4849
  bottom: Infinity,
4869
4850
  offset: 0,
@@ -4883,7 +4864,7 @@ var _Pushpin = class _Pushpin extends Component {
4883
4864
  this._updatePosition();
4884
4865
  }
4885
4866
  static get defaults() {
4886
- return _defaults16;
4867
+ return _defaults15;
4887
4868
  }
4888
4869
  /**
4889
4870
  * Initializes instances of Pushpin.
@@ -4952,16 +4933,12 @@ _Pushpin._pushpins = [];
4952
4933
  var Pushpin = _Pushpin;
4953
4934
 
4954
4935
  // src/ts/components/scrollspy.ts
4955
- var _defaults17 = {
4956
- throttle: 100,
4936
+ var _defaultGetActiveElement = (id) => `a[href="#${id}"]`;
4937
+ var _defaults16 = {
4957
4938
  scrollOffset: 200,
4958
- // offset - 200 allows elements near bottom of page to scroll
4959
4939
  activeClass: "active",
4960
- getActiveElement: (id) => {
4961
- return 'a[href="#' + id + '"]';
4962
- },
4963
- keepTopElementActive: false,
4964
- animationDuration: null
4940
+ getActiveElement: _defaultGetActiveElement,
4941
+ keepTopElementActive: false
4965
4942
  };
4966
4943
  var _ScrollSpy = class _ScrollSpy extends Component {
4967
4944
  constructor(el, options) {
@@ -4971,22 +4948,17 @@ var _ScrollSpy = class _ScrollSpy extends Component {
4971
4948
  ..._ScrollSpy.defaults,
4972
4949
  ...options
4973
4950
  };
4951
+ this.el.style.setProperty(
4952
+ "--md-comp-scrollspy-offset",
4953
+ `${this.options.scrollOffset}px`
4954
+ );
4974
4955
  _ScrollSpy._elements.push(this);
4975
- _ScrollSpy._count++;
4976
- _ScrollSpy._increment++;
4977
- this.tickId = -1;
4978
- this.id = _ScrollSpy._increment.toString();
4979
- this._setupEventHandlers();
4980
- _ScrollSpy._handleWindowScroll();
4956
+ _ScrollSpy._ensureObserver(this.options.scrollOffset);
4957
+ _ScrollSpy._observer?.observe(this.el);
4981
4958
  }
4982
4959
  static get defaults() {
4983
- return _defaults17;
4960
+ return _defaults16;
4984
4961
  }
4985
- /**
4986
- * Initializes instances of ScrollSpy.
4987
- * @param els HTML elements.
4988
- * @param options Component options.
4989
- */
4990
4962
  static init(els, options = {}) {
4991
4963
  return super.init(els, options, _ScrollSpy);
4992
4964
  }
@@ -4994,348 +4966,233 @@ var _ScrollSpy = class _ScrollSpy extends Component {
4994
4966
  return el["Expressive_ScrollSpy"];
4995
4967
  }
4996
4968
  destroy() {
4997
- const elementIndex = _ScrollSpy._elements.indexOf(this);
4998
- if (elementIndex >= 0) _ScrollSpy._elements.splice(elementIndex, 1);
4999
- const inViewIndex = _ScrollSpy._elementsInView.indexOf(this);
5000
- if (inViewIndex >= 0) _ScrollSpy._elementsInView.splice(inViewIndex, 1);
5001
- const visibleIndex = _ScrollSpy._visibleElements.indexOf(this.el);
5002
- if (visibleIndex >= 0) _ScrollSpy._visibleElements.splice(visibleIndex, 1);
5003
- _ScrollSpy._count--;
5004
- this._removeEventHandlers();
5005
- const actElem = document.querySelector(this.options.getActiveElement(this.el.id));
5006
- actElem?.classList.remove(this.options.activeClass);
5007
- this.el["Expressive_ScrollSpy"] = void 0;
5008
- }
5009
- _setupEventHandlers() {
5010
- if (_ScrollSpy._count === 1) {
5011
- _ScrollSpy._throttledScroll = Utils.throttle(_ScrollSpy._handleWindowScroll, this.options.throttle);
5012
- _ScrollSpy._throttledResize = Utils.throttle(_ScrollSpy._handleWindowScroll, 200);
5013
- window.addEventListener("scroll", _ScrollSpy._throttledScroll, { passive: true });
5014
- window.addEventListener("resize", _ScrollSpy._throttledResize, { passive: true });
5015
- document.body.addEventListener("click", _ScrollSpy._handleTriggerClick);
5016
- }
5017
- }
5018
- _removeEventHandlers() {
5019
- if (_ScrollSpy._count === 0) {
5020
- window.removeEventListener("scroll", _ScrollSpy._throttledScroll);
5021
- window.removeEventListener("resize", _ScrollSpy._throttledResize);
5022
- document.body.removeEventListener("click", _ScrollSpy._handleTriggerClick);
5023
- _ScrollSpy._throttledScroll = null;
5024
- _ScrollSpy._throttledResize = null;
4969
+ const index = _ScrollSpy._elements.indexOf(this);
4970
+ if (index >= 0) _ScrollSpy._elements.splice(index, 1);
4971
+ _ScrollSpy._ratios.delete(this.el);
4972
+ _ScrollSpy._observer?.unobserve(this.el);
4973
+ const link = _ScrollSpy._linkFor(this.el.id, this.options);
4974
+ if (link && link === _ScrollSpy._active) {
4975
+ _ScrollSpy._clearActive(this.options);
4976
+ } else {
4977
+ link?.classList.remove(this.options.activeClass);
4978
+ link?.removeAttribute("aria-current");
4979
+ }
4980
+ if (_ScrollSpy._elements.length === 0) {
4981
+ _ScrollSpy._observer?.disconnect();
4982
+ _ScrollSpy._observer = null;
4983
+ _ScrollSpy._ratios.clear();
4984
+ _ScrollSpy._active = null;
4985
+ } else {
4986
+ _ScrollSpy._syncActive();
5025
4987
  }
4988
+ this.el["Expressive_ScrollSpy"] = void 0;
5026
4989
  }
5027
- static _findElements(top, right, bottom, left) {
5028
- const hits = [];
5029
- const docElem = document.documentElement;
5030
- const clientTop = docElem.clientTop;
5031
- const clientLeft = docElem.clientLeft;
5032
- const scrollY = window.scrollY;
5033
- const scrollX = window.scrollX;
5034
- for (let i = 0; i < _ScrollSpy._elements.length; i++) {
5035
- const scrollspy = _ScrollSpy._elements[i];
5036
- const currTop = top + scrollspy.options.scrollOffset || 200;
5037
- const box = scrollspy.el.getBoundingClientRect();
5038
- if (box.height > 0) {
5039
- const elTop = box.top + scrollY - clientTop, elLeft = box.left + scrollX - clientLeft, elRight = elLeft + box.width, elBottom = elTop + box.height;
5040
- const isIntersect = !(elLeft > right || elRight < left || elTop > bottom || elBottom < currTop);
5041
- if (isIntersect) {
5042
- hits.push(scrollspy);
5043
- }
5044
- }
5045
- }
5046
- return hits;
4990
+ static _ensureObserver(offset) {
4991
+ if (_ScrollSpy._observer) return;
4992
+ if (typeof IntersectionObserver === "undefined") return;
4993
+ _ScrollSpy._observer = new IntersectionObserver(_ScrollSpy._onIntersect, {
4994
+ rootMargin: `-${offset}px 0px -45% 0px`,
4995
+ threshold: [0, 0.1, 0.25, 0.5, 0.75, 1]
4996
+ });
5047
4997
  }
5048
- _enter() {
5049
- _ScrollSpy._visibleElements = _ScrollSpy._visibleElements.filter(
5050
- (value) => value.getBoundingClientRect().height !== 0
5051
- );
5052
- if (_ScrollSpy._visibleElements[0]) {
5053
- const actElem = document.querySelector(
5054
- this.options.getActiveElement(_ScrollSpy._visibleElements[0].id)
5055
- );
5056
- actElem?.classList.remove(this.options.activeClass);
5057
- if (_ScrollSpy._visibleElements[0]["Expressive_ScrollSpy"] && this.id < _ScrollSpy._visibleElements[0]["Expressive_ScrollSpy"].id) {
5058
- _ScrollSpy._visibleElements.unshift(this.el);
4998
+ static _syncActive() {
4999
+ if (!_ScrollSpy._elements.length) return;
5000
+ const options = _ScrollSpy._elements[0].options;
5001
+ let best = null;
5002
+ let bestRatio = 0;
5003
+ for (const spy of _ScrollSpy._elements) {
5004
+ const ratio = _ScrollSpy._ratios.get(spy.el) ?? 0;
5005
+ if (ratio > bestRatio) {
5006
+ bestRatio = ratio;
5007
+ best = spy;
5008
+ }
5009
+ }
5010
+ if (!best) {
5011
+ if (options.keepTopElementActive) {
5012
+ best = _ScrollSpy._nearestAbove() ?? _ScrollSpy._elements[0];
5059
5013
  } else {
5060
- _ScrollSpy._visibleElements.push(this.el);
5014
+ _ScrollSpy._clearActive(options);
5015
+ return;
5061
5016
  }
5062
- } else {
5063
- _ScrollSpy._visibleElements.push(this.el);
5064
5017
  }
5065
- _ScrollSpy._resetKeptTopActiveElement(this.options.activeClass);
5066
- const selector = this.options.getActiveElement(_ScrollSpy._visibleElements[0].id);
5067
- document.querySelector(selector)?.classList.add(this.options.activeClass);
5018
+ const next = _ScrollSpy._linkFor(best.el.id, best.options);
5019
+ if (next === _ScrollSpy._active) return;
5020
+ _ScrollSpy._clearActive(options);
5021
+ if (!next) return;
5022
+ next.classList.add(best.options.activeClass);
5023
+ next.setAttribute("aria-current", "true");
5024
+ _ScrollSpy._active = next;
5068
5025
  }
5069
- _exit() {
5070
- _ScrollSpy._visibleElements = _ScrollSpy._visibleElements.filter(
5071
- (value) => value.getBoundingClientRect().height !== 0
5072
- );
5073
- if (_ScrollSpy._visibleElements[0]) {
5074
- const actElem = document.querySelector(
5075
- this.options.getActiveElement(_ScrollSpy._visibleElements[0].id)
5076
- );
5077
- actElem?.classList.remove(this.options.activeClass);
5078
- _ScrollSpy._visibleElements = _ScrollSpy._visibleElements.filter((x) => x.id != this.el.id);
5079
- if (_ScrollSpy._visibleElements[0]) {
5080
- const selector = this.options.getActiveElement(_ScrollSpy._visibleElements[0].id);
5081
- document.querySelector(selector)?.classList.add(this.options.activeClass);
5082
- _ScrollSpy._resetKeptTopActiveElement(this.options.activeClass);
5083
- }
5084
- }
5085
- }
5086
- static _resetKeptTopActiveElement(activeClass) {
5087
- if (_ScrollSpy._keptTopActiveElement) {
5088
- _ScrollSpy._keptTopActiveElement.classList.remove(activeClass);
5089
- _ScrollSpy._keptTopActiveElement = null;
5090
- }
5091
- }
5092
- static _getDistanceToViewport(element) {
5093
- const rect = element.getBoundingClientRect();
5094
- const distance = rect.top;
5095
- return distance;
5096
- }
5097
- static _smoothScrollIntoView(element, duration = 300) {
5098
- const targetPosition = element.getBoundingClientRect().top + (window.scrollY || window.pageYOffset);
5099
- const startPosition = window.scrollY || window.pageYOffset;
5100
- const distance = targetPosition - startPosition;
5101
- const startTime = performance.now();
5102
- function scrollStep(currentTime) {
5103
- const elapsed = currentTime - startTime;
5104
- const progress = Math.min(elapsed / duration, 1);
5105
- const scrollY = startPosition + distance * progress;
5106
- if (progress < 1) {
5107
- window.scrollTo(0, scrollY);
5108
- requestAnimationFrame(scrollStep);
5109
- } else {
5110
- window.scrollTo(0, targetPosition);
5026
+ static _nearestAbove() {
5027
+ let best = null;
5028
+ let bestTop = -Infinity;
5029
+ for (const spy of _ScrollSpy._elements) {
5030
+ const top = spy.el.getBoundingClientRect().top;
5031
+ if (top <= 0 && top >= bestTop) {
5032
+ bestTop = top;
5033
+ best = spy;
5111
5034
  }
5112
5035
  }
5113
- requestAnimationFrame(scrollStep);
5036
+ return best;
5114
5037
  }
5115
- };
5116
- _ScrollSpy._keptTopActiveElement = null;
5117
- // The document-level listeners are shared by every instance, so the
5118
- // references they are registered with have to be shared too - registering
5119
- // with one instance's bound handler and unregistering with another's is a
5120
- // silent no-op that leaves the listener attached forever.
5121
- _ScrollSpy._throttledScroll = null;
5122
- _ScrollSpy._throttledResize = null;
5123
- _ScrollSpy._handleTriggerClick = (e) => {
5124
- const trigger = e.target;
5125
- for (let i = _ScrollSpy._elements.length - 1; i >= 0; i--) {
5126
- const scrollspy = _ScrollSpy._elements[i];
5127
- const x = document.querySelector('a[href="#' + scrollspy.el.id + '"]');
5128
- if (trigger === x) {
5129
- e.preventDefault();
5130
- if (scrollspy.el["Expressive_ScrollSpy"].options.animationDuration) {
5131
- _ScrollSpy._smoothScrollIntoView(
5132
- scrollspy.el,
5133
- scrollspy.el["Expressive_ScrollSpy"].options.animationDuration
5134
- );
5135
- } else {
5136
- scrollspy.el.scrollIntoView({ behavior: "smooth" });
5038
+ static _clearActive(options) {
5039
+ if (!_ScrollSpy._active) return;
5040
+ _ScrollSpy._active.classList.remove(options.activeClass);
5041
+ _ScrollSpy._active.removeAttribute("aria-current");
5042
+ _ScrollSpy._active = null;
5043
+ }
5044
+ /**
5045
+ * Default lookup compares href attributes (no interpolated selector).
5046
+ * A custom getActiveElement still returns a selector.
5047
+ */
5048
+ static _linkFor(id, options) {
5049
+ if (!id) return null;
5050
+ if (options.getActiveElement !== _defaultGetActiveElement) {
5051
+ try {
5052
+ return document.querySelector(options.getActiveElement(id));
5053
+ } catch {
5054
+ return null;
5137
5055
  }
5138
- break;
5139
5056
  }
5057
+ const href = `#${id}`;
5058
+ const links = document.querySelectorAll('a[href^="#"]');
5059
+ for (let i = 0; i < links.length; i++) {
5060
+ if (links[i].getAttribute("href") === href) return links[i];
5061
+ }
5062
+ return null;
5140
5063
  }
5141
5064
  };
5142
- _ScrollSpy._handleWindowScroll = () => {
5143
- _ScrollSpy._ticks++;
5144
- const top = Utils.getDocumentScrollTop(), left = Utils.getDocumentScrollLeft(), right = left + window.innerWidth, bottom = top + window.innerHeight;
5145
- const intersections = _ScrollSpy._findElements(top, right, bottom, left);
5146
- for (let i = 0; i < intersections.length; i++) {
5147
- const scrollspy = intersections[i];
5148
- const lastTick = scrollspy.tickId;
5149
- if (lastTick < 0) {
5150
- scrollspy._enter();
5151
- }
5152
- scrollspy.tickId = _ScrollSpy._ticks;
5153
- }
5154
- for (let i = 0; i < _ScrollSpy._elementsInView.length; i++) {
5155
- const scrollspy = _ScrollSpy._elementsInView[i];
5156
- const lastTick = scrollspy.tickId;
5157
- if (lastTick >= 0 && lastTick !== _ScrollSpy._ticks) {
5158
- scrollspy._exit();
5159
- scrollspy.tickId = -1;
5160
- }
5161
- }
5162
- _ScrollSpy._elementsInView = intersections;
5163
- if (_ScrollSpy._elements.length) {
5164
- const options = _ScrollSpy._elements[0].el["Expressive_ScrollSpy"].options;
5165
- if (options.keepTopElementActive && _ScrollSpy._visibleElements.length === 0) {
5166
- _ScrollSpy._resetKeptTopActiveElement(options.activeClass);
5167
- const topElements = _ScrollSpy._elements.map((value) => ({ value, distance: _ScrollSpy._getDistanceToViewport(value.el) })).filter((entry) => entry.distance <= 0).sort((a, b) => a.distance - b.distance).map((entry) => entry.value);
5168
- const nearestTopElement = topElements.length ? topElements[topElements.length - 1] : _ScrollSpy._elements[0];
5169
- const actElem = document.querySelector(options.getActiveElement(nearestTopElement.el.id));
5170
- actElem?.classList.add(options.activeClass);
5171
- _ScrollSpy._keptTopActiveElement = actElem;
5065
+ _ScrollSpy._elements = [];
5066
+ _ScrollSpy._observer = null;
5067
+ _ScrollSpy._ratios = /* @__PURE__ */ new Map();
5068
+ _ScrollSpy._active = null;
5069
+ _ScrollSpy._onIntersect = (entries) => {
5070
+ for (const entry of entries) {
5071
+ if (entry.isIntersecting && entry.intersectionRatio > 0) {
5072
+ _ScrollSpy._ratios.set(entry.target, entry.intersectionRatio);
5073
+ } else {
5074
+ _ScrollSpy._ratios.delete(entry.target);
5172
5075
  }
5173
5076
  }
5077
+ _ScrollSpy._syncActive();
5174
5078
  };
5175
- _ScrollSpy._elements = [];
5176
- _ScrollSpy._elementsInView = [];
5177
- _ScrollSpy._visibleElements = [];
5178
- _ScrollSpy._count = 0;
5179
- _ScrollSpy._increment = 0;
5180
- _ScrollSpy._ticks = 0;
5181
5079
  var ScrollSpy = _ScrollSpy;
5182
5080
 
5183
5081
  // src/ts/components/sidenav.ts
5184
- var _defaults18 = {
5082
+ var _defaults17 = {
5185
5083
  edge: "left",
5186
5084
  draggable: true,
5187
5085
  dragTargetWidth: "10px",
5188
- inDuration: 250,
5189
- outDuration: 200,
5190
5086
  onOpenStart: null,
5191
5087
  onOpenEnd: null,
5192
5088
  onCloseStart: null,
5193
- onCloseEnd: null,
5194
- preventScrolling: true
5089
+ onCloseEnd: null
5195
5090
  };
5091
+ var LARGE_UP = "(width >= 993px)";
5196
5092
  var _Sidenav = class _Sidenav extends Component {
5197
5093
  constructor(el, options) {
5198
5094
  super(el, options, _Sidenav);
5199
- this._handleDragTargetDrag = (e) => {
5200
- if (!this._isDraggable()) return;
5201
- let totalDeltaX = this._calculateDelta(e);
5202
- const dragDirection = totalDeltaX > 0 ? "right" : "left";
5203
- totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
5204
- if (this.options.edge === dragDirection) {
5205
- totalDeltaX = 0;
5206
- }
5207
- let transformX = totalDeltaX;
5208
- let transformPrefix = "translateX(-100%)";
5209
- if (this.options.edge === "right") {
5210
- transformPrefix = "translateX(100%)";
5211
- transformX = -transformX;
5212
- }
5213
- this.percentOpen = Math.min(1, totalDeltaX / this._width);
5214
- this.el.style.transform = `${transformPrefix} translateX(${transformX}px)`;
5215
- this._overlay.style.opacity = this.percentOpen.toString();
5216
- };
5217
- this._handleDragTargetRelease = () => {
5218
- if (this.isDragged) {
5219
- if (this.percentOpen > 0.2) {
5220
- this.open();
5221
- } else {
5222
- this._animateOut();
5095
+ /**
5096
+ * Opens the overlay drawer. No-op while the sidenav is docked
5097
+ * (sidenav-fixed at the large breakpoint).
5098
+ */
5099
+ this.open = () => {
5100
+ if (this._isCurrentlyFixed() || this.isOpen || !this._dialog) return;
5101
+ _Sidenav._sidenavs.forEach((other) => {
5102
+ if (other !== this && other.isOpen) other.close();
5103
+ });
5104
+ if (typeof this.options.onOpenStart === "function") {
5105
+ this.options.onOpenStart.call(this, this.el);
5106
+ }
5107
+ this.isOpen = true;
5108
+ this._dialog.classList.remove("dragging");
5109
+ this._clearShift();
5110
+ if (!this._dialog.open) {
5111
+ try {
5112
+ this._dialog.showModal();
5113
+ } catch {
5223
5114
  }
5224
- this.isDragged = false;
5225
- this._verticallyScrolling = false;
5226
5115
  }
5227
- };
5228
- this._handleCloseDrag = (e) => {
5229
- if (!this.isOpen || !this._isDraggable()) return;
5230
- let totalDeltaX = this._calculateDelta(e);
5231
- const dragDirection = totalDeltaX > 0 ? "right" : "left";
5232
- totalDeltaX = Math.min(this._width, Math.abs(totalDeltaX));
5233
- if (this.options.edge !== dragDirection) {
5234
- totalDeltaX = 0;
5116
+ this._syncTriggers();
5117
+ if (typeof this.options.onOpenEnd === "function") {
5118
+ this.options.onOpenEnd.call(this, this.el);
5235
5119
  }
5236
- let transformX = -totalDeltaX;
5237
- if (this.options.edge === "right") {
5238
- transformX = -transformX;
5120
+ };
5121
+ /**
5122
+ * Closes the overlay drawer. No-op while the sidenav is docked.
5123
+ */
5124
+ this.close = () => {
5125
+ if (this._isCurrentlyFixed() || !this.isOpen) return;
5126
+ this._beginClose();
5127
+ if (this._dialog?.open) {
5128
+ this._closing = true;
5129
+ this._dialog.close();
5130
+ } else {
5131
+ this._finishClose();
5239
5132
  }
5240
- this.percentOpen = Math.min(1, 1 - totalDeltaX / this._width);
5241
- this.el.style.transform = `translateX(${transformX}px)`;
5242
- this._overlay.style.opacity = this.percentOpen.toString();
5243
5133
  };
5244
- this._calculateDelta = (e) => {
5245
- if (!this.isDragged) {
5246
- this._startDrag(e);
5134
+ this._onDialogClose = () => {
5135
+ if (this.isOpen) {
5136
+ this._beginClose();
5137
+ this._finishClose();
5138
+ return;
5139
+ }
5140
+ if (this._closing) {
5141
+ this._closing = false;
5142
+ this._finishClose();
5247
5143
  }
5248
- this._dragMoveUpdate(e);
5249
- return this._xPos - this._startingXpos;
5250
5144
  };
5251
- this._handleCloseRelease = () => {
5252
- if (this.isOpen && this.isDragged) {
5253
- if (this.percentOpen > 0.8) {
5254
- this._animateIn();
5255
- } else {
5256
- this.close();
5257
- }
5258
- this.isDragged = false;
5259
- this._verticallyScrolling = false;
5145
+ this._onBreakpointChange = () => {
5146
+ if (this._isCurrentlyFixed() && this.isOpen) {
5147
+ this.close();
5260
5148
  }
5261
5149
  };
5262
- // Handles closing of Sidenav when element with class .sidenav-close
5263
5150
  this._handleCloseTriggerClick = (e) => {
5264
- const closeTrigger = e.target.closest(".sidenav-close");
5151
+ const target = e.target;
5152
+ if (!(target instanceof Element)) return;
5153
+ const closeTrigger = target.closest(".sidenav-close");
5265
5154
  if (closeTrigger && !this._isCurrentlyFixed()) {
5266
5155
  this.close();
5267
5156
  }
5268
5157
  };
5269
- this._handleWindowResize = () => {
5270
- if (this.lastWindowWidth !== window.innerWidth) {
5271
- if (window.innerWidth > 992) {
5272
- this.open();
5273
- } else {
5274
- this.close();
5275
- }
5276
- }
5277
- this.lastWindowWidth = window.innerWidth;
5278
- this.lastWindowHeight = window.innerHeight;
5158
+ this._handleDragTargetDrag = (e) => {
5159
+ if (!this._isDraggable()) return;
5160
+ const delta = this._rawDelta(e);
5161
+ const towardOpen = this.options.edge === "left" ? delta : -delta;
5162
+ const visible = Math.min(this._width, Math.max(0, towardOpen));
5163
+ const percentOpen = this._width ? visible / this._width : 0;
5164
+ this._applyShift(visible - this._width, percentOpen);
5279
5165
  };
5280
- /**
5281
- * Opens Sidenav.
5282
- */
5283
- this.open = () => {
5284
- if (this.isOpen === true) return;
5285
- this.isOpen = true;
5286
- if (typeof this.options.onOpenStart === "function") {
5287
- this.options.onOpenStart.call(this, this.el);
5288
- }
5289
- if (this._isCurrentlyFixed()) {
5290
- this.el.style.transform = "translateX(0)";
5291
- this._enableBodyScrolling();
5292
- this._overlay.style.display = "none";
5293
- } else {
5294
- if (this.options.preventScrolling) this._preventBodyScrolling();
5295
- if (!this.isDragged || this.percentOpen != 1) this._animateIn();
5296
- this._setAriaHidden();
5297
- this._setTabIndex();
5166
+ this._handleDragTargetRelease = () => {
5167
+ if (!this.isDragged) return;
5168
+ this._dialog?.classList.remove("dragging");
5169
+ if (this.percentOpen > 0.2) {
5170
+ this.open();
5171
+ } else if (this._dialog?.open && !this.isOpen) {
5172
+ this._clearShift();
5173
+ this._dialog.close();
5298
5174
  }
5175
+ this.isDragged = false;
5176
+ this._verticallyScrolling = false;
5299
5177
  };
5300
- /**
5301
- * Closes Sidenav.
5302
- */
5303
- this.close = () => {
5304
- if (this.isOpen === false) return;
5305
- this.isOpen = false;
5306
- if (typeof this.options.onCloseStart === "function") {
5307
- this.options.onCloseStart.call(this, this.el);
5308
- }
5309
- if (this._isCurrentlyFixed()) {
5310
- const transformX = this.options.edge === "left" ? "-105%" : "105%";
5311
- this.el.style.transform = `translateX(${transformX})`;
5178
+ this._handleCloseDrag = (e) => {
5179
+ if (!this.isOpen || !this._isDraggable()) return;
5180
+ const delta = this._rawDelta(e);
5181
+ const towardClose = this.options.edge === "left" ? -delta : delta;
5182
+ const hidden = Math.min(this._width, Math.max(0, towardClose));
5183
+ const percentOpen = this._width ? 1 - hidden / this._width : 1;
5184
+ this._applyShift(-hidden, percentOpen);
5185
+ };
5186
+ this._handleCloseRelease = () => {
5187
+ if (!this.isOpen || !this.isDragged) return;
5188
+ this._dialog?.classList.remove("dragging");
5189
+ if (this.percentOpen > 0.8) {
5190
+ this._clearShift();
5312
5191
  } else {
5313
- this._enableBodyScrolling();
5314
- if (!this.isDragged || this.percentOpen != 0) {
5315
- this._animateOut();
5316
- } else {
5317
- this._overlay.style.display = "none";
5318
- }
5319
- this._setAriaHidden();
5320
- this._setTabIndex();
5192
+ this.close();
5321
5193
  }
5322
- };
5323
- this._setAriaHidden = () => {
5324
- this.el.ariaHidden = this.isOpen ? "false" : "true";
5325
- const navWrapper = document.querySelector(".nav-wrapper ul");
5326
- if (navWrapper) navWrapper.ariaHidden = this.isOpen.toString();
5327
- };
5328
- this._setTabIndex = () => {
5329
- const navLinks = document.querySelectorAll(".nav-wrapper ul li a");
5330
- const sideNavLinks = document.querySelectorAll(".sidenav li a");
5331
- if (navLinks)
5332
- navLinks.forEach((navLink) => {
5333
- navLink.tabIndex = this.isOpen ? -1 : 0;
5334
- });
5335
- if (sideNavLinks)
5336
- sideNavLinks.forEach((sideNavLink) => {
5337
- sideNavLink.tabIndex = this.isOpen ? 0 : -1;
5338
- });
5194
+ this.isDragged = false;
5195
+ this._verticallyScrolling = false;
5339
5196
  };
5340
5197
  this.el["Expressive_Sidenav"] = this;
5341
5198
  this.options = {
@@ -5346,17 +5203,26 @@ var _Sidenav = class _Sidenav extends Component {
5346
5203
  this.isOpen = false;
5347
5204
  this.isFixed = this.el.classList.contains("sidenav-fixed");
5348
5205
  this.isDragged = false;
5349
- this.lastWindowWidth = window.innerWidth;
5350
- this.lastWindowHeight = window.innerHeight;
5351
- this._createOverlay();
5206
+ this.dragTarget = null;
5207
+ this._dialog = null;
5208
+ this._createdDialog = false;
5209
+ this._closing = false;
5210
+ this.percentOpen = 0;
5211
+ this._startingXpos = 0;
5212
+ this._xPos = 0;
5213
+ this._width = 0;
5214
+ this._initialScrollTop = 0;
5215
+ this._verticallyScrolling = false;
5216
+ this._mql = window.matchMedia(LARGE_UP);
5217
+ this._setupDialog();
5352
5218
  this._createDragTarget();
5353
- this._setupEventHandlers();
5354
5219
  this._setupClasses();
5355
- this._setupFixed();
5220
+ this._setupEventHandlers();
5221
+ this._syncTriggers();
5356
5222
  _Sidenav._sidenavs.push(this);
5357
5223
  }
5358
5224
  static get defaults() {
5359
- return _defaults18;
5225
+ return _defaults17;
5360
5226
  }
5361
5227
  /**
5362
5228
  * Initializes instances of Sidenav.
@@ -5371,182 +5237,178 @@ var _Sidenav = class _Sidenav extends Component {
5371
5237
  }
5372
5238
  destroy() {
5373
5239
  this._removeEventHandlers();
5374
- this._enableBodyScrolling();
5375
- this._overlay.parentNode.removeChild(this._overlay);
5376
- this.dragTarget.parentNode.removeChild(this.dragTarget);
5240
+ if (this._dialog?.open) {
5241
+ try {
5242
+ this._dialog.close();
5243
+ } catch {
5244
+ }
5245
+ }
5246
+ this._clearShift();
5247
+ this._unwrapDialog();
5248
+ this._removeDragTarget();
5377
5249
  this.el["Expressive_Sidenav"] = void 0;
5378
- this.el.style.transform = "";
5379
5250
  const index = _Sidenav._sidenavs.indexOf(this);
5380
5251
  if (index >= 0) {
5381
5252
  _Sidenav._sidenavs.splice(index, 1);
5382
5253
  }
5383
5254
  }
5384
- _createOverlay() {
5385
- this._overlay = document.createElement("div");
5386
- this._overlay.classList.add("sidenav-overlay");
5387
- this._overlay.addEventListener("click", this.close);
5388
- document.body.appendChild(this._overlay);
5255
+ _beginClose() {
5256
+ this.isOpen = false;
5257
+ this._dialog?.classList.remove("dragging");
5258
+ this._clearShift();
5259
+ if (typeof this.options.onCloseStart === "function") {
5260
+ this.options.onCloseStart.call(this, this.el);
5261
+ }
5262
+ this._syncTriggers();
5263
+ }
5264
+ _finishClose() {
5265
+ if (typeof this.options.onCloseEnd === "function") {
5266
+ this.options.onCloseEnd.call(this, this.el);
5267
+ }
5268
+ }
5269
+ _setupDialog() {
5270
+ if (this.el instanceof HTMLDialogElement) {
5271
+ this._dialog = this.el;
5272
+ this._createdDialog = false;
5273
+ return;
5274
+ }
5275
+ const parent = this.el.parentElement;
5276
+ if (parent instanceof HTMLDialogElement && parent.classList.contains("sidenav-overlay")) {
5277
+ this._dialog = parent;
5278
+ this._createdDialog = false;
5279
+ return;
5280
+ }
5281
+ const dialog = document.createElement("dialog");
5282
+ dialog.classList.add("sidenav-overlay");
5283
+ this.el.replaceWith(dialog);
5284
+ dialog.appendChild(this.el);
5285
+ this._dialog = dialog;
5286
+ this._createdDialog = true;
5287
+ }
5288
+ _unwrapDialog() {
5289
+ if (!this._createdDialog || !this._dialog) return;
5290
+ this._dialog.replaceWith(this.el);
5291
+ this._dialog = null;
5292
+ this._createdDialog = false;
5293
+ }
5294
+ _createDragTarget() {
5295
+ if (!this.options.draggable) return;
5296
+ const dragTarget = document.createElement("div");
5297
+ dragTarget.classList.add("drag-target");
5298
+ dragTarget.style.width = this.options.dragTargetWidth;
5299
+ if (this.isFixed) dragTarget.dataset.fixed = "";
5300
+ document.body.appendChild(dragTarget);
5301
+ this.dragTarget = dragTarget;
5302
+ }
5303
+ _removeDragTarget() {
5304
+ this.dragTarget?.remove();
5305
+ this.dragTarget = null;
5306
+ }
5307
+ _setupClasses() {
5308
+ if (this.options.edge === "right") {
5309
+ this.el.classList.add("right-aligned");
5310
+ this._dialog?.classList.add("right-aligned");
5311
+ this.dragTarget?.classList.add("right-aligned");
5312
+ }
5389
5313
  }
5390
5314
  _setupEventHandlers() {
5391
5315
  if (_Sidenav._sidenavs.length === 0) {
5392
- document.body.addEventListener("click", this._handleTriggerClick);
5316
+ document.body.addEventListener("click", _Sidenav._handleTriggerClick);
5393
5317
  }
5394
5318
  const passive = { passive: true };
5395
- this.dragTarget.addEventListener("touchmove", this._handleDragTargetDrag, passive);
5396
- this.dragTarget.addEventListener("touchend", this._handleDragTargetRelease);
5397
- this._overlay.addEventListener("touchmove", this._handleCloseDrag, passive);
5398
- this._overlay.addEventListener("touchend", this._handleCloseRelease);
5399
- this.el.addEventListener("touchmove", this._handleCloseDrag, passive);
5400
- this.el.addEventListener("touchend", this._handleCloseRelease);
5319
+ this.dragTarget?.addEventListener("touchmove", this._handleDragTargetDrag, passive);
5320
+ this.dragTarget?.addEventListener("touchend", this._handleDragTargetRelease);
5321
+ this._dialog?.addEventListener("touchmove", this._handleCloseDrag, passive);
5322
+ this._dialog?.addEventListener("touchend", this._handleCloseRelease);
5323
+ this._dialog?.addEventListener("close", this._onDialogClose);
5401
5324
  this.el.addEventListener("click", this._handleCloseTriggerClick);
5402
- if (this.isFixed) {
5403
- window.addEventListener("resize", this._handleWindowResize, passive);
5404
- }
5405
- this._setAriaHidden();
5406
- this._setTabIndex();
5325
+ this._mql.addEventListener("change", this._onBreakpointChange);
5407
5326
  }
5408
5327
  _removeEventHandlers() {
5409
5328
  if (_Sidenav._sidenavs.length === 1) {
5410
- document.body.removeEventListener("click", this._handleTriggerClick);
5411
- }
5412
- this.dragTarget.removeEventListener("touchmove", this._handleDragTargetDrag);
5413
- this.dragTarget.removeEventListener("touchend", this._handleDragTargetRelease);
5414
- this._overlay.removeEventListener("touchmove", this._handleCloseDrag);
5415
- this._overlay.removeEventListener("touchend", this._handleCloseRelease);
5416
- this.el.removeEventListener("touchmove", this._handleCloseDrag);
5417
- this.el.removeEventListener("touchend", this._handleCloseRelease);
5418
- this.el.removeEventListener("click", this._handleCloseTriggerClick);
5419
- if (this.isFixed) {
5420
- window.removeEventListener("resize", this._handleWindowResize);
5329
+ document.body.removeEventListener("click", _Sidenav._handleTriggerClick);
5421
5330
  }
5331
+ this.dragTarget?.removeEventListener("touchmove", this._handleDragTargetDrag);
5332
+ this.dragTarget?.removeEventListener("touchend", this._handleDragTargetRelease);
5333
+ this._dialog?.removeEventListener("touchmove", this._handleCloseDrag);
5334
+ this._dialog?.removeEventListener("touchend", this._handleCloseRelease);
5335
+ this._dialog?.removeEventListener("close", this._onDialogClose);
5336
+ this.el.removeEventListener("click", this._handleCloseTriggerClick);
5337
+ this._mql.removeEventListener("change", this._onBreakpointChange);
5422
5338
  }
5423
- _handleTriggerClick(e) {
5424
- const trigger = e.target.closest(".sidenav-trigger");
5425
- if (e.target && trigger) {
5426
- const sidenavId = Utils.getIdFromTrigger(trigger);
5427
- const sidenavInstance = document.getElementById(sidenavId)?.["Expressive_Sidenav"];
5428
- if (sidenavInstance) {
5429
- sidenavInstance.open();
5430
- }
5339
+ static _handleTriggerClick(e) {
5340
+ const target = e.target;
5341
+ if (!(target instanceof Element)) return;
5342
+ const trigger = target.closest(".sidenav-trigger");
5343
+ if (!trigger || !(trigger instanceof HTMLElement)) return;
5344
+ const sidenavId = Utils.getIdFromTrigger(trigger);
5345
+ const sidenavInstance = document.getElementById(sidenavId)?.["Expressive_Sidenav"];
5346
+ if (sidenavInstance) {
5347
+ sidenavInstance.open();
5431
5348
  e.preventDefault();
5432
5349
  }
5433
5350
  }
5434
- // Set variables needed at the beginning of drag and stop any current transition.
5351
+ _isDraggable() {
5352
+ return this.options.draggable && !this._isCurrentlyFixed() && !this._verticallyScrolling;
5353
+ }
5354
+ _isCurrentlyFixed() {
5355
+ return this.isFixed && this._mql.matches;
5356
+ }
5435
5357
  _startDrag(e) {
5436
5358
  const clientX = e.targetTouches[0].clientX;
5437
5359
  this.isDragged = true;
5438
5360
  this._startingXpos = clientX;
5439
- this._xPos = this._startingXpos;
5440
- this._time = Date.now();
5441
- this._width = this.el.getBoundingClientRect().width;
5442
- this._overlay.style.display = "block";
5361
+ this._xPos = clientX;
5362
+ this._width = this._dialog?.getBoundingClientRect().width || this.el.getBoundingClientRect().width;
5443
5363
  this._initialScrollTop = this.isOpen ? this.el.scrollTop : Utils.getDocumentScrollTop();
5444
5364
  this._verticallyScrolling = false;
5365
+ this._dialog?.classList.add("dragging");
5366
+ if (this._dialog && !this._dialog.open) {
5367
+ try {
5368
+ this._dialog.showModal();
5369
+ } catch {
5370
+ }
5371
+ }
5445
5372
  }
5446
- //Set variables needed at each drag move update tick
5447
5373
  _dragMoveUpdate(e) {
5448
5374
  const clientX = e.targetTouches[0].clientX;
5449
5375
  const currentScrollTop = this.isOpen ? this.el.scrollTop : Utils.getDocumentScrollTop();
5450
- this.deltaX = Math.abs(this._xPos - clientX);
5451
5376
  this._xPos = clientX;
5452
- this.velocityX = this.deltaX / (Date.now() - this._time);
5453
- this._time = Date.now();
5454
5377
  if (this._initialScrollTop !== currentScrollTop) {
5455
5378
  this._verticallyScrolling = true;
5456
5379
  }
5457
5380
  }
5458
- _setupClasses() {
5459
- if (this.options.edge === "right") {
5460
- this.el.classList.add("right-aligned");
5461
- this.dragTarget.classList.add("right-aligned");
5462
- }
5463
- }
5464
- _removeClasses() {
5465
- this.el.classList.remove("right-aligned");
5466
- this.dragTarget.classList.remove("right-aligned");
5467
- }
5468
- _setupFixed() {
5469
- if (this._isCurrentlyFixed()) this.open();
5470
- }
5471
- _isDraggable() {
5472
- return this.options.draggable && !this._isCurrentlyFixed() && !this._verticallyScrolling;
5473
- }
5474
- _isCurrentlyFixed() {
5475
- return this.isFixed && window.innerWidth > 992;
5476
- }
5477
- _createDragTarget() {
5478
- const dragTarget = document.createElement("div");
5479
- dragTarget.classList.add("drag-target");
5480
- dragTarget.style.width = this.options.dragTargetWidth;
5481
- document.body.appendChild(dragTarget);
5482
- this.dragTarget = dragTarget;
5483
- }
5484
- _preventBodyScrolling() {
5485
- document.body.style.overflow = "hidden";
5486
- }
5487
- _enableBodyScrolling() {
5488
- document.body.style.overflow = "";
5489
- }
5490
- _animateIn() {
5491
- this._animateSidenavIn();
5492
- this._animateOverlayIn();
5493
- }
5494
- _animateOut() {
5495
- this._animateSidenavOut();
5496
- this._animateOverlayOut();
5497
- }
5498
- _animateSidenavIn() {
5499
- let slideOutPercent = this.options.edge === "left" ? -1 : 1;
5500
- if (this.isDragged) {
5501
- slideOutPercent = this.options.edge === "left" ? slideOutPercent + this.percentOpen : slideOutPercent - this.percentOpen;
5502
- }
5503
- const duration = this.options.inDuration;
5504
- this.el.style.transition = "none";
5505
- this.el.style.transform = "translateX(" + slideOutPercent * 100 + "%)";
5506
- setTimeout(() => {
5507
- this.el.style.transition = `transform ${duration}ms ease`;
5508
- this.el.style.transform = "translateX(0)";
5509
- }, 1);
5510
- setTimeout(() => {
5511
- if (typeof this.options.onOpenEnd === "function") this.options.onOpenEnd.call(this, this.el);
5512
- }, duration);
5513
- }
5514
- _animateSidenavOut() {
5515
- const endPercent = this.options.edge === "left" ? -1 : 1;
5516
- const duration = this.options.outDuration;
5517
- this.el.style.transition = `transform ${duration}ms ease`;
5518
- this.el.style.transform = "translateX(" + endPercent * 100 + "%)";
5519
- setTimeout(() => {
5520
- if (typeof this.options.onCloseEnd === "function")
5521
- this.options.onCloseEnd.call(this, this.el);
5522
- }, duration);
5523
- }
5524
- _animateOverlayIn() {
5525
- let start = 0;
5526
- if (this.isDragged) start = this.percentOpen;
5527
- else this._overlay.style.display = "block";
5528
- const duration = this.options.inDuration;
5529
- this._overlay.style.transition = "none";
5530
- this._overlay.style.opacity = start.toString();
5531
- setTimeout(() => {
5532
- this._overlay.style.transition = `opacity ${duration}ms ease`;
5533
- this._overlay.style.opacity = "1";
5534
- }, 1);
5535
- }
5536
- _animateOverlayOut() {
5537
- const duration = this.options.outDuration;
5538
- this._overlay.style.transition = `opacity ${duration}ms ease`;
5539
- this._overlay.style.opacity = "0";
5540
- setTimeout(() => {
5541
- this._overlay.style.display = "none";
5542
- }, duration);
5381
+ _rawDelta(e) {
5382
+ if (!this.isDragged) this._startDrag(e);
5383
+ this._dragMoveUpdate(e);
5384
+ return this._xPos - this._startingXpos;
5385
+ }
5386
+ _applyShift(shift, percentOpen) {
5387
+ this.percentOpen = percentOpen;
5388
+ const host = this._dialog ?? this.el;
5389
+ host.style.setProperty("--md-comp-nav-drawer-shift", `${shift}px`);
5390
+ host.style.setProperty("--md-comp-nav-drawer-open", String(percentOpen));
5391
+ }
5392
+ _clearShift() {
5393
+ const host = this._dialog ?? this.el;
5394
+ host.style.removeProperty("--md-comp-nav-drawer-shift");
5395
+ host.style.removeProperty("--md-comp-nav-drawer-open");
5396
+ }
5397
+ _syncTriggers() {
5398
+ if (!this.id) return;
5399
+ document.querySelectorAll(".sidenav-trigger").forEach((trigger) => {
5400
+ if (!(trigger instanceof HTMLElement)) return;
5401
+ if (Utils.getIdFromTrigger(trigger) !== this.id) return;
5402
+ trigger.setAttribute("aria-expanded", this.isOpen ? "true" : "false");
5403
+ trigger.setAttribute("aria-controls", this.id);
5404
+ });
5543
5405
  }
5544
5406
  };
5545
5407
  _Sidenav._sidenavs = [];
5546
5408
  var Sidenav = _Sidenav;
5547
5409
 
5548
5410
  // src/ts/components/slider.ts
5549
- var _defaults19 = {
5411
+ var _defaults18 = {
5550
5412
  indicators: true,
5551
5413
  height: 400,
5552
5414
  duration: 500,
@@ -5694,7 +5556,7 @@ var Slider = class _Slider extends Component {
5694
5556
  this.start();
5695
5557
  }
5696
5558
  static get defaults() {
5697
- return _defaults19;
5559
+ return _defaults18;
5698
5560
  }
5699
5561
  /**
5700
5562
  * Initializes instances of Slider.
@@ -5847,7 +5709,7 @@ var Slider = class _Slider extends Component {
5847
5709
  };
5848
5710
 
5849
5711
  // src/ts/components/tabs.ts
5850
- var _defaults20 = {
5712
+ var _defaults19 = {
5851
5713
  duration: 300,
5852
5714
  onShow: null,
5853
5715
  swipeable: false,
@@ -5925,7 +5787,7 @@ var Tabs = class _Tabs extends Component {
5925
5787
  this._setupEventHandlers();
5926
5788
  }
5927
5789
  static get defaults() {
5928
- return _defaults20;
5790
+ return _defaults19;
5929
5791
  }
5930
5792
  /**
5931
5793
  * Initializes instances of Tabs.
@@ -5964,7 +5826,7 @@ var Tabs = class _Tabs extends Component {
5964
5826
  }
5965
5827
  _queryTabLinks() {
5966
5828
  return this.el.querySelectorAll(
5967
- ":scope > a, :scope > .tab > a, :scope > li.tab > a"
5829
+ ":scope > a, :scope > .tab > a"
5968
5830
  );
5969
5831
  }
5970
5832
  _createIndicator() {
@@ -6006,7 +5868,7 @@ var Tabs = class _Tabs extends Component {
6006
5868
  }
6007
5869
  });
6008
5870
  const tabsWrapper = document.createElement("div");
6009
- tabsWrapper.classList.add("tabs-content", "carousel", "carousel-slider");
5871
+ tabsWrapper.classList.add("tabs-content", "carousel", "flat");
6010
5872
  tabsContent[0].parentElement.insertBefore(tabsWrapper, tabsContent[0]);
6011
5873
  tabsContent.forEach((tabContent) => {
6012
5874
  tabsWrapper.appendChild(tabContent);
@@ -6093,7 +5955,7 @@ var Tabs = class _Tabs extends Component {
6093
5955
  };
6094
5956
 
6095
5957
  // src/ts/components/tapTarget.ts
6096
- var _defaults21 = {
5958
+ var _defaults20 = {
6097
5959
  onOpen: null,
6098
5960
  onClose: null
6099
5961
  };
@@ -6208,7 +6070,7 @@ var _TapTarget = class _TapTarget extends Component {
6208
6070
  _TapTarget._taptargets.push(this);
6209
6071
  }
6210
6072
  static get defaults() {
6211
- return _defaults21;
6073
+ return _defaults20;
6212
6074
  }
6213
6075
  static init(els, options = {}) {
6214
6076
  return super.init(els, options, _TapTarget);
@@ -6281,7 +6143,7 @@ var _TapTarget = class _TapTarget extends Component {
6281
6143
  _setupEventHandlers() {
6282
6144
  if (!this.originEl) return;
6283
6145
  this.originEl.addEventListener("click", this._handleTargetToggle);
6284
- if (!this.originEl.matches('button, a, [tabindex], .btn, [role="button"]')) {
6146
+ if (!this.originEl.matches('button, a, [tabindex], [role="button"]')) {
6285
6147
  this.originEl.tabIndex = 0;
6286
6148
  this.originEl.addEventListener("keydown", this._handleOriginKeydown);
6287
6149
  }
@@ -6314,7 +6176,7 @@ _TapTarget._taptargets = [];
6314
6176
  var TapTarget = _TapTarget;
6315
6177
 
6316
6178
  // src/ts/components/timepicker.ts
6317
- var _defaults22 = {
6179
+ var _defaults21 = {
6318
6180
  dialRadius: 135,
6319
6181
  outerRadius: 105,
6320
6182
  innerRadius: 70,
@@ -6512,7 +6374,7 @@ var _Timepicker = class _Timepicker extends Component {
6512
6374
  }
6513
6375
  }
6514
6376
  static get defaults() {
6515
- return _defaults22;
6377
+ return _defaults21;
6516
6378
  }
6517
6379
  /**
6518
6380
  * Initializes instances of Timepicker.
@@ -6595,7 +6457,7 @@ var _Timepicker = class _Timepicker extends Component {
6595
6457
  }
6596
6458
  /*private _createButton(text: string, visibility: string): HTMLButtonElement {
6597
6459
  const button = document.createElement('button');
6598
- button.classList.add('btn', 'waves-effect', 'text');
6460
+ button.classList.add('waves-effect', 'text');
6599
6461
  button.style.visibility = visibility;
6600
6462
  button.type = 'button';
6601
6463
  button.tabIndex = -1;
@@ -6636,14 +6498,14 @@ var _Timepicker = class _Timepicker extends Component {
6636
6498
  _clockSetup() {
6637
6499
  if (this.options.twelveHour) {
6638
6500
  this._amBtn = document.createElement("div");
6639
- this._amBtn.classList.add("am-btn", "btn");
6501
+ this._amBtn.classList.add("am-btn");
6640
6502
  this._amBtn.innerText = "AM";
6641
6503
  this._amBtn.tabIndex = 0;
6642
6504
  this._amBtn.addEventListener("click", this._handleAmPmClick);
6643
6505
  this._amBtn.addEventListener("keypress", this._handleAmPmKeypress);
6644
6506
  this.spanAmPm.appendChild(this._amBtn);
6645
6507
  this._pmBtn = document.createElement("div");
6646
- this._pmBtn.classList.add("pm-btn", "btn");
6508
+ this._pmBtn.classList.add("pm-btn");
6647
6509
  this._pmBtn.innerText = "PM";
6648
6510
  this._pmBtn.tabIndex = 0;
6649
6511
  this._pmBtn.addEventListener("click", this._handleAmPmClick);
@@ -6850,19 +6712,6 @@ var _Timepicker = class _Timepicker extends Component {
6850
6712
  this.hours = (/* @__PURE__ */ new Date()).getHours();
6851
6713
  this.inputHours.value = (this.hours % (this.options.twelveHour ? 12 : 24)).toString();
6852
6714
  }
6853
- // deprecated
6854
- open() {
6855
- console.warn(
6856
- "Timepicker.close() is deprecated. Remove this method and wrap in modal yourself."
6857
- );
6858
- return this;
6859
- }
6860
- close() {
6861
- console.warn(
6862
- "Timepicker.close() is deprecated. Remove this method and wrap in modal yourself."
6863
- );
6864
- return this;
6865
- }
6866
6715
  };
6867
6716
  _Timepicker._template = `<div class="timepicker-container">
6868
6717
  <div class="timepicker-digital-display">
@@ -6895,7 +6744,7 @@ _Timepicker._template = `<div class="timepicker-container">
6895
6744
  var Timepicker = _Timepicker;
6896
6745
 
6897
6746
  // src/ts/components/toasts.ts
6898
- var _defaults23 = {
6747
+ var _defaults22 = {
6899
6748
  text: "",
6900
6749
  action: "",
6901
6750
  onAction: null,
@@ -6927,7 +6776,7 @@ var _Toast = class _Toast {
6927
6776
  this._setTimer();
6928
6777
  }
6929
6778
  static get defaults() {
6930
- return _defaults23;
6779
+ return _defaults22;
6931
6780
  }
6932
6781
  static getInstance(el) {
6933
6782
  return el["Expressive_Toast"];
@@ -6952,8 +6801,8 @@ var _Toast = class _Toast {
6952
6801
  }
6953
6802
  static _onDragStart(e) {
6954
6803
  const target = e.target;
6955
- if (target && !target.closest("button, a") && target.closest(".toast, .snackbar")) {
6956
- const toastElem = target.closest(".toast, .snackbar");
6804
+ if (target && !target.closest("button, a") && target.closest(".snackbar")) {
6805
+ const toastElem = target.closest(".snackbar");
6957
6806
  const toast = toastElem["Expressive_Toast"];
6958
6807
  if (!toast) return;
6959
6808
  toast.panning = true;
@@ -7020,7 +6869,7 @@ var _Toast = class _Toast {
7020
6869
  const node = toast.content.cloneNode(true);
7021
6870
  toast = node.firstElementChild;
7022
6871
  }
7023
- toast.classList.add("toast", "snackbar");
6872
+ toast.classList.add("snackbar");
7024
6873
  toast.setAttribute("role", "status");
7025
6874
  toast.setAttribute("aria-live", "polite");
7026
6875
  toast.setAttribute("aria-atomic", "true");
@@ -7140,7 +6989,7 @@ _Toast._draggedToast = null;
7140
6989
  var Toast = _Toast;
7141
6990
 
7142
6991
  // src/ts/components/tooltip.ts
7143
- var _defaults24 = {
6992
+ var _defaults23 = {
7144
6993
  exitDelay: 200,
7145
6994
  enterDelay: 0,
7146
6995
  text: "",
@@ -7208,7 +7057,7 @@ var Tooltip = class _Tooltip extends Component {
7208
7057
  this._setupEventHandlers();
7209
7058
  }
7210
7059
  static get defaults() {
7211
- return _defaults24;
7060
+ return _defaults23;
7212
7061
  }
7213
7062
  /**
7214
7063
  * Initializes instances of Tooltip.
@@ -7231,7 +7080,7 @@ var Tooltip = class _Tooltip extends Component {
7231
7080
  }
7232
7081
  _appendTooltipEl() {
7233
7082
  this.tooltipEl = document.createElement("div");
7234
- this.tooltipEl.classList.add("tooltip", "material-tooltip");
7083
+ this.tooltipEl.classList.add("tooltip");
7235
7084
  this.tooltipEl.id = `tooltip-${Utils.guid()}`;
7236
7085
  this.tooltipEl.setAttribute("role", "tooltip");
7237
7086
  this.el.setAttribute("aria-describedby", this.tooltipEl.id);
@@ -7392,7 +7241,6 @@ var AUTO_INIT_COMPONENTS = {
7392
7241
  Datepicker: { component: Datepicker, selector: ".datepicker" },
7393
7242
  Dropdown: { component: Dropdown, selector: ".dropdown-trigger" },
7394
7243
  Lightbox: { component: Lightbox, selector: ".lightboxed" },
7395
- Modal: { component: Modal, selector: ".modal" },
7396
7244
  Parallax: { component: Parallax, selector: ".parallax" },
7397
7245
  Pushpin: { component: Pushpin, selector: ".pushpin" },
7398
7246
  ScrollSpy: { component: ScrollSpy, selector: ".scrollspy" },
@@ -7416,7 +7264,7 @@ function AutoInit(context = document.body, options) {
7416
7264
  }
7417
7265
 
7418
7266
  // src/ts/index.ts
7419
- var version = "0.3.0";
7267
+ var version = "0.4.0";
7420
7268
  if (typeof document !== "undefined") {
7421
7269
  document.addEventListener("keydown", Utils.docHandleKeydown, true);
7422
7270
  document.addEventListener("keyup", Utils.docHandleKeyup, true);
@@ -7444,7 +7292,6 @@ export {
7444
7292
  FormSelect,
7445
7293
  Forms,
7446
7294
  Lightbox,
7447
- Modal,
7448
7295
  Parallax,
7449
7296
  Pushpin,
7450
7297
  Range,