@expressivecss/expressive 0.4.0 → 0.6.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 (69) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/README.md +4 -9
  3. package/dist/css/expressive.css +2617 -951
  4. package/dist/css/expressive.css.map +1 -1
  5. package/dist/css/expressive.min.css +1 -1
  6. package/dist/css/expressive.min.css.map +1 -1
  7. package/dist/js/expressive.cjs +643 -804
  8. package/dist/js/expressive.cjs.map +4 -4
  9. package/dist/js/expressive.js +643 -804
  10. package/dist/js/expressive.js.map +4 -4
  11. package/dist/js/expressive.min.js +11 -11
  12. package/dist/js/expressive.min.js.map +4 -4
  13. package/dist/js/expressive.mjs +643 -804
  14. package/dist/js/expressive.mjs.map +4 -4
  15. package/dist/types/behaviors/bottomSheets.d.ts +18 -0
  16. package/dist/types/behaviors/sideSheets.d.ts +18 -0
  17. package/dist/types/components/autocomplete.d.ts +11 -11
  18. package/dist/types/components/index.d.ts +3 -5
  19. package/dist/types/components/{dropdown.d.ts → menu.d.ts} +38 -37
  20. package/dist/types/components/navigationRail.d.ts +53 -0
  21. package/dist/types/components/range.d.ts +3 -0
  22. package/dist/types/components/registry.d.ts +7 -15
  23. package/dist/types/components/select.d.ts +12 -12
  24. package/dist/types/components/{toasts.d.ts → snackbar.d.ts} +28 -25
  25. package/dist/types/index.d.ts +3 -1
  26. package/package.json +3 -2
  27. package/src/sass/README.md +13 -11
  28. package/src/sass/abstracts/_breakpoints.scss +14 -3
  29. package/src/sass/abstracts/_mixins.scss +3 -3
  30. package/src/sass/abstracts/_variables.scss +27 -2
  31. package/src/sass/base/_global.scss +1 -1
  32. package/src/sass/base/_grid.scss +66 -116
  33. package/src/sass/base/_index.scss +1 -1
  34. package/src/sass/components/_badges.scss +80 -60
  35. package/src/sass/components/_bottom-sheet.scss +137 -0
  36. package/src/sass/components/_cards.scss +4 -4
  37. package/src/sass/components/_chips.scss +6 -5
  38. package/src/sass/components/_dialog.scss +268 -0
  39. package/src/sass/components/_index.scss +9 -7
  40. package/src/sass/components/_list.scss +253 -0
  41. package/src/sass/components/_menu.scss +341 -0
  42. package/src/sass/components/_navbar.scss +65 -117
  43. package/src/sass/components/_navigation-bar.scss +165 -0
  44. package/src/sass/components/_navigation-rail.scss +308 -0
  45. package/src/sass/components/_page-footer.scss +7 -3
  46. package/src/sass/components/_panes.scss +294 -0
  47. package/src/sass/components/_side-sheet.scss +193 -0
  48. package/src/sass/components/_sidenav.scss +78 -49
  49. package/src/sass/components/{_toast.scss → _snackbar.scss} +35 -34
  50. package/src/sass/components/_tabs.scss +1 -27
  51. package/src/sass/components/_toolbar.scss +91 -25
  52. package/src/sass/components/_tooltip.scss +1 -1
  53. package/src/sass/components/forms/_fieldset.scss +1 -1
  54. package/src/sass/components/forms/_input-fields.scss +3 -3
  55. package/src/sass/components/forms/_range.scss +423 -98
  56. package/src/sass/components/forms/_select.scss +19 -17
  57. package/src/sass/tokens/_reference.scss +37 -13
  58. package/src/sass/tokens/_theme.scss +5 -13
  59. package/src/sass/utilities/_colors.scss +16 -74
  60. package/src/sass/utilities/_visibility.scss +8 -0
  61. package/dist/types/components/collapsible.d.ts +0 -79
  62. package/dist/types/components/pushpin.d.ts +0 -51
  63. package/dist/types/components/tapTarget.d.ts +0 -57
  64. package/src/sass/components/_collapsible.scss +0 -179
  65. package/src/sass/components/_collection.scss +0 -180
  66. package/src/sass/components/_dropdown.scss +0 -225
  67. package/src/sass/components/_modal.scss +0 -190
  68. package/src/sass/components/_pushpin.scss +0 -11
  69. package/src/sass/components/_tapTarget.scss +0 -187
@@ -516,13 +516,13 @@ var Cards = class _Cards extends Component {
516
516
  }
517
517
  };
518
518
 
