@expressivecss/expressive 0.9.0 → 0.10.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 (188) hide show
  1. package/CHANGELOG.md +174 -1
  2. package/README.md +178 -25
  3. package/dist/css/expressive.css +365 -1222
  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/fonts/material-symbols-outlined.woff2 +0 -0
  8. package/dist/fonts/material-symbols-rounded.woff2 +0 -0
  9. package/dist/fonts/material-symbols-sharp.woff2 +0 -0
  10. package/dist/js/chunks/chunk-7MM4VJJO.mjs +509 -0
  11. package/dist/js/chunks/chunk-7MM4VJJO.mjs.map +7 -0
  12. package/dist/js/chunks/chunk-7UXHSYIA.mjs +183 -0
  13. package/dist/js/chunks/chunk-7UXHSYIA.mjs.map +7 -0
  14. package/dist/js/chunks/chunk-A3BJA7V4.mjs +28 -0
  15. package/dist/js/chunks/chunk-A3BJA7V4.mjs.map +7 -0
  16. package/dist/js/chunks/chunk-AOGFNMXS.mjs +691 -0
  17. package/dist/js/chunks/chunk-AOGFNMXS.mjs.map +7 -0
  18. package/dist/js/chunks/chunk-D4UZ4HFN.mjs +560 -0
  19. package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +7 -0
  20. package/dist/js/chunks/chunk-EP3CVKB5.mjs +88 -0
  21. package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +7 -0
  22. package/dist/js/chunks/chunk-G576EP5O.mjs +459 -0
  23. package/dist/js/chunks/chunk-G576EP5O.mjs.map +7 -0
  24. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs +320 -0
  25. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +7 -0
  26. package/dist/js/chunks/chunk-JKNPQQWY.mjs +191 -0
  27. package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +7 -0
  28. package/dist/js/chunks/chunk-JNPIWFJT.mjs +365 -0
  29. package/dist/js/chunks/chunk-JNPIWFJT.mjs.map +7 -0
  30. package/dist/js/chunks/chunk-JODJAGFS.mjs +267 -0
  31. package/dist/js/chunks/chunk-JODJAGFS.mjs.map +7 -0
  32. package/dist/js/chunks/chunk-JR24UB4X.mjs +100 -0
  33. package/dist/js/chunks/chunk-JR24UB4X.mjs.map +7 -0
  34. package/dist/js/chunks/chunk-KR44BSYQ.mjs +55 -0
  35. package/dist/js/chunks/chunk-KR44BSYQ.mjs.map +7 -0
  36. package/dist/js/chunks/chunk-LZVBJ33S.mjs +102 -0
  37. package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +7 -0
  38. package/dist/js/chunks/chunk-MISGHDUU.mjs +326 -0
  39. package/dist/js/chunks/chunk-MISGHDUU.mjs.map +7 -0
  40. package/dist/js/chunks/chunk-N3UHGN3N.mjs +175 -0
  41. package/dist/js/chunks/chunk-N3UHGN3N.mjs.map +7 -0
  42. package/dist/js/chunks/chunk-PB5L3EXF.mjs +7 -0
  43. package/dist/js/chunks/chunk-PB5L3EXF.mjs.map +7 -0
  44. package/dist/js/chunks/chunk-PIIAEYAJ.mjs +85 -0
  45. package/dist/js/chunks/chunk-PIIAEYAJ.mjs.map +7 -0
  46. package/dist/js/chunks/chunk-QSQ24FYT.mjs +59 -0
  47. package/dist/js/chunks/chunk-QSQ24FYT.mjs.map +7 -0
  48. package/dist/js/chunks/chunk-QYCYP443.mjs +1111 -0
  49. package/dist/js/chunks/chunk-QYCYP443.mjs.map +7 -0
  50. package/dist/js/chunks/chunk-SLFNPY5M.mjs +78 -0
  51. package/dist/js/chunks/chunk-SLFNPY5M.mjs.map +7 -0
  52. package/dist/js/chunks/chunk-TK6PX2GC.mjs +663 -0
  53. package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +7 -0
  54. package/dist/js/chunks/chunk-TYM6U5DY.mjs +76 -0
  55. package/dist/js/chunks/chunk-TYM6U5DY.mjs.map +7 -0
  56. package/dist/js/chunks/chunk-TZZ24ZQS.mjs +154 -0
  57. package/dist/js/chunks/chunk-TZZ24ZQS.mjs.map +7 -0
  58. package/dist/js/chunks/chunk-VAS6JQ6P.mjs +94 -0
  59. package/dist/js/chunks/chunk-VAS6JQ6P.mjs.map +7 -0
  60. package/dist/js/chunks/chunk-WWPAPHMA.mjs +1 -0
  61. package/dist/js/chunks/chunk-WWPAPHMA.mjs.map +7 -0
  62. package/dist/js/chunks/chunk-XDB3G6RL.mjs +114 -0
  63. package/dist/js/chunks/chunk-XDB3G6RL.mjs.map +7 -0
  64. package/dist/js/chunks/chunk-XO5WX3TK.mjs +226 -0
  65. package/dist/js/chunks/chunk-XO5WX3TK.mjs.map +7 -0
  66. package/dist/js/chunks/chunk-YFXEJ7GR.mjs +286 -0
  67. package/dist/js/chunks/chunk-YFXEJ7GR.mjs.map +7 -0
  68. package/dist/js/chunks/chunk-ZIZVUWRL.mjs +120 -0
  69. package/dist/js/chunks/chunk-ZIZVUWRL.mjs.map +7 -0
  70. package/dist/js/chunks/chunk-ZZBZI2XN.mjs +338 -0
  71. package/dist/js/chunks/chunk-ZZBZI2XN.mjs.map +7 -0
  72. package/dist/js/expressive.cjs +801 -761
  73. package/dist/js/expressive.cjs.map +4 -4
  74. package/dist/js/expressive.js +801 -761
  75. package/dist/js/expressive.js.map +4 -4
  76. package/dist/js/expressive.min.js +11 -15
  77. package/dist/js/expressive.min.js.map +4 -4
  78. package/dist/js/expressive.mjs +83 -7443
  79. package/dist/js/expressive.mjs.map +4 -4
  80. package/dist/js/internal/behaviors/bottomSheets.mjs +9 -0
  81. package/dist/js/internal/behaviors/bottomSheets.mjs.map +7 -0
  82. package/dist/js/internal/behaviors/dialogs.mjs +8 -0
  83. package/dist/js/internal/behaviors/dialogs.mjs.map +7 -0
  84. package/dist/js/internal/behaviors/forms.mjs +8 -0
  85. package/dist/js/internal/behaviors/forms.mjs.map +7 -0
  86. package/dist/js/internal/behaviors/sheetDrag.mjs +8 -0
  87. package/dist/js/internal/behaviors/sheetDrag.mjs.map +7 -0
  88. package/dist/js/internal/behaviors/sideSheets.mjs +9 -0
  89. package/dist/js/internal/behaviors/sideSheets.mjs.map +7 -0
  90. package/dist/js/internal/components/appBar.mjs +8 -0
  91. package/dist/js/internal/components/appBar.mjs.map +7 -0
  92. package/dist/js/internal/components/autocomplete.mjs +10 -0
  93. package/dist/js/internal/components/autocomplete.mjs.map +7 -0
  94. package/dist/js/internal/components/buttonGroup.mjs +8 -0
  95. package/dist/js/internal/components/buttonGroup.mjs.map +7 -0
  96. package/dist/js/internal/components/buttons.mjs +9 -0
  97. package/dist/js/internal/components/buttons.mjs.map +7 -0
  98. package/dist/js/internal/components/cards.mjs +13 -0
  99. package/dist/js/internal/components/cards.mjs.map +7 -0
  100. package/dist/js/internal/components/carousel.mjs +9 -0
  101. package/dist/js/internal/components/carousel.mjs.map +7 -0
  102. package/dist/js/internal/components/characterCounter.mjs +8 -0
  103. package/dist/js/internal/components/characterCounter.mjs.map +7 -0
  104. package/dist/js/internal/components/chips.mjs +11 -0
  105. package/dist/js/internal/components/chips.mjs.map +7 -0
  106. package/dist/js/internal/components/datepicker.mjs +12 -0
  107. package/dist/js/internal/components/datepicker.mjs.map +7 -0
  108. package/dist/js/internal/components/expandingCard.mjs +11 -0
  109. package/dist/js/internal/components/expandingCard.mjs.map +7 -0
  110. package/dist/js/internal/components/index.mjs +88 -0
  111. package/dist/js/internal/components/index.mjs.map +7 -0
  112. package/dist/js/internal/components/lightbox.mjs +9 -0
  113. package/dist/js/internal/components/lightbox.mjs.map +7 -0
  114. package/dist/js/internal/components/menu.mjs +9 -0
  115. package/dist/js/internal/components/menu.mjs.map +7 -0
  116. package/dist/js/internal/components/navigationRail.mjs +8 -0
  117. package/dist/js/internal/components/navigationRail.mjs.map +7 -0
  118. package/dist/js/internal/components/registry.mjs +33 -0
  119. package/dist/js/internal/components/registry.mjs.map +7 -0
  120. package/dist/js/internal/components/scrollspy.mjs +8 -0
  121. package/dist/js/internal/components/scrollspy.mjs.map +7 -0
  122. package/dist/js/internal/components/select.mjs +10 -0
  123. package/dist/js/internal/components/select.mjs.map +7 -0
  124. package/dist/js/internal/components/slider.mjs +9 -0
  125. package/dist/js/internal/components/slider.mjs.map +7 -0
  126. package/dist/js/internal/components/snackbar.mjs +8 -0
  127. package/dist/js/internal/components/snackbar.mjs.map +7 -0
  128. package/dist/js/internal/components/tabs.mjs +10 -0
  129. package/dist/js/internal/components/tabs.mjs.map +7 -0
  130. package/dist/js/internal/components/timepicker.mjs +10 -0
  131. package/dist/js/internal/components/timepicker.mjs.map +7 -0
  132. package/dist/js/internal/components/tooltip.mjs +9 -0
  133. package/dist/js/internal/components/tooltip.mjs.map +7 -0
  134. package/dist/js/internal/core/component.mjs +7 -0
  135. package/dist/js/internal/core/component.mjs.map +7 -0
  136. package/dist/js/internal/core/utils.mjs +7 -0
  137. package/dist/js/internal/core/utils.mjs.map +7 -0
  138. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +8 -0
  139. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs.map +7 -0
  140. package/dist/js/modular.mjs +113 -0
  141. package/dist/js/modular.mjs.map +7 -0
  142. package/dist/types/behaviors/sheetDrag.d.ts +1 -1
  143. package/dist/types/components/appBar.d.ts +1 -1
  144. package/dist/types/components/autocomplete.d.ts +9 -0
  145. package/dist/types/components/buttons.d.ts +4 -39
  146. package/dist/types/components/carousel.d.ts +10 -1
  147. package/dist/types/components/chips.d.ts +1 -0
  148. package/dist/types/components/datepicker.d.ts +11 -0
  149. package/dist/types/components/index.d.ts +0 -2
  150. package/dist/types/components/lightbox.d.ts +12 -0
  151. package/dist/types/components/menu.d.ts +3 -0
  152. package/dist/types/components/registry.d.ts +0 -4
  153. package/dist/types/components/select.d.ts +4 -0
  154. package/dist/types/components/slider.d.ts +2 -1
  155. package/dist/types/components/snackbar.d.ts +4 -2
  156. package/dist/types/components/tabs.d.ts +2 -1
  157. package/dist/types/components/timepicker.d.ts +5 -3
  158. package/dist/types/components/tooltip.d.ts +5 -3
  159. package/dist/types/index.d.ts +1 -8
  160. package/dist/types/modular.d.ts +28 -0
  161. package/package.json +16 -4
  162. package/src/sass/README.md +8 -0
  163. package/src/sass/components/_badges.scss +1 -6
  164. package/src/sass/components/_button-groups.scss +5 -1
  165. package/src/sass/components/_buttons.scss +8 -287
  166. package/src/sass/components/_chips.scss +17 -2
  167. package/src/sass/components/_dialog.scss +9 -4
  168. package/src/sass/components/_fab-menu.scss +11 -9
  169. package/src/sass/components/_icon-buttons.scss +0 -5
  170. package/src/sass/components/_index.scss +0 -5
  171. package/src/sass/components/_menu.scss +2 -2
  172. package/src/sass/components/_navigation-rail.scss +1 -1
  173. package/src/sass/components/_panes.scss +50 -78
  174. package/src/sass/components/_progress.scss +73 -13
  175. package/src/sass/components/_scrim.scss +4 -4
  176. package/src/sass/components/_side-sheet.scss +22 -12
  177. package/src/sass/components/_toolbar.scss +1 -4
  178. package/src/sass/components/_tooltip.scss +20 -2
  179. package/src/sass/components/forms/_input-fields.scss +5 -1
  180. package/src/sass/components/forms/_select.scss +1 -0
  181. package/src/sass/components/forms/_slider.scss +81 -25
  182. package/src/sass/custom.scss +38 -0
  183. package/dist/types/components/navigationDrawer.d.ts +0 -110
  184. package/src/sass/components/_banners.scss +0 -298
  185. package/src/sass/components/_bottom-app-bar.scss +0 -180
  186. package/src/sass/components/_floating-sheet.scss +0 -86
  187. package/src/sass/components/_navigation-drawer.scss +0 -476
  188. package/src/sass/components/_segmented-buttons.scss +0 -188
@@ -36,12 +36,10 @@ __export(index_exports, {
36
36
  Forms: () => Forms,
37
37
  Lightbox: () => Lightbox,
38
38
  Menu: () => Menu,
39
- NavigationDrawer: () => NavigationDrawer,
40
39
  NavigationRail: () => NavigationRail,
41
40
  Range: () => Slider,
42
41
  ScrollSpy: () => ScrollSpy,
43
42
  SideSheets: () => SideSheets,
44
- Sidenav: () => NavigationDrawer,
45
43
  Slider: () => Slider,
46
44
  Snackbar: () => Snackbar,
47
45
  Tabs: () => Tabs,
@@ -867,34 +865,45 @@ var _Menu = class _Menu extends Component {
867
865
  }
868
866
  };
869
867
  this._handleMenuKeydown = (e) => {
868
+ if (!this.isOpen || e.ctrlKey || e.metaKey || e.altKey || e.isComposing) return;
869
+ const list = this._containingSubmenu(e) ?? this.menuEl;
870
+ const rtl = getComputedStyle(list).direction === "rtl";
871
+ const openKey = rtl ? Utils.keys.ARROW_LEFT : Utils.keys.ARROW_RIGHT;
872
+ const backKey = rtl ? Utils.keys.ARROW_RIGHT : Utils.keys.ARROW_LEFT;
873
+ if ([openKey, backKey, Utils.keys.ARROW_UP, Utils.keys.ARROW_DOWN, Utils.keys.ESC, Utils.keys.TAB].includes(e.key)) {
874
+ clearTimeout(this.filterTimeout);
875
+ this._resetFilterQuery();
876
+ }
870
877
  const arrowUpOrDown = e.key === Utils.keys.ARROW_DOWN || e.key === Utils.keys.ARROW_UP;
871
878
  if (e.key === Utils.keys.TAB) {
872
879
  e.preventDefault();
873
880
  this.close();
874
- } else if (e.key === Utils.keys.ARROW_RIGHT && this.isOpen) {
881
+ } else if (e.key === openKey) {
875
882
  const li = this._focusedRow(e);
876
- if (li?.querySelector(":scope > menu")) {
883
+ if (li?.querySelector(":scope > menu") && !li.matches('.disabled, [aria-disabled="true"]')) {
877
884
  e.preventDefault();
878
885
  li.classList.add("open");
879
886
  this._alignSubmenu(li);
880
887
  this._syncSubmenuAria(li, true);
881
- const first = li.querySelector(":scope > menu > li");
882
- first?.focus();
888
+ const first = Array.from(li.querySelector(":scope > menu").children).find(
889
+ (child) => child instanceof HTMLElement && child.tabIndex !== -1
890
+ );
891
+ if (first) this._focusRow(first);
883
892
  }
884
- } else if (e.key === Utils.keys.ARROW_LEFT && this.isOpen) {
893
+ } else if (e.key === backKey) {
885
894
  const submenu = this._containingSubmenu(e);
886
895
  if (submenu) {
887
896
  e.preventDefault();
888
897
  const parentLi = submenu.parentElement;
889
898
  parentLi.classList.remove("open", "submenu-start");
890
899
  this._syncSubmenuAria(parentLi, false);
891
- parentLi.focus();
900
+ this._focusRow(parentLi);
892
901
  }
893
902
  } else if (arrowUpOrDown && this.isOpen) {
894
903
  e.preventDefault();
895
904
  const direction = e.key === Utils.keys.ARROW_DOWN ? 1 : -1;
896
- const list = this._containingSubmenu(e) ?? this.menuEl;
897
- let newFocusedIndex = this.focusedIndex;
905
+ const row = this._focusedRow(e);
906
+ let newFocusedIndex = row ? Array.from(list.children).indexOf(row) : this.focusedIndex;
898
907
  let hasFoundNewIndex = false;
899
908
  do {
900
909
  newFocusedIndex = newFocusedIndex + direction;
@@ -905,10 +914,9 @@ var _Menu = class _Menu extends Component {
905
914
  } while (newFocusedIndex < list.children.length && newFocusedIndex >= 0);
906
915
  if (hasFoundNewIndex) {
907
916
  if (this.focusedIndex >= 0) list.children[this.focusedIndex]?.classList.remove("active");
908
- this.focusedIndex = newFocusedIndex;
909
- const item = list.children[this.focusedIndex];
917
+ const item = list.children[newFocusedIndex];
910
918
  item.classList.add("active");
911
- item.focus({ preventScroll: true });
919
+ this._focusRow(item);
912
920
  }
913
921
  } else if ((e.key === Utils.keys.ENTER || e.key === SPACE) && this.isOpen) {
914
922
  const li = this._focusedRow(e);
@@ -919,7 +927,7 @@ var _Menu = class _Menu extends Component {
919
927
  return;
920
928
  }
921
929
  const focusedElement = li ?? this.menuEl.children[this.focusedIndex];
922
- const activatableElement = focusedElement?.querySelector("a, button");
930
+ const activatableElement = focusedElement?.querySelector(":scope > a, :scope > button");
923
931
  if (!!activatableElement) {
924
932
  activatableElement.click();
925
933
  } else if (focusedElement instanceof HTMLElement) {
@@ -927,39 +935,28 @@ var _Menu = class _Menu extends Component {
927
935
  }
928
936
  } else if (e.key === Utils.keys.ESC && this.isOpen) {
929
937
  e.preventDefault();
930
- const openSub = this.menuEl.querySelector("li.open");
938
+ const openSub = this._containingSubmenu(e)?.parentElement ?? Array.from(this.menuEl.querySelectorAll("li.open")).reverse()[0];
931
939
  if (openSub) {
932
940
  openSub.classList.remove("open", "submenu-start");
933
941
  this._syncSubmenuAria(openSub, false);
934
- openSub.focus();
942
+ this._focusRow(openSub);
935
943
  } else {
936
944
  this.close();
937
945
  }
938
946
  }
939
947
  const keyText = e.key.toLowerCase();
940
- const isLetter = /[a-zA-Z0-9-_]/.test(keyText);
941
- const specialKeys = [
942
- Utils.keys.ARROW_DOWN,
943
- Utils.keys.ARROW_UP,
944
- Utils.keys.ENTER,
945
- Utils.keys.ESC,
946
- Utils.keys.TAB,
947
- SPACE
948
- ];
949
- if (isLetter && !specialKeys.includes(e.key)) {
948
+ if (e.key.length === 1 && e.key !== SPACE && !e.ctrlKey && !e.metaKey && !e.altKey && !e.isComposing) {
950
949
  this.filterQuery.push(keyText);
951
950
  const string = this.filterQuery.join("");
952
- const list = this._containingSubmenu(e) ?? this.menuEl;
953
951
  const newOptionEl = Array.from(list.querySelectorAll(":scope > li")).find(
954
- (el) => el.textContent.trim().toLowerCase().indexOf(string) === 0
952
+ (el) => el.tabIndex !== -1 && !el.matches('.disabled, [aria-disabled="true"]') && Array.from(el.childNodes).filter((node) => !(node instanceof Element && node.matches("menu"))).map((node) => node.textContent).join("").trim().toLowerCase().startsWith(string)
955
953
  );
956
954
  if (newOptionEl) {
957
- this.focusedIndex = [...newOptionEl.parentNode.children].indexOf(newOptionEl);
958
- this._focusFocusedItem();
955
+ this._focusRow(newOptionEl);
959
956
  }
957
+ clearTimeout(this.filterTimeout);
958
+ this.filterTimeout = setTimeout(this._resetFilterQuery, 1e3);
960
959
  }
961
- clearTimeout(this.filterTimeout);
962
- this.filterTimeout = setTimeout(this._resetFilterQuery, 1e3);
963
960
  };
964
961
  this._handleWindowResize = () => {
965
962
  if (this.el.offsetParent) {
@@ -982,6 +979,7 @@ var _Menu = class _Menu extends Component {
982
979
  if (transition !== this._transition) return;
983
980
  this._resetMenuStyles();
984
981
  this.menuEl.style.display = "block";
982
+ this._restoreInert();
985
983
  this._placeMenu();
986
984
  this._schedule(() => this._setupTemporaryEventHandlers(), 0);
987
985
  this._animateIn();
@@ -993,7 +991,12 @@ var _Menu = class _Menu extends Component {
993
991
  this.close = () => {
994
992
  if (!this.isOpen) return;
995
993
  const transition = this._clearPendingTimers();
994
+ const root = this.menuEl.getRootNode();
995
+ const focused = root.activeElement;
996
996
  this.isOpen = false;
997
+ this.menuEl.setAttribute("inert", "");
998
+ clearTimeout(this.filterTimeout);
999
+ this._resetFilterQuery();
997
1000
  this.focusedIndex = -1;
998
1001
  this._closeSubmenus();
999
1002
  if (typeof this.options.onCloseStart === "function") {
@@ -1003,7 +1006,7 @@ var _Menu = class _Menu extends Component {
1003
1006
  this._animateOut();
1004
1007
  this._removeTemporaryEventHandlers();
1005
1008
  this.el.ariaExpanded = "false";
1006
- if (this.options.autoFocus) {
1009
+ if (this.options.autoFocus && (root.activeElement === focused || !root.activeElement || root.activeElement === document.body)) {
1007
1010
  this.el.focus();
1008
1011
  }
1009
1012
  };
@@ -1020,6 +1023,7 @@ var _Menu = class _Menu extends Component {
1020
1023
  _Menu._menus.push(this);
1021
1024
  this.id = Utils.getIdFromTrigger(el);
1022
1025
  this.menuEl = Utils.getElementById(el, this.id);
1026
+ this._originalInert = this.menuEl?.getAttribute("inert") ?? null;
1023
1027
  this.options = {
1024
1028
  ..._Menu.defaults,
1025
1029
  ...options
@@ -1059,6 +1063,7 @@ var _Menu = class _Menu extends Component {
1059
1063
  this.el.ariaExpanded = "false";
1060
1064
  clearTimeout(this.filterTimeout);
1061
1065
  this._resetMenuStyles();
1066
+ this._restoreInert();
1062
1067
  this._removeEventHandlers();
1063
1068
  this._removeTemporaryEventHandlers();
1064
1069
  const index = _Menu._menus.indexOf(this);
@@ -1169,7 +1174,7 @@ var _Menu = class _Menu extends Component {
1169
1174
  if (!menu) return;
1170
1175
  li.classList.remove("submenu-start");
1171
1176
  const rect = menu.getBoundingClientRect();
1172
- if (rect.right > window.innerWidth - 8) li.classList.add("submenu-start");
1177
+ if (rect.left < 8 || rect.right > window.innerWidth - 8) li.classList.add("submenu-start");
1173
1178
  }
1174
1179
  _closeSubmenus() {
1175
1180
  this.menuEl?.querySelectorAll("li.open").forEach((li) => {
@@ -1191,6 +1196,15 @@ var _Menu = class _Menu extends Component {
1191
1196
  if (li instanceof HTMLElement && this.menuEl?.contains(li)) return li;
1192
1197
  return null;
1193
1198
  }
1199
+ _restoreInert() {
1200
+ if (this._originalInert === null) this.menuEl?.removeAttribute("inert");
1201
+ else this.menuEl?.setAttribute("inert", this._originalInert);
1202
+ }
1203
+ _focusRow(item) {
1204
+ this.focusedIndex = Array.from(item.parentElement.children).indexOf(item);
1205
+ item.focus({ preventScroll: true });
1206
+ item.scrollIntoView({ block: "nearest", inline: "nearest" });
1207
+ }
1194
1208
  _resetMenuStyles() {
1195
1209
  this.menuEl.style.display = "";
1196
1210
  this._resetMenuPositioningStyles();
@@ -1399,6 +1413,12 @@ var Menu = _Menu;
1399
1413
 
1400
1414
  // src/ts/components/autocomplete.ts
1401
1415
  var _defaults4 = {
1416
+ i18n: {
1417
+ loading: "Loading results.",
1418
+ noResults: "No results.",
1419
+ results: (count) => `${count} ${count === 1 ? "result" : "results"} available.`,
1420
+ selected: (count) => `${count} ${count === 1 ? "item" : "items"} selected.`
1421
+ },
1402
1422
  data: [],
1403
1423
  // Autocomplete data set
1404
1424
  onAutocomplete: null,
@@ -1414,11 +1434,13 @@ var _defaults4 = {
1414
1434
  isMultiSelect: false,
1415
1435
  onSearch: (text, autocomplete) => {
1416
1436
  const normSearch = text.toLocaleLowerCase();
1437
+ const data = autocomplete.options.data;
1417
1438
  autocomplete.setMenuItems(
1418
- autocomplete.options.data.filter(
1439
+ data.filter(
1419
1440
  (option) => option.id.toString().toLocaleLowerCase().includes(normSearch) || option.text?.toLocaleLowerCase().includes(normSearch)
1420
1441
  )
1421
1442
  );
1443
+ autocomplete.options.data = data;
1422
1444
  },
1423
1445
  maxMenuHeight: "300px",
1424
1446
  allowUnsafeHTML: false,
@@ -1437,7 +1459,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1437
1459
  if (e.type === "keyup") _Autocomplete._keydown = false;
1438
1460
  this.count = 0;
1439
1461
  const actualValue = this.el.value.toLocaleLowerCase();
1440
- if (e.key === Utils.keys.ENTER || e.key === Utils.keys.ARROW_UP || e.key === Utils.keys.ARROW_DOWN)
1462
+ if (e.key === Utils.keys.ENTER || e.key === Utils.keys.ARROW_UP || e.key === Utils.keys.ARROW_DOWN || e.key === Utils.keys.ESC || e.key === "Tab")
1441
1463
  return;
1442
1464
  if (this.oldVal !== actualValue && this.el.matches(":focus-visible")) {
1443
1465
  this.open();
@@ -1450,6 +1472,9 @@ var _Autocomplete = class _Autocomplete extends Component {
1450
1472
  this._inputChangeDetection(actualValue);
1451
1473
  };
1452
1474
  this._inputChangeDetection = (value) => {
1475
+ if (!this.options.isMultiSelect && this.selectedValues.length && this.el.value !== (this.selectedValues[0].text || String(this.selectedValues[0].id))) {
1476
+ this.selectedValues = [];
1477
+ }
1453
1478
  if (this.oldVal !== value) {
1454
1479
  this._setStatusLoading();
1455
1480
  this.options.onSearch(this.el.value, this);
@@ -1462,6 +1487,11 @@ var _Autocomplete = class _Autocomplete extends Component {
1462
1487
  };
1463
1488
  this._handleInputKeydown = (e) => {
1464
1489
  _Autocomplete._keydown = true;
1490
+ if (e.key === Utils.keys.ESC || e.key === "Tab") {
1491
+ this.close();
1492
+ this._resetCurrentElementPosition();
1493
+ return;
1494
+ }
1465
1495
  const numItems = this.container.querySelectorAll("li").length;
1466
1496
  if (e.key === Utils.keys.ENTER && this.activeIndex >= 0) {
1467
1497
  const liElement = this.container.querySelectorAll("li")[this.activeIndex];
@@ -1511,6 +1541,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1511
1541
  if (inputText.length >= this.options.minLength) {
1512
1542
  this.isOpen = true;
1513
1543
  this._renderMenu();
1544
+ this._announce(this.menuItems.length ? this.options.i18n.results(this.menuItems.length) : this.options.i18n.noResults);
1514
1545
  }
1515
1546
  if (!this.menu.isOpen) {
1516
1547
  if (this._openTimer !== void 0) clearTimeout(this._openTimer);
@@ -1524,18 +1555,25 @@ var _Autocomplete = class _Autocomplete extends Component {
1524
1555
  * Hide autocomplete.
1525
1556
  */
1526
1557
  this.close = () => {
1558
+ if (this._announcer) this._announcer.textContent = "";
1559
+ if (this._openTimer !== void 0) {
1560
+ clearTimeout(this._openTimer);
1561
+ this._openTimer = void 0;
1562
+ }
1563
+ this.isOpen = false;
1527
1564
  this.menu.close();
1528
1565
  };
1529
1566
  this.el["Expressive_Autocomplete"] = this;
1530
1567
  this.options = {
1531
1568
  ..._Autocomplete.defaults,
1532
- ...options
1569
+ ...options,
1570
+ i18n: { ..._Autocomplete.defaults.i18n, ...options?.i18n }
1533
1571
  };
1534
1572
  this.isOpen = false;
1535
1573
  this.count = 0;
1536
1574
  this.activeIndex = -1;
1537
1575
  this.oldVal = "";
1538
- this.selectedValues = this.selectedValues || this.options.selected.map((value) => ({ id: value })) || [];
1576
+ this.selectedValues = this.options.selected.map((id) => this.options.data.find((entry) => entry.id === id) ?? { id });
1539
1577
  this.menuItems = this.options.data || [];
1540
1578
  this.$active = null;
1541
1579
  this._pointerDown = false;
@@ -1594,7 +1632,10 @@ var _Autocomplete = class _Autocomplete extends Component {
1594
1632
  this._openTimer = void 0;
1595
1633
  }
1596
1634
  this._removeEventHandlers();
1635
+ this.menu.destroy();
1597
1636
  this._removeMenu();
1637
+ this._statusInfo.remove();
1638
+ this._announcer.remove();
1598
1639
  this.el["Expressive_Autocomplete"] = void 0;
1599
1640
  }
1600
1641
  _setupEventHandlers() {
@@ -1645,6 +1686,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1645
1686
  if (typeof userOnItemClick === "function") userOnItemClick.call(this.menu, li);
1646
1687
  };
1647
1688
  this.menu = Menu.init(this.el, menuOptions);
1689
+ this.el.setAttribute("aria-haspopup", "listbox");
1648
1690
  const label = this.el.parentElement.querySelector("label");
1649
1691
  if (label) this.el.after(label);
1650
1692
  this.el.removeEventListener("click", this.menu._handleClick);
@@ -1655,8 +1697,16 @@ var _Autocomplete = class _Autocomplete extends Component {
1655
1697
  if (this.el.value) this.selectOption(this.el.value);
1656
1698
  const div = document.createElement("div");
1657
1699
  div.classList.add("status-info");
1700
+ div.setAttribute("aria-hidden", "true");
1658
1701
  div.setAttribute("style", "position: absolute;right:0;top:0;");
1659
1702
  this.el.parentElement.appendChild(div);
1703
+ this._statusInfo = div;
1704
+ this._announcer = document.createElement("div");
1705
+ this._announcer.classList.add("autocomplete-status");
1706
+ this._announcer.setAttribute("role", "status");
1707
+ this._announcer.setAttribute("aria-live", "polite");
1708
+ this._announcer.setAttribute("aria-atomic", "true");
1709
+ this.el.parentElement.appendChild(this._announcer);
1660
1710
  this._updateSelectedInfo();
1661
1711
  }
1662
1712
  _removeMenu() {
@@ -1693,13 +1743,14 @@ var _Autocomplete = class _Autocomplete extends Component {
1693
1743
  "style",
1694
1744
  "display:grid; grid-auto-flow: column; user-select: none; align-items: center;"
1695
1745
  );
1696
- item.tabIndex = 0;
1746
+ item.tabIndex = -1;
1697
1747
  if (this.options.isMultiSelect) {
1698
1748
  const selection = document.createElement("div");
1699
1749
  selection.classList.add("item-selection");
1700
1750
  selection.style.textAlign = "center";
1701
1751
  const checkbox = document.createElement("input");
1702
1752
  checkbox.type = "checkbox";
1753
+ checkbox.tabIndex = -1;
1703
1754
  checkbox.checked = isSelected;
1704
1755
  const spacer = document.createElement("span");
1705
1756
  spacer.style.paddingLeft = "21px";
@@ -1764,11 +1815,17 @@ var _Autocomplete = class _Autocomplete extends Component {
1764
1815
  }
1765
1816
  }
1766
1817
  _setStatusLoading() {
1767
- const statusElement = this.el.parentElement.querySelector(".status-info");
1818
+ const statusElement = this._statusInfo;
1768
1819
  if (statusElement) statusElement.replaceChildren(_Autocomplete._loadingIndicator());
1820
+ this._announce(this.options.i18n.loading);
1821
+ }
1822
+ _announce(message) {
1823
+ if (!this._announcer) return;
1824
+ const text = this.el.matches(":focus") && this.el.value.length >= this.options.minLength ? message : "";
1825
+ if (this._announcer.textContent !== text) this._announcer.textContent = text;
1769
1826
  }
1770
1827
  _updateSelectedInfo() {
1771
- const statusElement = this.el.parentElement.querySelector(".status-info");
1828
+ const statusElement = this._statusInfo;
1772
1829
  if (statusElement) {
1773
1830
  if (this.options.isMultiSelect)
1774
1831
  statusElement.textContent = this.selectedValues.length.toString();
@@ -1793,6 +1850,8 @@ var _Autocomplete = class _Autocomplete extends Component {
1793
1850
  * @param open Option to conditionally open menu
1794
1851
  */
1795
1852
  setMenuItems(menuItems, selected = null, open = true) {
1853
+ if (this.el["Expressive_Autocomplete"] !== this) return;
1854
+ const resultCount = menuItems.length;
1796
1855
  this.menuItems = menuItems;
1797
1856
  this.options.data = menuItems;
1798
1857
  if (selected) {
@@ -1807,6 +1866,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1807
1866
  }
1808
1867
  if (open) this.open();
1809
1868
  this._updateSelectedInfo();
1869
+ this._announce(open ? resultCount ? this.options.i18n.results(resultCount) : this.options.i18n.noResults : "");
1810
1870
  this._triggerChanged();
1811
1871
  }
1812
1872
  /**
@@ -1832,6 +1892,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1832
1892
  this.close();
1833
1893
  }
1834
1894
  this._updateSelectedInfo();
1895
+ if (this.options.isMultiSelect) this._announce(this.options.i18n.selected(this.selectedValues.length));
1835
1896
  this._triggerChanged();
1836
1897
  }
1837
1898
  };
@@ -1870,8 +1931,7 @@ var _Chips = class _Chips extends Component {
1870
1931
  const index = this._chips.indexOf(_chip);
1871
1932
  if (index < 0) return;
1872
1933
  if (clickedClose) {
1873
- this.deleteChip(index);
1874
- this._input.focus();
1934
+ this._deleteChip(index, "input");
1875
1935
  } else {
1876
1936
  this.selectChip(index);
1877
1937
  }
@@ -1963,8 +2023,8 @@ var _Chips = class _Chips extends Component {
1963
2023
  }
1964
2024
  _setupEventHandlers() {
1965
2025
  this.el.addEventListener("click", this._handleChipClick);
1966
- document.addEventListener("keydown", _Chips._handleChipsKeydown);
1967
- document.addEventListener("keyup", _Chips._handleChipsKeyup);
2026
+ this.el.addEventListener("keydown", _Chips._handleChipsKeydown);
2027
+ this.el.addEventListener("keyup", _Chips._handleChipsKeyup);
1968
2028
  this.el.addEventListener("blur", _Chips._handleChipsBlur, true);
1969
2029
  this._input.addEventListener("focus", this._handleInputFocus);
1970
2030
  this._input.addEventListener("blur", this._handleInputBlur);
@@ -1972,8 +2032,8 @@ var _Chips = class _Chips extends Component {
1972
2032
  }
1973
2033
  _removeEventHandlers() {
1974
2034
  this.el.removeEventListener("click", this._handleChipClick);
1975
- document.removeEventListener("keydown", _Chips._handleChipsKeydown);
1976
- document.removeEventListener("keyup", _Chips._handleChipsKeyup);
2035
+ this.el.removeEventListener("keydown", _Chips._handleChipsKeydown);
2036
+ this.el.removeEventListener("keyup", _Chips._handleChipsKeyup);
1977
2037
  this.el.removeEventListener("blur", _Chips._handleChipsBlur, true);
1978
2038
  this._input.removeEventListener("focus", this._handleInputFocus);
1979
2039
  this._input.removeEventListener("blur", this._handleInputBlur);
@@ -1988,16 +2048,10 @@ var _Chips = class _Chips extends Component {
1988
2048
  const currChips = chips["Expressive_Chips"];
1989
2049
  if (!currChips) return;
1990
2050
  if (e.key === Utils.keys.BACKSPACE || e.key === Utils.keys.DELETE) {
2051
+ const index = currChips._chips.indexOf(e.target.closest(".chip"));
2052
+ if (index < 0) return;
1991
2053
  e.preventDefault();
1992
- let selectIndex = currChips.chipsData.length;
1993
- if (currChips._selectedChip) {
1994
- const index = currChips._chips.indexOf(currChips._selectedChip);
1995
- currChips.deleteChip(index);
1996
- currChips._setSelected(null);
1997
- selectIndex = Math.max(index - 1, 0);
1998
- }
1999
- if (currChips.chipsData.length) currChips.selectChip(selectIndex);
2000
- else currChips._input.focus();
2054
+ currChips._deleteChip(index, "previous");
2001
2055
  } else if (e.key === Utils.keys.ARROW_LEFT) {
2002
2056
  if (currChips._selectedChip) {
2003
2057
  const selectIndex = currChips._chips.indexOf(currChips._selectedChip) - 1;
@@ -2118,6 +2172,10 @@ var _Chips = class _Chips extends Component {
2118
2172
  * @param chipIndex Index of chip
2119
2173
  */
2120
2174
  deleteChip(chipIndex) {
2175
+ const root = this.el.getRootNode();
2176
+ this._deleteChip(chipIndex, this._chips[chipIndex]?.contains(root.activeElement) ? "input" : null);
2177
+ }
2178
+ _deleteChip(chipIndex, focus) {
2121
2179
  const chip = this._chips[chipIndex];
2122
2180
  if (!chip) return;
2123
2181
  if (this._selectedChip === chip) this._setSelected(null);
@@ -2125,9 +2183,21 @@ var _Chips = class _Chips extends Component {
2125
2183
  this._chips.splice(chipIndex, 1);
2126
2184
  this.chipsData.splice(chipIndex, 1);
2127
2185
  this._setPlaceholder();
2186
+ const focusPath = [];
2187
+ let root = this.el.getRootNode();
2188
+ while (root) {
2189
+ focusPath.push({ root, element: root.activeElement });
2190
+ root = "host" in root ? root.host.getRootNode() : null;
2191
+ }
2128
2192
  if (typeof this.options.onChipDelete === "function") {
2129
2193
  this.options.onChipDelete(this.el, chip);
2130
2194
  }
2195
+ if (!focus || focusPath.some(({ root: root2, element }) => root2.activeElement !== element) || this.el["Expressive_Chips"] !== this) return;
2196
+ if (focus === "previous" && this._chips.length) this.selectChip(Math.max(chipIndex - 1, 0));
2197
+ else {
2198
+ this._setSelected(null);
2199
+ this._input?.focus();
2200
+ }
2131
2201
  }
2132
2202
  /**
2133
2203
  * Select nth chip.
@@ -2165,6 +2235,7 @@ var _defaults6 = {};
2165
2235
  var Slider = class _Slider extends Component {
2166
2236
  constructor(el, options) {
2167
2237
  super(el, options, _Slider);
2238
+ this._resizeObserver = null;
2168
2239
  this._handleRangeChange = () => {
2169
2240
  this._clampDual();
2170
2241
  this._sync();
@@ -2179,8 +2250,8 @@ var Slider = class _Slider extends Component {
2179
2250
  this._sync();
2180
2251
  this.thumb.classList.add("active");
2181
2252
  };
2182
- this._handleRangeInputOrMove = () => {
2183
- if (this._pointerDown) {
2253
+ this._handleRangeInputOrMove = (e) => {
2254
+ if (e.type === "input" || this._pointerDown) {
2184
2255
  this._clampDual();
2185
2256
  this._sync();
2186
2257
  this.thumb.classList.add("active");
@@ -2205,6 +2276,10 @@ var Slider = class _Slider extends Component {
2205
2276
  this._setupThumb();
2206
2277
  this._sync();
2207
2278
  this._setupEventHandlers();
2279
+ if (typeof ResizeObserver !== "undefined") {
2280
+ this._resizeObserver = new ResizeObserver(() => this._sync());
2281
+ this._resizeObserver.observe(this.el);
2282
+ }
2208
2283
  }
2209
2284
  static get defaults() {
2210
2285
  return _defaults6;
@@ -2221,6 +2296,7 @@ var Slider = class _Slider extends Component {
2221
2296
  return el["Expressive_Slider"];
2222
2297
  }
2223
2298
  destroy() {
2299
+ this._resizeObserver?.disconnect();
2224
2300
  this._removeEventHandlers();
2225
2301
  this._removeThumb();
2226
2302
  this.el["Expressive_Slider"] = void 0;
@@ -2275,7 +2351,8 @@ var Slider = class _Slider extends Component {
2275
2351
  if (this.el === end && +end.value < +start.value) end.value = start.value;
2276
2352
  }
2277
2353
  _fraction(el) {
2278
- const max = parseFloat(el.max) || 100;
2354
+ const parsedMax = parseFloat(el.max);
2355
+ const max = Number.isNaN(parsedMax) ? 100 : parsedMax;
2279
2356
  const min = parseFloat(el.min) || 0;
2280
2357
  const val = parseFloat(el.value) || 0;
2281
2358
  return max === min ? 0 : (val - min) / (max - min);
@@ -2287,16 +2364,26 @@ var Slider = class _Slider extends Component {
2287
2364
  const top = this.el.offsetTop;
2288
2365
  const width = this.el.offsetWidth;
2289
2366
  const height = this.el.offsetHeight;
2367
+ const style = getComputedStyle(this.el);
2368
+ const rtl = style.direction === "rtl";
2369
+ const vertical = this._isVertical();
2370
+ const handle = parseFloat(style.getPropertyValue("--md-comp-slider-handle-width")) || 4;
2371
+ const length = vertical ? height : width;
2372
+ const position = handle / 2 + percent * (length - handle);
2290
2373
  this.el.style.setProperty("--md-comp-slider-active-fraction", fraction);
2374
+ this.el.style.setProperty("--md-comp-slider-active-position", `${position}px`);
2291
2375
  const host = this._host();
2292
2376
  const peers = host?.querySelectorAll('input[type="range"]');
2293
2377
  if (host && peers && peers.length === 2) {
2294
2378
  const nums = Array.from(peers).map((el) => this._fraction(el));
2295
2379
  host.style.setProperty("--md-comp-slider-start-fraction", `${Math.min(...nums) * 100}%`);
2296
2380
  host.style.setProperty("--md-comp-slider-end-fraction", `${Math.max(...nums) * 100}%`);
2381
+ host.style.setProperty("--md-comp-slider-start-position", `${handle / 2 + Math.min(...nums) * (length - handle)}px`);
2382
+ host.style.setProperty("--md-comp-slider-end-position", `${handle / 2 + Math.max(...nums) * (length - handle)}px`);
2297
2383
  }
2298
2384
  if (host?.classList.contains("stops")) {
2299
- const max = parseFloat(this.el.max) || 100;
2385
+ const parsedMax = parseFloat(this.el.max);
2386
+ const max = Number.isNaN(parsedMax) ? 100 : parsedMax;
2300
2387
  const min = parseFloat(this.el.min) || 0;
2301
2388
  const step = parseFloat(this.el.step);
2302
2389
  if (step > 0 && Number.isFinite(step)) {
@@ -2305,11 +2392,11 @@ var Slider = class _Slider extends Component {
2305
2392
  }
2306
2393
  }
2307
2394
  this.value.textContent = this.el.value;
2308
- if (this._isVertical()) {
2395
+ if (vertical) {
2309
2396
  this.thumb.style.left = `${left + width / 2}px`;
2310
- this.thumb.style.top = `${top + (1 - percent) * height}px`;
2397
+ this.thumb.style.top = `${top + height - position}px`;
2311
2398
  } else {
2312
- this.thumb.style.left = `${left + percent * width}px`;
2399
+ this.thumb.style.left = `${left + (rtl ? width - position : position)}px`;
2313
2400
  this.thumb.style.top = `${top}px`;
2314
2401
  }
2315
2402
  }
@@ -2397,6 +2484,7 @@ var DISMISS_VELOCITY = 0.5;
2397
2484
  var DRAG_SLOP = 4;
2398
2485
  function installSheetDrag(config) {
2399
2486
  const coord = (event) => config.axis === "x" ? event.clientX : event.clientY;
2487
+ let observer;
2400
2488
  let drag = null;
2401
2489
  const sheetFor = (target) => {
2402
2490
  if (!(target instanceof Element)) return null;
@@ -2408,9 +2496,10 @@ function installSheetDrag(config) {
2408
2496
  dialog.style.setProperty(config.property, "0px");
2409
2497
  };
2410
2498
  const onDown = (event) => {
2411
- config.onPress?.();
2412
2499
  if (!event.isPrimary) return;
2413
2500
  if (event.pointerType === "mouse" && event.button !== 0) return;
2501
+ onCancel();
2502
+ config.onPress?.();
2414
2503
  const dialog = sheetFor(event.target);
2415
2504
  if (!dialog?.open) {
2416
2505
  drag = null;
@@ -2430,9 +2519,14 @@ function installSheetDrag(config) {
2430
2519
  lastT: Date.now(),
2431
2520
  shift: 0
2432
2521
  };
2522
+ observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ["open"], attributeOldValue: true });
2433
2523
  };
2434
2524
  const onMove = (event) => {
2435
2525
  if (!drag || drag.pointerId !== event.pointerId) return;
2526
+ if (!drag.dialog.open || !drag.dialog.isConnected) {
2527
+ onCancel();
2528
+ return;
2529
+ }
2436
2530
  const delta = coord(event) - drag.start;
2437
2531
  drag.shift = drag.direction === 1 ? Math.max(0, delta) : Math.min(0, delta);
2438
2532
  drag.last = coord(event);
@@ -2442,7 +2536,12 @@ function installSheetDrag(config) {
2442
2536
  const onUp = (event) => {
2443
2537
  const held = drag;
2444
2538
  if (!held || held.pointerId !== event.pointerId) return;
2539
+ if (!held.dialog.open || !held.dialog.isConnected) {
2540
+ onCancel();
2541
+ return;
2542
+ }
2445
2543
  drag = null;
2544
+ observer.disconnect();
2446
2545
  held.dialog.style.transition = "";
2447
2546
  const dt = Math.max(1, Date.now() - held.lastT);
2448
2547
  const velocity = (coord(event) - held.last) / dt;
@@ -2451,13 +2550,21 @@ function installSheetDrag(config) {
2451
2550
  if (dismiss && held.dialog.open) held.dialog.close();
2452
2551
  held.dialog.style.setProperty(config.property, "0px");
2453
2552
  };
2454
- const onCancel = () => {
2553
+ const onCancel = (event) => {
2554
+ if (event && drag?.pointerId !== event.pointerId) return;
2555
+ observer.disconnect();
2455
2556
  config.onRelease?.(false);
2456
2557
  const held = drag;
2457
2558
  drag = null;
2458
2559
  if (held) reset(held.dialog);
2459
2560
  };
2460
2561
  Utils.onDocumentReady(() => {
2562
+ observer = new MutationObserver((records) => {
2563
+ const dialog = drag?.dialog;
2564
+ if (dialog && (!dialog.open || !dialog.isConnected || records.some(
2565
+ (record) => record.type === "attributes" && record.target === dialog && record.oldValue === null || [...record.removedNodes].some((node) => node.contains(dialog))
2566
+ ))) onCancel();
2567
+ });
2461
2568
  document.addEventListener("pointerdown", onDown, { passive: true });
2462
2569
  document.addEventListener("pointermove", onMove, { passive: true });
2463
2570
  document.addEventListener("pointerup", onUp, { passive: true });
@@ -2511,20 +2618,19 @@ var BottomSheets = _BottomSheets;
2511
2618
 
2512
2619
  // src/ts/behaviors/sideSheets.ts
2513
2620
  var startDocked = (dialog) => dialog.classList.contains("left") || dialog.classList.contains("left-sheet") || dialog.classList.contains("start");
2621
+ var leftDocked = (dialog) => startDocked(dialog) !== (getComputedStyle(dialog).direction === "rtl");
2514
2622
  var SideSheets = class {
2515
2623
  static Init() {
2516
2624
  installSheetDrag({
2517
2625
  selector: "dialog.side-sheet, dialog.right, dialog.right-sheet, dialog.left, dialog.left-sheet",
2518
2626
  axis: "x",
2519
2627
  property: "--md-comp-side-sheet-shift",
2520
- // A start-docked sheet leaves toward the start edge, so its dismissal
2521
- // direction is the negative one.
2522
- direction: (dialog) => startDocked(dialog) ? -1 : 1,
2628
+ direction: (dialog) => leftDocked(dialog) ? -1 : 1,
2523
2629
  inHandle: (event, dialog) => {
2524
2630
  const target = event.target;
2525
2631
  if (target instanceof Element && target.closest("header")) return true;
2526
2632
  const rect = dialog.getBoundingClientRect();
2527
- return startDocked(dialog) ? event.clientX >= rect.right - 24 && event.clientX <= rect.right : event.clientX >= rect.left && event.clientX <= rect.left + 24;
2633
+ return leftDocked(dialog) ? event.clientX >= rect.right - 24 && event.clientX <= rect.right : event.clientX >= rect.left && event.clientX <= rect.left + 24;
2528
2634
  }
2529
2635
  });
2530
2636
  }
@@ -2631,22 +2737,19 @@ var AppBar = class _AppBar extends Component {
2631
2737
  this._sentinel = null;
2632
2738
  this._input = null;
2633
2739
  this._view = null;
2634
- this._suppressSearchOpen = false;
2740
+ this._searchOpen = false;
2635
2741
  this._onIntersect = (entries) => {
2636
2742
  const entry = entries[0];
2637
2743
  if (!entry) return;
2638
2744
  this.el.classList.toggle("collapsed", !entry.isIntersecting);
2639
2745
  };
2640
2746
  this._onSearchViewClose = () => {
2641
- this._suppressSearchOpen = true;
2747
+ this._searchOpen = this._view.open;
2642
2748
  };
2643
2749
  this._onSearchFocus = () => {
2644
- if (!this._view) return;
2645
- if (this._suppressSearchOpen) {
2646
- this._suppressSearchOpen = false;
2647
- return;
2648
- }
2750
+ if (!this._view || this._searchOpen) return;
2649
2751
  if (this._view instanceof HTMLDialogElement) {
2752
+ this._searchOpen = true;
2650
2753
  if (!this._view.open) this._view.showModal();
2651
2754
  return;
2652
2755
  }
@@ -2673,6 +2776,7 @@ var AppBar = class _AppBar extends Component {
2673
2776
  this._sentinel?.remove();
2674
2777
  this._sentinel = null;
2675
2778
  this._input?.removeEventListener("focus", this._onSearchFocus);
2779
+ this._input?.removeEventListener("click", this._onSearchFocus);
2676
2780
  this._view?.removeEventListener("close", this._onSearchViewClose);
2677
2781
  this.el.classList.remove("collapsed");
2678
2782
  this.el["Expressive_AppBar"] = void 0;
@@ -2697,6 +2801,7 @@ var AppBar = class _AppBar extends Component {
2697
2801
  if (!this._view) this._view = this.el.querySelector(".search-view");
2698
2802
  if (!this._view) return;
2699
2803
  this._input.addEventListener("focus", this._onSearchFocus);
2804
+ this._input.addEventListener("click", this._onSearchFocus);
2700
2805
  if (this._view instanceof HTMLDialogElement) {
2701
2806
  this._view.addEventListener("close", this._onSearchViewClose);
2702
2807
  }
@@ -2704,30 +2809,24 @@ var AppBar = class _AppBar extends Component {
2704
2809
  };
2705
2810
 
2706
2811
  // src/ts/components/buttons.ts
2707
- var _defaults8 = {
2708
- direction: "top",
2709
- hoverEnabled: true,
2710
- toolbarEnabled: false
2711
- };
2812
+ var _defaults8 = {};
2712
2813
  var FloatingActionButton = class _FloatingActionButton extends Component {
2713
2814
  constructor(el, options) {
2714
2815
  super(el, options, _FloatingActionButton);
2715
- /**
2716
- * Open FAB.
2717
- */
2718
2816
  this.open = () => {
2719
2817
  if (this.isOpen) return;
2720
2818
  this.isOpen = true;
2819
+ if (this._list) this._list.inert = false;
2721
2820
  this.el.classList.add("active");
2722
2821
  this._anchor?.setAttribute("aria-expanded", "true");
2723
2822
  document.addEventListener("click", this._handleDocumentClick);
2724
2823
  document.addEventListener("keydown", this._handleDocumentKeydown);
2725
2824
  };
2726
- /**
2727
- * Close FAB.
2728
- */
2729
2825
  this.close = () => {
2730
2826
  if (!this.isOpen) return;
2827
+ const focused = this.el.getRootNode().activeElement;
2828
+ if (focused && this._list?.contains(focused)) this._anchor?.focus();
2829
+ if (this._list) this._list.inert = true;
2731
2830
  this.isOpen = false;
2732
2831
  this.el.classList.remove("active");
2733
2832
  this._anchor?.setAttribute("aria-expanded", "false");
@@ -2735,8 +2834,12 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
2735
2834
  document.removeEventListener("keydown", this._handleDocumentKeydown);
2736
2835
  };
2737
2836
  this._handleFABClick = (e) => {
2738
- e.stopPropagation();
2739
- this._toggle();
2837
+ const target = e.target;
2838
+ if (!(target instanceof Element)) return;
2839
+ const control = target.closest("a, button");
2840
+ if (!control || control.matches(':disabled, [aria-disabled="true"]')) return;
2841
+ if (control === this._anchor) this._toggle();
2842
+ else if (this._list?.contains(control)) this.close();
2740
2843
  };
2741
2844
  this._handleAnchorKeydown = (e) => {
2742
2845
  if (e.key === Utils.keys.ENTER || e.key === " ") {
@@ -2745,36 +2848,26 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
2745
2848
  }
2746
2849
  };
2747
2850
  this._handleDocumentKeydown = (e) => {
2748
- if (e.key === Utils.keys.ESC) this.close();
2851
+ if (e.key === Utils.keys.ESC && !e.defaultPrevented) this.close();
2749
2852
  };
2750
2853
  this._handleDocumentClick = (e) => {
2751
- const target = e.target;
2752
- if (!(target instanceof Node) || this.el.contains(target)) return;
2854
+ if (e.composedPath().includes(this.el)) return;
2753
2855
  this.close();
2754
2856
  };
2755
2857
  this.el["Expressive_FloatingActionButton"] = this;
2756
- const fromMarkup = this._directionFromClass();
2757
- const toolbar = el.classList.contains("toolbar") || options.toolbarEnabled === true;
2758
- const clickToToggle = el.classList.contains("click-to-toggle") || options.hoverEnabled === false;
2759
- this.options = {
2760
- ..._FloatingActionButton.defaults,
2761
- ...options,
2762
- direction: options.direction ?? fromMarkup ?? _FloatingActionButton.defaults.direction,
2763
- hoverEnabled: !clickToToggle,
2764
- toolbarEnabled: toolbar
2765
- };
2858
+ this.options = { ..._FloatingActionButton.defaults, ...options };
2766
2859
  this.isOpen = false;
2767
2860
  this._anchor = this.el.querySelector(":scope > a, :scope > button");
2768
- this.el.classList.add(`direction-${this.options.direction}`);
2769
- if (clickToToggle) this.el.classList.add("click-to-toggle");
2770
- if (toolbar) this.el.classList.add("toolbar");
2771
- if (this._anchor) {
2772
- this._anchor.setAttribute("aria-expanded", "false");
2773
- if (this._anchor instanceof HTMLAnchorElement && !this._anchor.hasAttribute("href") && this._anchor.tabIndex < 0) {
2774
- this._anchor.tabIndex = 0;
2775
- }
2861
+ this._list = this.el.querySelector(":scope > ul, :scope > menu");
2862
+ this._listWasInert = this._list?.inert ?? false;
2863
+ this.el.classList.remove("active");
2864
+ if (this._list) this._list.inert = true;
2865
+ this._anchor?.setAttribute("aria-expanded", "false");
2866
+ if (this._anchor instanceof HTMLAnchorElement && !this._anchor.hasAttribute("href")) {
2867
+ if (this._anchor.tabIndex < 0) this._anchor.tabIndex = 0;
2868
+ this._anchor.addEventListener("keydown", this._handleAnchorKeydown);
2776
2869
  }
2777
- this._setupEventHandlers();
2870
+ this.el.addEventListener("click", this._handleFABClick);
2778
2871
  }
2779
2872
  static get defaults() {
2780
2873
  return _defaults8;
@@ -2787,26 +2880,10 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
2787
2880
  }
2788
2881
  destroy() {
2789
2882
  this.close();
2790
- this._removeEventHandlers();
2791
- this.el["Expressive_FloatingActionButton"] = void 0;
2792
- }
2793
- _directionFromClass() {
2794
- const match = [...this.el.classList].find((c) => c.startsWith("direction-"));
2795
- const value = match?.slice("direction-".length);
2796
- if (value === "top" || value === "right" || value === "bottom" || value === "left") {
2797
- return value;
2798
- }
2799
- return null;
2800
- }
2801
- _setupEventHandlers() {
2802
- this.el.addEventListener("click", this._handleFABClick);
2803
- if (this._anchor instanceof HTMLAnchorElement && !this._anchor.hasAttribute("href")) {
2804
- this._anchor.addEventListener("keydown", this._handleAnchorKeydown);
2805
- }
2806
- }
2807
- _removeEventHandlers() {
2883
+ if (this._list) this._list.inert = this._listWasInert;
2808
2884
  this.el.removeEventListener("click", this._handleFABClick);
2809
2885
  this._anchor?.removeEventListener("keydown", this._handleAnchorKeydown);
2886
+ this.el["Expressive_FloatingActionButton"] = void 0;
2810
2887
  }
2811
2888
  _toggle() {
2812
2889
  if (this.isOpen) this.close();
@@ -3056,10 +3133,12 @@ var _Carousel = class _Carousel extends Component {
3056
3133
  this._ownIndicators = false;
3057
3134
  this._trackEl = null;
3058
3135
  this._ignoreScroll = false;
3136
+ this._alignAfterResize = false;
3059
3137
  this._trackRaf = null;
3060
3138
  this._started = false;
3061
3139
  this._vertical = false;
3062
3140
  this._resizeObserver = null;
3141
+ this._resizeTimeout = null;
3063
3142
  this._usesWindowResize = false;
3064
3143
  this._dragPointerId = null;
3065
3144
  this._dragStartX = 0;
@@ -3078,20 +3157,33 @@ var _Carousel = class _Carousel extends Component {
3078
3157
  this._autoPaused = false;
3079
3158
  this._hovered = false;
3080
3159
  this._focused = false;
3160
+ this._motion = window.matchMedia("(prefers-reduced-motion: reduce)");
3081
3161
  this._generatedItemTabIndexes = /* @__PURE__ */ new Set();
3082
3162
  this._generatedItemLabels = /* @__PURE__ */ new Set();
3083
3163
  this._generatedItemDescriptions = /* @__PURE__ */ new Set();
3084
3164
  this._generatedItemSizes = /* @__PURE__ */ new Set();
3085
3165
  this._authoredItemSizes = /* @__PURE__ */ new Set();
3086
3166
  this._itemA11yOriginal = /* @__PURE__ */ new Map();
3087
- this._handleThrottledResize = Utils.throttle(() => this._handleResize(), 200);
3167
+ this._handleThrottledResize = () => {
3168
+ if (!this._started || this._resizeTimeout !== null) return;
3169
+ this._handleResize();
3170
+ this._resizeTimeout = setTimeout(() => {
3171
+ this._resizeTimeout = null;
3172
+ this._handleResize();
3173
+ }, 200);
3174
+ };
3088
3175
  this._handleAutoAdvanceState = (e) => {
3089
3176
  if (e.type === "mouseenter") this._hovered = true;
3090
3177
  else if (e.type === "mouseleave") this._hovered = false;
3091
3178
  else if (e.type === "focusin") this._focused = true;
3092
- else if (e.type === "focusout") this._focused = false;
3179
+ else if (e.type === "focusout") this._focused = this.el.contains(e.relatedTarget);
3093
3180
  this._syncAutoAdvance();
3094
3181
  };
3182
+ this._handleMotionChange = () => {
3183
+ this._syncAutoAdvance();
3184
+ if (this._motion.matches) this._scrollToIndex(this.center, false);
3185
+ this._updateParallax();
3186
+ };
3095
3187
  this._tick = () => {
3096
3188
  this._autoAdvanceTimer = null;
3097
3189
  this._advance();
@@ -3110,7 +3202,12 @@ var _Carousel = class _Carousel extends Component {
3110
3202
  }
3111
3203
  this.set(0);
3112
3204
  };
3205
+ this._handleNativeScroll = () => {
3206
+ this._alignAfterResize = false;
3207
+ this._finishScroll();
3208
+ };
3113
3209
  this._handleTrackPointerDown = (e) => {
3210
+ this._handleNativeScroll();
3114
3211
  if (e.pointerType !== "mouse" || e.button !== 0) return;
3115
3212
  this.pressed = true;
3116
3213
  this.dragged = false;
@@ -3165,6 +3262,11 @@ var _Carousel = class _Carousel extends Component {
3165
3262
  this._handleTrackDragStart = (e) => {
3166
3263
  if (e.target.closest("img, picture, video")) e.preventDefault();
3167
3264
  };
3265
+ this._handleItemResize = (e) => {
3266
+ if (this._alignAfterResize && !this.pressed && e.propertyName === "flex-basis" && this.images.includes(e.target)) {
3267
+ this._scrollToIndex(this.center, false);
3268
+ }
3269
+ };
3168
3270
  this._handleIndicatorClick = (e) => {
3169
3271
  e.stopPropagation();
3170
3272
  const indicator = e.target.closest(".indicator-item");
@@ -3175,9 +3277,10 @@ var _Carousel = class _Carousel extends Component {
3175
3277
  };
3176
3278
  this._handleKeydown = (e) => {
3177
3279
  const target = e.target;
3178
- if (target.closest('input, textarea, select, [contenteditable="true"]')) return;
3179
- const forward = this._vertical ? e.key === "ArrowDown" : e.key === Utils.keys.ARROW_RIGHT;
3180
- const backward = this._vertical ? e.key === "ArrowUp" : e.key === Utils.keys.ARROW_LEFT;
3280
+ if (target.isContentEditable || target.closest("input, textarea, select")) return;
3281
+ const rtl = getComputedStyle(this._scroller).direction === "rtl";
3282
+ const forward = this._vertical ? e.key === "ArrowDown" : e.key === (rtl ? Utils.keys.ARROW_LEFT : Utils.keys.ARROW_RIGHT);
3283
+ const backward = this._vertical ? e.key === "ArrowUp" : e.key === (rtl ? Utils.keys.ARROW_RIGHT : Utils.keys.ARROW_LEFT);
3181
3284
  if (e.key === "Home") {
3182
3285
  e.preventDefault();
3183
3286
  this.set(0);
@@ -3210,12 +3313,22 @@ var _Carousel = class _Carousel extends Component {
3210
3313
  });
3211
3314
  };
3212
3315
  this._handleResize = () => {
3213
- if (!this.images.length) return;
3316
+ if (!this._started || !this.images.length) return;
3214
3317
  this._syncAdaptiveMode();
3215
3318
  this._syncLayoutRoles(this.center);
3216
3319
  this._scrollToIndex(this.center, false);
3217
3320
  this._updateParallax();
3218
3321
  };
3322
+ this._finishScroll = () => {
3323
+ this._ignoreScroll = false;
3324
+ clearTimeout(this._scrollEndTimeout);
3325
+ this._scroller.removeEventListener("scrollend", this._handleScrollEnd);
3326
+ };
3327
+ this._handleScrollEnd = () => {
3328
+ if (!this.images.some((item) => item.getAnimations().some((animation) => animation.playState === "running"))) {
3329
+ this._finishScroll();
3330
+ }
3331
+ };
3219
3332
  this.el["Expressive_Carousel"] = this;
3220
3333
  this.options = {
3221
3334
  ..._Carousel.defaults,
@@ -3229,8 +3342,6 @@ var _Carousel = class _Carousel extends Component {
3229
3342
  this.options.fullWidth = true;
3230
3343
  }
3231
3344
  this._vertical = this.el.classList.contains("full-screen");
3232
- const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3233
- if (reducedMotion) this.options.duration = 1;
3234
3345
  this.pressed = false;
3235
3346
  this.dragged = false;
3236
3347
  this.images = this._collectItems();
@@ -3248,7 +3359,7 @@ var _Carousel = class _Carousel extends Component {
3248
3359
  this.hasMultipleSlides = this.images.length > 1;
3249
3360
  this.showIndicators = this.options.indicators && this.hasMultipleSlides;
3250
3361
  this.count = this.images.length;
3251
- this._autoAdvances = this.options.interval > 0 && this.hasMultipleSlides && !reducedMotion;
3362
+ this._autoAdvances = this.options.interval > 0 && this.hasMultipleSlides;
3252
3363
  this.images.forEach((item) => item.classList.add("carousel-item"));
3253
3364
  if (this.options.height !== null) {
3254
3365
  this._generatedFixedHeight = !this.el.classList.contains("fixed-height");
@@ -3359,6 +3470,7 @@ var _Carousel = class _Carousel extends Component {
3359
3470
  }
3360
3471
  _setupEventHandlers() {
3361
3472
  this.el.addEventListener("keydown", this._handleKeydown);
3473
+ this._motion.addEventListener("change", this._handleMotionChange);
3362
3474
  if (this._autoAdvances) {
3363
3475
  this.el.addEventListener("mouseenter", this._handleAutoAdvanceState);
3364
3476
  this.el.addEventListener("mouseleave", this._handleAutoAdvanceState);
@@ -3387,14 +3499,17 @@ var _Carousel = class _Carousel extends Component {
3387
3499
  passive: true
3388
3500
  });
3389
3501
  this._scroller.addEventListener("pointerdown", this._handleTrackPointerDown);
3502
+ this._scroller.addEventListener("wheel", this._handleNativeScroll, { passive: true });
3390
3503
  this._scroller.addEventListener("pointermove", this._handleTrackPointerMove);
3391
3504
  this._scroller.addEventListener("pointerup", this._handleTrackPointerUp);
3392
3505
  this._scroller.addEventListener("pointercancel", this._handleTrackPointerUp);
3393
3506
  this._scroller.addEventListener("click", this._handleTrackClick, true);
3394
3507
  this._scroller.addEventListener("dragstart", this._handleTrackDragStart);
3508
+ this._scroller.addEventListener("transitionend", this._handleItemResize);
3395
3509
  }
3396
3510
  _removeEventHandlers() {
3397
3511
  this.el.removeEventListener("keydown", this._handleKeydown);
3512
+ this._motion.removeEventListener("change", this._handleMotionChange);
3398
3513
  this.el.removeEventListener("mouseenter", this._handleAutoAdvanceState);
3399
3514
  this.el.removeEventListener("mouseleave", this._handleAutoAdvanceState);
3400
3515
  this.el.removeEventListener("focusin", this._handleAutoAdvanceState);
@@ -3405,11 +3520,13 @@ var _Carousel = class _Carousel extends Component {
3405
3520
  }
3406
3521
  this._scroller.removeEventListener("scroll", this._handleTrackScroll);
3407
3522
  this._scroller.removeEventListener("pointerdown", this._handleTrackPointerDown);
3523
+ this._scroller.removeEventListener("wheel", this._handleNativeScroll);
3408
3524
  this._scroller.removeEventListener("pointermove", this._handleTrackPointerMove);
3409
3525
  this._scroller.removeEventListener("pointerup", this._handleTrackPointerUp);
3410
3526
  this._scroller.removeEventListener("pointercancel", this._handleTrackPointerUp);
3411
3527
  this._scroller.removeEventListener("click", this._handleTrackClick, true);
3412
3528
  this._scroller.removeEventListener("dragstart", this._handleTrackDragStart);
3529
+ this._scroller.removeEventListener("transitionend", this._handleItemResize);
3413
3530
  this._resizeObserver?.disconnect();
3414
3531
  this._resizeObserver = null;
3415
3532
  if (this._usesWindowResize) {
@@ -3421,12 +3538,15 @@ var _Carousel = class _Carousel extends Component {
3421
3538
  }
3422
3539
  }
3423
3540
  _teardown() {
3541
+ this._started = false;
3424
3542
  this._removeEventHandlers();
3543
+ this._finishScroll();
3425
3544
  this._autoAdvances = false;
3426
3545
  this._syncAutoAdvance();
3427
3546
  if (this._trackRaf !== null) cancelAnimationFrame(this._trackRaf);
3428
3547
  window.clearTimeout(this.scrollingTimeout);
3429
3548
  window.clearTimeout(this._suppressClickTimeout);
3549
+ clearTimeout(this._resizeTimeout);
3430
3550
  if (this._ownIndicators) this._indicators?.remove();
3431
3551
  this._unwrapTrack();
3432
3552
  this.images.forEach((el) => {
@@ -3459,7 +3579,7 @@ var _Carousel = class _Carousel extends Component {
3459
3579
  }
3460
3580
  /** Start or stop the timer to match the current pause state. */
3461
3581
  _syncAutoAdvance() {
3462
- const run = this._autoAdvances && !this._autoPaused && !this._hovered && !this._focused && !document.hidden;
3582
+ const run = this._autoAdvances && !this._autoPaused && !this._hovered && !this._focused && !this._motion.matches && !document.hidden;
3463
3583
  if (run && this._autoAdvanceTimer === null) {
3464
3584
  this._autoAdvanceTimer = setTimeout(
3465
3585
  this._tick,
@@ -3585,16 +3705,21 @@ var _Carousel = class _Carousel extends Component {
3585
3705
  }
3586
3706
  _nearestIndex() {
3587
3707
  const centered = this.el.classList.contains("center-aligned");
3708
+ const style = getComputedStyle(this._scroller);
3709
+ const rtl = !this._vertical && style.direction === "rtl";
3588
3710
  const position = this._vertical ? this._scroller.scrollTop : this._scroller.scrollLeft;
3589
- const viewportCenter = position + (this._vertical ? this._scroller.clientHeight : this._scroller.clientWidth) / 2;
3590
- let best = 0;
3711
+ const viewport = this._vertical ? this._scroller.clientHeight : this._scroller.clientWidth;
3712
+ const extent = (this._vertical ? this._scroller.scrollHeight : this._scroller.scrollWidth) - viewport;
3713
+ const padding = parseFloat(this._vertical ? style.paddingBlockStart : style.paddingInlineStart) || 0;
3714
+ let best = this.center;
3591
3715
  let bestDist = Infinity;
3592
3716
  this.images.forEach((el, i) => {
3593
3717
  const start = this._vertical ? el.offsetTop : el.offsetLeft;
3594
3718
  const size = this._vertical ? el.offsetHeight : el.offsetWidth;
3595
- const target = centered ? start + size / 2 : start;
3596
- const dist = Math.abs(target - (centered ? viewportCenter : position));
3597
- if (dist < bestDist) {
3719
+ const target = centered ? start - (viewport - size) / 2 : start + (rtl ? size - viewport + padding : -padding);
3720
+ const bounded = Math.max(rtl ? -extent : 0, Math.min(rtl ? 0 : extent, target));
3721
+ const dist = Math.abs(bounded - position);
3722
+ if (dist < bestDist || dist === bestDist && i === this.center) {
3598
3723
  bestDist = dist;
3599
3724
  best = i;
3600
3725
  }
@@ -3604,31 +3729,24 @@ var _Carousel = class _Carousel extends Component {
3604
3729
  _scrollToIndex(n, smooth = true) {
3605
3730
  const el = this.images[n];
3606
3731
  if (!el) return;
3732
+ this._finishScroll();
3607
3733
  const centered = this.el.classList.contains("center-aligned");
3608
3734
  const style = getComputedStyle(this._scroller);
3609
3735
  const inlinePadding = Number.parseFloat(style.paddingInlineStart) || 0;
3610
3736
  const blockPadding = Number.parseFloat(style.paddingBlockStart) || 0;
3611
- const left = centered ? el.offsetLeft - (this._scroller.clientWidth - el.offsetWidth) / 2 : el.offsetLeft - inlinePadding;
3737
+ const left = centered ? el.offsetLeft - (this._scroller.clientWidth - el.offsetWidth) / 2 : style.direction === "rtl" ? el.offsetLeft + el.offsetWidth - this._scroller.clientWidth + inlinePadding : el.offsetLeft - inlinePadding;
3612
3738
  const top = el.offsetTop - blockPadding;
3613
- const current = this._vertical ? this._scroller.scrollTop : this._scroller.scrollLeft;
3614
- const target = this._vertical ? top : left;
3615
- if (Math.abs(current - target) < 1) {
3616
- this._syncActive(n, false);
3617
- return;
3618
- }
3619
3739
  this._ignoreScroll = true;
3620
3740
  this._scroller.scrollTo({
3621
3741
  left: this._vertical ? 0 : left,
3622
3742
  top: this._vertical ? top : 0,
3623
- behavior: smooth ? "smooth" : "auto"
3743
+ behavior: smooth && !this._motion.matches ? "smooth" : "instant"
3624
3744
  });
3625
- const done = () => {
3626
- this._ignoreScroll = false;
3627
- };
3628
- this._scroller.addEventListener("scrollend", done, { once: true });
3629
- window.setTimeout(done, this.options.duration + 350);
3745
+ this._scroller.addEventListener("scrollend", this._handleScrollEnd);
3746
+ this._scrollEndTimeout = setTimeout(this._finishScroll, this.options.duration + 350);
3630
3747
  }
3631
3748
  _cycleTo(n, callback = null) {
3749
+ this._alignAfterResize = true;
3632
3750
  if (typeof callback === "function") this.oneTimeCallback = callback;
3633
3751
  this._syncActive(n, false);
3634
3752
  this._scrollToIndex(n);
@@ -3758,6 +3876,13 @@ var FormSelect = class _FormSelect extends Component {
3758
3876
  super(el, options, _FormSelect);
3759
3877
  this._handleSelectChange = () => {
3760
3878
  this._setValueToInput();
3879
+ this._setSelectedStates();
3880
+ };
3881
+ this._handleReset = (e) => {
3882
+ clearTimeout(this._resetTimer);
3883
+ this._resetTimer = setTimeout(() => {
3884
+ if (!e.defaultPrevented) this._handleSelectChange();
3885
+ }, 0);
3761
3886
  };
3762
3887
  // Named rather than inline so that _removeEventHandlers can actually detach
3763
3888
  // it - an anonymous listener per option was unremovable.
@@ -3828,21 +3953,41 @@ var FormSelect = class _FormSelect extends Component {
3828
3953
  */
3829
3954
  refresh() {
3830
3955
  if (!this.menuEl) return;
3956
+ this._bindForm();
3957
+ const root = this.menuEl.getRootNode();
3958
+ const focused = this._values.find((value) => value.optionEl.contains(root.activeElement))?.el;
3959
+ this.input.disabled = this.el.matches(":disabled");
3960
+ this.wrapper.classList.toggle("disabled", this.input.disabled);
3961
+ if (this.input.disabled) this.menu?.close();
3962
+ else if (!this.menu) this._initMenu();
3963
+ this.input.removeAttribute("aria-activedescendant");
3831
3964
  this._rebuildOptions();
3832
- this._setValueToInput();
3833
- this._setSelectedStates();
3965
+ this._handleSelectChange();
3966
+ if (this.menu) this.menu.focusedIndex = -1;
3967
+ if (this.menu?.isOpen) {
3968
+ this.menu.recalculateDimensions();
3969
+ if (focused) (this._values.find((value) => value.el === focused)?.optionEl ?? this.input).focus();
3970
+ }
3834
3971
  }
3835
3972
  _setupEventHandlers() {
3836
3973
  this._setupOptionHandlers();
3837
3974
  this.el.addEventListener("change", this._handleSelectChange);
3838
3975
  this.input.addEventListener("click", this._handleInputClick);
3839
3976
  this.menuEl.addEventListener("focusin", this._handleOptionFocus);
3977
+ this._bindForm();
3978
+ }
3979
+ _bindForm() {
3980
+ this._form?.removeEventListener("reset", this._handleReset);
3981
+ this._form = this.el.form;
3982
+ this._form?.addEventListener("reset", this._handleReset);
3840
3983
  }
3841
3984
  _removeEventHandlers() {
3842
3985
  this._removeOptionHandlers();
3843
3986
  this.el.removeEventListener("change", this._handleSelectChange);
3844
3987
  this.input?.removeEventListener("click", this._handleInputClick);
3845
3988
  this.menuEl?.removeEventListener("focusin", this._handleOptionFocus);
3989
+ this._form?.removeEventListener("reset", this._handleReset);
3990
+ clearTimeout(this._resetTimer);
3846
3991
  }
3847
3992
  _setupOptionHandlers() {
3848
3993
  this.menuEl.querySelectorAll("li:not(.optgroup)").forEach((el) => {
@@ -3864,9 +4009,10 @@ var FormSelect = class _FormSelect extends Component {
3864
4009
  return true;
3865
4010
  }
3866
4011
  _selectOptionElement(virtualOption) {
4012
+ if (this.el.matches(":disabled")) return;
3867
4013
  if (!virtualOption.classList.contains("disabled") && !virtualOption.classList.contains("optgroup")) {
3868
4014
  const value = this._values.find((value2) => value2.optionEl === virtualOption);
3869
- if (!value) return;
4015
+ if (!value || value.el.matches(":disabled")) return;
3870
4016
  const previousSelectedValues = this.getSelectedValues();
3871
4017
  if (this.isMultiple) {
3872
4018
  this._toggleEntryFromArray(value);
@@ -3874,7 +4020,7 @@ var FormSelect = class _FormSelect extends Component {
3874
4020
  this._deselectAll();
3875
4021
  this._selectValue(value);
3876
4022
  }
3877
- this._setValueToInput();
4023
+ this._handleSelectChange();
3878
4024
  const actualSelectedValues = this.getSelectedValues();
3879
4025
  const selectionHasChanged = !this._arraysEqual(previousSelectedValues, actualSelectedValues);
3880
4026
  if (selectionHasChanged)
@@ -3888,7 +4034,7 @@ var FormSelect = class _FormSelect extends Component {
3888
4034
  this.labelEl = this.el.labels?.[0] ?? null;
3889
4035
  this._setupWrapper();
3890
4036
  this._hideNativeSelect();
3891
- if (this.el.disabled) this.wrapper.classList.add("disabled");
4037
+ if (this.el.matches(":disabled")) this.wrapper.classList.add("disabled");
3892
4038
  this.menuEl = document.createElement("menu");
3893
4039
  this.menuEl.id = `select-options-${Utils.guid()}`;
3894
4040
  this.menuEl.setAttribute("popover", "auto");
@@ -3935,7 +4081,7 @@ var FormSelect = class _FormSelect extends Component {
3935
4081
  this.input.setAttribute("data-target", this.menuEl.id);
3936
4082
  this.input.ariaReadOnly = "true";
3937
4083
  this.input.ariaRequired = this.el.hasAttribute("required").toString();
3938
- if (this.el.disabled) this.input.disabled = true;
4084
+ this.input.disabled = this.el.matches(":disabled");
3939
4085
  this.input.setAttribute("tabindex", this.nativeTabIndex.toString());
3940
4086
  const attrs = this.el.attributes;
3941
4087
  for (let i = 0; i < attrs.length; ++i) {
@@ -3961,7 +4107,7 @@ var FormSelect = class _FormSelect extends Component {
3961
4107
  this.wrapper.prepend(caret);
3962
4108
  }
3963
4109
  _initMenu() {
3964
- if (this.el.disabled) return;
4110
+ if (this.el.matches(":disabled")) return;
3965
4111
  const menuOptions = { ...this.options.menuOptions };
3966
4112
  menuOptions.coverTrigger = false;
3967
4113
  const userOnOpenEnd = menuOptions.onOpenEnd;
@@ -4062,7 +4208,8 @@ var FormSelect = class _FormSelect extends Component {
4062
4208
  li.id = "select-option-" + Utils.guid();
4063
4209
  li.setAttribute("role", "option");
4064
4210
  li.tabIndex = 0;
4065
- if (realOption.disabled) {
4211
+ const disabled = this.el.matches(":disabled") || realOption.matches(":disabled");
4212
+ if (disabled) {
4066
4213
  li.classList.add("disabled");
4067
4214
  li.ariaDisabled = "true";
4068
4215
  li.tabIndex = -1;
@@ -4070,7 +4217,7 @@ var FormSelect = class _FormSelect extends Component {
4070
4217
  if (type === "optgroup-option") li.classList.add(type);
4071
4218
  const optionText = realOption.textContent;
4072
4219
  const span = document.createElement("span");
4073
- if (this.isMultiple && !realOption.disabled) {
4220
+ if (this.isMultiple && !disabled) {
4074
4221
  const label = document.createElement("label");
4075
4222
  const checkbox = document.createElement("input");
4076
4223
  checkbox.type = "checkbox";
@@ -4084,11 +4231,21 @@ var FormSelect = class _FormSelect extends Component {
4084
4231
  }
4085
4232
  li.appendChild(span);
4086
4233
  const iconUrl = realOption.getAttribute("data-icon");
4087
- const classes = realOption.getAttribute("class")?.split(" ").filter(Boolean);
4234
+ let imageUrl;
4088
4235
  if (iconUrl) {
4236
+ try {
4237
+ const url = new URL(iconUrl, this.el.ownerDocument.baseURI);
4238
+ if (["http:", "https:", "blob:"].includes(url.protocol) || /^data:image\/(?:avif|bmp|gif|jpeg|png|svg\+xml|webp|x-icon)(?:;|,)/i.test(url.href)) {
4239
+ imageUrl = url;
4240
+ }
4241
+ } catch {
4242
+ }
4243
+ }
4244
+ const classes = realOption.getAttribute("class")?.split(" ").filter(Boolean);
4245
+ if (imageUrl) {
4089
4246
  const img = document.createElement("img");
4090
4247
  if (classes?.length) img.classList.add(...classes);
4091
- img.src = iconUrl;
4248
+ img.src = imageUrl.href;
4092
4249
  img.ariaHidden = "true";
4093
4250
  li.prepend(img);
4094
4251
  }
@@ -4127,22 +4284,7 @@ var FormSelect = class _FormSelect extends Component {
4127
4284
  );
4128
4285
  }
4129
4286
  _setValueToInput() {
4130
- const selectedRealOptions = this._getSelectedOptions();
4131
- const selectedOptionPairs = this._values.filter(
4132
- (value) => selectedRealOptions.indexOf(value.el) >= 0
4133
- );
4134
- const notDisabledOptionPairs = selectedOptionPairs.filter((op) => !op.el.disabled);
4135
- const texts = notDisabledOptionPairs.map(
4136
- (value) => value.optionEl.querySelector("span").textContent.trim()
4137
- );
4138
- if (texts.length === 0) {
4139
- const firstDisabledOption = this.el.querySelector("option:disabled");
4140
- if (firstDisabledOption && firstDisabledOption.value === "") {
4141
- this.input.value = firstDisabledOption.textContent;
4142
- return;
4143
- }
4144
- }
4145
- this.input.value = texts.join(", ");
4287
+ this.input.value = this._getSelectedOptions().map((option) => option.textContent.trim()).join(", ");
4146
4288
  }
4147
4289
  _setSelectedStates() {
4148
4290
  this._values.forEach((value) => {
@@ -4179,7 +4321,7 @@ var _defaults13 = {
4179
4321
  var DockedDisplayPlugin = class _DockedDisplayPlugin {
4180
4322
  constructor(el, container, options) {
4181
4323
  this._handleDocumentClick = (e) => {
4182
- if (this.visible && !(this.el === e.target) && !e.target.closest(".display-docked")) {
4324
+ if (this.visible && !e.composedPath().includes(this.el) && !e.composedPath().includes(this.container)) {
4183
4325
  this.hide();
4184
4326
  }
4185
4327
  };
@@ -4352,6 +4494,7 @@ var _Datepicker = class _Datepicker extends Component {
4352
4494
  this._controlsKey = null;
4353
4495
  /** id linking the controls element to the table's aria-labelledby. */
4354
4496
  this._randId = null;
4497
+ this._focusedDate = null;
4355
4498
  this._handleInputClick = (e) => {
4356
4499
  if (e.type == "date") {
4357
4500
  e.preventDefault();
@@ -4369,17 +4512,55 @@ var _Datepicker = class _Datepicker extends Component {
4369
4512
  e.preventDefault();
4370
4513
  this._batchDraws(() => {
4371
4514
  this.setDateFromInput(e.target);
4515
+ this._focusedDate = e.target === this.endDateEl ? this.endDate : this.date;
4372
4516
  this.draw();
4373
4517
  });
4374
4518
  if (this.displayPlugin) this.displayPlugin.show();
4519
+ this._syncCalendarFocus(true);
4375
4520
  if (this.options.onInputInteraction) this.options.onInputInteraction.call(this);
4376
4521
  }
4377
4522
  };
4523
+ this._handleCalendarFocus = (event) => {
4524
+ const button = event.target;
4525
+ if (!button.matches(".datepicker-day-button")) return;
4526
+ this._focusedDate = this._dayDate(button);
4527
+ this._syncCalendarFocus();
4528
+ };
4529
+ this._handleCalendarKeydown = (event) => {
4530
+ const button = event.target;
4531
+ if (!button.matches(".datepicker-day-button") || event.altKey || event.ctrlKey || event.metaKey) return;
4532
+ const date = this._dayDate(button);
4533
+ const weekday = (date.getDay() - this.options.firstDay + 7) % 7;
4534
+ const offsets = {
4535
+ ArrowLeft: this.options.isRTL ? 1 : -1,
4536
+ ArrowRight: this.options.isRTL ? -1 : 1,
4537
+ ArrowUp: -7,
4538
+ ArrowDown: 7,
4539
+ Home: -weekday,
4540
+ End: 6 - weekday
4541
+ };
4542
+ if (Object.hasOwn(offsets, event.key)) date.setDate(date.getDate() + offsets[event.key]);
4543
+ else if (event.key === "PageUp" || event.key === "PageDown") {
4544
+ const day = date.getDate();
4545
+ date.setDate(1);
4546
+ date.setMonth(date.getMonth() + (event.key === "PageUp" ? -1 : 1) * (event.shiftKey ? 12 : 1));
4547
+ const last = new Date(date.getTime());
4548
+ last.setMonth(last.getMonth() + 1, 0);
4549
+ date.setDate(Math.min(day, last.getDate()));
4550
+ } else return;
4551
+ event.preventDefault();
4552
+ const { minDate, maxDate, minYear, maxYear, minMonth, maxMonth } = this.options;
4553
+ if (minDate && date < minDate) date.setTime(minDate.getTime());
4554
+ if (maxDate && date > maxDate) date.setTime(maxDate.getTime());
4555
+ if (date.getFullYear() < minYear || date.getFullYear() > maxYear || date.getFullYear() === minYear && date.getMonth() < (minMonth ?? 0) || date.getFullYear() === maxYear && date.getMonth() > (maxMonth ?? 11)) return;
4556
+ this._focusedDate = date;
4557
+ this.gotoDate(date);
4558
+ };
4378
4559
  this._handleCalendarClick = (e) => {
4379
4560
  const target = e.target;
4380
4561
  if (target.classList.contains("is-disabled")) return;
4381
4562
  this._batchDraws(() => {
4382
- if (target.classList.contains("datepicker-day-button") && !target.classList.contains("is-empty") && !target.parentElement.classList.contains("is-disabled")) {
4563
+ if (target.classList.contains("datepicker-day-button") && !target.classList.contains("is-empty") && !target.parentElement.classList.contains("is-disabled") && !target.parentElement.classList.contains("is-selection-disabled")) {
4383
4564
  const selectedDate = new Date(
4384
4565
  e.target.getAttribute("data-year"),
4385
4566
  e.target.getAttribute("data-month"),
@@ -4417,6 +4598,7 @@ var _Datepicker = class _Datepicker extends Component {
4417
4598
  this._clearDates = () => {
4418
4599
  this.date = null;
4419
4600
  this.endDate = null;
4601
+ this.dates?.splice(0);
4420
4602
  this.draw();
4421
4603
  };
4422
4604
  this._handleMonthChange = (e) => {
@@ -4439,6 +4621,7 @@ var _Datepicker = class _Datepicker extends Component {
4439
4621
  date = new Date(Date.parse(e.target.value));
4440
4622
  }
4441
4623
  if (_Datepicker._isDate(date)) {
4624
+ if (el == this.endDateEl && date < this.date) return this.setInputValue(el, this.endDate);
4442
4625
  this.setDate(date, false, el == this.endDateEl, true);
4443
4626
  if (e.type == "date") {
4444
4627
  this.setDataDate(e, date);
@@ -4467,6 +4650,11 @@ var _Datepicker = class _Datepicker extends Component {
4467
4650
  if (this.options.minDate) this.options.minDate.setHours(0, 0, 0, 0);
4468
4651
  if (this.options.maxDate) this.options.maxDate.setHours(0, 0, 0, 0);
4469
4652
  this.id = Utils.guid();
4653
+ if (this.options.isMultipleSelection) {
4654
+ this.multiple = true;
4655
+ this.dates = [];
4656
+ this.dateEls = [el];
4657
+ }
4470
4658
  this._setupVariables();
4471
4659
  this._insertHTMLIntoDOM();
4472
4660
  this._setupEventHandlers();
@@ -4494,12 +4682,6 @@ var _Datepicker = class _Datepicker extends Component {
4494
4682
  }
4495
4683
  }
4496
4684
  }
4497
- if (this.options.isMultipleSelection) {
4498
- this.multiple = true;
4499
- this.dates = [];
4500
- this.dateEls = [];
4501
- this.dateEls.push(el);
4502
- }
4503
4685
  if (this.options.displayPlugin) {
4504
4686
  if (this.options.displayPlugin === "docked") this.displayPlugin = DockedDisplayPlugin.init(this.el, this.containerEl, this.options.displayPluginOptions);
4505
4687
  }
@@ -4560,6 +4742,8 @@ var _Datepicker = class _Datepicker extends Component {
4560
4742
  }
4561
4743
  destroy() {
4562
4744
  this._removeEventHandlers();
4745
+ this.dateEls?.slice(1).forEach((input) => this._removeDateInput(input));
4746
+ if (!this.options.dateRangeEndEl && this.endDateEl) this._removeDateInput(this.endDateEl);
4563
4747
  this.displayPlugin?.destroy();
4564
4748
  this.containerEl.remove();
4565
4749
  this.destroySelects();
@@ -4652,9 +4836,9 @@ var _Datepicker = class _Datepicker extends Component {
4652
4836
  if (!selectedDate) {
4653
4837
  return;
4654
4838
  }
4839
+ _Datepicker._setToStartOfDay(selectedDate);
4655
4840
  if (!this.options.isMultipleSelection) this.setSingleDate(selectedDate, isEndDate);
4656
4841
  else if (!fromUserInput) this.setMultiDate(selectedDate);
4657
- _Datepicker._setToStartOfDay(selectedDate);
4658
4842
  this.gotoDate(selectedDate);
4659
4843
  if (!preventOnSelect && typeof this.options.onSelect === "function") {
4660
4844
  this.options.onSelect.call(this, selectedDate);
@@ -4726,27 +4910,20 @@ var _Datepicker = class _Datepicker extends Component {
4726
4910
  this.setMultipleSelectionInputValues();
4727
4911
  }
4728
4912
  setMultipleSelectionInputValues() {
4729
- const dateElsArr = Array.from(this.dateEls).filter((el, index) => {
4730
- if (index > this.dates.length - 1) return el;
4731
- });
4732
- dateElsArr.forEach((el) => {
4733
- el.remove();
4734
- });
4735
- this.dates.forEach((date, index) => {
4736
- if (Array.from(this.dateEls)[index]) {
4737
- this.setInputValue(this.dateEls[index], date);
4738
- return;
4739
- }
4740
- const dateEl = this.createDateInput();
4741
- this.setInputValue(dateEl, date);
4742
- this.dateEls.push(dateEl);
4743
- });
4913
+ const count = Math.max(1, this.dates.length);
4914
+ for (const input of this.dateEls.splice(count)) this._removeDateInput(input);
4915
+ while (this.dateEls.length < count) this.dateEls.push(this.createDateInput());
4916
+ this.dateEls.forEach((input, index) => this.setInputValue(input, this.dates[index] ?? null));
4744
4917
  }
4745
4918
  /**
4746
4919
  * Sets given date as the input value on the given element.
4747
4920
  */
4748
4921
  setInputValue(el, date) {
4749
- if (el.type == "date") {
4922
+ if (!el) return;
4923
+ if (!_Datepicker._isDate(date)) {
4924
+ el.value = "";
4925
+ if (el.type === "date") el.setAttribute("data-date", "");
4926
+ } else if (el.type == "date") {
4750
4927
  this.setDataDate(el, date);
4751
4928
  el.value = this.formatDate(date, "yyyy-mm-dd");
4752
4929
  } else {
@@ -4919,13 +5096,18 @@ var _Datepicker = class _Datepicker extends Component {
4919
5096
  arr.push(className);
4920
5097
  }
4921
5098
  }
4922
- return `<td data-day="${opts.day}" class="${arr.join(" ")}" aria-selected="${ariaSelected}"><button class="datepicker-day-button" type="button" data-year="${opts.year}" data-month="${opts.month}" data-day="${opts.day}">${opts.day}</button></td>`;
5099
+ const day = _Datepicker._escape(opts.day);
5100
+ const month = _Datepicker._escape(opts.month);
5101
+ const year = _Datepicker._escape(opts.year);
5102
+ return `<td data-day="${day}" class="${arr.join(" ")}" aria-selected="${ariaSelected}"><button class="datepicker-day-button" type="button" data-year="${year}" data-month="${month}" data-day="${day}">${day}</button></td>`;
4923
5103
  }
5104
+ /** Assemble calendar cells; reject unsupported elements and attributes. */
4924
5105
  renderRow(days, isRTL, isRowSelected) {
4925
- return '<tr class="datepicker-row' + (isRowSelected ? " is-selected" : "") + '">' + (isRTL ? days.reverse() : days).join("") + "</tr>";
5106
+ return '<tr class="datepicker-row' + (isRowSelected ? " is-selected" : "") + '">' + _Datepicker._calendarMarkup((isRTL ? days.reverse() : days).join(""), "tr") + "</tr>";
4926
5107
  }
5108
+ /** Assemble calendar rows; reject unsupported elements and attributes. */
4927
5109
  renderTable(opts, data, randId) {
4928
- return '<div class="datepicker-table-wrapper"><table cellpadding="0" cellspacing="0" class="datepicker-table" role="grid" aria-labelledby="' + randId + '">' + this.renderHead(opts) + this.renderBody(data) + "</table></div>";
5110
+ return '<div class="datepicker-table-wrapper"><table cellpadding="0" cellspacing="0" class="datepicker-table" role="grid" aria-labelledby="' + _Datepicker._escape(randId) + '">' + this.renderHead(opts) + this.renderBody(data) + "</table></div>";
4929
5111
  }
4930
5112
  renderHead(opts) {
4931
5113
  const arr = [];
@@ -4937,8 +5119,40 @@ var _Datepicker = class _Datepicker extends Component {
4937
5119
  }
4938
5120
  return "<thead><tr>" + (opts.isRTL ? arr.reverse() : arr).join("") + "</tr></thead>";
4939
5121
  }
5122
+ /** Wrap calendar rows after validating and encoding their contents. */
4940
5123
  renderBody(rows) {
4941
- return "<tbody>" + rows.join("") + "</tbody>";
5124
+ return "<tbody>" + _Datepicker._calendarMarkup(rows.join(""), "tbody") + "</tbody>";
5125
+ }
5126
+ static _calendarMarkup(html, parent) {
5127
+ const template = document.createElement("template");
5128
+ template.innerHTML = html;
5129
+ const attributes = {
5130
+ tr: ["class"],
5131
+ td: ["class", "data-day", "aria-selected"],
5132
+ button: ["class", "type", "data-year", "data-month", "data-day", "aria-label", "disabled", "tabindex"]
5133
+ };
5134
+ const render = (node, container) => {
5135
+ if (node.nodeType === Node.TEXT_NODE) {
5136
+ if (container === "tbody" || container === "tr") {
5137
+ if (node.textContent.trim()) throw new TypeError("Unsupported calendar row content");
5138
+ }
5139
+ return _Datepicker._escape(node.textContent);
5140
+ }
5141
+ if (!(node instanceof HTMLElement)) throw new TypeError("Unsupported calendar row content");
5142
+ const tag = node.localName === "tr" ? "tr" : node.localName === "td" ? "td" : node.localName === "button" ? "button" : null;
5143
+ if (!tag || !(container === "tbody" && tag === "tr" || container === "tr" && tag === "td" || container === "td" && tag === "button")) {
5144
+ throw new TypeError("Unsupported calendar row element");
5145
+ }
5146
+ if ([...node.attributes].some((attr) => !attributes[tag].includes(attr.name))) {
5147
+ throw new TypeError("Unsupported calendar row attribute");
5148
+ }
5149
+ if (tag === "button" && node.getAttribute("type") !== "button") {
5150
+ throw new TypeError('Calendar day buttons require type="button"');
5151
+ }
5152
+ const attrs = attributes[tag].filter((name) => node.hasAttribute(name)).map((name) => ` ${name}="${_Datepicker._escape(node.getAttribute(name))}"`).join("");
5153
+ return `<${tag}${attrs}>${[...node.childNodes].map((child) => render(child, tag)).join("")}</${tag}>`;
5154
+ };
5155
+ return [...template.content.childNodes].map((node) => render(node, parent)).join("");
4942
5156
  }
4943
5157
  /**
4944
5158
  * Whether each month arrow is usable at this position in the allowed range.
@@ -4978,7 +5192,7 @@ var _Datepicker = class _Datepicker extends Component {
4978
5192
  }
4979
5193
  renderTitle(instance, c, year, month, refYear, randId) {
4980
5194
  const opts = this.options, isMinYear = year === opts.minYear, isMaxYear = year === opts.maxYear;
4981
- let i, j, arr = [], html = '<div id="' + randId + '" class="datepicker-controls" role="heading" aria-live="assertive">';
5195
+ let i, j, arr = [], html = '<div id="' + _Datepicker._escape(randId) + '" class="datepicker-controls" role="heading" aria-live="assertive">';
4982
5196
  const { prev, next } = this._arrowState(year, month);
4983
5197
  for (i = 0; i < 12; i++) {
4984
5198
  arr.push(
@@ -5047,6 +5261,9 @@ var _Datepicker = class _Datepicker extends Component {
5047
5261
  this._drawDirty = true;
5048
5262
  return;
5049
5263
  }
5264
+ const active = this.calendarEl.getRootNode().activeElement;
5265
+ const restoreDayFocus = active?.matches(".datepicker-day-button") && this.calendarEl.contains(active);
5266
+ const restoreArrow = this.calendarEl.contains(active) && active?.matches(".month-prev, .month-next") ? active.classList.contains("month-prev") ? ".month-prev" : ".month-next" : null;
5050
5267
  const opts = this.options, minYear = opts.minYear, maxYear = opts.maxYear, minMonth = opts.minMonth, maxMonth = opts.maxMonth;
5051
5268
  if (this._y <= minYear) {
5052
5269
  this._y = minYear;
@@ -5076,6 +5293,8 @@ var _Datepicker = class _Datepicker extends Component {
5076
5293
  this._rebuildControls(year, month);
5077
5294
  }
5078
5295
  this._renderCalendarTable(year, month);
5296
+ this._syncCalendarFocus(!!restoreDayFocus);
5297
+ if (restoreArrow) this.calendarEl.querySelector(restoreArrow)?.focus();
5079
5298
  if (typeof this.options.onDraw === "function") {
5080
5299
  this.options.onDraw.call(this);
5081
5300
  }
@@ -5122,7 +5341,12 @@ var _Datepicker = class _Datepicker extends Component {
5122
5341
  this.el.addEventListener("click", this._handleInputClick);
5123
5342
  this.el.addEventListener("keydown", this._handleInputKeydown);
5124
5343
  this.el.addEventListener("change", this._handleInputChange);
5344
+ this.endDateEl?.addEventListener("click", this._handleInputClick);
5345
+ this.endDateEl?.addEventListener("keydown", this._handleInputKeydown);
5346
+ this.endDateEl?.addEventListener("change", this._handleInputChange);
5125
5347
  this.calendarEl.addEventListener("click", this._handleCalendarClick);
5348
+ this.calendarEl.addEventListener("keydown", this._handleCalendarKeydown);
5349
+ this.calendarEl.addEventListener("focusin", this._handleCalendarFocus);
5126
5350
  }
5127
5351
  _setupVariables() {
5128
5352
  const template = document.createElement("template");
@@ -5168,14 +5392,43 @@ var _Datepicker = class _Datepicker extends Component {
5168
5392
  };
5169
5393
  }
5170
5394
  _removeEventHandlers() {
5171
- this.el.removeEventListener("click", this._handleInputClick);
5172
- this.el.removeEventListener("keydown", this._handleInputKeydown);
5173
- this.el.removeEventListener("change", this._handleInputChange);
5395
+ for (const input of this.dateEls ?? [this.el]) this._removeInputEventHandlers(input);
5174
5396
  this.calendarEl.removeEventListener("click", this._handleCalendarClick);
5397
+ this.calendarEl.removeEventListener("keydown", this._handleCalendarKeydown);
5398
+ this.calendarEl.removeEventListener("focusin", this._handleCalendarFocus);
5175
5399
  if (this.options.isDateRange && this.endDateEl) {
5176
- this.endDateEl.removeEventListener("click", this._handleInputClick);
5177
- this.endDateEl.removeEventListener("keypress", this._handleInputKeydown);
5178
- this.endDateEl.removeEventListener("change", this._handleInputChange);
5400
+ this._removeInputEventHandlers(this.endDateEl);
5401
+ }
5402
+ }
5403
+ _removeInputEventHandlers(input) {
5404
+ input.removeEventListener("click", this._handleInputClick);
5405
+ input.removeEventListener("keydown", this._handleInputKeydown);
5406
+ input.removeEventListener("change", this._handleInputChange);
5407
+ }
5408
+ _removeDateInput(input) {
5409
+ const focused = input.getRootNode().activeElement === input;
5410
+ this._removeInputEventHandlers(input);
5411
+ input.remove();
5412
+ if (focused && document.activeElement === document.body) this.el.focus();
5413
+ }
5414
+ _dayDate(button) {
5415
+ const date = /* @__PURE__ */ new Date(0);
5416
+ date.setFullYear(Number(button.dataset.year), Number(button.dataset.month), Number(button.dataset.day));
5417
+ _Datepicker._setToStartOfDay(date);
5418
+ return date;
5419
+ }
5420
+ _syncCalendarFocus(restore = false) {
5421
+ const buttons = [...this.calendarEl.querySelectorAll(".datepicker-day-button")];
5422
+ const current = buttons.filter((button) => !button.parentElement.classList.contains("is-selection-disabled"));
5423
+ const preferred = this._focusedDate || this.date || /* @__PURE__ */ new Date();
5424
+ const target = current.find((button) => _Datepicker._compareDates(this._dayDate(button), preferred)) || current.find((button) => button.parentElement.classList.contains("is-selected")) || current.find((button) => !button.parentElement.classList.contains("is-disabled")) || current[0];
5425
+ for (const button of buttons) {
5426
+ button.tabIndex = button === target ? 0 : -1;
5427
+ button.setAttribute("aria-disabled", String(button.parentElement.matches(".is-disabled, .is-selection-disabled")));
5428
+ }
5429
+ if (target) {
5430
+ this._focusedDate = this._dayDate(target);
5431
+ if (restore) target.focus();
5179
5432
  }
5180
5433
  }
5181
5434
  // change view to a specific month (zero-index, e.g. 0: January)
@@ -5203,7 +5456,7 @@ var _Datepicker = class _Datepicker extends Component {
5203
5456
  const dateInput = this.el.cloneNode(true);
5204
5457
  dateInput.removeAttribute("id");
5205
5458
  dateInput.addEventListener("click", this._handleInputClick);
5206
- dateInput.addEventListener("keypress", this._handleInputKeydown);
5459
+ dateInput.addEventListener("keydown", this._handleInputKeydown);
5207
5460
  dateInput.addEventListener("change", this._handleInputChange);
5208
5461
  this.el.parentElement.appendChild(dateInput);
5209
5462
  return dateInput;
@@ -5231,19 +5484,39 @@ var _defaults15 = {
5231
5484
  onCloseStart: null,
5232
5485
  onCloseEnd: null
5233
5486
  };
5234
- var Lightbox = class _Lightbox extends Component {
5487
+ var _Lightbox = class _Lightbox extends Component {
5235
5488
  constructor(el, options) {
5236
5489
  super(el, options, _Lightbox);
5490
+ /** Ancestors forced to `overflow: visible`, with the inline value to put back. */
5491
+ this._changedAncestorList = [];
5492
+ this._timers = /* @__PURE__ */ new Map();
5493
+ this._motion = window.matchMedia("(prefers-reduced-motion: reduce)");
5494
+ this._isOpen = false;
5495
+ this._destroyed = false;
5496
+ this._revision = 0;
5497
+ this._handleMotionChange = () => {
5498
+ if (!this._motion.matches) return;
5499
+ const callbacks = [...this._timers.values()];
5500
+ const revision = this._cancel();
5501
+ for (const callback of callbacks) {
5502
+ if (revision !== this._revision) break;
5503
+ callback();
5504
+ }
5505
+ if (this.overlayActive) {
5506
+ for (const el of [this.el, this._overlay, this._photoCaption]) if (el) el.style.transition = "none";
5507
+ }
5508
+ };
5237
5509
  this._handleLightboxClick = () => {
5238
5510
  this._handleLightboxToggle();
5239
5511
  };
5240
5512
  this._handleLightboxKeypress = (e) => {
5241
- if (e.key === Utils.keys.ENTER) {
5513
+ if (this._trigger === this.el && (e.key === Utils.keys.ENTER || e.key === " ")) {
5514
+ e.preventDefault();
5242
5515
  this._handleLightboxToggle();
5243
5516
  }
5244
5517
  };
5245
5518
  this._handleLightboxToggle = () => {
5246
- if (this.doneAnimating === false || this.overlayActive && this.doneAnimating) this.close();
5519
+ if (this._isOpen) this.close();
5247
5520
  else this.open();
5248
5521
  };
5249
5522
  this._handleWindowScroll = () => {
@@ -5253,12 +5526,16 @@ var Lightbox = class _Lightbox extends Component {
5253
5526
  if (this.overlayActive) this.close();
5254
5527
  };
5255
5528
  this._handleWindowEscape = (e) => {
5256
- if (e.key === Utils.keys.ESC && this.doneAnimating && this.overlayActive) this.close();
5529
+ if (e.key === Utils.keys.ESC) this.close();
5257
5530
  };
5258
5531
  /**
5259
5532
  * Open lightbox.
5260
5533
  */
5261
5534
  this.open = () => {
5535
+ if (this._destroyed || this._isOpen) return;
5536
+ const revision = this._cancel();
5537
+ if (this.overlayActive) this._reset();
5538
+ this._isOpen = true;
5262
5539
  this._updateVars();
5263
5540
  const originRect = this.el.getBoundingClientRect();
5264
5541
  const placeholderRect = this.placeholder.getBoundingClientRect();
@@ -5269,6 +5546,7 @@ var Lightbox = class _Lightbox extends Component {
5269
5546
  this.overlayActive = true;
5270
5547
  if (typeof this.options.onOpenStart === "function")
5271
5548
  this.options.onOpenStart.call(this, this.el);
5549
+ if (revision !== this._revision) return;
5272
5550
  this.placeholder.style.width = placeholderRect.width + "px";
5273
5551
  this.placeholder.style.height = placeholderRect.height + "px";
5274
5552
  this.placeholder.style.position = "relative";
@@ -5303,25 +5581,28 @@ var Lightbox = class _Lightbox extends Component {
5303
5581
  this.newWidth = this.windowHeight * 0.9 * ratio;
5304
5582
  this.newHeight = this.windowHeight * 0.9;
5305
5583
  }
5306
- this._animateImageIn();
5307
5584
  window.addEventListener("scroll", this._handleWindowScroll, { passive: true });
5308
5585
  window.addEventListener("resize", this._handleWindowResize, { passive: true });
5309
5586
  window.addEventListener("keyup", this._handleWindowEscape);
5587
+ this._animateImageIn();
5310
5588
  };
5311
5589
  /**
5312
5590
  * Close lightbox.
5313
5591
  */
5314
5592
  this.close = () => {
5315
- this._updateVars();
5593
+ if (this._destroyed || !this._isOpen) return;
5594
+ const revision = this._cancel();
5595
+ this._isOpen = false;
5316
5596
  this.doneAnimating = false;
5317
5597
  if (typeof this.options.onCloseStart === "function")
5318
5598
  this.options.onCloseStart.call(this, this.el);
5599
+ if (revision !== this._revision) return;
5319
5600
  window.removeEventListener("scroll", this._handleWindowScroll);
5320
5601
  window.removeEventListener("resize", this._handleWindowResize);
5321
5602
  window.removeEventListener("keyup", this._handleWindowEscape);
5322
- this._removeOverlay();
5603
+ if (this._overlay) this._removeOverlay();
5604
+ if (this._photoCaption) this._removeCaption();
5323
5605
  this._animateImageOut();
5324
- if (this.caption !== "") this._removeCaption();
5325
5606
  };
5326
5607
  this.el["Expressive_Lightbox"] = this;
5327
5608
  this.options = {
@@ -5336,7 +5617,9 @@ var Lightbox = class _Lightbox extends Component {
5336
5617
  this.originalHeight = 0;
5337
5618
  this.originInlineStyles = this.el.getAttribute("style");
5338
5619
  this.caption = this.el.getAttribute("data-caption") || "";
5339
- this.el.tabIndex = 0;
5620
+ this._tabindex = this.el.getAttribute("tabindex");
5621
+ this._trigger = this.el.closest("button") ?? this.el;
5622
+ this.el.tabIndex = this._trigger === this.el ? 0 : -1;
5340
5623
  this.el.before(this.placeholder);
5341
5624
  this.placeholder.append(this.el);
5342
5625
  this._setupEventHandlers();
@@ -5356,26 +5639,81 @@ var Lightbox = class _Lightbox extends Component {
5356
5639
  return el["Expressive_Lightbox"];
5357
5640
  }
5358
5641
  destroy() {
5642
+ if (this._destroyed) return;
5643
+ this._destroyed = true;
5644
+ const root = this.el.getRootNode();
5645
+ const focused = root.activeElement === this.el;
5359
5646
  this._removeEventHandlers();
5647
+ this._cancel();
5648
+ this._reset();
5649
+ this.placeholder.replaceWith(this.el);
5650
+ let active = document.activeElement;
5651
+ while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
5652
+ if (focused && (active === document.body || active === root.host)) this._trigger.focus();
5653
+ if (this._tabindex === null) this.el.removeAttribute("tabindex");
5654
+ else this.el.setAttribute("tabindex", this._tabindex);
5360
5655
  this.el["Expressive_Lightbox"] = void 0;
5361
- this.placeholder.remove();
5362
- this.el.removeAttribute("style");
5656
+ }
5657
+ _reset() {
5658
+ window.removeEventListener("scroll", this._handleWindowScroll);
5659
+ window.removeEventListener("resize", this._handleWindowResize);
5660
+ window.removeEventListener("keyup", this._handleWindowEscape);
5661
+ this._overlay?.remove();
5662
+ this._photoCaption?.remove();
5663
+ for (const ancestor of this._changedAncestorList) {
5664
+ const saved = _Lightbox._overflow.get(ancestor);
5665
+ if (--saved.count === 0) {
5666
+ ancestor.style.setProperty("overflow", saved.value, saved.priority);
5667
+ _Lightbox._overflow.delete(ancestor);
5668
+ }
5669
+ }
5670
+ this._changedAncestorList = [];
5671
+ if (this.attrWidth !== null && this.attrWidth !== void 0) this.el.setAttribute("width", this.attrWidth);
5672
+ if (this.attrHeight !== null && this.attrHeight !== void 0) this.el.setAttribute("height", this.attrHeight);
5673
+ this.el.classList.remove("active");
5674
+ this.placeholder.removeAttribute("style");
5675
+ if (this.originInlineStyles === null) this.el.removeAttribute("style");
5676
+ else this.el.setAttribute("style", this.originInlineStyles);
5677
+ this.overlayActive = false;
5678
+ this._isOpen = false;
5679
+ this.doneAnimating = true;
5680
+ }
5681
+ _cancel() {
5682
+ for (const timer of this._timers.keys()) clearTimeout(timer);
5683
+ this._timers.clear();
5684
+ return ++this._revision;
5685
+ }
5686
+ _schedule(callback, delay) {
5687
+ if (this._motion.matches) {
5688
+ callback();
5689
+ return;
5690
+ }
5691
+ const timer = setTimeout(() => {
5692
+ this._timers.delete(timer);
5693
+ callback();
5694
+ }, delay);
5695
+ this._timers.set(timer, callback);
5363
5696
  }
5364
5697
  _setupEventHandlers() {
5365
- this.el.addEventListener("click", this._handleLightboxClick);
5366
- this.el.addEventListener("keypress", this._handleLightboxKeypress);
5698
+ this._motion.addEventListener("change", this._handleMotionChange);
5699
+ this._trigger.addEventListener("click", this._handleLightboxClick);
5700
+ this.el.addEventListener("keydown", this._handleLightboxKeypress);
5367
5701
  }
5368
5702
  _removeEventHandlers() {
5369
- this.el.removeEventListener("click", this._handleLightboxClick);
5370
- this.el.removeEventListener("keypress", this._handleLightboxKeypress);
5703
+ this._motion.removeEventListener("change", this._handleMotionChange);
5704
+ this._trigger.removeEventListener("click", this._handleLightboxClick);
5705
+ this.el.removeEventListener("keydown", this._handleLightboxKeypress);
5371
5706
  }
5372
5707
  _makeAncestorsOverflowVisible() {
5373
5708
  this._changedAncestorList = [];
5374
5709
  let ancestor = this.placeholder.parentNode;
5375
5710
  while (ancestor !== null && ancestor !== void 0 && ancestor !== document) {
5376
5711
  const curr = ancestor;
5377
- if (curr.style && curr.style.overflow !== "visible") {
5378
- this._changedAncestorList.push([curr, curr.style.overflow]);
5712
+ if (curr.style && (curr.style.overflow !== "visible" || _Lightbox._overflow.has(curr))) {
5713
+ const saved = _Lightbox._overflow.get(curr) ?? { count: 0, value: curr.style.overflow, priority: curr.style.getPropertyPriority("overflow") };
5714
+ saved.count++;
5715
+ _Lightbox._overflow.set(curr, saved);
5716
+ this._changedAncestorList.push(curr);
5379
5717
  curr.style.overflow = "visible";
5380
5718
  }
5381
5719
  ancestor = ancestor.parentNode ?? ancestor.host;
@@ -5398,11 +5736,11 @@ var Lightbox = class _Lightbox extends Component {
5398
5736
  _animateImageIn() {
5399
5737
  this.el.style.maxHeight = this.newHeight.toString() + "px";
5400
5738
  this.el.style.maxWidth = this.newWidth.toString() + "px";
5401
- const duration = this.options.inDuration;
5739
+ const duration = this._motion.matches ? 0 : this.options.inDuration;
5402
5740
  this.el.style.transition = "none";
5403
5741
  this.el.style.height = this.originalHeight + "px";
5404
5742
  this.el.style.width = this.originalWidth + "px";
5405
- setTimeout(() => {
5743
+ this._schedule(() => {
5406
5744
  const placeholderOffset = this._offset(this.placeholder);
5407
5745
  this.el.style.transition = `height ${duration}ms ease,
5408
5746
  width ${duration}ms ease,
@@ -5414,13 +5752,13 @@ var Lightbox = class _Lightbox extends Component {
5414
5752
  this.el.style.left = Utils.getDocumentScrollLeft() + this.windowWidth / 2 - placeholderOffset.left - this.newWidth / 2 + "px";
5415
5753
  this.el.style.top = Utils.getDocumentScrollTop() + this.windowHeight / 2 - placeholderOffset.top - this.newHeight / 2 + "px";
5416
5754
  }, 1);
5417
- setTimeout(() => {
5755
+ this._schedule(() => {
5418
5756
  this.doneAnimating = true;
5419
5757
  if (typeof this.options.onOpenEnd === "function") this.options.onOpenEnd.call(this, this.el);
5420
5758
  }, duration);
5421
5759
  }
5422
5760
  _animateImageOut() {
5423
- const duration = this.options.outDuration;
5761
+ const duration = this._motion.matches ? 0 : this.options.outDuration;
5424
5762
  this.el.style.transition = `height ${duration}ms ease,
5425
5763
  width ${duration}ms ease,
5426
5764
  left ${duration}ms ease,
@@ -5430,19 +5768,8 @@ var Lightbox = class _Lightbox extends Component {
5430
5768
  this.el.style.width = this.originalWidth + "px";
5431
5769
  this.el.style.left = "0";
5432
5770
  this.el.style.top = "0";
5433
- setTimeout(() => {
5434
- this.placeholder.style.height = "";
5435
- this.placeholder.style.width = "";
5436
- this.placeholder.style.position = "";
5437
- this.placeholder.style.top = "";
5438
- this.placeholder.style.left = "";
5439
- if (this.attrWidth) this.el.setAttribute("width", this.attrWidth.toString());
5440
- if (this.attrHeight) this.el.setAttribute("height", this.attrHeight.toString());
5441
- this.el.removeAttribute("style");
5442
- if (this.originInlineStyles) this.el.setAttribute("style", this.originInlineStyles);
5443
- this.el.classList.remove("active");
5444
- this.doneAnimating = true;
5445
- this._changedAncestorList.forEach(([ancestor, overflow]) => ancestor.style.overflow = overflow);
5771
+ this._schedule(() => {
5772
+ this._reset();
5446
5773
  if (typeof this.options.onCloseEnd === "function")
5447
5774
  this.options.onCloseEnd.call(this, this.el);
5448
5775
  }, duration);
@@ -5456,19 +5783,16 @@ var Lightbox = class _Lightbox extends Component {
5456
5783
  this._photoCaption.style.display = "inline";
5457
5784
  this._photoCaption.style.transition = "none";
5458
5785
  this._photoCaption.style.opacity = "0";
5459
- const duration = this.options.inDuration;
5460
- setTimeout(() => {
5786
+ const duration = this._motion.matches ? 0 : this.options.inDuration;
5787
+ this._schedule(() => {
5461
5788
  this._photoCaption.style.transition = `opacity ${duration}ms ease`;
5462
5789
  this._photoCaption.style.opacity = "1";
5463
5790
  }, 1);
5464
5791
  }
5465
5792
  _removeCaption() {
5466
- const duration = this.options.outDuration;
5793
+ const duration = this._motion.matches ? 0 : this.options.outDuration;
5467
5794
  this._photoCaption.style.transition = `opacity ${duration}ms ease`;
5468
5795
  this._photoCaption.style.opacity = "0";
5469
- setTimeout(() => {
5470
- this._photoCaption.remove();
5471
- }, duration);
5472
5796
  }
5473
5797
  // Overlay
5474
5798
  _addOverlay() {
@@ -5476,8 +5800,9 @@ var Lightbox = class _Lightbox extends Component {
5476
5800
  this._overlay.id = "lightbox-overlay";
5477
5801
  this._overlay.addEventListener(
5478
5802
  "click",
5479
- () => {
5480
- if (this.doneAnimating) this.close();
5803
+ (event) => {
5804
+ event.stopPropagation();
5805
+ this.close();
5481
5806
  },
5482
5807
  { once: true }
5483
5808
  );
@@ -5489,22 +5814,20 @@ var Lightbox = class _Lightbox extends Component {
5489
5814
  this._overlay.style.top = -1 * overlayOffset.top + "px";
5490
5815
  this._overlay.style.transition = "none";
5491
5816
  this._overlay.style.opacity = "0";
5492
- const duration = this.options.inDuration;
5493
- setTimeout(() => {
5817
+ const duration = this._motion.matches ? 0 : this.options.inDuration;
5818
+ this._schedule(() => {
5494
5819
  this._overlay.style.transition = `opacity ${duration}ms ease`;
5495
5820
  this._overlay.style.opacity = "1";
5496
5821
  }, 1);
5497
5822
  }
5498
5823
  _removeOverlay() {
5499
- const duration = this.options.outDuration;
5824
+ const duration = this._motion.matches ? 0 : this.options.outDuration;
5500
5825
  this._overlay.style.transition = `opacity ${duration}ms ease`;
5501
5826
  this._overlay.style.opacity = "0";
5502
- setTimeout(() => {
5503
- this.overlayActive = false;
5504
- this._overlay.remove();
5505
- }, duration);
5506
5827
  }
5507
5828
  };
5829
+ _Lightbox._overflow = /* @__PURE__ */ new WeakMap();
5830
+ var Lightbox = _Lightbox;
5508
5831
 
5509
5832
  // src/ts/components/scrollspy.ts
5510
5833
  var _defaultGetActiveElement = (id) => `a[href="#${id}"]`;
@@ -5652,342 +5975,8 @@ _ScrollSpy._onIntersect = (entries) => {
5652
5975
  };
5653
5976
  var ScrollSpy = _ScrollSpy;
5654
5977
 
5655
- // src/ts/components/navigationDrawer.ts
5656
- var _defaults17 = {
5657
- edge: "left",
5658
- draggable: true,
5659
- dragTargetWidth: "10px",
5660
- onOpenStart: null,
5661
- onOpenEnd: null,
5662
- onCloseStart: null,
5663
- onCloseEnd: null
5664
- };
5665
- var EXPANDED_UP = "(width >= 840px)";
5666
- var _NavigationDrawer = class _NavigationDrawer extends Component {
5667
- constructor(el, options) {
5668
- super(el, options, _NavigationDrawer);
5669
- /**
5670
- * Opens the overlay drawer. No-op while the sidenav is docked
5671
- * (navigation-drawer-fixed at the Expanded breakpoint).
5672
- */
5673
- this.open = () => {
5674
- if (this._isCurrentlyFixed() || this.isOpen || !this._dialog) return;
5675
- _NavigationDrawer._sidenavs.forEach((other) => {
5676
- if (other !== this && other.isOpen) other.close();
5677
- });
5678
- if (typeof this.options.onOpenStart === "function") {
5679
- this.options.onOpenStart.call(this, this.el);
5680
- }
5681
- this.isOpen = true;
5682
- this._dialog.classList.remove("dragging");
5683
- this._clearShift();
5684
- if (!this._dialog.open) {
5685
- try {
5686
- this._dialog.showModal();
5687
- } catch {
5688
- }
5689
- }
5690
- this._syncTriggers();
5691
- if (typeof this.options.onOpenEnd === "function") {
5692
- this.options.onOpenEnd.call(this, this.el);
5693
- }
5694
- };
5695
- /**
5696
- * Closes the overlay drawer. No-op while the sidenav is docked.
5697
- */
5698
- this.close = () => {
5699
- if (this._isCurrentlyFixed() || !this.isOpen) return;
5700
- this._beginClose();
5701
- if (this._dialog?.open) {
5702
- this._closing = true;
5703
- this._dialog.close();
5704
- } else {
5705
- this._finishClose();
5706
- }
5707
- };
5708
- this._onDialogClose = () => {
5709
- if (this.isOpen) {
5710
- this._beginClose();
5711
- this._finishClose();
5712
- return;
5713
- }
5714
- if (this._closing) {
5715
- this._closing = false;
5716
- this._finishClose();
5717
- }
5718
- };
5719
- this._onBreakpointChange = () => {
5720
- if (this._isCurrentlyFixed() && this.isOpen) {
5721
- this.close();
5722
- }
5723
- };
5724
- this._handleCloseTriggerClick = (e) => {
5725
- const target = e.target;
5726
- if (!(target instanceof Element)) return;
5727
- const closeTrigger = target.closest(".sidenav-close, .navigation-drawer-close");
5728
- if (closeTrigger && !this._isCurrentlyFixed()) {
5729
- this.close();
5730
- }
5731
- };
5732
- this._handleDragTargetDrag = (e) => {
5733
- if (!this._isDraggable()) return;
5734
- const delta = this._rawDelta(e);
5735
- const towardOpen = this.options.edge === "left" ? delta : -delta;
5736
- const visible = Math.min(this._width, Math.max(0, towardOpen));
5737
- const percentOpen = this._width ? visible / this._width : 0;
5738
- this._applyShift(visible - this._width, percentOpen);
5739
- };
5740
- this._handleDragTargetRelease = () => {
5741
- if (!this.isDragged) return;
5742
- this._dialog?.classList.remove("dragging");
5743
- if (this.percentOpen > 0.2) {
5744
- this.open();
5745
- } else if (this._dialog?.open && !this.isOpen) {
5746
- this._clearShift();
5747
- this._dialog.close();
5748
- }
5749
- this.isDragged = false;
5750
- this._verticallyScrolling = false;
5751
- };
5752
- this._handleCloseDrag = (e) => {
5753
- if (!this.isOpen || !this._isDraggable()) return;
5754
- const delta = this._rawDelta(e);
5755
- const towardClose = this.options.edge === "left" ? -delta : delta;
5756
- const hidden = Math.min(this._width, Math.max(0, towardClose));
5757
- const percentOpen = this._width ? 1 - hidden / this._width : 1;
5758
- this._applyShift(-hidden, percentOpen);
5759
- };
5760
- this._handleCloseRelease = () => {
5761
- if (!this.isOpen || !this.isDragged) return;
5762
- this._dialog?.classList.remove("dragging");
5763
- if (this.percentOpen > 0.8) {
5764
- this._clearShift();
5765
- } else {
5766
- this.close();
5767
- }
5768
- this.isDragged = false;
5769
- this._verticallyScrolling = false;
5770
- };
5771
- this.el["Expressive_NavigationDrawer"] = this;
5772
- this.options = {
5773
- ..._NavigationDrawer.defaults,
5774
- ...options
5775
- };
5776
- this.id = this.el.id;
5777
- this.isOpen = false;
5778
- this.isFixed = this.el.classList.contains("navigation-drawer-fixed") || this.el.classList.contains("sidenav-fixed");
5779
- this.isDragged = false;
5780
- this.dragTarget = null;
5781
- this._dialog = null;
5782
- this._createdDialog = false;
5783
- this._closing = false;
5784
- this.percentOpen = 0;
5785
- this._startingXpos = 0;
5786
- this._xPos = 0;
5787
- this._width = 0;
5788
- this._initialScrollTop = 0;
5789
- this._verticallyScrolling = false;
5790
- this._mql = window.matchMedia(EXPANDED_UP);
5791
- this._setupDialog();
5792
- this._createDragTarget();
5793
- this._setupClasses();
5794
- this._setupEventHandlers();
5795
- this._syncTriggers();
5796
- _NavigationDrawer._sidenavs.push(this);
5797
- }
5798
- static get defaults() {
5799
- return _defaults17;
5800
- }
5801
- /**
5802
- * Initializes instances of NavigationDrawer.
5803
- * @param els HTML elements.
5804
- * @param options Component options.
5805
- */
5806
- static init(els, options = {}) {
5807
- return super.init(els, options, _NavigationDrawer);
5808
- }
5809
- static getInstance(el) {
5810
- return el["Expressive_NavigationDrawer"];
5811
- }
5812
- destroy() {
5813
- this._removeEventHandlers();
5814
- if (this._dialog?.open) {
5815
- try {
5816
- this._dialog.close();
5817
- } catch {
5818
- }
5819
- }
5820
- this._clearShift();
5821
- this._unwrapDialog();
5822
- this._removeDragTarget();
5823
- this.el["Expressive_NavigationDrawer"] = void 0;
5824
- const index = _NavigationDrawer._sidenavs.indexOf(this);
5825
- if (index >= 0) {
5826
- _NavigationDrawer._sidenavs.splice(index, 1);
5827
- }
5828
- }
5829
- _beginClose() {
5830
- this.isOpen = false;
5831
- this._dialog?.classList.remove("dragging");
5832
- this._clearShift();
5833
- if (typeof this.options.onCloseStart === "function") {
5834
- this.options.onCloseStart.call(this, this.el);
5835
- }
5836
- this._syncTriggers();
5837
- }
5838
- _finishClose() {
5839
- if (typeof this.options.onCloseEnd === "function") {
5840
- this.options.onCloseEnd.call(this, this.el);
5841
- }
5842
- }
5843
- _setupDialog() {
5844
- if (this.el instanceof HTMLDialogElement) {
5845
- this._dialog = this.el;
5846
- this._createdDialog = false;
5847
- return;
5848
- }
5849
- const parent = this.el.parentElement;
5850
- if (parent instanceof HTMLDialogElement && parent.classList.contains("sidenav-overlay")) {
5851
- this._dialog = parent;
5852
- this._createdDialog = false;
5853
- return;
5854
- }
5855
- const dialog = document.createElement("dialog");
5856
- dialog.classList.add("sidenav-overlay");
5857
- const named = this.el.closest("[aria-label], [aria-labelledby]") ?? this.el;
5858
- const label = named.getAttribute("aria-label");
5859
- const labelledBy = named.getAttribute("aria-labelledby");
5860
- if (label) dialog.setAttribute("aria-label", label);
5861
- else if (labelledBy) dialog.setAttribute("aria-labelledby", labelledBy);
5862
- this.el.replaceWith(dialog);
5863
- dialog.appendChild(this.el);
5864
- this._dialog = dialog;
5865
- this._createdDialog = true;
5866
- }
5867
- _unwrapDialog() {
5868
- if (!this._createdDialog || !this._dialog) return;
5869
- this._dialog.replaceWith(this.el);
5870
- this._dialog = null;
5871
- this._createdDialog = false;
5872
- }
5873
- _createDragTarget() {
5874
- if (!this.options.draggable) return;
5875
- const dragTarget = document.createElement("div");
5876
- dragTarget.classList.add("drag-target");
5877
- dragTarget.style.width = this.options.dragTargetWidth;
5878
- if (this.isFixed) dragTarget.dataset.fixed = "";
5879
- Utils.portalRoot(this.el).appendChild(dragTarget);
5880
- this.dragTarget = dragTarget;
5881
- }
5882
- _removeDragTarget() {
5883
- this.dragTarget?.remove();
5884
- this.dragTarget = null;
5885
- }
5886
- _setupClasses() {
5887
- if (this.options.edge === "right") {
5888
- this.el.classList.add("right-aligned");
5889
- this._dialog?.classList.add("right-aligned");
5890
- this.dragTarget?.classList.add("right-aligned");
5891
- }
5892
- }
5893
- _setupEventHandlers() {
5894
- if (_NavigationDrawer._sidenavs.length === 0) {
5895
- document.body.addEventListener("click", _NavigationDrawer._handleTriggerClick);
5896
- }
5897
- const passive = { passive: true };
5898
- this.dragTarget?.addEventListener("touchmove", this._handleDragTargetDrag, passive);
5899
- this.dragTarget?.addEventListener("touchend", this._handleDragTargetRelease);
5900
- this._dialog?.addEventListener("touchmove", this._handleCloseDrag, passive);
5901
- this._dialog?.addEventListener("touchend", this._handleCloseRelease);
5902
- this._dialog?.addEventListener("close", this._onDialogClose);
5903
- this.el.addEventListener("click", this._handleCloseTriggerClick);
5904
- this._mql.addEventListener("change", this._onBreakpointChange);
5905
- }
5906
- _removeEventHandlers() {
5907
- if (_NavigationDrawer._sidenavs.length === 1) {
5908
- document.body.removeEventListener("click", _NavigationDrawer._handleTriggerClick);
5909
- }
5910
- this.dragTarget?.removeEventListener("touchmove", this._handleDragTargetDrag);
5911
- this.dragTarget?.removeEventListener("touchend", this._handleDragTargetRelease);
5912
- this._dialog?.removeEventListener("touchmove", this._handleCloseDrag);
5913
- this._dialog?.removeEventListener("touchend", this._handleCloseRelease);
5914
- this._dialog?.removeEventListener("close", this._onDialogClose);
5915
- this.el.removeEventListener("click", this._handleCloseTriggerClick);
5916
- this._mql.removeEventListener("change", this._onBreakpointChange);
5917
- }
5918
- static _handleTriggerClick(e) {
5919
- const target = e.target;
5920
- if (!(target instanceof Element)) return;
5921
- const trigger = target.closest(".sidenav-trigger, .navigation-drawer-trigger");
5922
- if (!trigger || !(trigger instanceof HTMLElement)) return;
5923
- const sidenavId = Utils.getIdFromTrigger(trigger);
5924
- const sidenavInstance = Utils.getElementById(trigger, sidenavId)?.["Expressive_NavigationDrawer"];
5925
- if (sidenavInstance) {
5926
- sidenavInstance.open();
5927
- e.preventDefault();
5928
- }
5929
- }
5930
- _isDraggable() {
5931
- return this.options.draggable && !this._isCurrentlyFixed() && !this._verticallyScrolling;
5932
- }
5933
- _isCurrentlyFixed() {
5934
- return this.isFixed && this._mql.matches;
5935
- }
5936
- _startDrag(e) {
5937
- const clientX = e.targetTouches[0].clientX;
5938
- this.isDragged = true;
5939
- this._startingXpos = clientX;
5940
- this._xPos = clientX;
5941
- this._width = this._dialog?.getBoundingClientRect().width || this.el.getBoundingClientRect().width;
5942
- this._initialScrollTop = this.isOpen ? this.el.scrollTop : Utils.getDocumentScrollTop();
5943
- this._verticallyScrolling = false;
5944
- this._dialog?.classList.add("dragging");
5945
- if (this._dialog && !this._dialog.open) {
5946
- try {
5947
- this._dialog.showModal();
5948
- } catch {
5949
- }
5950
- }
5951
- }
5952
- _dragMoveUpdate(e) {
5953
- const clientX = e.targetTouches[0].clientX;
5954
- const currentScrollTop = this.isOpen ? this.el.scrollTop : Utils.getDocumentScrollTop();
5955
- this._xPos = clientX;
5956
- if (this._initialScrollTop !== currentScrollTop) {
5957
- this._verticallyScrolling = true;
5958
- }
5959
- }
5960
- _rawDelta(e) {
5961
- if (!this.isDragged) this._startDrag(e);
5962
- this._dragMoveUpdate(e);
5963
- return this._xPos - this._startingXpos;
5964
- }
5965
- _applyShift(shift, percentOpen) {
5966
- this.percentOpen = percentOpen;
5967
- const host = this._dialog ?? this.el;
5968
- host.style.setProperty("--md-comp-nav-drawer-shift", `${shift}px`);
5969
- host.style.setProperty("--md-comp-nav-drawer-open", String(percentOpen));
5970
- }
5971
- _clearShift() {
5972
- const host = this._dialog ?? this.el;
5973
- host.style.removeProperty("--md-comp-nav-drawer-shift");
5974
- host.style.removeProperty("--md-comp-nav-drawer-open");
5975
- }
5976
- _syncTriggers() {
5977
- if (!this.id) return;
5978
- document.querySelectorAll(".sidenav-trigger, .navigation-drawer-trigger").forEach((trigger) => {
5979
- if (!(trigger instanceof HTMLElement)) return;
5980
- if (Utils.getIdFromTrigger(trigger) !== this.id) return;
5981
- trigger.setAttribute("aria-expanded", this.isOpen ? "true" : "false");
5982
- trigger.setAttribute("aria-controls", this.id);
5983
- });
5984
- }
5985
- };
5986
- _NavigationDrawer._sidenavs = [];
5987
- var NavigationDrawer = _NavigationDrawer;
5988
-
5989
5978
  // src/ts/components/navigationRail.ts
5990
- var _defaults18 = {
5979
+ var _defaults17 = {
5991
5980
  onOpenStart: null,
5992
5981
  onOpenEnd: null,
5993
5982
  onCloseStart: null,
@@ -6063,7 +6052,7 @@ var NavigationRail = class _NavigationRail extends Component {
6063
6052
  document.addEventListener("keydown", this._onKeyDown);
6064
6053
  }
6065
6054
  static get defaults() {
6066
- return _defaults18;
6055
+ return _defaults17;
6067
6056
  }
6068
6057
  static init(els, options = {}) {
6069
6058
  return super.init(els, options, _NavigationRail);
@@ -6093,7 +6082,7 @@ var NavigationRail = class _NavigationRail extends Component {
6093
6082
  };
6094
6083
 
6095
6084
  // src/ts/components/tabs.ts
6096
- var _defaults19 = {
6085
+ var _defaults18 = {
6097
6086
  duration: 300,
6098
6087
  onShow: null,
6099
6088
  swipeable: false,
@@ -6102,7 +6091,10 @@ var _defaults19 = {
6102
6091
  };
6103
6092
  var Tabs = class _Tabs extends Component {
6104
6093
  constructor(el, options) {
6094
+ var _a;
6105
6095
  super(el, options, _Tabs);
6096
+ this._originalPanels = /* @__PURE__ */ new Map();
6097
+ this._originalLinks = /* @__PURE__ */ new Map();
6106
6098
  this._handleWindowResize = () => {
6107
6099
  this._setTabsAndTabWidth();
6108
6100
  if (this._tabWidth !== 0 && this._tabsWidth !== 0) {
@@ -6122,29 +6114,26 @@ var Tabs = class _Tabs extends Component {
6122
6114
  return;
6123
6115
  }
6124
6116
  if (tabLink.hasAttribute("target")) return;
6117
+ if (this.options.swipeable) {
6118
+ const panel = tabLink.hash && document.querySelector(tabLink.hash);
6119
+ const index = this._tabsCarousel.images.indexOf(panel);
6120
+ if (index >= 0) this._tabsCarousel.set(index);
6121
+ e.preventDefault();
6122
+ return;
6123
+ }
6125
6124
  const _oldContent = this._content;
6126
6125
  if (tabLink.hash) this._content = document.querySelector(tabLink.hash);
6127
6126
  this._tabLinks = this._queryTabLinks();
6128
- this._setActiveTabLink(tabLink);
6129
6127
  const prevIndex = this._index;
6130
- this._index = Math.max(Array.from(this._tabLinks).indexOf(tabLink), 0);
6131
- if (this.options.swipeable) {
6132
- if (this._tabsCarousel) {
6133
- this._tabsCarousel.set(this._index, () => {
6134
- if (typeof this.options.onShow === "function")
6135
- this.options.onShow.call(this, this._content);
6136
- });
6137
- }
6138
- } else {
6139
- if (this._content) {
6140
- this._content.style.display = "block";
6141
- this._content.classList.add("active");
6142
- if (typeof this.options.onShow === "function")
6143
- this.options.onShow.call(this, this._content);
6144
- if (_oldContent && _oldContent !== this._content) {
6145
- _oldContent.style.display = "none";
6146
- _oldContent.classList.remove("active");
6147
- }
6128
+ this._setActiveTabLink(tabLink);
6129
+ if (this._content) {
6130
+ this._content.style.display = "block";
6131
+ this._content.classList.add("active");
6132
+ if (typeof this.options.onShow === "function")
6133
+ this.options.onShow.call(this, this._content);
6134
+ if (_oldContent && _oldContent !== this._content) {
6135
+ _oldContent.style.display = "none";
6136
+ _oldContent.classList.remove("active");
6148
6137
  }
6149
6138
  }
6150
6139
  this._setTabsAndTabWidth();
@@ -6157,6 +6146,18 @@ var Tabs = class _Tabs extends Component {
6157
6146
  ...options
6158
6147
  };
6159
6148
  this._tabLinks = this._queryTabLinks();
6149
+ this._tabLinks.forEach((link) => {
6150
+ this._originalLinks.set(link, { active: link.classList.contains("active"), current: link.getAttribute("aria-current") });
6151
+ if (link.hasAttribute("target")) return;
6152
+ const panel = link.hash && document.querySelector(link.hash);
6153
+ if (panel) this._originalPanels.set(panel, {
6154
+ display: panel.style.display,
6155
+ priority: panel.style.getPropertyPriority("display"),
6156
+ active: panel.classList.contains("active"),
6157
+ carousel: panel.classList.contains("carousel-item")
6158
+ });
6159
+ });
6160
+ (_a = this.options).swipeable && (_a.swipeable = window.innerWidth <= this.options.responsiveThreshold);
6160
6161
  this._index = 0;
6161
6162
  this._setupActiveTabLink();
6162
6163
  if (this.options.swipeable) {
@@ -6169,7 +6170,7 @@ var Tabs = class _Tabs extends Component {
6169
6170
  this._setupEventHandlers();
6170
6171
  }
6171
6172
  static get defaults() {
6172
- return _defaults19;
6173
+ return _defaults18;
6173
6174
  }
6174
6175
  /**
6175
6176
  * Initializes instances of Tabs.
@@ -6184,12 +6185,21 @@ var Tabs = class _Tabs extends Component {
6184
6185
  }
6185
6186
  destroy() {
6186
6187
  this._removeEventHandlers();
6187
- this._indicator.parentNode.removeChild(this._indicator);
6188
+ this._indicator.remove();
6188
6189
  if (this.options.swipeable) {
6189
6190
  this._teardownSwipeableTabs();
6190
- } else {
6191
- this._teardownNormalTabs();
6192
6191
  }
6192
+ this._originalPanels.forEach((original, panel) => {
6193
+ panel.style.setProperty("display", original.display, original.priority);
6194
+ panel.classList.toggle("active", original.active);
6195
+ panel.classList.toggle("carousel-item", original.carousel);
6196
+ if (!panel.className) panel.removeAttribute("class");
6197
+ });
6198
+ this._originalLinks.forEach((original, link) => {
6199
+ link.classList.toggle("active", original.active);
6200
+ if (original.current === null) link.removeAttribute("aria-current");
6201
+ else link.setAttribute("aria-current", original.current);
6202
+ });
6193
6203
  this.el["Expressive_Tabs"] = void 0;
6194
6204
  }
6195
6205
  /**
@@ -6239,6 +6249,8 @@ var Tabs = class _Tabs extends Component {
6239
6249
  this._activeTabLink = tabLink;
6240
6250
  tabLink.classList.add("active");
6241
6251
  tabLink.setAttribute("aria-current", "page");
6252
+ this._index = Array.from(this._tabLinks).indexOf(tabLink);
6253
+ this._content = tabLink.hasAttribute("target") ? null : document.getElementById(tabLink.hash.slice(1));
6242
6254
  }
6243
6255
  _setupActiveTabLink() {
6244
6256
  this._activeTabLink = Array.from(this._tabLinks).find(
@@ -6252,18 +6264,14 @@ var Tabs = class _Tabs extends Component {
6252
6264
  this._activeTabLink = activeTabLink;
6253
6265
  }
6254
6266
  this._setActiveTabLink(this._activeTabLink);
6255
- this._index = Math.max(Array.from(this._tabLinks).indexOf(this._activeTabLink), 0);
6256
- if (this._activeTabLink && this._activeTabLink.hash) {
6257
- this._content = document.querySelector(this._activeTabLink.hash);
6258
- if (this._content) this._content.classList.add("active");
6259
- }
6267
+ this._originalPanels.forEach((_, panel) => panel.classList.toggle("active", panel === this._content));
6260
6268
  }
6261
6269
  _setupSwipeableTabs() {
6262
- if (window.innerWidth > this.options.responsiveThreshold) this.options.swipeable = false;
6263
6270
  const tabsContent = [];
6264
6271
  this._tabLinks.forEach((a) => {
6265
- if (a.hash) {
6272
+ if (a.hash && !a.hasAttribute("target")) {
6266
6273
  const currContent = document.querySelector(a.hash);
6274
+ if (!currContent) return;
6267
6275
  currContent.classList.add("carousel-item");
6268
6276
  tabsContent.push(currContent);
6269
6277
  }
@@ -6272,48 +6280,41 @@ var Tabs = class _Tabs extends Component {
6272
6280
  tabsWrapper.classList.add("tabs-content", "carousel", "flat");
6273
6281
  tabsContent[0].parentElement.insertBefore(tabsWrapper, tabsContent[0]);
6274
6282
  tabsContent.forEach((tabContent) => {
6283
+ const marker = document.createComment("");
6284
+ tabContent.before(marker);
6285
+ this._originalPanels.get(tabContent).marker = marker;
6275
6286
  tabsWrapper.appendChild(tabContent);
6276
6287
  tabContent.style.display = "";
6277
6288
  });
6278
6289
  this._tabsCarousel = Carousel.init(tabsWrapper, {
6279
6290
  fullWidth: true,
6280
6291
  noWrap: true,
6292
+ duration: this.options.duration,
6281
6293
  onCycleTo: (item) => {
6282
6294
  const prevIndex = this._index;
6283
- this._index = Array.from(item.parentNode.children).indexOf(item);
6284
- this._activeTabLink.classList.remove("active");
6285
- this._activeTabLink = Array.from(this._tabLinks)[this._index];
6286
- this._activeTabLink.classList.add("active");
6295
+ this._setActiveTabLink(Array.from(this._tabLinks).find((a) => !a.hasAttribute("target") && a.hash === "#" + item.id));
6296
+ this._setTabsAndTabWidth();
6287
6297
  this._animateIndicator(prevIndex);
6288
6298
  if (typeof this.options.onShow === "function")
6289
6299
  this.options.onShow.call(this, this._content);
6290
6300
  }
6291
6301
  });
6292
- this._tabsCarousel.set(this._index);
6293
6302
  }
6294
6303
  _teardownSwipeableTabs() {
6295
6304
  const tabsWrapper = this._tabsCarousel.el;
6296
6305
  this._tabsCarousel.destroy();
6297
- tabsWrapper.append(tabsWrapper.parentElement);
6306
+ this._originalPanels.forEach((original, panel) => original.marker?.replaceWith(panel));
6298
6307
  tabsWrapper.remove();
6299
6308
  }
6300
6309
  _setupNormalTabs() {
6301
6310
  Array.from(this._tabLinks).forEach((a) => {
6302
- if (a === this._activeTabLink) return;
6311
+ if (a === this._activeTabLink || a.hasAttribute("target")) return;
6303
6312
  if (a.hash) {
6304
6313
  const currContent = document.querySelector(a.hash);
6305
6314
  if (currContent) currContent.style.display = "none";
6306
6315
  }
6307
6316
  });
6308
6317
  }
6309
- _teardownNormalTabs() {
6310
- this._tabLinks.forEach((a) => {
6311
- if (a.hash) {
6312
- const currContent = document.querySelector(a.hash);
6313
- if (currContent) currContent.style.display = "";
6314
- }
6315
- });
6316
- }
6317
6318
  _setTabsAndTabWidth() {
6318
6319
  this._tabsWidth = this.el.getBoundingClientRect().width;
6319
6320
  this._tabWidth = Math.max(this._tabsWidth, this.el.scrollWidth) / this._tabLinks.length;
@@ -6356,7 +6357,7 @@ var Tabs = class _Tabs extends Component {
6356
6357
  };
6357
6358
 
6358
6359
  // src/ts/components/timepicker.ts
6359
- var _defaults20 = {
6360
+ var _defaults19 = {
6360
6361
  dialRadius: 135,
6361
6362
  outerRadius: 105,
6362
6363
  innerRadius: 70,
@@ -6373,7 +6374,9 @@ var _defaults20 = {
6373
6374
  i18n: {
6374
6375
  cancel: "Cancel",
6375
6376
  clear: "Clear",
6376
- done: "Ok"
6377
+ done: "Ok",
6378
+ hours: "Hours",
6379
+ minutes: "Minutes"
6377
6380
  },
6378
6381
  twelveHour: true,
6379
6382
  // change to 12 hour AM/PM clock from 24 hour
@@ -6396,17 +6399,17 @@ var _Timepicker = class _Timepicker extends Component {
6396
6399
  this._clockBuilt = false;
6397
6400
  this._handleInputClick = () => {
6398
6401
  this._ensureClockBuilt();
6402
+ if (this.displayPlugin) this.displayPlugin.show();
6399
6403
  this.inputHours.focus();
6400
6404
  if (typeof this.options.onInputInteraction === "function") this.options.onInputInteraction.call(this);
6401
- if (this.displayPlugin) this.displayPlugin.show();
6402
6405
  };
6403
6406
  this._handleInputKeydown = (e) => {
6404
6407
  if (e.key === Utils.keys.ENTER) {
6405
6408
  e.preventDefault();
6406
6409
  this._ensureClockBuilt();
6410
+ if (this.displayPlugin) this.displayPlugin.show();
6407
6411
  this.inputHours.focus();
6408
6412
  if (typeof this.options.onInputInteraction === "function") this.options.onInputInteraction.call(this);
6409
- if (this.displayPlugin) this.displayPlugin.show();
6410
6413
  }
6411
6414
  };
6412
6415
  this._handleClockClickStart = (e) => {
@@ -6476,11 +6479,6 @@ var _Timepicker = class _Timepicker extends Component {
6476
6479
  this._handleAmPmClick = (e) => {
6477
6480
  this._handleAmPmInteraction(e.target);
6478
6481
  };
6479
- this._handleAmPmKeypress = (e) => {
6480
- if (e.key === Utils.keys.ENTER) {
6481
- this._handleAmPmInteraction(e.target);
6482
- }
6483
- };
6484
6482
  this._handleAmPmInteraction = (e) => {
6485
6483
  this.amOrPm = e.classList.contains("am-btn") ? "AM" : "PM";
6486
6484
  this._updateAmPmView();
@@ -6503,26 +6501,16 @@ var _Timepicker = class _Timepicker extends Component {
6503
6501
  hideView.style.visibility = "hidden";
6504
6502
  }, this.options.duration);
6505
6503
  };
6506
- this._inputFromTextField = () => {
6507
- const isHours = this.currentView === "hours";
6508
- if (isHours && this.inputHours.value !== "") {
6509
- const value = parseInt(this.inputHours.value);
6510
- if (value > 0 && value < (this.options.twelveHour ? 13 : 24)) {
6511
- this.hours = value;
6512
- } else {
6513
- this.setHoursDefault();
6514
- }
6515
- this.drawClockFromTimeInput(this.hours, isHours);
6516
- } else if (!isHours && this.inputMinutes.value !== "") {
6517
- const value = parseInt(this.inputMinutes.value);
6518
- if (value >= 0 && value < 60) {
6519
- this.minutes = value;
6520
- } else {
6521
- this.minutes = (/* @__PURE__ */ new Date()).getMinutes();
6522
- this.inputMinutes.value = this.minutes.toString();
6523
- }
6524
- this.drawClockFromTimeInput(this.minutes, isHours);
6525
- }
6504
+ this._inputFromTextField = (event) => {
6505
+ const input = event.target;
6506
+ const isHours = input === this.inputHours;
6507
+ if (!isHours && input !== this.inputMinutes) return;
6508
+ const value = Number(input.value);
6509
+ const min = isHours && this.options.twelveHour ? 1 : 0;
6510
+ const max = isHours ? this.options.twelveHour ? 12 : 23 : 59;
6511
+ if (!input.value.trim() || !Number.isInteger(value) || value < min || value > max) return;
6512
+ this[isHours ? "hours" : "minutes"] = value;
6513
+ this.drawClockFromTimeInput(value, isHours);
6526
6514
  };
6527
6515
  this.done = (clearValue = null) => {
6528
6516
  const last = this.el.value;
@@ -6551,7 +6539,8 @@ var _Timepicker = class _Timepicker extends Component {
6551
6539
  this.el["Expressive_Timepicker"] = this;
6552
6540
  this.options = {
6553
6541
  ..._Timepicker.defaults,
6554
- ...options
6542
+ ...options,
6543
+ i18n: { ..._Timepicker.defaults.i18n, ...options?.i18n }
6555
6544
  };
6556
6545
  this.id = Utils.guid();
6557
6546
  this._insertHTMLIntoDOM();
@@ -6563,7 +6552,7 @@ var _Timepicker = class _Timepicker extends Component {
6563
6552
  }
6564
6553
  }
6565
6554
  static get defaults() {
6566
- return _defaults20;
6555
+ return _defaults19;
6567
6556
  }
6568
6557
  /**
6569
6558
  * Initializes instances of Timepicker.
@@ -6593,13 +6582,14 @@ var _Timepicker = class _Timepicker extends Component {
6593
6582
  this.el.addEventListener("click", this._handleInputClick);
6594
6583
  this.el.addEventListener("keydown", this._handleInputKeydown);
6595
6584
  this.plate.addEventListener("pointerdown", this._handleClockClickStart);
6596
- this.digitalClock.addEventListener("keyup", this._inputFromTextField);
6585
+ this.digitalClock.addEventListener("input", this._inputFromTextField);
6597
6586
  this.inputHours.addEventListener("focus", () => this.showView("hours"));
6598
6587
  this.inputHours.addEventListener("focusout", () => this.formatHours());
6599
6588
  this.inputMinutes.addEventListener("focus", () => this.showView("minutes"));
6600
6589
  this.inputMinutes.addEventListener("focusout", () => this.formatMinutes());
6601
6590
  }
6602
6591
  _removeEventHandlers() {
6592
+ this.digitalClock.removeEventListener("input", this._inputFromTextField);
6603
6593
  this.el.removeEventListener("click", this._handleInputClick);
6604
6594
  this.el.removeEventListener("keydown", this._handleInputKeydown);
6605
6595
  document.removeEventListener("pointermove", this._handleDocumentClickMove);
@@ -6629,6 +6619,8 @@ var _Timepicker = class _Timepicker extends Component {
6629
6619
  this.minutesView = this.containerEl.querySelector(".timepicker-minutes");
6630
6620
  this.inputHours = this.containerEl.querySelector(".timepicker-input-hours");
6631
6621
  this.inputMinutes = this.containerEl.querySelector(".timepicker-input-minutes");
6622
+ this.inputHours.setAttribute("aria-label", this.options.i18n.hours);
6623
+ this.inputMinutes.setAttribute("aria-label", this.options.i18n.minutes);
6632
6624
  this.spanAmPm = this.containerEl.querySelector(".timepicker-span-am-pm");
6633
6625
  this.footer = this.containerEl.querySelector(".timepicker-footer");
6634
6626
  this.amOrPm = "PM";
@@ -6666,19 +6658,17 @@ var _Timepicker = class _Timepicker extends Component {
6666
6658
  }
6667
6659
  _clockSetup() {
6668
6660
  if (this.options.twelveHour) {
6669
- this._amBtn = document.createElement("div");
6661
+ this._amBtn = document.createElement("button");
6662
+ this._amBtn.type = "button";
6670
6663
  this._amBtn.classList.add("am-btn");
6671
6664
  this._amBtn.innerText = "AM";
6672
- this._amBtn.tabIndex = 0;
6673
6665
  this._amBtn.addEventListener("click", this._handleAmPmClick);
6674
- this._amBtn.addEventListener("keypress", this._handleAmPmKeypress);
6675
6666
  this.spanAmPm.appendChild(this._amBtn);
6676
- this._pmBtn = document.createElement("div");
6667
+ this._pmBtn = document.createElement("button");
6668
+ this._pmBtn.type = "button";
6677
6669
  this._pmBtn.classList.add("pm-btn");
6678
6670
  this._pmBtn.innerText = "PM";
6679
- this._pmBtn.tabIndex = 0;
6680
6671
  this._pmBtn.addEventListener("click", this._handleAmPmClick);
6681
- this._pmBtn.addEventListener("keypress", this._handleAmPmKeypress);
6682
6672
  this.spanAmPm.appendChild(this._pmBtn);
6683
6673
  }
6684
6674
  this._buildHoursView();
@@ -6754,6 +6744,10 @@ var _Timepicker = class _Timepicker extends Component {
6754
6744
  }
6755
6745
  _updateAmPmView() {
6756
6746
  if (!this._amBtn || !this._pmBtn) return;
6747
+ this._amBtn.setAttribute("aria-pressed", String(this.amOrPm === "AM"));
6748
+ this._pmBtn.setAttribute("aria-pressed", String(this.amOrPm === "PM"));
6749
+ this._amBtn.classList.toggle("outlined", this.amOrPm !== "AM");
6750
+ this._pmBtn.classList.toggle("outlined", this.amOrPm !== "PM");
6757
6751
  if (this.options.twelveHour) {
6758
6752
  if (this.amOrPm === "PM") {
6759
6753
  this._amBtn.classList.remove("filled");
@@ -6765,24 +6759,19 @@ var _Timepicker = class _Timepicker extends Component {
6765
6759
  }
6766
6760
  }
6767
6761
  _updateTimeFromInput() {
6768
- let value = ((this.el.value || this.options.defaultTime || "") + "").split(":");
6769
- if (this.options.twelveHour && !(typeof value[1] === "undefined")) {
6770
- if (value[1].toUpperCase().indexOf("AM") > 0) {
6771
- this.amOrPm = "AM";
6772
- } else {
6773
- this.amOrPm = "PM";
6774
- }
6775
- value[1] = value[1].replace("AM", "").replace("PM", "");
6776
- }
6777
- if (value[0] === "now") {
6762
+ let value = ((this.el.value || this.options.defaultTime || "") + "").trim().toUpperCase().split(":");
6763
+ const period = value[1]?.match(/AM|PM/)?.[0];
6764
+ value[1] = value[1]?.replace(/AM|PM/, "");
6765
+ if (value[0] === "NOW") {
6778
6766
  const now = new Date(+/* @__PURE__ */ new Date() + this.options.fromNow);
6779
6767
  value = [now.getHours().toString(), now.getMinutes().toString()];
6780
- if (this.options.twelveHour) {
6781
- this.amOrPm = parseInt(value[0]) >= 12 && parseInt(value[0]) < 24 ? "PM" : "AM";
6782
- }
6783
6768
  }
6784
6769
  this.hours = +value[0] || 0;
6785
6770
  this.minutes = +value[1] || 0;
6771
+ if (this.options.twelveHour) {
6772
+ this.amOrPm = period === "AM" || period === "PM" ? period : this.hours >= 12 ? "PM" : "AM";
6773
+ this.hours = this.hours % 12 || 12;
6774
+ }
6786
6775
  this.inputHours.value = _Timepicker._addLeadingZero(this.hours);
6787
6776
  this.inputMinutes.value = _Timepicker._addLeadingZero(this.minutes);
6788
6777
  this._updateAmPmView();
@@ -6871,15 +6860,16 @@ var _Timepicker = class _Timepicker extends Component {
6871
6860
  }
6872
6861
  formatHours() {
6873
6862
  if (this.inputHours.value == "") this.setHoursDefault();
6874
- this.inputHours.value = _Timepicker._addLeadingZero(Number(this.inputHours.value));
6863
+ this.inputHours.value = _Timepicker._addLeadingZero(this.hours);
6875
6864
  }
6876
6865
  formatMinutes() {
6877
6866
  if (this.inputMinutes.value == "") this.minutes = (/* @__PURE__ */ new Date()).getMinutes();
6878
- this.inputMinutes.value = _Timepicker._addLeadingZero(Number(this.inputMinutes.value));
6867
+ this.inputMinutes.value = _Timepicker._addLeadingZero(this.minutes);
6879
6868
  }
6880
6869
  setHoursDefault() {
6881
6870
  this.hours = (/* @__PURE__ */ new Date()).getHours();
6882
- this.inputHours.value = (this.hours % (this.options.twelveHour ? 12 : 24)).toString();
6871
+ if (this.options.twelveHour) this.hours = this.hours % 12 || 12;
6872
+ this.inputHours.value = this.hours.toString();
6883
6873
  }
6884
6874
  };
6885
6875
  _Timepicker._template = `<div class="timepicker-container">
@@ -6913,7 +6903,7 @@ _Timepicker._template = `<div class="timepicker-container">
6913
6903
  var Timepicker = _Timepicker;
6914
6904
 
6915
6905
  // src/ts/components/snackbar.ts
6916
- var _defaults21 = {
6906
+ var _defaults20 = {
6917
6907
  text: "",
6918
6908
  action: "",
6919
6909
  onAction: null,
@@ -6929,24 +6919,28 @@ var _defaults21 = {
6929
6919
  var _Snackbar = class _Snackbar {
6930
6920
  constructor(options = {}) {
6931
6921
  this._dismissed = false;
6922
+ this._returnFocus = null;
6932
6923
  this.options = {
6933
6924
  ..._Snackbar.defaults,
6934
6925
  ...options
6935
6926
  };
6936
6927
  if (options.displayLength === void 0 && this.options.action) {
6937
- this.options.displayLength = 1e4;
6928
+ this.options.displayLength = Infinity;
6938
6929
  }
6930
+ if (options.dismissible === void 0 && this.options.action) this.options.dismissible = true;
6939
6931
  this.message = this.options.text;
6940
6932
  this.panning = false;
6941
6933
  this.timeRemaining = this.options.displayLength;
6942
- if (_Snackbar._snackbars.length > 0) {
6943
- for (const snackbar of [..._Snackbar._snackbars]) {
6944
- snackbar._dismissed = true;
6945
- clearTimeout(snackbar.counterTimeout);
6946
- snackbar.el.remove();
6947
- }
6948
- _Snackbar._snackbars.length = 0;
6949
- }
6934
+ while (_Snackbar._snackbars.length > 0) {
6935
+ const snackbar = _Snackbar._snackbars.shift();
6936
+ snackbar._dismissed = true;
6937
+ clearTimeout(snackbar.counterTimeout);
6938
+ snackbar._restoreFocus();
6939
+ snackbar.el.remove();
6940
+ }
6941
+ let focused = document.activeElement;
6942
+ while (focused?.shadowRoot?.activeElement) focused = focused.shadowRoot.activeElement;
6943
+ this._returnFocus = focused instanceof HTMLElement ? focused : null;
6950
6944
  const root = Utils.portalRoot(this.options.root ?? document.body);
6951
6945
  if (!_Snackbar._container || !_Snackbar._container.isConnected || _Snackbar._container.parentNode !== root) {
6952
6946
  if (_Snackbar._container) _Snackbar._removeContainer();
@@ -6960,7 +6954,7 @@ var _Snackbar = class _Snackbar {
6960
6954
  this._setTimer();
6961
6955
  }
6962
6956
  static get defaults() {
6963
- return _defaults21;
6957
+ return _defaults20;
6964
6958
  }
6965
6959
  static getInstance(el) {
6966
6960
  return el["Expressive_Snackbar"];
@@ -7074,6 +7068,22 @@ var _Snackbar = class _Snackbar {
7074
7068
  snackbar.setAttribute("role", "status");
7075
7069
  snackbar.setAttribute("aria-live", "polite");
7076
7070
  snackbar.setAttribute("aria-atomic", "true");
7071
+ snackbar.inert = false;
7072
+ snackbar.addEventListener("focusin", (e) => {
7073
+ if (e.relatedTarget instanceof HTMLElement && !snackbar.contains(e.relatedTarget)) {
7074
+ this._returnFocus = e.relatedTarget;
7075
+ }
7076
+ this._pauseTimer();
7077
+ });
7078
+ snackbar.addEventListener("keydown", (e) => {
7079
+ if (e.key !== "Escape" || e.defaultPrevented || this._dismissed) return;
7080
+ e.preventDefault();
7081
+ e.stopPropagation();
7082
+ this.dismiss();
7083
+ });
7084
+ snackbar.addEventListener("focusout", () => setTimeout(() => this._resumeTimer(), 0));
7085
+ snackbar.addEventListener("pointerenter", () => this._pauseTimer());
7086
+ snackbar.addEventListener("pointerleave", () => this._resumeTimer());
7077
7087
  if (this.options.classes.length > 0) {
7078
7088
  snackbar.classList.add(...this.options.classes.split(" ").filter(Boolean));
7079
7089
  }
@@ -7088,10 +7098,12 @@ var _Snackbar = class _Snackbar {
7088
7098
  action.textContent = this.options.action;
7089
7099
  action.addEventListener("click", (e) => {
7090
7100
  e.stopPropagation();
7091
- if (typeof this.options.onAction === "function") {
7092
- this.options.onAction();
7101
+ if (this._dismissed) return;
7102
+ try {
7103
+ if (typeof this.options.onAction === "function") this.options.onAction();
7104
+ } finally {
7105
+ this.dismiss();
7093
7106
  }
7094
- this.dismiss();
7095
7107
  });
7096
7108
  snackbar.appendChild(action);
7097
7109
  }
@@ -7148,9 +7160,16 @@ var _Snackbar = class _Snackbar {
7148
7160
  }
7149
7161
  /** Restart a countdown stopped by {@link _pauseTimer}. */
7150
7162
  _resumeTimer() {
7151
- if (this.counterTimeout != null) return;
7163
+ if (this._dismissed || this.panning || this.el.matches(":hover, :focus-within") || this.counterTimeout != null) return;
7152
7164
  this._setTimer();
7153
7165
  }
7166
+ _restoreFocus() {
7167
+ const focused = this.el.getRootNode().activeElement;
7168
+ if (focused && this.el.contains(focused) && this._returnFocus?.isConnected) {
7169
+ this._returnFocus.focus({ preventScroll: true });
7170
+ }
7171
+ this.el.inert = true;
7172
+ }
7154
7173
  /**
7155
7174
  * Dismiss snackbar with animation.
7156
7175
  */
@@ -7159,6 +7178,7 @@ var _Snackbar = class _Snackbar {
7159
7178
  this._dismissed = true;
7160
7179
  clearTimeout(this.counterTimeout);
7161
7180
  this.counterTimeout = null;
7181
+ this._restoreFocus();
7162
7182
  const activationDistance = this.el.offsetWidth * this.options.activationPercent;
7163
7183
  if (this.wasSwiped) {
7164
7184
  this.el.style.transition = "transform .05s, opacity .05s";
@@ -7195,7 +7215,7 @@ _Snackbar._draggedSnackbar = null;
7195
7215
  var Snackbar = _Snackbar;
7196
7216
 
7197
7217
  // src/ts/components/tooltip.ts
7198
- var _defaults22 = {
7218
+ var _defaults21 = {
7199
7219
  exitDelay: 200,
7200
7220
  enterDelay: 0,
7201
7221
  text: "",
@@ -7215,6 +7235,8 @@ var Tooltip = class _Tooltip extends Component {
7215
7235
  this.open = (isManual) => {
7216
7236
  if (this.isOpen) return;
7217
7237
  isManual = isManual === void 0 ? true : void 0;
7238
+ clearTimeout(this._exitDelayTimeout);
7239
+ clearTimeout(this._animationTimeout);
7218
7240
  this.isOpen = true;
7219
7241
  this.options = { ...this.options, ...this._getAttributeOptions() };
7220
7242
  this._updateTooltipContent();
@@ -7228,29 +7250,40 @@ var Tooltip = class _Tooltip extends Component {
7228
7250
  this.isHovered = false;
7229
7251
  this.isFocused = false;
7230
7252
  this.isOpen = false;
7253
+ clearTimeout(this._enterDelayTimeout);
7231
7254
  this._setExitDelayTimeout();
7232
7255
  };
7233
7256
  this._handleMouseEnter = () => {
7234
7257
  this.isHovered = true;
7235
- this.isFocused = false;
7236
7258
  this.open(false);
7237
7259
  };
7238
- this._handleMouseLeave = () => {
7260
+ this._handleMouseLeave = (event) => {
7261
+ const next = event.relatedTarget;
7262
+ if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;
7239
7263
  this.isHovered = false;
7240
- this.isFocused = false;
7264
+ if (!this.isFocused) this.close();
7265
+ };
7266
+ this._handleKeydown = (event) => {
7267
+ if (event.key !== "Escape" || !this.isOpen) return;
7268
+ event.preventDefault();
7269
+ event.stopPropagation();
7241
7270
  this.close();
7271
+ clearTimeout(this._exitDelayTimeout);
7272
+ this._animateOut();
7242
7273
  };
7243
7274
  // Focus opens the tooltip only when it arrived by keyboard: a pointer press
7244
7275
  // on the trigger also focuses it, and _handleMouseEnter already covers that.
7245
- this._handleFocus = () => {
7246
- if (this.el.matches(":focus-visible")) {
7276
+ this._handleFocus = (event) => {
7277
+ if (event.target.matches(":focus-visible")) {
7247
7278
  this.isFocused = true;
7248
7279
  this.open(false);
7249
7280
  }
7250
7281
  };
7251
- this._handleBlur = () => {
7282
+ this._handleBlur = (event) => {
7283
+ const next = event.relatedTarget;
7284
+ if (next && (this.el.contains(next) || this.tooltipEl.contains(next))) return;
7252
7285
  this.isFocused = false;
7253
- this.close();
7286
+ if (!this.isHovered) this.close();
7254
7287
  };
7255
7288
  this.el["Expressive_Tooltip"] = this;
7256
7289
  this.options = {
@@ -7265,7 +7298,7 @@ var Tooltip = class _Tooltip extends Component {
7265
7298
  this._setupEventHandlers();
7266
7299
  }
7267
7300
  static get defaults() {
7268
- return _defaults22;
7301
+ return _defaults21;
7269
7302
  }
7270
7303
  /**
7271
7304
  * Initializes instances of Tooltip.
@@ -7316,16 +7349,22 @@ var Tooltip = class _Tooltip extends Component {
7316
7349
  this._setTooltipContent(this.tooltipEl.querySelector(".tooltip-content"));
7317
7350
  }
7318
7351
  _setupEventHandlers() {
7319
- this.el.addEventListener("mouseenter", this._handleMouseEnter);
7320
- this.el.addEventListener("mouseleave", this._handleMouseLeave);
7321
- this.el.addEventListener("focus", this._handleFocus, true);
7322
- this.el.addEventListener("blur", this._handleBlur, true);
7352
+ for (const el of [this.el, this.tooltipEl]) {
7353
+ el.addEventListener("mouseenter", this._handleMouseEnter);
7354
+ el.addEventListener("mouseleave", this._handleMouseLeave);
7355
+ el.addEventListener("focus", this._handleFocus, true);
7356
+ el.addEventListener("blur", this._handleBlur, true);
7357
+ }
7358
+ this.el.ownerDocument.addEventListener("keydown", this._handleKeydown, true);
7323
7359
  }
7324
7360
  _removeEventHandlers() {
7325
- this.el.removeEventListener("mouseenter", this._handleMouseEnter);
7326
- this.el.removeEventListener("mouseleave", this._handleMouseLeave);
7327
- this.el.removeEventListener("focus", this._handleFocus, true);
7328
- this.el.removeEventListener("blur", this._handleBlur, true);
7361
+ for (const el of [this.el, this.tooltipEl]) {
7362
+ el.removeEventListener("mouseenter", this._handleMouseEnter);
7363
+ el.removeEventListener("mouseleave", this._handleMouseLeave);
7364
+ el.removeEventListener("focus", this._handleFocus, true);
7365
+ el.removeEventListener("blur", this._handleBlur, true);
7366
+ }
7367
+ this.el.ownerDocument.removeEventListener("keydown", this._handleKeydown, true);
7329
7368
  }
7330
7369
  _setExitDelayTimeout() {
7331
7370
  clearTimeout(this._exitDelayTimeout);
@@ -7372,6 +7411,7 @@ var Tooltip = class _Tooltip extends Component {
7372
7411
  tooltipWidth,
7373
7412
  tooltipHeight
7374
7413
  );
7414
+ tooltip.style.setProperty("--md-comp-tooltip-anchor-gap", `${Math.max(0, margin) + Math.abs(this.options.transitionMovement)}px`);
7375
7415
  tooltip.style.top = newCoordinates.y + "px";
7376
7416
  tooltip.style.left = newCoordinates.x + "px";
7377
7417
  }
@@ -7387,27 +7427,29 @@ var Tooltip = class _Tooltip extends Component {
7387
7427
  );
7388
7428
  }
7389
7429
  _animateIn() {
7390
- this._positionTooltip();
7391
- this.tooltipEl.style.visibility = "visible";
7392
- const duration = this.options.inDuration;
7393
- this.tooltipEl.style.transition = `
7394
- transform ${duration}ms ease-out,
7395
- opacity ${duration}ms ease-out`;
7396
- clearTimeout(this._animationTimeout);
7397
- this._animationTimeout = setTimeout(() => {
7398
- this.tooltipEl.style.transform = `translateX(${this.xMovement}px) translateY(${this.yMovement}px)`;
7399
- this.tooltipEl.style.opacity = (this.options.opacity || 1).toString();
7400
- }, 1);
7430
+ this._animate(true);
7401
7431
  }
7402
7432
  _animateOut() {
7403
- const duration = this.options.outDuration;
7404
- this.tooltipEl.style.transition = `
7405
- transform ${duration}ms ease-out,
7406
- opacity ${duration}ms ease-out`;
7433
+ this._animate(false);
7434
+ }
7435
+ _animate(show) {
7436
+ const style = this.tooltipEl.style;
7437
+ const reduce = this.el.ownerDocument.defaultView.matchMedia("(prefers-reduced-motion: reduce)").matches;
7438
+ const duration = reduce ? 0 : show ? this.options.inDuration : this.options.outDuration;
7439
+ if (show) {
7440
+ this._positionTooltip();
7441
+ style.visibility = "visible";
7442
+ style.overflow = "visible";
7443
+ }
7444
+ style.transition = `transform ${duration}ms ease-out, opacity ${duration}ms ease-out`;
7407
7445
  clearTimeout(this._animationTimeout);
7408
7446
  this._animationTimeout = setTimeout(() => {
7409
- this.tooltipEl.style.transform = `translateX(0px) translateY(0px)`;
7410
- this.tooltipEl.style.opacity = "0";
7447
+ style.transform = show && !reduce ? `translateX(${this.xMovement}px) translateY(${this.yMovement}px)` : "none";
7448
+ style.opacity = show ? (this.options.opacity || 1).toString() : "0";
7449
+ if (!show) this._animationTimeout = setTimeout(() => {
7450
+ style.visibility = "hidden";
7451
+ style.overflow = "";
7452
+ }, duration);
7411
7453
  }, 1);
7412
7454
  }
7413
7455
  _getAttributeOptions() {
@@ -7459,10 +7501,6 @@ var AUTO_INIT_COMPONENTS = {
7459
7501
  Lightbox: { component: Lightbox, selector: ".lightboxed" },
7460
7502
  ScrollSpy: { component: ScrollSpy, selector: ".scrollspy" },
7461
7503
  FormSelect: { component: FormSelect, selector: "select" },
7462
- NavigationDrawer: {
7463
- component: NavigationDrawer,
7464
- selector: ".sidenav, .navigation-drawer"
7465
- },
7466
7504
  NavigationRail: {
7467
7505
  component: NavigationRail,
7468
7506
  selector: ".navigation-rail"
@@ -7475,7 +7513,7 @@ var AUTO_INIT_COMPONENTS = {
7475
7513
  Tooltip: { component: Tooltip, selector: ".tooltipped" },
7476
7514
  FloatingActionButton: {
7477
7515
  component: FloatingActionButton,
7478
- selector: ".fab, .fixed-action-btn, .fab-menu"
7516
+ selector: ".fab-menu"
7479
7517
  }
7480
7518
  };
7481
7519
  function AutoInit(context = document.body, options) {
@@ -7492,8 +7530,10 @@ function AutoInit(context = document.body, options) {
7492
7530
  }
7493
7531
  }
7494
7532
 
7533
+ // src/ts/modular.ts
7534
+ var version = "0.10.0";
7535
+
7495
7536
  // src/ts/index.ts
7496
- var version = "0.9.0";
7497
7537
  Forms.Init();
7498
7538
  Chips.Init();
7499
7539
  Slider.Init();