519
- // src/ts/components/dropdown.ts
519
+ // src/ts/components/menu.ts
520
520
  var _defaults2 = {
521
521
  alignment: "left",
522
522
  autoFocus: true,
523
523
  constrainWidth: true,
524
524
  container: null,
525
- coverTrigger: true,
525
+ coverTrigger: false,
526
526
  closeOnClick: true,
527
527
  hover: false,
528
528
  inDuration: 150,
@@ -533,9 +533,9 @@ var _defaults2 = {
533
533
  onCloseEnd: null,
534
534
  onItemClick: null
535
535
  };
536
- var _Dropdown = class _Dropdown extends Component {
536
+ var _Menu = class _Menu extends Component {
537
537
  constructor(el, options) {
538
- super(el, options, _Dropdown);
538
+ super(el, options, _Menu);
539
539
  this._handleClick = (e) => {
540
540
  e.preventDefault();
541
541
  if (this.isOpen) {
@@ -553,22 +553,22 @@ var _Dropdown = class _Dropdown extends Component {
553
553
  this.close();
554
554
  return;
555
555
  }
556
- const leaveToDropdownContent = !!(this.dropdownEl && toEl && this.dropdownEl.contains(toEl));
557
- let leaveToActiveDropdownTrigger = false;
558
- const closestTrigger = toEl.closest(".dropdown-trigger");
559
- if (closestTrigger && !!closestTrigger["Expressive_Dropdown"] && closestTrigger["Expressive_Dropdown"].isOpen) {
560
- leaveToActiveDropdownTrigger = true;
556
+ const leaveToMenuContent = !!(this.menuEl && toEl && this.menuEl.contains(toEl));
557
+ let leaveToActiveMenuTrigger = false;
558
+ const closestTrigger = toEl.closest(".menu-trigger");
559
+ if (closestTrigger && !!closestTrigger["Expressive_Menu"] && closestTrigger["Expressive_Menu"].isOpen) {
560
+ leaveToActiveMenuTrigger = true;
561
561
  }
562
- if (!leaveToActiveDropdownTrigger && !leaveToDropdownContent) {
562
+ if (!leaveToActiveMenuTrigger && !leaveToMenuContent) {
563
563
  this.close();
564
564
  }
565
565
  };
566
566
  this._handleDocumentClick = (e) => {
567
567
  const target = e.target;
568
568
  if (this._isSubmenuTriggerClick(target)) return;
569
- if (this.options.closeOnClick && this.dropdownEl?.contains(target) && !this.isTouchMoving) {
569
+ if (this.options.closeOnClick && this.menuEl?.contains(target) && !this.isTouchMoving) {
570
570
  this.close();
571
- } else if (!this.dropdownEl?.contains(target)) {
571
+ } else if (!this.menuEl?.contains(target)) {
572
572
  setTimeout(() => {
573
573
  if (this.isOpen) {
574
574
  this.close();
@@ -586,11 +586,11 @@ var _Dropdown = class _Dropdown extends Component {
586
586
  };
587
587
  this._handleDocumentTouchmove = (e) => {
588
588
  const target = e.target;
589
- if (this.dropdownEl?.contains(target)) {
589
+ if (this.menuEl?.contains(target)) {
590
590
  this.isTouchMoving = true;
591
591
  }
592
592
  };
593
- this._handleDropdownClick = (e) => {
593
+ this._handleMenuClick = (e) => {
594
594
  const target = e.target;
595
595
  const li = target.closest("li");
596
596
  if (li && this._isSubmenuTriggerClick(target)) {
@@ -607,11 +607,11 @@ var _Dropdown = class _Dropdown extends Component {
607
607
  const target = e.target;
608
608
  if (!(target instanceof Element)) return;
609
609
  const li = target.closest("li");
610
- if (li?.querySelector(":scope > menu") && this.dropdownEl?.contains(li)) {
610
+ if (li?.querySelector(":scope > menu") && this.menuEl?.contains(li)) {
611
611
  this._alignSubmenu(li);
612
612
  }
613
613
  };
614
- this._handleDropdownKeydown = (e) => {
614
+ this._handleMenuKeydown = (e) => {
615
615
  const arrowUpOrDown = Utils.keys.ARROW_DOWN.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key);
616
616
  if (Utils.keys.TAB.includes(e.key)) {
617
617
  e.preventDefault();
@@ -638,7 +638,7 @@ var _Dropdown = class _Dropdown extends Component {
638
638
  } else if (arrowUpOrDown && this.isOpen) {
639
639
  e.preventDefault();
640
640
  const direction = Utils.keys.ARROW_DOWN.includes(e.key) ? 1 : -1;
641
- const list = this._containingSubmenu(e) ?? this.dropdownEl;
641
+ const list = this._containingSubmenu(e) ?? this.menuEl;
642
642
  let newFocusedIndex = this.focusedIndex;
643
643
  let hasFoundNewIndex = false;
644
644
  do {
@@ -663,7 +663,7 @@ var _Dropdown = class _Dropdown extends Component {
663
663
  this._toggleSubmenu(li);
664
664
  return;
665
665
  }
666
- const focusedElement = li ?? this.dropdownEl.children[this.focusedIndex];
666
+ const focusedElement = li ?? this.menuEl.children[this.focusedIndex];
667
667
  const activatableElement = focusedElement?.querySelector("a, button");
668
668
  if (!!activatableElement) {
669
669
  activatableElement.click();
@@ -672,7 +672,7 @@ var _Dropdown = class _Dropdown extends Component {
672
672
  }
673
673
  } else if (Utils.keys.ESC.includes(e.key) && this.isOpen) {
674
674
  e.preventDefault();
675
- const openSub = this.dropdownEl.querySelector("li.open");
675
+ const openSub = this.menuEl.querySelector("li.open");
676
676
  if (openSub) {
677
677
  openSub.classList.remove("open", "submenu-start");
678
678
  this._syncSubmenuAria(openSub, false);
@@ -693,7 +693,7 @@ var _Dropdown = class _Dropdown extends Component {
693
693
  if (isLetter && !specialKeys.includes(e.key)) {
694
694
  this.filterQuery.push(keyText);
695
695
  const string = this.filterQuery.join("");
696
- const list = this._containingSubmenu(e) ?? this.dropdownEl;
696
+ const list = this._containingSubmenu(e) ?? this.menuEl;
697
697
  const newOptionEl = Array.from(list.querySelectorAll(":scope > li")).find(
698
698
  (el) => el.textContent.trim().toLowerCase().indexOf(string) === 0
699
699
  );
@@ -714,7 +714,7 @@ var _Dropdown = class _Dropdown extends Component {
714
714
  this.filterQuery = [];
715
715
  };
716
716
  /**
717
- * Open dropdown.
717
+ * Open menu.
718
718
  */
719
719
  this.open = () => {
720
720
  if (this.isOpen) return;
@@ -722,15 +722,15 @@ var _Dropdown = class _Dropdown extends Component {
722
722
  if (typeof this.options.onOpenStart === "function") {
723
723
  this.options.onOpenStart.call(this, this.el);
724
724
  }
725
- this._resetDropdownStyles();
726
- this.dropdownEl.style.display = "block";
727
- this._placeDropdown();
725
+ this._resetMenuStyles();
726
+ this.menuEl.style.display = "block";
727
+ this._placeMenu();
728
728
  this._animateIn();
729
729
  setTimeout(() => this._setupTemporaryEventHandlers(), 0);
730
730
  this.el.ariaExpanded = "true";
731
731
  };
732
732
  /**
733
- * Close dropdown.
733
+ * Close menu.
734
734
  */
735
735
  this.close = () => {
736
736
  if (!this.isOpen) return;
@@ -748,20 +748,20 @@ var _Dropdown = class _Dropdown extends Component {
748
748
  this.el.ariaExpanded = "false";
749
749
  };
750
750
  /**
751
- * While dropdown is open, you can recalculate its dimensions if its contents have changed.
751
+ * While menu is open, you can recalculate its dimensions if its contents have changed.
752
752
  */
753
753
  this.recalculateDimensions = () => {
754
754
  if (this.isOpen) {
755
- this._resetDropdownPositioningStyles();
756
- this._placeDropdown();
755
+ this._resetMenuPositioningStyles();
756
+ this._placeMenu();
757
757
  }
758
758
  };
759
- this.el["Expressive_Dropdown"] = this;
760
- _Dropdown._dropdowns.push(this);
759
+ this.el["Expressive_Menu"] = this;
760
+ _Menu._menus.push(this);
761
761
  this.id = Utils.getIdFromTrigger(el);
762
- this.dropdownEl = document.getElementById(this.id);
762
+ this.menuEl = document.getElementById(this.id);
763
763
  this.options = {
764
- ..._Dropdown.defaults,
764
+ ..._Menu.defaults,
765
765
  ...options
766
766
  };
767
767
  this.isOpen = false;
@@ -770,8 +770,8 @@ var _Dropdown = class _Dropdown extends Component {
770
770
  this.focusedIndex = -1;
771
771
  this.filterQuery = [];
772
772
  this.el.ariaExpanded = "false";
773
- this._moveDropdownToElement();
774
- this._makeDropdownFocusable();
773
+ this._moveMenuToElement();
774
+ this._makeMenuFocusable();
775
775
  this._setupSubmenus();
776
776
  this._setupEventHandlers();
777
777
  }
@@ -779,47 +779,47 @@ var _Dropdown = class _Dropdown extends Component {
779
779
  return _defaults2;
780
780
  }
781
781
  /**
782
- * Initializes instances of Dropdown.
782
+ * Initializes instances of Menu.
783
783
  * @param els HTML elements.
784
784
  * @param options Component options.
785
785
  */
786
786
  static init(els, options = {}) {
787
- return super.init(els, options, _Dropdown);
787
+ return super.init(els, options, _Menu);
788
788
  }
789
789
  static getInstance(el) {
790
- return el["Expressive_Dropdown"];
790
+ return el["Expressive_Menu"];
791
791
  }
792
792
  destroy() {
793
793
  clearTimeout(this.filterTimeout);
794
- this._resetDropdownStyles();
794
+ this._resetMenuStyles();
795
795
  this._removeEventHandlers();
796
796
  this._removeTemporaryEventHandlers();
797
- const index = _Dropdown._dropdowns.indexOf(this);
798
- if (index >= 0) _Dropdown._dropdowns.splice(index, 1);
799
- this.el["Expressive_Dropdown"] = void 0;
797
+ const index = _Menu._menus.indexOf(this);
798
+ if (index >= 0) _Menu._menus.splice(index, 1);
799
+ this.el["Expressive_Menu"] = void 0;
800
800
  }
801
801
  _setupEventHandlers() {
802
802
  this.el.addEventListener("keydown", this._handleTriggerKeydown);
803
- this.dropdownEl?.addEventListener("click", this._handleDropdownClick);
804
- if (this.dropdownEl?.querySelector(":scope > li > menu")) {
805
- this.dropdownEl.addEventListener("mouseover", this._handleSubmenuAlign);
803
+ this.menuEl?.addEventListener("click", this._handleMenuClick);
804
+ if (this.menuEl?.querySelector(":scope > li > menu")) {
805
+ this.menuEl.addEventListener("mouseover", this._handleSubmenuAlign);
806
806
  }
807
807
  if (this.options.hover) {
808
808
  this.el.addEventListener("mouseenter", this._handleMouseEnter);
809
809
  this.el.addEventListener("mouseleave", this._handleMouseLeave);
810
- this.dropdownEl.addEventListener("mouseleave", this._handleMouseLeave);
810
+ this.menuEl.addEventListener("mouseleave", this._handleMouseLeave);
811
811
  } else {
812
812
  this.el.addEventListener("click", this._handleClick);
813
813
  }
814
814
  }
815
815
  _removeEventHandlers() {
816
816
  this.el.removeEventListener("keydown", this._handleTriggerKeydown);
817
- this.dropdownEl?.removeEventListener("click", this._handleDropdownClick);
818
- this.dropdownEl?.removeEventListener("mouseover", this._handleSubmenuAlign);
817
+ this.menuEl?.removeEventListener("click", this._handleMenuClick);
818
+ this.menuEl?.removeEventListener("mouseover", this._handleSubmenuAlign);
819
819
  if (this.options.hover) {
820
820
  this.el.removeEventListener("mouseenter", this._handleMouseEnter);
821
821
  this.el.removeEventListener("mouseleave", this._handleMouseLeave);
822
- this.dropdownEl?.removeEventListener("mouseleave", this._handleMouseLeave);
822
+ this.menuEl?.removeEventListener("mouseleave", this._handleMouseLeave);
823
823
  } else {
824
824
  this.el.removeEventListener("click", this._handleClick);
825
825
  }
@@ -827,25 +827,25 @@ var _Dropdown = class _Dropdown extends Component {
827
827
  _setupTemporaryEventHandlers() {
828
828
  document.body.addEventListener("click", this._handleDocumentClick);
829
829
  document.body.addEventListener("touchmove", this._handleDocumentTouchmove, { passive: true });
830
- this.dropdownEl?.addEventListener("keydown", this._handleDropdownKeydown);
830
+ this.menuEl?.addEventListener("keydown", this._handleMenuKeydown);
831
831
  window.addEventListener("resize", this._handleWindowResize);
832
832
  }
833
833
  _removeTemporaryEventHandlers() {
834
834
  document.body.removeEventListener("click", this._handleDocumentClick);
835
835
  document.body.removeEventListener("touchmove", this._handleDocumentTouchmove);
836
- this.dropdownEl?.removeEventListener("keydown", this._handleDropdownKeydown);
836
+ this.menuEl?.removeEventListener("keydown", this._handleMenuKeydown);
837
837
  window.removeEventListener("resize", this._handleWindowResize);
838
838
  }
839
839
  _isSubmenuTriggerClick(target) {
840
- if (!this.dropdownEl) return false;
840
+ if (!this.menuEl) return false;
841
841
  const li = target.closest("li");
842
- if (!li || !this.dropdownEl.contains(li)) return false;
842
+ if (!li || !this.menuEl.contains(li)) return false;
843
843
  const submenu = li.querySelector(":scope > menu");
844
844
  if (!submenu) return false;
845
845
  return !submenu.contains(target);
846
846
  }
847
847
  _setupSubmenus() {
848
- this.dropdownEl?.querySelectorAll("li").forEach((li) => {
848
+ this.menuEl?.querySelectorAll("li").forEach((li) => {
849
849
  if (!li.querySelector(":scope > menu")) return;
850
850
  const trigger = li.querySelector(":scope > a, :scope > button, :scope > span") ?? li;
851
851
  trigger.setAttribute("aria-haspopup", "menu");
@@ -871,15 +871,12 @@ var _Dropdown = class _Dropdown extends Component {
871
871
  _alignSubmenu(li) {
872
872
  const menu = li.querySelector(":scope > menu");
873
873
  if (!menu) return;
874
- const wasHidden = getComputedStyle(menu).display === "none";
875
- if (wasHidden) menu.style.display = "block";
876
874
  li.classList.remove("submenu-start");
877
875
  const rect = menu.getBoundingClientRect();
878
876
  if (rect.right > window.innerWidth - 8) li.classList.add("submenu-start");
879
- if (wasHidden) menu.style.display = "";
880
877
  }
881
878
  _closeSubmenus() {
882
- this.dropdownEl?.querySelectorAll("li.open").forEach((li) => {
879
+ this.menuEl?.querySelectorAll("li.open").forEach((li) => {
883
880
  li.classList.remove("open", "submenu-start");
884
881
  this._syncSubmenuAria(li, false);
885
882
  });
@@ -888,46 +885,46 @@ var _Dropdown = class _Dropdown extends Component {
888
885
  const target = e.target;
889
886
  if (!(target instanceof Element)) return null;
890
887
  const submenu = target.closest("li > menu");
891
- if (submenu instanceof HTMLElement && this.dropdownEl?.contains(submenu)) return submenu;
888
+ if (submenu instanceof HTMLElement && this.menuEl?.contains(submenu)) return submenu;
892
889
  return null;
893
890
  }
894
891
  _focusedRow(e) {
895
892
  const target = e.target;
896
893
  if (!(target instanceof Element)) return null;
897
894
  const li = target.closest("li");
898
- if (li instanceof HTMLElement && this.dropdownEl?.contains(li)) return li;
895
+ if (li instanceof HTMLElement && this.menuEl?.contains(li)) return li;
899
896
  return null;
900
897
  }
901
- _resetDropdownStyles() {
902
- this.dropdownEl.style.display = "";
903
- this._resetDropdownPositioningStyles();
904
- this.dropdownEl.style.transform = "";
905
- this.dropdownEl.style.opacity = "";
898
+ _resetMenuStyles() {
899
+ this.menuEl.style.display = "";
900
+ this._resetMenuPositioningStyles();
901
+ this.menuEl.style.transform = "";
902
+ this.menuEl.style.opacity = "";
906
903
  }
907
- _resetDropdownPositioningStyles() {
908
- this.dropdownEl.style.width = "";
909
- this.dropdownEl.style.height = "";
910
- this.dropdownEl.style.left = "";
911
- this.dropdownEl.style.top = "";
912
- this.dropdownEl.style.transformOrigin = "";
904
+ _resetMenuPositioningStyles() {
905
+ this.menuEl.style.width = "";
906
+ this.menuEl.style.height = "";
907
+ this.menuEl.style.left = "";
908
+ this.menuEl.style.top = "";
909
+ this.menuEl.style.transformOrigin = "";
913
910
  }
914
- _moveDropdownToElement(containerEl = null) {
911
+ _moveMenuToElement(containerEl = null) {
915
912
  if (this.options.container) {
916
- this.options.container.append(this.dropdownEl);
913
+ this.options.container.append(this.menuEl);
917
914
  return;
918
915
  }
919
916
  if (containerEl) {
920
- if (!containerEl.contains(this.dropdownEl)) containerEl.append(this.dropdownEl);
917
+ if (!containerEl.contains(this.menuEl)) containerEl.append(this.menuEl);
921
918
  return;
922
919
  }
923
- this.el.after(this.dropdownEl);
920
+ this.el.after(this.menuEl);
924
921
  }
925
- _makeDropdownFocusable() {
926
- if (!this.dropdownEl) return;
927
- this.dropdownEl.popover = "";
928
- this.dropdownEl.tabIndex = 0;
929
- this.dropdownEl.querySelectorAll(":scope li, :scope > hr").forEach((el) => {
930
- if (el instanceof HTMLHRElement || el.classList.contains("divider")) {
922
+ _makeMenuFocusable() {
923
+ if (!this.menuEl) return;
924
+ this.menuEl.popover = "";
925
+ this.menuEl.tabIndex = 0;
926
+ this.menuEl.querySelectorAll(":scope li, :scope > hr").forEach((el) => {
927
+ if (el instanceof HTMLHRElement || el.classList.contains("divider") || el.classList.contains("gap") || el.classList.contains("label") || el.classList.contains("optgroup")) {
931
928
  el.setAttribute("tabindex", "-1");
932
929
  return;
933
930
  }
@@ -935,25 +932,25 @@ var _Dropdown = class _Dropdown extends Component {
935
932
  });
936
933
  }
937
934
  _focusFocusedItem() {
938
- if (this.focusedIndex >= 0 && this.focusedIndex < this.dropdownEl.children.length && this.options.autoFocus) {
939
- this.dropdownEl.children[this.focusedIndex].focus({
935
+ if (this.focusedIndex >= 0 && this.focusedIndex < this.menuEl.children.length && this.options.autoFocus) {
936
+ this.menuEl.children[this.focusedIndex].focus({
940
937
  preventScroll: true
941
938
  });
942
- this.dropdownEl.children[this.focusedIndex].scrollIntoView({
939
+ this.menuEl.children[this.focusedIndex].scrollIntoView({
943
940
  behavior: "smooth",
944
941
  block: "nearest",
945
942
  inline: "nearest"
946
943
  });
947
944
  }
948
945
  }
949
- _getDropdownPosition(closestOverflowParent) {
946
+ _getMenuPosition(closestOverflowParent) {
950
947
  const triggerBRect = this.el.getBoundingClientRect();
951
- const dropdownBRect = this.dropdownEl.getBoundingClientRect();
952
- let idealHeight = dropdownBRect.height;
953
- let idealWidth = dropdownBRect.width;
954
- let idealXPos = triggerBRect.left - dropdownBRect.left;
955
- let idealYPos = triggerBRect.top - dropdownBRect.top;
956
- const dropdownBounds = {
948
+ const menuBRect = this.menuEl.getBoundingClientRect();
949
+ let idealHeight = menuBRect.height;
950
+ let idealWidth = menuBRect.width;
951
+ let idealXPos = triggerBRect.left - menuBRect.left;
952
+ let idealYPos = triggerBRect.top - menuBRect.top;
953
+ const menuBounds = {
957
954
  left: idealXPos,
958
955
  top: idealYPos,
959
956
  height: idealHeight,
@@ -962,7 +959,7 @@ var _Dropdown = class _Dropdown extends Component {
962
959
  const alignments = Utils.checkPossibleAlignments(
963
960
  this.el,
964
961
  closestOverflowParent,
965
- dropdownBounds,
962
+ menuBounds,
966
963
  this.options.coverTrigger ? 0 : triggerBRect.height
967
964
  );
968
965
  let verticalAlignment = "top";
@@ -1003,10 +1000,10 @@ var _Dropdown = class _Dropdown extends Component {
1003
1000
  }
1004
1001
  }
1005
1002
  if (verticalAlignment === "bottom") {
1006
- idealYPos = idealYPos - dropdownBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
1003
+ idealYPos = idealYPos - menuBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
1007
1004
  }
1008
1005
  if (horizontalAlignment === "right") {
1009
- idealXPos = idealXPos - dropdownBRect.width + triggerBRect.width;
1006
+ idealXPos = idealXPos - menuBRect.width + triggerBRect.width;
1010
1007
  }
1011
1008
  return {
1012
1009
  x: idealXPos,
@@ -1019,26 +1016,26 @@ var _Dropdown = class _Dropdown extends Component {
1019
1016
  }
1020
1017
  _animateIn() {
1021
1018
  const duration = this.options.inDuration;
1022
- this.dropdownEl.style.transition = "none";
1023
- this.dropdownEl.style.opacity = "0";
1024
- this.dropdownEl.style.transform = "scale(0.3, 0.3)";
1019
+ this.menuEl.style.transition = "none";
1020
+ this.menuEl.style.opacity = "0";
1021
+ this.menuEl.style.transform = "scale(0.85)";
1025
1022
  setTimeout(() => {
1026
- this.dropdownEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1027
- this.dropdownEl.style.opacity = "1";
1028
- this.dropdownEl.style.transform = "scale(1, 1)";
1023
+ this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1024
+ this.menuEl.style.opacity = "1";
1025
+ this.menuEl.style.transform = "scale(1)";
1029
1026
  }, 1);
1030
1027
  setTimeout(() => {
1031
- if (this.options.autoFocus) this.dropdownEl.focus();
1028
+ if (this.options.autoFocus) this.menuEl.focus();
1032
1029
  if (typeof this.options.onOpenEnd === "function") this.options.onOpenEnd.call(this, this.el);
1033
1030
  }, duration);
1034
1031
  }
1035
1032
  _animateOut() {
1036
1033
  const duration = this.options.outDuration;
1037
- this.dropdownEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1038
- this.dropdownEl.style.opacity = "0";
1039
- this.dropdownEl.style.transform = "scale(0.3, 0.3)";
1034
+ this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1035
+ this.menuEl.style.opacity = "0";
1036
+ this.menuEl.style.transform = "scale(0.85)";
1040
1037
  setTimeout(() => {
1041
- this._resetDropdownStyles();
1038
+ this._resetMenuStyles();
1042
1039
  if (typeof this.options.onCloseEnd === "function")
1043
1040
  this.options.onCloseEnd.call(this, this.el);
1044
1041
  }, duration);
@@ -1053,30 +1050,31 @@ var _Dropdown = class _Dropdown extends Component {
1053
1050
  }
1054
1051
  return null;
1055
1052
  }
1056
- _placeDropdown() {
1053
+ _placeMenu() {
1057
1054
  let closestOverflowParent = this._getClosestAncestor(
1058
- this.dropdownEl,
1055
+ this.menuEl,
1059
1056
  (ancestor) => {
1060
1057
  return !["HTML", "BODY"].includes(ancestor.tagName) && getComputedStyle(ancestor).overflow !== "visible";
1061
1058
  }
1062
1059
  );
1063
1060
  if (!closestOverflowParent) {
1064
- closestOverflowParent = !!this.dropdownEl.offsetParent ? this.dropdownEl.offsetParent : this.dropdownEl.parentNode;
1061
+ closestOverflowParent = !!this.menuEl.offsetParent ? this.menuEl.offsetParent : this.menuEl.parentNode;
1065
1062
  }
1066
1063
  if (getComputedStyle(closestOverflowParent).position === "static")
1067
1064
  closestOverflowParent.style.position = "relative";
1068
- const idealWidth = this.options.constrainWidth ? this.el.getBoundingClientRect().width : this.dropdownEl.getBoundingClientRect().width;
1069
- this.dropdownEl.style.width = idealWidth + "px";
1070
- const positionInfo = this._getDropdownPosition(closestOverflowParent);
1071
- this.dropdownEl.style.left = positionInfo.x + "px";
1072
- this.dropdownEl.style.top = positionInfo.y + "px";
1073
- this.dropdownEl.style.height = positionInfo.height + "px";
1074
- this.dropdownEl.style.width = positionInfo.width + "px";
1075
- this.dropdownEl.style.transformOrigin = `${positionInfo.horizontalAlignment === "left" ? "0" : "100%"} ${positionInfo.verticalAlignment === "top" ? "0" : "100%"}`;
1065
+ const natural = this.menuEl.getBoundingClientRect().width;
1066
+ const idealWidth = this.options.constrainWidth ? this.el.getBoundingClientRect().width : Math.min(280, Math.max(112, natural));
1067
+ this.menuEl.style.width = idealWidth + "px";
1068
+ const positionInfo = this._getMenuPosition(closestOverflowParent);
1069
+ this.menuEl.style.left = positionInfo.x + "px";
1070
+ this.menuEl.style.top = positionInfo.y + "px";
1071
+ this.menuEl.style.height = positionInfo.height + "px";
1072
+ this.menuEl.style.width = positionInfo.width + "px";
1073
+ this.menuEl.style.transformOrigin = `${positionInfo.horizontalAlignment === "left" ? "0" : "100%"} ${positionInfo.verticalAlignment === "top" ? "0" : "100%"}`;
1076
1074
  }
1077
1075
  };
1078
- _Dropdown._dropdowns = [];
1079
- var Dropdown = _Dropdown;
1076
+ _Menu._menus = [];
1077
+ var Menu = _Menu;
1080
1078
 
1081
1079
  // src/ts/components/autocomplete.ts
1082
1080
  var _defaults3 = {
@@ -1084,8 +1082,8 @@ var _defaults3 = {
1084
1082
  // Autocomplete data set
1085
1083
  onAutocomplete: null,
1086
1084
  // Callback for when autocompleted
1087
- dropdownOptions: {
1088
- // Default dropdown options
1085
+ menuOptions: {
1086
+ // Default menu options
1089
1087
  autoFocus: false,
1090
1088
  closeOnClick: false,
1091
1089
  coverTrigger: false
@@ -1101,7 +1099,7 @@ var _defaults3 = {
1101
1099
  )
1102
1100
  );
1103
1101
  },
1104
- maxDropDownHeight: "300px",
1102
+ maxMenuHeight: "300px",
1105
1103
  allowUnsafeHTML: false,
1106
1104
  selected: []
1107
1105
  };
@@ -1186,19 +1184,19 @@ var _Autocomplete = class _Autocomplete extends Component {
1186
1184
  this._resetAutocomplete();
1187
1185
  if (inputText.length >= this.options.minLength) {
1188
1186
  this.isOpen = true;
1189
- this._renderDropdown();
1187
+ this._renderMenu();
1190
1188
  }
1191
- if (!this.dropdown.isOpen) {
1189
+ if (!this.menu.isOpen) {
1192
1190
  setTimeout(() => {
1193
- this.dropdown.open();
1191
+ this.menu.open();
1194
1192
  }, 0);
1195
- } else this.dropdown.recalculateDimensions();
1193
+ } else this.menu.recalculateDimensions();
1196
1194
  };
1197
1195
  /**
1198
1196
  * Hide autocomplete.
1199
1197
  */
1200
1198
  this.close = () => {
1201
- this.dropdown.close();
1199
+ this.menu.close();
1202
1200
  };
1203
1201
  this.el["Expressive_Autocomplete"] = this;
1204
1202
  this.options = {
@@ -1213,7 +1211,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1213
1211
  this.menuItems = this.options.data || [];
1214
1212
  this.$active = null;
1215
1213
  this._mousedown = false;
1216
- this._setupDropdown();
1214
+ this._setupMenu();
1217
1215
  this._setupEventHandlers();
1218
1216
  }
1219
1217
  static get defaults() {
@@ -1244,7 +1242,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1244
1242
  }
1245
1243
  destroy() {
1246
1244
  this._removeEventHandlers();
1247
- this._removeDropdown();
1245
+ this._removeMenu();
1248
1246
  this.el["Expressive_Autocomplete"] = void 0;
1249
1247
  }
1250
1248
  _setupEventHandlers() {
@@ -1273,34 +1271,33 @@ var _Autocomplete = class _Autocomplete extends Component {
1273
1271
  this.container.removeEventListener("touchend", this._handleContainerMouseupAndTouchend);
1274
1272
  }
1275
1273
  }
1276
- _setupDropdown() {
1274
+ _setupMenu() {
1277
1275
  this.container = document.createElement("menu");
1278
- this.container.style.maxHeight = this.options.maxDropDownHeight;
1276
+ this.container.style.maxHeight = this.options.maxMenuHeight;
1279
1277
  this.container.id = `autocomplete-options-${Utils.guid()}`;
1280
1278
  this.container.classList.add("autocomplete-content");
1281
1279
  this.container.ariaExpanded = "true";
1282
1280
  this.el.setAttribute("data-target", this.container.id);
1283
1281
  this.menuItems.forEach((menuItem) => {
1284
- const itemElement = this._createDropdownItem(menuItem);
1282
+ const itemElement = this._createMenuItem(menuItem);
1285
1283
  this.container.append(itemElement);
1286
1284
  });
1287
1285
  this.el.parentElement.appendChild(this.container);
1288
- const dropdownOptions = {
1289
- ..._Autocomplete.defaults.dropdownOptions,
1290
- ...this.options.dropdownOptions
1286
+ const menuOptions = {
1287
+ ..._Autocomplete.defaults.menuOptions,
1288
+ ...this.options.menuOptions
1291
1289
  };
1292
- const userOnItemClick = dropdownOptions.onItemClick;
1293
- dropdownOptions.onItemClick = (li) => {
1290
+ const userOnItemClick = menuOptions.onItemClick;
1291
+ menuOptions.onItemClick = (li) => {
1294
1292
  if (!li) return;
1295
1293
  const entryID = li.getAttribute("data-id");
1296
1294
  this.selectOption(entryID);
1297
- if (userOnItemClick && typeof userOnItemClick === "function")
1298
- userOnItemClick.call(this.dropdown, this.el);
1295
+ if (typeof userOnItemClick === "function") userOnItemClick.call(this.menu, li);
1299
1296
  };
1300
- this.dropdown = Dropdown.init(this.el, dropdownOptions);
1297
+ this.menu = Menu.init(this.el, menuOptions);
1301
1298
  const label = this.el.parentElement.querySelector("label");
1302
1299
  if (label) this.el.after(label);
1303
- this.el.removeEventListener("click", this.dropdown._handleClick);
1300
+ this.el.removeEventListener("click", this.menu._handleClick);
1304
1301
  if (!this.options.isMultiSelect && !(this.options.selected.length === 0)) {
1305
1302
  const selectedValue = this.menuItems.filter((value) => value.id === this.selectedValues[0].id);
1306
1303
  this.el.value = selectedValue[0].text;
@@ -1312,7 +1309,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1312
1309
  this.el.parentElement.appendChild(div);
1313
1310
  this._updateSelectedInfo();
1314
1311
  }
1315
- _removeDropdown() {
1312
+ _removeMenu() {
1316
1313
  this.container.ariaExpanded = "false";
1317
1314
  this.container.parentNode.removeChild(this.container);
1318
1315
  }
@@ -1335,7 +1332,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1335
1332
  }
1336
1333
  return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
1337
1334
  }
1338
- _createDropdownItem(entry) {
1335
+ _createMenuItem(entry) {
1339
1336
  const item = document.createElement("li");
1340
1337
  item.setAttribute("data-id", entry.id);
1341
1338
  item.setAttribute(
@@ -1402,13 +1399,13 @@ var _Autocomplete = class _Autocomplete extends Component {
1402
1399
  item.style.gridTemplateColumns = getGridConfig();
1403
1400
  return item;
1404
1401
  }
1405
- _renderDropdown() {
1402
+ _renderMenu() {
1406
1403
  this._resetAutocomplete();
1407
1404
  if (this.menuItems.length === 0) {
1408
1405
  this.menuItems = this.selectedValues;
1409
1406
  }
1410
1407
  for (let i = 0; i < this.menuItems.length; i++) {
1411
- const item = this._createDropdownItem(this.menuItems[i]);
1408
+ const item = this._createMenuItem(this.menuItems[i]);
1412
1409
  this.container.append(item);
1413
1410
  }
1414
1411
  }
@@ -1439,7 +1436,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1439
1436
  * Updates the visible or selectable items shown in the menu.
1440
1437
  * @param menuItems Items to be available.
1441
1438
  * @param selected Selected item ids
1442
- * @param open Option to conditionally open dropdown
1439
+ * @param open Option to conditionally open menu
1443
1440
  */
1444
1441
  setMenuItems(menuItems, selected = null, open = true) {
1445
1442
  this.menuItems = menuItems;
@@ -1450,7 +1447,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1450
1447
  );
1451
1448
  }
1452
1449
  if (this.options.isMultiSelect) {
1453
- this._renderDropdown();
1450
+ this._renderMenu();
1454
1451
  } else {
1455
1452
  this._refreshInputText();
1456
1453
  }
@@ -1472,7 +1469,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1472
1469
  else this.selectedValues = this.selectedValues.filter(
1473
1470
  (selectedEntry) => selectedEntry.id !== entry.id
1474
1471
  );
1475
- this._renderDropdown();
1472
+ this._renderMenu();
1476
1473
  this.el.focus();
1477
1474
  } else {
1478
1475
  this.selectedValues = [entry];
@@ -1790,12 +1787,14 @@ var Range = class _Range extends Component {
1790
1787
  constructor(el, options) {
1791
1788
  super(el, options, _Range);
1792
1789
  this._handleRangeChange = () => {
1790
+ this._clampDual();
1793
1791
  this._sync();
1794
1792
  this.thumb.classList.add("active");
1795
1793
  };
1796
1794
  this._handleRangeMousedownTouchstart = (e) => {
1797
1795
  this._mousedown = true;
1798
1796
  this.el.classList.add("active");
1797
+ this._clampDual();
1799
1798
  this._sync();
1800
1799
  if (e.type !== "input") {
1801
1800
  this.thumb.classList.add("active");
@@ -1803,6 +1802,7 @@ var Range = class _Range extends Component {
1803
1802
  };
1804
1803
  this._handleRangeInputMousemoveTouchmove = () => {
1805
1804
  if (this._mousedown) {
1805
+ this._clampDual();
1806
1806
  this._sync();
1807
1807
  this.thumb.classList.add("active");
1808
1808
  }
@@ -1887,16 +1887,48 @@ var Range = class _Range extends Component {
1887
1887
  _isVertical() {
1888
1888
  return !!this.el.closest(".vertical");
1889
1889
  }
1890
+ _host() {
1891
+ return this.el.closest(".range, .range-field, label");
1892
+ }
1893
+ _clampDual() {
1894
+ const host = this._host();
1895
+ const peers = host?.querySelectorAll('input[type="range"]');
1896
+ if (!peers || peers.length !== 2) return;
1897
+ const start = peers[0];
1898
+ const end = peers[1];
1899
+ if (this.el === start && +start.value > +end.value) start.value = end.value;
1900
+ if (this.el === end && +end.value < +start.value) end.value = start.value;
1901
+ }
1902
+ _fraction(el) {
1903
+ const max = parseFloat(el.max) || 100;
1904
+ const min = parseFloat(el.min) || 0;
1905
+ const val = parseFloat(el.value) || 0;
1906
+ return max === min ? 0 : (val - min) / (max - min);
1907
+ }
1890
1908
  _sync() {
1891
- const max = parseFloat(this.el.getAttribute("max")) || 100;
1892
- const min = parseFloat(this.el.getAttribute("min")) || 0;
1893
- const val = parseFloat(this.el.value) || 0;
1894
- const percent = max === min ? 0 : (val - min) / (max - min);
1909
+ const percent = this._fraction(this.el);
1910
+ const fraction = `${percent * 100}%`;
1895
1911
  const left = this.el.offsetLeft;
1896
1912
  const top = this.el.offsetTop;
1897
1913
  const width = this.el.offsetWidth;
1898
1914
  const height = this.el.offsetHeight;
1899
- this.el.style.setProperty("--md-comp-slider-active-fraction", `${percent * 100}%`);
1915
+ this.el.style.setProperty("--md-comp-slider-active-fraction", fraction);
1916
+ const host = this._host();
1917
+ const peers = host?.querySelectorAll('input[type="range"]');
1918
+ if (host && peers && peers.length === 2) {
1919
+ const nums = Array.from(peers).map((el) => this._fraction(el));
1920
+ host.style.setProperty("--md-comp-slider-start-fraction", `${Math.min(...nums) * 100}%`);
1921
+ host.style.setProperty("--md-comp-slider-end-fraction", `${Math.max(...nums) * 100}%`);
1922
+ }
1923
+ if (host?.classList.contains("stops")) {
1924
+ const max = parseFloat(this.el.max) || 100;
1925
+ const min = parseFloat(this.el.min) || 0;
1926
+ const step = parseFloat(this.el.step);
1927
+ if (step > 0 && Number.isFinite(step)) {
1928
+ const n = Math.round((max - min) / step) + 1;
1929
+ host.style.setProperty("--md-comp-slider-stop-count", String(Math.max(2, n)));
1930
+ }
1931
+ }
1900
1932
  this.value.textContent = this.el.value;
1901
1933
  if (this._isVertical()) {
1902
1934
  this.thumb.style.left = `${left + width / 2}px`;
@@ -1984,6 +2016,170 @@ var _Dialogs = class _Dialogs {
1984
2016
  _Dialogs._down = null;
1985
2017
  var Dialogs = _Dialogs;
1986
2018
 
2019
+ // src/ts/behaviors/bottomSheets.ts
2020
+ var _BottomSheets = class _BottomSheets {
2021
+ static Init() {
2022
+ Utils.onDocumentReady(() => {
2023
+ document.addEventListener("pointerdown", _BottomSheets._onDown, { passive: true });
2024
+ document.addEventListener("pointermove", _BottomSheets._onMove, { passive: true });
2025
+ document.addEventListener("pointerup", _BottomSheets._onUp, { passive: true });
2026
+ document.addEventListener("pointercancel", _BottomSheets._onCancel, { passive: true });
2027
+ });
2028
+ }
2029
+ static _onDown(event) {
2030
+ if (!event.isPrimary) return;
2031
+ if (event.pointerType === "mouse" && event.button !== 0) return;
2032
+ const dialog = _BottomSheets._sheet(event.target);
2033
+ if (!dialog?.open) {
2034
+ _BottomSheets._drag = null;
2035
+ return;
2036
+ }
2037
+ if (!_BottomSheets._inHandle(event, dialog)) {
2038
+ _BottomSheets._drag = null;
2039
+ return;
2040
+ }
2041
+ dialog.style.transition = "none";
2042
+ _BottomSheets._drag = {
2043
+ dialog,
2044
+ pointerId: event.pointerId,
2045
+ startY: event.clientY,
2046
+ lastY: event.clientY,
2047
+ lastT: Date.now(),
2048
+ shift: 0
2049
+ };
2050
+ }
2051
+ static _onMove(event) {
2052
+ const drag = _BottomSheets._drag;
2053
+ if (!drag || drag.pointerId !== event.pointerId) return;
2054
+ const shift = Math.max(0, event.clientY - drag.startY);
2055
+ drag.shift = shift;
2056
+ drag.lastY = event.clientY;
2057
+ drag.lastT = Date.now();
2058
+ drag.dialog.style.setProperty("--md-comp-bottom-sheet-shift", `${shift}px`);
2059
+ }
2060
+ static _onUp(event) {
2061
+ const drag = _BottomSheets._drag;
2062
+ _BottomSheets._drag = null;
2063
+ if (!drag || drag.pointerId !== event.pointerId) return;
2064
+ const dialog = drag.dialog;
2065
+ dialog.style.transition = "";
2066
+ const dt = Math.max(1, Date.now() - drag.lastT);
2067
+ const velocity = (event.clientY - drag.lastY) / dt;
2068
+ const dismiss = drag.shift > 96 || velocity > 0.5;
2069
+ if (dismiss && dialog.open) {
2070
+ dialog.close();
2071
+ }
2072
+ dialog.style.setProperty("--md-comp-bottom-sheet-shift", "0px");
2073
+ }
2074
+ static _onCancel() {
2075
+ const drag = _BottomSheets._drag;
2076
+ _BottomSheets._drag = null;
2077
+ if (!drag) return;
2078
+ drag.dialog.style.transition = "";
2079
+ drag.dialog.style.setProperty("--md-comp-bottom-sheet-shift", "0px");
2080
+ }
2081
+ static _sheet(target) {
2082
+ if (!(target instanceof Element)) return null;
2083
+ const dialog = target.closest("dialog.bottom-sheet, dialog.bottom");
2084
+ return dialog instanceof HTMLDialogElement ? dialog : null;
2085
+ }
2086
+ static _inHandle(event, dialog) {
2087
+ const target = event.target;
2088
+ if (target instanceof Element && target.closest(".handle")) return true;
2089
+ const rect = dialog.getBoundingClientRect();
2090
+ return event.clientY >= rect.top && event.clientY <= rect.top + 48;
2091
+ }
2092
+ };
2093
+ _BottomSheets._drag = null;
2094
+ var BottomSheets = _BottomSheets;
2095
+
2096
+ // src/ts/behaviors/sideSheets.ts
2097
+ var _SideSheets = class _SideSheets {
2098
+ static Init() {
2099
+ Utils.onDocumentReady(() => {
2100
+ document.addEventListener("pointerdown", _SideSheets._onDown, { passive: true });
2101
+ document.addEventListener("pointermove", _SideSheets._onMove, { passive: true });
2102
+ document.addEventListener("pointerup", _SideSheets._onUp, { passive: true });
2103
+ document.addEventListener("pointercancel", _SideSheets._onCancel, { passive: true });
2104
+ });
2105
+ }
2106
+ static _onDown(event) {
2107
+ if (!event.isPrimary) return;
2108
+ if (event.pointerType === "mouse" && event.button !== 0) return;
2109
+ const dialog = _SideSheets._sheet(event.target);
2110
+ if (!dialog?.open) {
2111
+ _SideSheets._drag = null;
2112
+ return;
2113
+ }
2114
+ if (!_SideSheets._inHandle(event, dialog)) {
2115
+ _SideSheets._drag = null;
2116
+ return;
2117
+ }
2118
+ dialog.style.transition = "none";
2119
+ _SideSheets._drag = {
2120
+ dialog,
2121
+ pointerId: event.pointerId,
2122
+ startX: event.clientX,
2123
+ lastX: event.clientX,
2124
+ lastT: Date.now(),
2125
+ shift: 0,
2126
+ startDocked: _SideSheets._startDocked(dialog)
2127
+ };
2128
+ }
2129
+ static _onMove(event) {
2130
+ const drag = _SideSheets._drag;
2131
+ if (!drag || drag.pointerId !== event.pointerId) return;
2132
+ const delta = event.clientX - drag.startX;
2133
+ const shift = drag.startDocked ? Math.min(0, delta) : Math.max(0, delta);
2134
+ drag.shift = shift;
2135
+ drag.lastX = event.clientX;
2136
+ drag.lastT = Date.now();
2137
+ drag.dialog.style.setProperty("--md-comp-side-sheet-shift", `${shift}px`);
2138
+ }
2139
+ static _onUp(event) {
2140
+ const drag = _SideSheets._drag;
2141
+ _SideSheets._drag = null;
2142
+ if (!drag || drag.pointerId !== event.pointerId) return;
2143
+ const dialog = drag.dialog;
2144
+ dialog.style.transition = "";
2145
+ const dt = Math.max(1, Date.now() - drag.lastT);
2146
+ const velocity = (event.clientX - drag.lastX) / dt;
2147
+ const dismiss = drag.startDocked ? drag.shift < -96 || velocity < -0.5 : drag.shift > 96 || velocity > 0.5;
2148
+ if (dismiss && dialog.open) {
2149
+ dialog.close();
2150
+ }
2151
+ dialog.style.setProperty("--md-comp-side-sheet-shift", "0px");
2152
+ }
2153
+ static _onCancel() {
2154
+ const drag = _SideSheets._drag;
2155
+ _SideSheets._drag = null;
2156
+ if (!drag) return;
2157
+ drag.dialog.style.transition = "";
2158
+ drag.dialog.style.setProperty("--md-comp-side-sheet-shift", "0px");
2159
+ }
2160
+ static _sheet(target) {
2161
+ if (!(target instanceof Element)) return null;
2162
+ const dialog = target.closest(
2163
+ "dialog.side-sheet, dialog.right, dialog.right-sheet, dialog.left, dialog.left-sheet"
2164
+ );
2165
+ return dialog instanceof HTMLDialogElement ? dialog : null;
2166
+ }
2167
+ static _startDocked(dialog) {
2168
+ return dialog.classList.contains("left") || dialog.classList.contains("left-sheet") || dialog.classList.contains("start");
2169
+ }
2170
+ static _inHandle(event, dialog) {
2171
+ const target = event.target;
2172
+ if (target instanceof Element && target.closest("header")) return true;
2173
+ const rect = dialog.getBoundingClientRect();
2174
+ if (_SideSheets._startDocked(dialog)) {
2175
+ return event.clientX >= rect.right - 24 && event.clientX <= rect.right;
2176
+ }
2177
+ return event.clientX >= rect.left && event.clientX <= rect.left + 24;
2178
+ }
2179
+ };
2180
+ _SideSheets._drag = null;
2181
+ var SideSheets = _SideSheets;
2182
+
1987
2183
  // src/ts/behaviors/forms.ts
1988
2184
  var Forms = class _Forms {
1989
2185
  /**
@@ -2887,178 +3083,10 @@ var CharacterCounter = class _CharacterCounter extends Component {
2887
3083
  }
2888
3084
  };
2889
3085
 
2890
- // src/ts/components/collapsible.ts
2891
- var _defaults9 = {
2892
- accordion: true,
2893
- onOpenStart: null,
2894
- onOpenEnd: null,
2895
- onCloseStart: null,
2896
- onCloseEnd: null
2897
- };
2898
- var Collapsible = class _Collapsible extends Component {
2899
- constructor(el, options) {
2900
- super(el, options, _Collapsible);
2901
- this._items = [];
2902
- this._endTimers = [];
2903
- this._wrappedBodies = [];
2904
- /**
2905
- * Open collapsible section.
2906
- * @param index 0-based index of the section to open.
2907
- */
2908
- this.open = (index) => {
2909
- const item = this._items[index];
2910
- if (!item || this._isOpen(item)) return;
2911
- if (this.options.accordion) {
2912
- this._items.forEach((other, i) => {
2913
- if (i !== index && this._isOpen(other)) this.close(i);
2914
- });
2915
- }
2916
- this._setOpen(item, true);
2917
- };
2918
- /**
2919
- * Close collapsible section.
2920
- * @param index 0-based index of the section to close.
2921
- */
2922
- this.close = (index) => {
2923
- const item = this._items[index];
2924
- if (!item || !this._isOpen(item)) return;
2925
- this._setOpen(item, false);
2926
- };
2927
- this._handleToggle = (e) => {
2928
- const item = e.target;
2929
- if (!(item instanceof HTMLDetailsElement)) return;
2930
- if (!this._items.includes(item)) return;
2931
- this._notify(item, item.open);
2932
- };
2933
- this.el["Expressive_Collapsible"] = this;
2934
- const accordion = options.accordion !== void 0 ? options.accordion : !el.classList.contains("expandable");
2935
- this.options = {
2936
- ..._Collapsible.defaults,
2937
- ...options,
2938
- accordion
2939
- };
2940
- this._groupName = el.id ? `collapsible-${el.id}` : `collapsible-${Utils.guid()}`;
2941
- this._items = this._collectItems();
2942
- this._wrapDetailsBodies();
2943
- this._setupItems();
2944
- this._setupEventHandlers();
2945
- }
2946
- static get defaults() {
2947
- return _defaults9;
2948
- }
2949
- /**
2950
- * Initializes instances of Collapsible.
2951
- * @param els HTML elements.
2952
- * @param options Component options.
2953
- */
2954
- static init(els, options = {}) {
2955
- return super.init(els, options, _Collapsible);
2956
- }
2957
- static getInstance(el) {
2958
- return el["Expressive_Collapsible"];
2959
- }
2960
- destroy() {
2961
- this._removeEventHandlers();
2962
- this._endTimers.forEach((id) => clearTimeout(id));
2963
- this._endTimers = [];
2964
- this._unwrapDetailsBodies();
2965
- this.el["Expressive_Collapsible"] = void 0;
2966
- }
2967
- _collectItems() {
2968
- return Array.from(this.el.querySelectorAll(":scope > details"));
2969
- }
2970
- _setupItems() {
2971
- if (this.options.accordion) {
2972
- this._items.forEach((item) => {
2973
- if (item instanceof HTMLDetailsElement && !item.getAttribute("name")) {
2974
- item.setAttribute("name", this._groupName);
2975
- }
2976
- });
2977
- }
2978
- const opened = this._items.filter((item) => this._isOpen(item));
2979
- if (this.options.accordion && opened.length > 1) {
2980
- opened.slice(1).forEach((item) => {
2981
- if (item instanceof HTMLDetailsElement) item.open = false;
2982
- });
2983
- }
2984
- }
2985
- _isOpen(item) {
2986
- return item instanceof HTMLDetailsElement && item.open;
2987
- }
2988
- _setOpen(item, open) {
2989
- if (item instanceof HTMLDetailsElement) item.open = open;
2990
- }
2991
- _wrapDetailsBodies() {
2992
- this._items.forEach((item) => {
2993
- if (!(item instanceof HTMLDetailsElement)) 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
- }
3001
- const body = document.createElement("div");
3002
- Array.from(item.childNodes).forEach((node) => {
3003
- if (node instanceof HTMLElement && node.tagName === "SUMMARY") return;
3004
- body.appendChild(node);
3005
- });
3006
- item.appendChild(body);
3007
- this._wrappedBodies.push(body);
3008
- });
3009
- }
3010
- _unwrapDetailsBodies() {
3011
- this._wrappedBodies.forEach((body) => {
3012
- const parent = body.parentNode;
3013
- if (!parent) return;
3014
- while (body.firstChild) parent.insertBefore(body.firstChild, body);
3015
- body.remove();
3016
- });
3017
- this._wrappedBodies = [];
3018
- }
3019
- _bodyOf(item) {
3020
- return item.querySelector(":scope > :not(summary)");
3021
- }
3022
- _setupEventHandlers() {
3023
- this.el.addEventListener("toggle", this._handleToggle, true);
3024
- }
3025
- _removeEventHandlers() {
3026
- this.el.removeEventListener("toggle", this._handleToggle, true);
3027
- }
3028
- _notify(item, opening) {
3029
- const start = opening ? this.options.onOpenStart : this.options.onCloseStart;
3030
- if (typeof start === "function") start.call(this, item);
3031
- const end = opening ? this.options.onOpenEnd : this.options.onCloseEnd;
3032
- if (typeof end !== "function") return;
3033
- const target = this._bodyOf(item) ?? item;
3034
- let done = false;
3035
- const finish = () => {
3036
- if (done) return;
3037
- done = true;
3038
- target.removeEventListener("transitionend", onEnd);
3039
- end.call(this, item);
3040
- };
3041
- const onEnd = (ev) => {
3042
- if (ev.target !== target) return;
3043
- finish();
3044
- };
3045
- target.addEventListener("transitionend", onEnd);
3046
- this._endTimers.push(window.setTimeout(finish, this._durationMs() + 50));
3047
- }
3048
- _durationMs() {
3049
- const raw = getComputedStyle(this.el).getPropertyValue("--md-comp-collapsible-duration").trim();
3050
- if (!raw) return 500;
3051
- if (raw.endsWith("ms")) return parseFloat(raw);
3052
- if (raw.endsWith("s")) return parseFloat(raw) * 1e3;
3053
- const n = parseFloat(raw);
3054
- return Number.isFinite(n) ? n : 500;
3055
- }
3056
- };
3057
-
3058
3086
  // src/ts/components/select.ts
3059
- var _defaults10 = {
3087
+ var _defaults9 = {
3060
3088
  classes: "",
3061
- dropdownOptions: {}
3089
+ menuOptions: {}
3062
3090
  };
3063
3091
  var FormSelect = class _FormSelect extends Component {
3064
3092
  constructor(el, options) {
@@ -3084,7 +3112,7 @@ var FormSelect = class _FormSelect extends Component {
3084
3112
  if (li?.id) this.input.setAttribute("aria-activedescendant", li.id);
3085
3113
  };
3086
3114
  this._handleInputClick = () => {
3087
- if (this.dropdown && this.dropdown.isOpen) {
3115
+ if (this.menu && this.menu.isOpen) {
3088
3116
  this._setValueToInput();
3089
3117
  this._setSelectedStates();
3090
3118
  }
@@ -3101,11 +3129,11 @@ var FormSelect = class _FormSelect extends Component {
3101
3129
  this._values = [];
3102
3130
  this._createdWrapper = false;
3103
3131
  this._originalLabelFor = null;
3104
- this._setupDropdown();
3132
+ this._setupMenu();
3105
3133
  this._setupEventHandlers();
3106
3134
  }
3107
3135
  static get defaults() {
3108
- return _defaults10;
3136
+ return _defaults9;
3109
3137
  }
3110
3138
  /**
3111
3139
  * Initializes instances of FormSelect.
@@ -3120,21 +3148,21 @@ var FormSelect = class _FormSelect extends Component {
3120
3148
  }
3121
3149
  destroy() {
3122
3150
  this._removeEventHandlers();
3123
- this.dropdown?.destroy();
3124
- this._removeDropdown();
3151
+ this.menu?.destroy();
3152
+ this._removeMenu();
3125
3153
  this.el.tabIndex = this.nativeTabIndex;
3126
3154
  this.el["Expressive_FormSelect"] = void 0;
3127
3155
  }
3128
3156
  /**
3129
- * Re-read the native `<select>` and update the generated dropdown to match.
3157
+ * Re-read the native `<select>` and update the generated menu to match.
3130
3158
  *
3131
3159
  * Assigning `select.value` from script fires no `change` event, so nothing
3132
3160
  * else syncs the visible input text or the `.selected` state on the virtual
3133
3161
  * 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.
3162
+ * rebuilt from the native list, the field and Menu instance stay put.
3135
3163
  */
3136
3164
  refresh() {
3137
- if (!this.dropdownOptions) return;
3165
+ if (!this.menuEl) return;
3138
3166
  this._rebuildOptions();
3139
3167
  this._setValueToInput();
3140
3168
  this._setSelectedStates();
@@ -3143,22 +3171,22 @@ var FormSelect = class _FormSelect extends Component {
3143
3171
  this._setupOptionHandlers();
3144
3172
  this.el.addEventListener("change", this._handleSelectChange);
3145
3173
  this.input.addEventListener("click", this._handleInputClick);
3146
- this.dropdownOptions.addEventListener("focusin", this._handleOptionFocus);
3174
+ this.menuEl.addEventListener("focusin", this._handleOptionFocus);
3147
3175
  }
3148
3176
  _removeEventHandlers() {
3149
3177
  this._removeOptionHandlers();
3150
3178
  this.el.removeEventListener("change", this._handleSelectChange);
3151
3179
  this.input?.removeEventListener("click", this._handleInputClick);
3152
- this.dropdownOptions?.removeEventListener("focusin", this._handleOptionFocus);
3180
+ this.menuEl?.removeEventListener("focusin", this._handleOptionFocus);
3153
3181
  }
3154
3182
  _setupOptionHandlers() {
3155
- this.dropdownOptions.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3183
+ this.menuEl.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3156
3184
  el.addEventListener("click", this._handleOptionClick);
3157
3185
  el.addEventListener("keydown", this._handleOptionKeydown);
3158
3186
  });
3159
3187
  }
3160
3188
  _removeOptionHandlers() {
3161
- this.dropdownOptions?.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3189
+ this.menuEl?.querySelectorAll("li:not(.optgroup)").forEach((el) => {
3162
3190
  el.removeEventListener("click", this._handleOptionClick);
3163
3191
  el.removeEventListener("keydown", this._handleOptionKeydown);
3164
3192
  });
@@ -3189,24 +3217,24 @@ var FormSelect = class _FormSelect extends Component {
3189
3217
  new Event("change", { bubbles: true, cancelable: true, composed: true })
3190
3218
  );
3191
3219
  }
3192
- if (!this.isMultiple) this.dropdown?.close();
3220
+ if (!this.isMultiple) this.menu?.close();
3193
3221
  }
3194
- _setupDropdown() {
3222
+ _setupMenu() {
3195
3223
  this.labelEl = this.el.labels?.[0] ?? null;
3196
3224
  this._setupWrapper();
3197
3225
  this._hideNativeSelect();
3198
3226
  if (this.el.disabled) this.wrapper.classList.add("disabled");
3199
- this.dropdownOptions = document.createElement("menu");
3200
- this.dropdownOptions.id = `select-options-${Utils.guid()}`;
3201
- this.dropdownOptions.setAttribute("popover", "auto");
3202
- this.dropdownOptions.setAttribute("role", "listbox");
3203
- this.dropdownOptions.ariaMultiSelectable = this.isMultiple.toString();
3204
- if (this.isMultiple) this.dropdownOptions.classList.add("multiple-select-dropdown");
3227
+ this.menuEl = document.createElement("menu");
3228
+ this.menuEl.id = `select-options-${Utils.guid()}`;
3229
+ this.menuEl.setAttribute("popover", "auto");
3230
+ this.menuEl.setAttribute("role", "listbox");
3231
+ this.menuEl.ariaMultiSelectable = this.isMultiple.toString();
3232
+ if (this.isMultiple) this.menuEl.classList.add("multiple-select-menu");
3205
3233
  this._buildOptions();
3206
- this.wrapper.append(this.dropdownOptions);
3234
+ this.wrapper.append(this.menuEl);
3207
3235
  this._buildInput();
3208
3236
  this._buildCaret();
3209
- this._initDropdown();
3237
+ this._initMenu();
3210
3238
  this._setSelectedStates();
3211
3239
  if (this.labelEl) this.input.after(this.labelEl);
3212
3240
  }
@@ -3236,10 +3264,10 @@ var FormSelect = class _FormSelect extends Component {
3236
3264
  _buildInput() {
3237
3265
  this.input = document.createElement("input");
3238
3266
  this.input.id = "select-input-" + Utils.guid();
3239
- this.input.classList.add("dropdown-trigger");
3267
+ this.input.classList.add("menu-trigger");
3240
3268
  this.input.type = "text";
3241
3269
  this.input.readOnly = true;
3242
- this.input.setAttribute("data-target", this.dropdownOptions.id);
3270
+ this.input.setAttribute("data-target", this.menuEl.id);
3243
3271
  this.input.ariaReadOnly = "true";
3244
3272
  this.input.ariaRequired = this.el.hasAttribute("required").toString();
3245
3273
  if (this.el.disabled) this.input.disabled = true;
@@ -3252,7 +3280,7 @@ var FormSelect = class _FormSelect extends Component {
3252
3280
  this.input.setAttribute("role", "combobox");
3253
3281
  this.input.setAttribute("aria-haspopup", "listbox");
3254
3282
  this.input.ariaExpanded = "false";
3255
- this.input.setAttribute("aria-controls", this.dropdownOptions.id);
3283
+ this.input.setAttribute("aria-controls", this.menuEl.id);
3256
3284
  this.input.placeholder = " ";
3257
3285
  if (this.labelEl) {
3258
3286
  this._originalLabelFor = this.labelEl.htmlFor;
@@ -3267,38 +3295,38 @@ var FormSelect = class _FormSelect extends Component {
3267
3295
  caret.setAttribute("aria-hidden", "true");
3268
3296
  this.wrapper.prepend(caret);
3269
3297
  }
3270
- _initDropdown() {
3298
+ _initMenu() {
3271
3299
  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");
3300
+ const menuOptions = { ...this.options.menuOptions };
3301
+ menuOptions.coverTrigger = false;
3302
+ const userOnOpenEnd = menuOptions.onOpenEnd;
3303
+ const userOnCloseEnd = menuOptions.onCloseEnd;
3304
+ menuOptions.onOpenEnd = () => {
3305
+ const selectedOption = this.menuEl.querySelector(".selected");
3278
3306
  if (selectedOption) {
3279
3307
  Utils.keyDown = true;
3280
- this.dropdown.focusedIndex = [...selectedOption.parentNode.children].indexOf(selectedOption);
3281
- this.dropdown._focusFocusedItem();
3308
+ this.menu.focusedIndex = [...selectedOption.parentNode.children].indexOf(selectedOption);
3309
+ this.menu._focusFocusedItem();
3282
3310
  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;
3311
+ if (this.menu.isScrollable) {
3312
+ let scrollOffset = selectedOption.getBoundingClientRect().top - this.menuEl.getBoundingClientRect().top;
3313
+ scrollOffset -= this.menuEl.clientHeight / 2;
3314
+ this.menuEl.scrollTop = scrollOffset;
3287
3315
  }
3288
3316
  if (selectedOption.id) this.input.setAttribute("aria-activedescendant", selectedOption.id);
3289
3317
  }
3290
3318
  this.input.ariaExpanded = "true";
3291
3319
  if (userOnOpenEnd && typeof userOnOpenEnd === "function")
3292
- userOnOpenEnd.call(this.dropdown, this.el);
3320
+ userOnOpenEnd.call(this.menu, this.el);
3293
3321
  };
3294
- dropdownOptions.onCloseEnd = () => {
3322
+ menuOptions.onCloseEnd = () => {
3295
3323
  this.input.ariaExpanded = "false";
3296
3324
  this.input.removeAttribute("aria-activedescendant");
3297
3325
  if (userOnCloseEnd && typeof userOnCloseEnd === "function")
3298
- userOnCloseEnd.call(this.dropdown, this.el);
3326
+ userOnCloseEnd.call(this.menu, this.el);
3299
3327
  };
3300
- dropdownOptions.closeOnClick = false;
3301
- this.dropdown = Dropdown.init(this.input, dropdownOptions);
3328
+ menuOptions.closeOnClick = false;
3329
+ this.menu = Menu.init(this.input, menuOptions);
3302
3330
  }
3303
3331
  _nativeOptions() {
3304
3332
  return Array.from(this.el.children).filter((el) => ["OPTION", "OPTGROUP"].includes(el.tagName));
@@ -3325,7 +3353,7 @@ var FormSelect = class _FormSelect extends Component {
3325
3353
  groupLabel.setAttribute("role", "presentation");
3326
3354
  groupLabel.textContent = realOption.getAttribute("label") ?? "";
3327
3355
  groupParent.replaceChildren(groupLabel);
3328
- this.dropdownOptions.append(groupParent);
3356
+ this.menuEl.append(groupParent);
3329
3357
  const groupChildren = [];
3330
3358
  const selectOptions = Array.from(realOption.children).filter((el) => el.tagName === "OPTION");
3331
3359
  selectOptions.forEach((child) => {
@@ -3339,18 +3367,18 @@ var FormSelect = class _FormSelect extends Component {
3339
3367
  }
3340
3368
  _rebuildOptions() {
3341
3369
  this._removeOptionHandlers();
3342
- this.dropdownOptions.replaceChildren();
3370
+ this.menuEl.replaceChildren();
3343
3371
  this._buildOptions();
3344
3372
  this._setupOptionHandlers();
3345
- this.dropdown?._makeDropdownFocusable();
3373
+ this.menu?._makeMenuFocusable();
3346
3374
  }
3347
3375
  _addOptionToValues(realOption, virtualOption) {
3348
3376
  this._values.push({ el: realOption, optionEl: virtualOption });
3349
3377
  }
3350
- _removeDropdown() {
3378
+ _removeMenu() {
3351
3379
  this.wrapper?.querySelector(":scope > .caret")?.remove();
3352
3380
  this.input?.remove();
3353
- this.dropdownOptions?.remove();
3381
+ this.menuEl?.remove();
3354
3382
  const hide = this.el.parentElement;
3355
3383
  if (hide?.classList.contains("hide-select")) hide.replaceWith(this.el);
3356
3384
  if (this.labelEl && this._originalLabelFor !== null) {
@@ -3401,7 +3429,7 @@ var FormSelect = class _FormSelect extends Component {
3401
3429
  img.ariaHidden = "true";
3402
3430
  li.prepend(img);
3403
3431
  }
3404
- this.dropdownOptions.append(li);
3432
+ this.menuEl.append(li);
3405
3433
  return li;
3406
3434
  }
3407
3435
  _selectValue(value) {
@@ -3459,7 +3487,7 @@ var FormSelect = class _FormSelect extends Component {
3459
3487
  const cb = value.optionEl.querySelector('input[type="checkbox"]');
3460
3488
  if (cb) cb.checked = optionIsSelected;
3461
3489
  if (optionIsSelected) {
3462
- this._activateOption(this.dropdownOptions, value.optionEl);
3490
+ this._activateOption(this.menuEl, value.optionEl);
3463
3491
  } else {
3464
3492
  value.optionEl.classList.remove("selected");
3465
3493
  value.optionEl.ariaSelected = "false";
@@ -3479,7 +3507,7 @@ var FormSelect = class _FormSelect extends Component {
3479
3507
  };
3480
3508
 
3481
3509
  // src/ts/plugins/dockedDisplayPlugin.ts
3482
- var _defaults11 = {
3510
+ var _defaults10 = {
3483
3511
  margin: 5,
3484
3512
  transition: 10,
3485
3513
  duration: 250,
@@ -3528,7 +3556,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
3528
3556
  };
3529
3557
  this.el = el;
3530
3558
  this.options = {
3531
- ..._defaults11,
3559
+ ..._defaults10,
3532
3560
  ...options
3533
3561
  };
3534
3562
  this.container = document.createElement("div");
@@ -3549,7 +3577,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
3549
3577
  };
3550
3578
 
3551
3579
  // src/ts/components/datepicker.ts
3552
- var _defaults12 = {
3580
+ var _defaults11 = {
3553
3581
  // the default output format for the input field value
3554
3582
  format: "mmm dd, yyyy",
3555
3583
  // Used to create date object from current input string
@@ -3814,7 +3842,7 @@ var _Datepicker = class _Datepicker extends Component {
3814
3842
  }
3815
3843
  }
3816
3844
  static get defaults() {
3817
- return _defaults12;
3845
+ return _defaults11;
3818
3846
  }
3819
3847
  /**
3820
3848
  * Initializes instances of Datepicker.
@@ -4397,11 +4425,11 @@ var _Datepicker = class _Datepicker extends Component {
4397
4425
  const monthSelect = this.calendarEl.querySelector(".orig-select-month");
4398
4426
  FormSelect.init(yearSelect, {
4399
4427
  classes: "select-year",
4400
- dropdownOptions: { container: document.body, constrainWidth: false }
4428
+ menuOptions: { container: document.body, constrainWidth: false }
4401
4429
  });
4402
4430
  FormSelect.init(monthSelect, {
4403
4431
  classes: "select-month",
4404
- dropdownOptions: { container: document.body, constrainWidth: false }
4432
+ menuOptions: { container: document.body, constrainWidth: false }
4405
4433
  });
4406
4434
  yearSelect.addEventListener("change", this._handleYearChange);
4407
4435
  monthSelect.addEventListener("change", this._handleMonthChange);
@@ -4532,7 +4560,7 @@ _Datepicker._template = `
4532
4560
  var Datepicker = _Datepicker;
4533
4561
 
4534
4562
  // src/ts/components/lightbox.ts
4535
- var _defaults13 = {
4563
+ var _defaults12 = {
4536
4564
  inDuration: 275,
4537
4565
  outDuration: 200,
4538
4566
  onOpenStart: null,
@@ -4651,7 +4679,7 @@ var Lightbox = class _Lightbox extends Component {
4651
4679
  this._setupEventHandlers();
4652
4680
  }
4653
4681
  static get defaults() {
4654
- return _defaults13;
4682
+ return _defaults12;
4655
4683
  }
4656
4684
  /**
4657
4685
  * Initializes instances of Lightbox.
@@ -4816,7 +4844,7 @@ var Lightbox = class _Lightbox extends Component {
4816
4844
  };
4817
4845
 
4818
4846
  // src/ts/components/parallax.ts
4819
- var _defaults14 = {};
4847
+ var _defaults13 = {};
4820
4848
  var Parallax = class _Parallax extends Component {
4821
4849
  constructor(el, options) {
4822
4850
  super(el, options, _Parallax);
@@ -4830,7 +4858,7 @@ var Parallax = class _Parallax extends Component {
4830
4858
  }
4831
4859
  }
4832
4860
  static get defaults() {
4833
- return _defaults14;
4861
+ return _defaults13;
4834
4862
  }
4835
4863
  static init(els, options = {}) {
4836
4864
  return super.init(els, options, _Parallax);
@@ -4843,98 +4871,9 @@ var Parallax = class _Parallax extends Component {
4843
4871
  }
4844
4872
  };
4845
4873
 
4846
- // src/ts/components/pushpin.ts
4847
- var _defaults15 = {
4848
- top: 0,
4849
- bottom: Infinity,
4850
- offset: 0,
4851
- onPositionChange: null
4852
- };
4853
- var _Pushpin = class _Pushpin extends Component {
4854
- constructor(el, options) {
4855
- super(el, options, _Pushpin);
4856
- this.el["Expressive_Pushpin"] = this;
4857
- this.options = {
4858
- ..._Pushpin.defaults,
4859
- ...options
4860
- };
4861
- this.originalOffset = this.el.offsetTop;
4862
- _Pushpin._pushpins.push(this);
4863
- this._setupEventHandlers();
4864
- this._updatePosition();
4865
- }
4866
- static get defaults() {
4867
- return _defaults15;
4868
- }
4869
- /**
4870
- * Initializes instances of Pushpin.
4871
- * @param els HTML elements.
4872
- * @param options Component options.
4873
- */
4874
- static init(els, options = {}) {
4875
- return super.init(els, options, _Pushpin);
4876
- }
4877
- static getInstance(el) {
4878
- return el["Expressive_Pushpin"];
4879
- }
4880
- destroy() {
4881
- this.el.style.top = null;
4882
- this._removePinClasses();
4883
- const index = _Pushpin._pushpins.indexOf(this);
4884
- _Pushpin._pushpins.splice(index, 1);
4885
- if (_Pushpin._pushpins.length === 0) {
4886
- this._removeEventHandlers();
4887
- }
4888
- this.el["Expressive_Pushpin"] = void 0;
4889
- }
4890
- static _updateElements() {
4891
- for (let i = 0; i < _Pushpin._pushpins.length; i++) {
4892
- _Pushpin._pushpins[i]._updatePosition();
4893
- }
4894
- }
4895
- _setupEventHandlers() {
4896
- document.addEventListener("scroll", _Pushpin._updateElements, { passive: true });
4897
- }
4898
- _removeEventHandlers() {
4899
- document.removeEventListener("scroll", _Pushpin._updateElements);
4900
- }
4901
- _updatePosition() {
4902
- const scrolled = Utils.getDocumentScrollTop() + this.options.offset;
4903
- if (this.options.top <= scrolled && this.options.bottom >= scrolled && !this.el.classList.contains("pinned")) {
4904
- this._removePinClasses();
4905
- this.el.style.top = `${this.options.offset}px`;
4906
- this.el.classList.add("pinned");
4907
- if (typeof this.options.onPositionChange === "function") {
4908
- this.options.onPositionChange.call(this, "pinned");
4909
- }
4910
- }
4911
- if (scrolled < this.options.top && !this.el.classList.contains("pin-top")) {
4912
- this._removePinClasses();
4913
- this.el.style.top = "0";
4914
- this.el.classList.add("pin-top");
4915
- if (typeof this.options.onPositionChange === "function") {
4916
- this.options.onPositionChange.call(this, "pin-top");
4917
- }
4918
- }
4919
- if (scrolled > this.options.bottom && !this.el.classList.contains("pin-bottom")) {
4920
- this._removePinClasses();
4921
- this.el.classList.add("pin-bottom");
4922
- this.el.style.top = `${this.options.bottom - this.originalOffset}px`;
4923
- if (typeof this.options.onPositionChange === "function") {
4924
- this.options.onPositionChange.call(this, "pin-bottom");
4925
- }
4926
- }
4927
- }
4928
- _removePinClasses() {
4929
- this.el.classList.remove("pin-top", "pinned", "pin-bottom");
4930
- }
4931
- };
4932
- _Pushpin._pushpins = [];
4933
- var Pushpin = _Pushpin;
4934
-
4935
4874
  // src/ts/components/scrollspy.ts
4936
4875
  var _defaultGetActiveElement = (id) => `a[href="#${id}"]`;
4937
- var _defaults16 = {
4876
+ var _defaults14 = {
4938
4877
  scrollOffset: 200,
4939
4878
  activeClass: "active",
4940
4879
  getActiveElement: _defaultGetActiveElement,
@@ -4957,7 +4896,7 @@ var _ScrollSpy = class _ScrollSpy extends Component {
4957
4896
  _ScrollSpy._observer?.observe(this.el);
4958
4897
  }
4959
4898
  static get defaults() {
4960
- return _defaults16;
4899
+ return _defaults14;
4961
4900
  }
4962
4901
  static init(els, options = {}) {
4963
4902
  return super.init(els, options, _ScrollSpy);
@@ -5079,7 +5018,7 @@ _ScrollSpy._onIntersect = (entries) => {
5079
5018
  var ScrollSpy = _ScrollSpy;
5080
5019
 
5081
5020
  // src/ts/components/sidenav.ts
5082
- var _defaults17 = {
5021
+ var _defaults15 = {
5083
5022
  edge: "left",
5084
5023
  draggable: true,
5085
5024
  dragTargetWidth: "10px",
@@ -5222,7 +5161,7 @@ var _Sidenav = class _Sidenav extends Component {
5222
5161
  _Sidenav._sidenavs.push(this);
5223
5162
  }
5224
5163
  static get defaults() {
5225
- return _defaults17;
5164
+ return _defaults15;
5226
5165
  }
5227
5166
  /**
5228
5167
  * Initializes instances of Sidenav.
@@ -5407,8 +5346,114 @@ var _Sidenav = class _Sidenav extends Component {
5407
5346
  _Sidenav._sidenavs = [];
5408
5347
  var Sidenav = _Sidenav;
5409
5348
 
5349
+ // src/ts/components/navigationRail.ts
5350
+ var _defaults16 = {
5351
+ onOpenStart: null,
5352
+ onOpenEnd: null,
5353
+ onCloseStart: null,
5354
+ onCloseEnd: null
5355
+ };
5356
+ var COMPACT = "(width < 601px)";
5357
+ var NavigationRail = class _NavigationRail extends Component {
5358
+ constructor(el, options) {
5359
+ super(el, options, _NavigationRail);
5360
+ /**
5361
+ * Expands the rail. On compact windows the overlay (scrim) is CSS.
5362
+ */
5363
+ this.expand = () => {
5364
+ if (this.isExpanded) return;
5365
+ if (typeof this.options.onOpenStart === "function") {
5366
+ this.options.onOpenStart.call(this, this.el);
5367
+ }
5368
+ this.isExpanded = true;
5369
+ this.el.classList.add("expanded");
5370
+ this._sync();
5371
+ if (typeof this.options.onOpenEnd === "function") {
5372
+ this.options.onOpenEnd.call(this, this.el);
5373
+ }
5374
+ };
5375
+ /**
5376
+ * Collapses the rail.
5377
+ */
5378
+ this.collapse = () => {
5379
+ if (!this.isExpanded) return;
5380
+ if (typeof this.options.onCloseStart === "function") {
5381
+ this.options.onCloseStart.call(this, this.el);
5382
+ }
5383
+ this.isExpanded = false;
5384
+ this.el.classList.remove("expanded");
5385
+ this._sync();
5386
+ if (typeof this.options.onCloseEnd === "function") {
5387
+ this.options.onCloseEnd.call(this, this.el);
5388
+ }
5389
+ };
5390
+ /**
5391
+ * Toggles expanded / collapsed.
5392
+ */
5393
+ this.toggle = () => {
5394
+ if (this.isExpanded) this.collapse();
5395
+ else this.expand();
5396
+ };
5397
+ this._onClick = (e) => {
5398
+ const target = e.target;
5399
+ if (!(target instanceof Node)) return;
5400
+ if (this._toggle && (target === this._toggle || this._toggle.contains(target))) {
5401
+ this.toggle();
5402
+ e.preventDefault();
5403
+ return;
5404
+ }
5405
+ if (target === this.el && this.isExpanded && this._isModal()) {
5406
+ this.collapse();
5407
+ }
5408
+ };
5409
+ this._onKeyDown = (e) => {
5410
+ if (e.key !== "Escape") return;
5411
+ if (this.isExpanded && this._isModal()) this.collapse();
5412
+ };
5413
+ this.el["Expressive_NavigationRail"] = this;
5414
+ this.options = {
5415
+ ..._NavigationRail.defaults,
5416
+ ...options
5417
+ };
5418
+ this._toggle = this._findToggle();
5419
+ this._mql = window.matchMedia(COMPACT);
5420
+ this.isExpanded = this.el.classList.contains("expanded");
5421
+ this._sync();
5422
+ this.el.addEventListener("click", this._onClick);
5423
+ document.addEventListener("keydown", this._onKeyDown);
5424
+ }
5425
+ static get defaults() {
5426
+ return _defaults16;
5427
+ }
5428
+ static init(els, options = {}) {
5429
+ return super.init(els, options, _NavigationRail);
5430
+ }
5431
+ static getInstance(el) {
5432
+ return el["Expressive_NavigationRail"];
5433
+ }
5434
+ destroy() {
5435
+ this.el.removeEventListener("click", this._onClick);
5436
+ document.removeEventListener("keydown", this._onKeyDown);
5437
+ this.el["Expressive_NavigationRail"] = void 0;
5438
+ }
5439
+ _findToggle() {
5440
+ const first = this.el.querySelector(":scope > button:not(.button)");
5441
+ return first instanceof HTMLButtonElement ? first : null;
5442
+ }
5443
+ _isCompact() {
5444
+ return this._mql.matches;
5445
+ }
5446
+ _isModal() {
5447
+ return this.el.classList.contains("modal") || this._isCompact();
5448
+ }
5449
+ _sync() {
5450
+ this.el.setAttribute("aria-expanded", this.isExpanded ? "true" : "false");
5451
+ this._toggle?.setAttribute("aria-expanded", this.isExpanded ? "true" : "false");
5452
+ }
5453
+ };
5454
+
5410
5455
  // src/ts/components/slider.ts
5411
- var _defaults18 = {
5456
+ var _defaults17 = {
5412
5457
  indicators: true,
5413
5458
  height: 400,
5414
5459
  duration: 500,
@@ -5556,7 +5601,7 @@ var Slider = class _Slider extends Component {
5556
5601
  this.start();
5557
5602
  }
5558
5603
  static get defaults() {
5559
- return _defaults18;
5604
+ return _defaults17;
5560
5605
  }
5561
5606
  /**
5562
5607
  * Initializes instances of Slider.
@@ -5709,7 +5754,7 @@ var Slider = class _Slider extends Component {
5709
5754
  };
5710
5755
 
5711
5756
  // src/ts/components/tabs.ts
5712
- var _defaults19 = {
5757
+ var _defaults18 = {
5713
5758
  duration: 300,
5714
5759
  onShow: null,
5715
5760
  swipeable: false,
@@ -5787,7 +5832,7 @@ var Tabs = class _Tabs extends Component {
5787
5832
  this._setupEventHandlers();
5788
5833
  }
5789
5834
  static get defaults() {
5790
- return _defaults19;
5835
+ return _defaults18;
5791
5836
  }
5792
5837
  /**
5793
5838
  * Initializes instances of Tabs.
@@ -5954,229 +5999,8 @@ var Tabs = class _Tabs extends Component {
5954
5999
  }
5955
6000
  };
5956
6001
 
5957
- // src/ts/components/tapTarget.ts
5958
- var _defaults20 = {
5959
- onOpen: null,
5960
- onClose: null
5961
- };
5962
- var _TapTarget = class _TapTarget extends Component {
5963
- constructor(el, options) {
5964
- super(el, options, _TapTarget);
5965
- this.wrapper = null;
5966
- this.waveEl = null;
5967
- this.contentEl = null;
5968
- this._createdWrapper = false;
5969
- this._createdWave = false;
5970
- this._usePopover = false;
5971
- this._liftedStatic = false;
5972
- this._opening = false;
5973
- /**
5974
- * Open Tap Target.
5975
- */
5976
- this.open = () => {
5977
- if (this.isOpen || !this.originEl || !this.wrapper) return;
5978
- _TapTarget._taptargets.forEach((other) => {
5979
- if (other !== this) other.close();
5980
- });
5981
- this._calculatePositioning();
5982
- if (typeof this.options.onOpen === "function") {
5983
- this.options.onOpen.call(this, this.originEl);
5984
- }
5985
- this.isOpen = true;
5986
- this.wrapper.classList.add("open");
5987
- this.originEl.setAttribute("aria-expanded", "true");
5988
- if (!this._usePopover) {
5989
- this.originEl.classList.add("tap-target-origin");
5990
- if (getComputedStyle(this.originEl).position === "static") {
5991
- this.originEl.style.position = "relative";
5992
- this._liftedStatic = true;
5993
- }
5994
- }
5995
- if (this._usePopover) {
5996
- this._opening = true;
5997
- try {
5998
- this.wrapper.showPopover();
5999
- } catch {
6000
- }
6001
- requestAnimationFrame(() => {
6002
- this._opening = false;
6003
- });
6004
- }
6005
- };
6006
- /**
6007
- * Close Tap Target.
6008
- */
6009
- this.close = () => {
6010
- if (!this.isOpen) return;
6011
- if (typeof this.options.onClose === "function" && this.originEl) {
6012
- this.options.onClose.call(this, this.originEl);
6013
- }
6014
- this.isOpen = false;
6015
- this.wrapper?.classList.remove("open");
6016
- this.originEl?.setAttribute("aria-expanded", "false");
6017
- this.originEl?.classList.remove("tap-target-origin");
6018
- if (this._liftedStatic && this.originEl) {
6019
- this.originEl.style.position = "";
6020
- this._liftedStatic = false;
6021
- }
6022
- if (this._usePopover && this.wrapper) {
6023
- try {
6024
- this.wrapper.hidePopover();
6025
- } catch {
6026
- }
6027
- }
6028
- };
6029
- // Built once per instance; a fresh throttle per event never fires.
6030
- this._handleThrottledResize = Utils.throttle(() => this._handleResize(), 200);
6031
- this._handleOriginKeydown = (e) => {
6032
- if (Utils.keys.ENTER.includes(e.key) || e.key === " ") {
6033
- e.preventDefault();
6034
- this._handleTargetToggle();
6035
- }
6036
- };
6037
- this._handleTargetToggle = () => {
6038
- if (!this.isOpen) this.open();
6039
- else this.close();
6040
- };
6041
- this._handleResize = () => {
6042
- if (this.isOpen) this._calculatePositioning();
6043
- };
6044
- this._handlePopoverToggle = (e) => {
6045
- const state = "newState" in e ? String(e.newState) : "";
6046
- if (state === "open") return;
6047
- if (this._opening) {
6048
- try {
6049
- this.wrapper?.showPopover();
6050
- } catch {
6051
- }
6052
- return;
6053
- }
6054
- if (this.isOpen) this.close();
6055
- };
6056
- this.el["Expressive_TapTarget"] = this;
6057
- this.options = {
6058
- ..._TapTarget.defaults,
6059
- ...options
6060
- };
6061
- this.isOpen = false;
6062
- this.originEl = el.dataset.target ? document.getElementById(el.dataset.target) : null;
6063
- if (!this.originEl) {
6064
- console.error(`TapTarget: no element with id "${el.dataset.target ?? ""}" to attach to`);
6065
- return;
6066
- }
6067
- this._setup();
6068
- this._calculatePositioning();
6069
- this._setupEventHandlers();
6070
- _TapTarget._taptargets.push(this);
6071
- }
6072
- static get defaults() {
6073
- return _defaults20;
6074
- }
6075
- static init(els, options = {}) {
6076
- return super.init(els, options, _TapTarget);
6077
- }
6078
- static getInstance(el) {
6079
- return el["Expressive_TapTarget"];
6080
- }
6081
- destroy() {
6082
- this.close();
6083
- this._removeEventHandlers();
6084
- this._teardownDom();
6085
- this.el["Expressive_TapTarget"] = void 0;
6086
- const index = _TapTarget._taptargets.indexOf(this);
6087
- if (index >= 0) _TapTarget._taptargets.splice(index, 1);
6088
- }
6089
- _setup() {
6090
- const parent = this.el.parentElement;
6091
- if (parent?.classList.contains("tap-target-wrapper")) {
6092
- this.wrapper = parent;
6093
- } else {
6094
- this.wrapper = document.createElement("div");
6095
- this.wrapper.classList.add("tap-target-wrapper");
6096
- this.el.before(this.wrapper);
6097
- this.wrapper.append(this.el);
6098
- this._createdWrapper = true;
6099
- }
6100
- this.contentEl = this.el.querySelector(".tap-target-content");
6101
- if (!this.contentEl) {
6102
- this.contentEl = document.createElement("div");
6103
- this.contentEl.className = "tap-target-content";
6104
- while (this.el.firstChild) this.contentEl.append(this.el.firstChild);
6105
- this.el.append(this.contentEl);
6106
- }
6107
- this.waveEl = this.el.querySelector(".tap-target-wave") ?? this.wrapper.querySelector(".tap-target-wave");
6108
- if (!this.waveEl) {
6109
- this.waveEl = document.createElement("div");
6110
- this.waveEl.className = "tap-target-wave";
6111
- this._createdWave = true;
6112
- }
6113
- this.el.prepend(this.waveEl);
6114
- this.el.setAttribute("role", "dialog");
6115
- this._labelFromHeading();
6116
- const origin = this.originEl;
6117
- origin.setAttribute("aria-expanded", "false");
6118
- origin.setAttribute("aria-controls", this.el.id || this._ensureId());
6119
- this._usePopover = typeof this.wrapper.showPopover === "function";
6120
- if (this._usePopover) {
6121
- this.wrapper.setAttribute("popover", "auto");
6122
- }
6123
- }
6124
- _ensureId() {
6125
- if (!this.el.id) this.el.id = `tap-target-${Utils.guid()}`;
6126
- return this.el.id;
6127
- }
6128
- _labelFromHeading() {
6129
- const heading = this.contentEl?.querySelector("h1, h2, h3, h4, h5, h6");
6130
- if (!heading) return;
6131
- if (!heading.id) heading.id = `tap-target-title-${Utils.guid()}`;
6132
- this.el.setAttribute("aria-labelledby", heading.id);
6133
- }
6134
- _teardownDom() {
6135
- if (this._createdWave) this.waveEl?.remove();
6136
- if (this._createdWrapper && this.wrapper) {
6137
- this.wrapper.before(this.el);
6138
- this.wrapper.remove();
6139
- }
6140
- this.wrapper = null;
6141
- this.waveEl = null;
6142
- }
6143
- _setupEventHandlers() {
6144
- if (!this.originEl) return;
6145
- this.originEl.addEventListener("click", this._handleTargetToggle);
6146
- if (!this.originEl.matches('button, a, [tabindex], [role="button"]')) {
6147
- this.originEl.tabIndex = 0;
6148
- this.originEl.addEventListener("keydown", this._handleOriginKeydown);
6149
- }
6150
- this.wrapper?.addEventListener("toggle", this._handlePopoverToggle);
6151
- window.addEventListener("resize", this._handleThrottledResize, { passive: true });
6152
- }
6153
- _removeEventHandlers() {
6154
- if (!this.originEl) return;
6155
- this.originEl.removeEventListener("click", this._handleTargetToggle);
6156
- this.originEl.removeEventListener("keydown", this._handleOriginKeydown);
6157
- this.wrapper?.removeEventListener("toggle", this._handlePopoverToggle);
6158
- window.removeEventListener("resize", this._handleThrottledResize);
6159
- }
6160
- _calculatePositioning() {
6161
- if (!this.originEl || !this.wrapper) return;
6162
- const rect = this.originEl.getBoundingClientRect();
6163
- const x = rect.left + rect.width / 2;
6164
- const y = rect.top + rect.height / 2;
6165
- const size = Math.max(rect.width, rect.height, 1);
6166
- this.wrapper.style.setProperty("--md-comp-tap-target-x", `${x}px`);
6167
- this.wrapper.style.setProperty("--md-comp-tap-target-y", `${y}px`);
6168
- this.wrapper.style.setProperty("--md-comp-tap-target-origin-size", `${size}px`);
6169
- const vertical = y <= window.innerHeight / 2 ? "top" : "bottom";
6170
- const onCenter = x >= window.innerWidth * 0.25 && x <= window.innerWidth * 0.75;
6171
- const horizontal = onCenter ? "center" : x <= window.innerWidth / 2 ? "left" : "right";
6172
- this.wrapper.dataset.edge = `${vertical}-${horizontal}`;
6173
- }
6174
- };
6175
- _TapTarget._taptargets = [];
6176
- var TapTarget = _TapTarget;
6177
-
6178
6002
  // src/ts/components/timepicker.ts
6179
- var _defaults21 = {
6003
+ var _defaults19 = {
6180
6004
  dialRadius: 135,
6181
6005
  outerRadius: 105,
6182
6006
  innerRadius: 70,
@@ -6374,7 +6198,7 @@ var _Timepicker = class _Timepicker extends Component {
6374
6198
  }
6375
6199
  }
6376
6200
  static get defaults() {
6377
- return _defaults21;
6201
+ return _defaults19;
6378
6202
  }
6379
6203
  /**
6380
6204
  * Initializes instances of Timepicker.
@@ -6743,8 +6567,8 @@ _Timepicker._template = `<div class="timepicker-container">
6743
6567
  </div>`;
6744
6568
  var Timepicker = _Timepicker;
6745
6569
 
6746
- // src/ts/components/toasts.ts
6747
- var _defaults22 = {
6570
+ // src/ts/components/snackbar.ts
6571
+ var _defaults20 = {
6748
6572
  text: "",
6749
6573
  action: "",
6750
6574
  onAction: null,
@@ -6756,97 +6580,109 @@ var _defaults22 = {
6756
6580
  completeCallback: null,
6757
6581
  activationPercent: 0.8
6758
6582
  };
6759
- var _Toast = class _Toast {
6760
- constructor(options) {
6583
+ var _Snackbar = class _Snackbar {
6584
+ constructor(options = {}) {
6585
+ this._dismissed = false;
6761
6586
  this.options = {
6762
- ..._Toast.defaults,
6587
+ ..._Snackbar.defaults,
6763
6588
  ...options
6764
6589
  };
6590
+ if (options.displayLength === void 0 && this.options.action) {
6591
+ this.options.displayLength = 1e4;
6592
+ }
6765
6593
  this.message = this.options.text;
6766
6594
  this.panning = false;
6767
6595
  this.timeRemaining = this.options.displayLength;
6768
- if (_Toast._toasts.length === 0) {
6769
- _Toast._createContainer();
6596
+ if (_Snackbar._snackbars.length > 0) {
6597
+ for (const snackbar of [..._Snackbar._snackbars]) {
6598
+ snackbar._dismissed = true;
6599
+ clearTimeout(snackbar.counterTimeout);
6600
+ snackbar.el.remove();
6601
+ }
6602
+ _Snackbar._snackbars.length = 0;
6770
6603
  }
6771
- _Toast._toasts.push(this);
6772
- const toastElement = this._createToast();
6773
- toastElement["Expressive_Toast"] = this;
6774
- this.el = toastElement;
6604
+ if (!_Snackbar._container || !_Snackbar._container.isConnected) {
6605
+ _Snackbar._createContainer();
6606
+ }
6607
+ _Snackbar._snackbars.push(this);
6608
+ const snackbarElement = this._createSnackbar();
6609
+ snackbarElement["Expressive_Snackbar"] = this;
6610
+ this.el = snackbarElement;
6775
6611
  this._animateIn();
6776
6612
  this._setTimer();
6777
6613
  }
6778
6614
  static get defaults() {
6779
- return _defaults22;
6615
+ return _defaults20;
6780
6616
  }
6781
6617
  static getInstance(el) {
6782
- return el["Expressive_Toast"];
6618
+ return el["Expressive_Snackbar"];
6783
6619
  }
6784
6620
  static _createContainer() {
6785
6621
  const container = document.createElement("div");
6786
- container.setAttribute("id", "toast-container");
6787
- container.addEventListener("touchstart", _Toast._onDragStart);
6788
- container.addEventListener("touchmove", _Toast._onDragMove);
6789
- container.addEventListener("touchend", _Toast._onDragEnd);
6790
- container.addEventListener("mousedown", _Toast._onDragStart);
6791
- document.addEventListener("mousemove", _Toast._onDragMove);
6792
- document.addEventListener("mouseup", _Toast._onDragEnd);
6622
+ container.setAttribute("id", "snackbar-container");
6623
+ container.addEventListener("touchstart", _Snackbar._onDragStart);
6624
+ container.addEventListener("touchmove", _Snackbar._onDragMove);
6625
+ container.addEventListener("touchend", _Snackbar._onDragEnd);
6626
+ container.addEventListener("mousedown", _Snackbar._onDragStart);
6627
+ document.addEventListener("mousemove", _Snackbar._onDragMove);
6628
+ document.addEventListener("mouseup", _Snackbar._onDragEnd);
6793
6629
  document.body.appendChild(container);
6794
- _Toast._container = container;
6630
+ _Snackbar._container = container;
6795
6631
  }
6796
6632
  static _removeContainer() {
6797
- document.removeEventListener("mousemove", _Toast._onDragMove);
6798
- document.removeEventListener("mouseup", _Toast._onDragEnd);
6799
- _Toast._container.remove();
6800
- _Toast._container = null;
6633
+ document.removeEventListener("mousemove", _Snackbar._onDragMove);
6634
+ document.removeEventListener("mouseup", _Snackbar._onDragEnd);
6635
+ _Snackbar._container.remove();
6636
+ _Snackbar._container = null;
6801
6637
  }
6802
6638
  static _onDragStart(e) {
6803
6639
  const target = e.target;
6804
6640
  if (target && !target.closest("button, a") && target.closest(".snackbar")) {
6805
- const toastElem = target.closest(".snackbar");
6806
- const toast = toastElem["Expressive_Toast"];
6807
- if (!toast) return;
6808
- toast.panning = true;
6809
- toast._pauseTimer();
6810
- _Toast._draggedToast = toast;
6811
- toast.el.classList.add("panning");
6812
- toast.el.style.transition = "";
6813
- toast.startingXPos = _Toast._xPos(e);
6814
- toast.time = Date.now();
6815
- toast.xPos = _Toast._xPos(e);
6641
+ const snackbarElem = target.closest(".snackbar");
6642
+ const snackbar = snackbarElem["Expressive_Snackbar"];
6643
+ if (!snackbar) return;
6644
+ snackbar.panning = true;
6645
+ snackbar._pauseTimer();
6646
+ _Snackbar._draggedSnackbar = snackbar;
6647
+ snackbar.el.classList.add("panning");
6648
+ snackbar.el.style.transition = "";
6649
+ snackbar.startingXPos = _Snackbar._xPos(e);
6650
+ snackbar.time = Date.now();
6651
+ snackbar.xPos = _Snackbar._xPos(e);
6816
6652
  }
6817
6653
  }
6818
6654
  static _onDragMove(e) {
6819
- if (!!_Toast._draggedToast) {
6655
+ if (!!_Snackbar._draggedSnackbar) {
6820
6656
  e.preventDefault();
6821
- const toast = _Toast._draggedToast;
6822
- toast.deltaX = Math.abs(toast.xPos - _Toast._xPos(e));
6823
- toast.xPos = _Toast._xPos(e);
6824
- toast.velocityX = toast.deltaX / (Date.now() - toast.time);
6825
- toast.time = Date.now();
6826
- const totalDeltaX = toast.xPos - toast.startingXPos;
6827
- const activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
6828
- toast.el.style.transform = `translateX(${totalDeltaX}px)`;
6829
- toast.el.style.opacity = (1 - Math.abs(totalDeltaX / activationDistance)).toString();
6657
+ const snackbar = _Snackbar._draggedSnackbar;
6658
+ snackbar.deltaX = Math.abs(snackbar.xPos - _Snackbar._xPos(e));
6659
+ snackbar.xPos = _Snackbar._xPos(e);
6660
+ snackbar.velocityX = snackbar.deltaX / (Date.now() - snackbar.time);
6661
+ snackbar.time = Date.now();
6662
+ const totalDeltaX = snackbar.xPos - snackbar.startingXPos;
6663
+ const activationDistance = snackbar.el.offsetWidth * snackbar.options.activationPercent;
6664
+ snackbar.el.style.transform = `translateX(${totalDeltaX}px)`;
6665
+ snackbar.el.style.opacity = (1 - Math.abs(totalDeltaX / activationDistance)).toString();
6830
6666
  }
6831
6667
  }
6832
6668
  static _onDragEnd() {
6833
- if (!!_Toast._draggedToast) {
6834
- const toast = _Toast._draggedToast;
6835
- toast.panning = false;
6836
- toast.el.classList.remove("panning");
6837
- const totalDeltaX = toast.xPos - toast.startingXPos;
6838
- const activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
6839
- const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
6669
+ if (!!_Snackbar._draggedSnackbar) {
6670
+ const snackbar = _Snackbar._draggedSnackbar;
6671
+ snackbar.panning = false;
6672
+ snackbar.el.classList.remove("panning");
6673
+ const totalDeltaX = snackbar.xPos - snackbar.startingXPos;
6674
+ const activationDistance = snackbar.el.offsetWidth * snackbar.options.activationPercent;
6675
+ const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || snackbar.velocityX > 1;
6840
6676
  if (shouldBeDismissed) {
6841
- toast.wasSwiped = true;
6842
- toast.dismiss();
6677
+ snackbar.wasSwiped = true;
6678
+ snackbar.dismiss();
6843
6679
  } else {
6844
- toast.el.style.transition = "transform .2s, opacity .2s";
6845
- toast.el.style.transform = "";
6846
- toast.el.style.opacity = "";
6847
- toast._resumeTimer();
6680
+ snackbar.el.style.transition = "transform .2s, opacity .2s";
6681
+ snackbar.el.style.transform = "";
6682
+ snackbar.el.style.opacity = "";
6683
+ snackbar._resumeTimer();
6848
6684
  }
6849
- _Toast._draggedToast = null;
6685
+ _Snackbar._draggedSnackbar = null;
6850
6686
  }
6851
6687
  }
6852
6688
  static _xPos(e) {
@@ -6856,30 +6692,30 @@ var _Toast = class _Toast {
6856
6692
  return e.clientX;
6857
6693
  }
6858
6694
  /**
6859
- * dismiss all toasts.
6695
+ * dismiss all snackbars.
6860
6696
  */
6861
6697
  static dismissAll() {
6862
- for (const toast of [..._Toast._toasts]) {
6863
- toast.dismiss();
6698
+ for (const snackbar of [..._Snackbar._snackbars]) {
6699
+ snackbar.dismiss();
6864
6700
  }
6865
6701
  }
6866
- _createToast() {
6867
- let toast = this.options.toastId ? document.getElementById(this.options.toastId) : document.createElement("div");
6868
- if (toast instanceof HTMLTemplateElement) {
6869
- const node = toast.content.cloneNode(true);
6870
- toast = node.firstElementChild;
6702
+ _createSnackbar() {
6703
+ let snackbar = this.options.snackbarId ? document.getElementById(this.options.snackbarId) : document.createElement("div");
6704
+ if (snackbar instanceof HTMLTemplateElement) {
6705
+ const node = snackbar.content.cloneNode(true);
6706
+ snackbar = node.firstElementChild;
6871
6707
  }
6872
- toast.classList.add("snackbar");
6873
- toast.setAttribute("role", "status");
6874
- toast.setAttribute("aria-live", "polite");
6875
- toast.setAttribute("aria-atomic", "true");
6708
+ snackbar.classList.add("snackbar");
6709
+ snackbar.setAttribute("role", "status");
6710
+ snackbar.setAttribute("aria-live", "polite");
6711
+ snackbar.setAttribute("aria-atomic", "true");
6876
6712
  if (this.options.classes.length > 0) {
6877
- toast.classList.add(...this.options.classes.split(" ").filter(Boolean));
6713
+ snackbar.classList.add(...this.options.classes.split(" ").filter(Boolean));
6878
6714
  }
6879
6715
  if (this.message) {
6880
6716
  const text = document.createElement("p");
6881
6717
  text.textContent = this.message;
6882
- toast.replaceChildren(text);
6718
+ snackbar.replaceChildren(text);
6883
6719
  }
6884
6720
  if (this.options.action) {
6885
6721
  const action = document.createElement("button");
@@ -6892,7 +6728,7 @@ var _Toast = class _Toast {
6892
6728
  }
6893
6729
  this.dismiss();
6894
6730
  });
6895
- toast.appendChild(action);
6731
+ snackbar.appendChild(action);
6896
6732
  }
6897
6733
  if (this.options.dismissible) {
6898
6734
  const close = document.createElement("button");
@@ -6908,20 +6744,21 @@ var _Toast = class _Toast {
6908
6744
  e.stopPropagation();
6909
6745
  this.dismiss();
6910
6746
  });
6911
- toast.appendChild(close);
6747
+ snackbar.appendChild(close);
6912
6748
  }
6913
- _Toast._container.appendChild(toast);
6914
- return toast;
6749
+ _Snackbar._container.appendChild(snackbar);
6750
+ return snackbar;
6915
6751
  }
6916
6752
  _animateIn() {
6917
6753
  this.el.style.display = "";
6918
6754
  this.el.style.opacity = "0";
6755
+ this.el.style.transform = "translateY(24px)";
6919
6756
  this.el.style.transition = `
6920
- top ${this.options.inDuration}ms ease,
6757
+ transform ${this.options.inDuration}ms ease,
6921
6758
  opacity ${this.options.inDuration}ms ease
6922
6759
  `;
6923
6760
  setTimeout(() => {
6924
- this.el.style.top = "0";
6761
+ this.el.style.transform = "";
6925
6762
  this.el.style.opacity = "1";
6926
6763
  }, 1);
6927
6764
  }
@@ -6929,7 +6766,7 @@ var _Toast = class _Toast {
6929
6766
  * Arm the dismissal timer.
6930
6767
  *
6931
6768
  * One timeout, not a 20ms interval ticking a counter down: the old form woke
6932
- * the page up 50 times a second per toast purely to subtract 20 from a
6769
+ * the page up 50 times a second per snackbar purely to subtract 20 from a
6933
6770
  * number. Dragging pauses the countdown via _pauseTimer/_resumeTimer instead.
6934
6771
  */
6935
6772
  _setTimer() {
@@ -6950,9 +6787,11 @@ var _Toast = class _Toast {
6950
6787
  this._setTimer();
6951
6788
  }
6952
6789
  /**
6953
- * Dismiss toast with animation.
6790
+ * Dismiss snackbar with animation.
6954
6791
  */
6955
6792
  dismiss() {
6793
+ if (this._dismissed) return;
6794
+ this._dismissed = true;
6956
6795
  clearTimeout(this.counterTimeout);
6957
6796
  this.counterTimeout = null;
6958
6797
  const activationDistance = this.el.offsetWidth * this.options.activationPercent;
@@ -6972,24 +6811,24 @@ var _Toast = class _Toast {
6972
6811
  if (typeof this.options.completeCallback === "function") {
6973
6812
  this.options.completeCallback();
6974
6813
  }
6975
- if (this.el.id != this.options.toastId) {
6814
+ if (this.el.id != this.options.snackbarId) {
6976
6815
  this.el.remove();
6977
- const index = _Toast._toasts.indexOf(this);
6978
- if (index >= 0) _Toast._toasts.splice(index, 1);
6979
- if (_Toast._toasts.length === 0 && _Toast._container) {
6980
- _Toast._removeContainer();
6816
+ const index = _Snackbar._snackbars.indexOf(this);
6817
+ if (index >= 0) _Snackbar._snackbars.splice(index, 1);
6818
+ if (_Snackbar._snackbars.length === 0 && _Snackbar._container && _Snackbar._container.childElementCount === 0) {
6819
+ _Snackbar._removeContainer();
6981
6820
  }
6982
6821
  }
6983
6822
  }, this.options.outDuration);
6984
6823
  }
6985
6824
  };
6986
- _Toast._toasts = [];
6987
- _Toast._container = null;
6988
- _Toast._draggedToast = null;
6989
- var Toast = _Toast;
6825
+ _Snackbar._snackbars = [];
6826
+ _Snackbar._container = null;
6827
+ _Snackbar._draggedSnackbar = null;
6828
+ var Snackbar = _Snackbar;
6990
6829
 
6991
6830
  // src/ts/components/tooltip.ts
6992
- var _defaults23 = {
6831
+ var _defaults21 = {
6993
6832
  exitDelay: 200,
6994
6833
  enterDelay: 0,
6995
6834
  text: "",
@@ -7057,7 +6896,7 @@ var Tooltip = class _Tooltip extends Component {
7057
6896
  this._setupEventHandlers();
7058
6897
  }
7059
6898
  static get defaults() {
7060
- return _defaults23;
6899
+ return _defaults21;
7061
6900
  }
7062
6901
  /**
7063
6902
  * Initializes instances of Tooltip.
@@ -7237,17 +7076,15 @@ var AUTO_INIT_COMPONENTS = {
7237
7076
  Cards: { component: Cards, selector: CARDS_SELECTOR },
7238
7077
  Carousel: { component: Carousel, selector: ".carousel" },
7239
7078
  Chips: { component: Chips, selector: ".chips" },
7240
- Collapsible: { component: Collapsible, selector: ".collapsible" },
7241
7079
  Datepicker: { component: Datepicker, selector: ".datepicker" },
7242
- Dropdown: { component: Dropdown, selector: ".dropdown-trigger" },
7080
+ Menu: { component: Menu, selector: ".menu-trigger" },
7243
7081
  Lightbox: { component: Lightbox, selector: ".lightboxed" },
7244
7082
  Parallax: { component: Parallax, selector: ".parallax" },
7245
- Pushpin: { component: Pushpin, selector: ".pushpin" },
7246
7083
  ScrollSpy: { component: ScrollSpy, selector: ".scrollspy" },
7247
7084
  FormSelect: { component: FormSelect, selector: "select" },
7248
7085
  Sidenav: { component: Sidenav, selector: ".sidenav" },
7086
+ NavigationRail: { component: NavigationRail, selector: ".navigation-rail" },
7249
7087
  Tabs: { component: Tabs, selector: ".tabs" },
7250
- TapTarget: { component: TapTarget, selector: ".tap-target" },
7251
7088
  Timepicker: { component: Timepicker, selector: ".timepicker" },
7252
7089
  Tooltip: { component: Tooltip, selector: ".tooltipped" },
7253
7090
  FloatingActionButton: {
@@ -7264,7 +7101,7 @@ function AutoInit(context = document.body, options) {
7264
7101
  }
7265
7102
 
7266
7103
  // src/ts/index.ts
7267
- var version = "0.4.0";
7104
+ var version = "0.6.0";
7268
7105
  if (typeof document !== "undefined") {
7269
7106
  document.addEventListener("keydown", Utils.docHandleKeydown, true);
7270
7107
  document.addEventListener("keyup", Utils.docHandleKeyup, true);
@@ -7277,31 +7114,33 @@ Waves.Init();
7277
7114
  Range.Init();
7278
7115
  Cards.Init();
7279
7116
  Dialogs.Init();
7117
+ BottomSheets.Init();
7118
+ SideSheets.Init();
7280
7119
  export {
7281
7120
  AutoInit,
7282
7121
  Autocomplete,
7122
+ BottomSheets,
7283
7123
  Cards,
7284
7124
  Carousel,
7285
7125
  CharacterCounter,
7286
7126
  Chips,
7287
- Collapsible,
7288
7127
  Datepicker,
7289
7128
  Dialogs,
7290
- Dropdown,
7291
7129
  FloatingActionButton,
7292
7130
  FormSelect,
7293
7131
  Forms,
7294
7132
  Lightbox,
7133
+ Menu,
7134
+ NavigationRail,
7295
7135
  Parallax,
7296
- Pushpin,
7297
7136
  Range,
7298
7137
  ScrollSpy,
7138
+ SideSheets,
7299
7139
  Sidenav,
7300
7140
  Slider,
7141
+ Snackbar,
7301
7142
  Tabs,
7302
- TapTarget,
7303
7143
  Timepicker,
7304
- Toast,
7305
7144
  Tooltip,
7306
7145
  Waves,
7307
7146
  version