@expressivecss/expressive 0.10.1 → 0.12.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 (157) hide show
  1. package/CHANGELOG.md +238 -7
  2. package/README.md +22 -1
  3. package/dist/css/expressive.css +272 -107
  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-YFXEJ7GR.mjs → chunk-3VOK6J7U.mjs} +7 -8
  11. package/dist/js/chunks/chunk-3VOK6J7U.mjs.map +7 -0
  12. package/dist/js/chunks/{chunk-XDB3G6RL.mjs → chunk-6N2XAEFK.mjs} +15 -4
  13. package/dist/js/chunks/{chunk-XDB3G6RL.mjs.map → chunk-6N2XAEFK.mjs.map} +2 -2
  14. package/dist/js/chunks/{chunk-MISGHDUU.mjs → chunk-6OMRGML6.mjs} +9 -7
  15. package/dist/js/chunks/{chunk-MISGHDUU.mjs.map → chunk-6OMRGML6.mjs.map} +2 -2
  16. package/dist/js/chunks/{chunk-A3BJA7V4.mjs → chunk-6WLSDZ4O.mjs} +2 -2
  17. package/dist/js/chunks/{chunk-JODJAGFS.mjs → chunk-CKQP6P76.mjs} +31 -8
  18. package/dist/js/chunks/chunk-CKQP6P76.mjs.map +7 -0
  19. package/dist/js/chunks/{chunk-KR44BSYQ.mjs → chunk-DLWYKFEI.mjs} +3 -3
  20. package/dist/js/chunks/{chunk-SLFNPY5M.mjs → chunk-EC63CHXU.mjs} +2 -2
  21. package/dist/js/chunks/chunk-G3I5H2U3.mjs +7 -0
  22. package/dist/js/chunks/{chunk-ZAOYQ6SY.mjs.map → chunk-G3I5H2U3.mjs.map} +1 -1
  23. package/dist/js/chunks/{chunk-LZVBJ33S.mjs → chunk-GZWPXXY6.mjs} +15 -8
  24. package/dist/js/chunks/chunk-GZWPXXY6.mjs.map +7 -0
  25. package/dist/js/chunks/{chunk-QYCYP443.mjs → chunk-H2WA4XHH.mjs} +43 -36
  26. package/dist/js/chunks/chunk-H2WA4XHH.mjs.map +7 -0
  27. package/dist/js/chunks/{chunk-G576EP5O.mjs → chunk-HB6IW7QQ.mjs} +78 -16
  28. package/dist/js/chunks/chunk-HB6IW7QQ.mjs.map +7 -0
  29. package/dist/js/chunks/{chunk-7MM4VJJO.mjs → chunk-HLDXZ7XB.mjs} +23 -15
  30. package/dist/js/chunks/chunk-HLDXZ7XB.mjs.map +7 -0
  31. package/dist/js/chunks/{chunk-ZIZVUWRL.mjs → chunk-HNFSMIBY.mjs} +18 -18
  32. package/dist/js/chunks/{chunk-D4UZ4HFN.mjs → chunk-IFXVDDDH.mjs} +23 -11
  33. package/dist/js/chunks/chunk-IFXVDDDH.mjs.map +7 -0
  34. package/dist/js/chunks/{chunk-QSQ24FYT.mjs → chunk-LTWPGFBR.mjs} +2 -2
  35. package/dist/js/chunks/{chunk-QSQ24FYT.mjs.map → chunk-LTWPGFBR.mjs.map} +2 -2
  36. package/dist/js/chunks/{chunk-AOGFNMXS.mjs → chunk-LWBQIX5J.mjs} +16 -16
  37. package/dist/js/chunks/chunk-LWBQIX5J.mjs.map +7 -0
  38. package/dist/js/chunks/{chunk-GY2Z5CJ2.mjs → chunk-NNYP33NB.mjs} +67 -32
  39. package/dist/js/chunks/chunk-NNYP33NB.mjs.map +7 -0
  40. package/dist/js/chunks/{chunk-VAS6JQ6P.mjs → chunk-PIJ2TAR3.mjs} +3 -3
  41. package/dist/js/chunks/{chunk-JR24UB4X.mjs → chunk-PSSHQWCX.mjs} +2 -2
  42. package/dist/js/chunks/{chunk-PIIAEYAJ.mjs → chunk-QDAL4IYN.mjs} +2 -2
  43. package/dist/js/chunks/chunk-QV2JAWIZ.mjs +135 -0
  44. package/dist/js/chunks/chunk-QV2JAWIZ.mjs.map +7 -0
  45. package/dist/js/chunks/{chunk-N3UHGN3N.mjs → chunk-QVVEWBOF.mjs} +3 -3
  46. package/dist/js/chunks/{chunk-ZZBZI2XN.mjs → chunk-RFZZCYVU.mjs} +18 -11
  47. package/dist/js/chunks/chunk-RFZZCYVU.mjs.map +7 -0
  48. package/dist/js/chunks/{chunk-TYM6U5DY.mjs → chunk-UAEAQBRC.mjs} +2 -2
  49. package/dist/js/chunks/{chunk-7UXHSYIA.mjs → chunk-UBLRRJ7N.mjs} +3 -3
  50. package/dist/js/chunks/{chunk-EP3CVKB5.mjs → chunk-UEZUJQ66.mjs} +8 -5
  51. package/dist/js/chunks/chunk-UEZUJQ66.mjs.map +7 -0
  52. package/dist/js/chunks/{chunk-JNPIWFJT.mjs → chunk-UNEMYWEW.mjs} +3 -3
  53. package/dist/js/chunks/{chunk-JKNPQQWY.mjs → chunk-WJXDBPXQ.mjs} +28 -12
  54. package/dist/js/chunks/chunk-WJXDBPXQ.mjs.map +7 -0
  55. package/dist/js/chunks/{chunk-XO5WX3TK.mjs → chunk-YDCS5S3J.mjs} +2 -2
  56. package/dist/js/chunks/{chunk-TK6PX2GC.mjs → chunk-YSBCHYXP.mjs} +16 -8
  57. package/dist/js/chunks/chunk-YSBCHYXP.mjs.map +7 -0
  58. package/dist/js/expressive.cjs +398 -217
  59. package/dist/js/expressive.cjs.map +2 -2
  60. package/dist/js/expressive.js +398 -217
  61. package/dist/js/expressive.js.map +2 -2
  62. package/dist/js/expressive.min.js +10 -10
  63. package/dist/js/expressive.min.js.map +3 -3
  64. package/dist/js/expressive.mjs +30 -30
  65. package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
  66. package/dist/js/internal/behaviors/dialogs.mjs +2 -2
  67. package/dist/js/internal/behaviors/forms.mjs +2 -2
  68. package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
  69. package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
  70. package/dist/js/internal/components/appBar.mjs +2 -2
  71. package/dist/js/internal/components/autocomplete.mjs +4 -4
  72. package/dist/js/internal/components/buttonGroup.mjs +2 -2
  73. package/dist/js/internal/components/buttons.mjs +3 -3
  74. package/dist/js/internal/components/cards.mjs +3 -3
  75. package/dist/js/internal/components/carousel.mjs +3 -3
  76. package/dist/js/internal/components/characterCounter.mjs +2 -2
  77. package/dist/js/internal/components/chips.mjs +5 -5
  78. package/dist/js/internal/components/datepicker.mjs +6 -6
  79. package/dist/js/internal/components/expandingCard.mjs +3 -3
  80. package/dist/js/internal/components/index.mjs +23 -23
  81. package/dist/js/internal/components/lightbox.mjs +3 -3
  82. package/dist/js/internal/components/menu.mjs +3 -3
  83. package/dist/js/internal/components/navigationRail.mjs +2 -2
  84. package/dist/js/internal/components/registry.mjs +24 -24
  85. package/dist/js/internal/components/scrollspy.mjs +2 -2
  86. package/dist/js/internal/components/select.mjs +4 -4
  87. package/dist/js/internal/components/slider.mjs +3 -3
  88. package/dist/js/internal/components/snackbar.mjs +2 -2
  89. package/dist/js/internal/components/tabs.mjs +4 -4
  90. package/dist/js/internal/components/timepicker.mjs +4 -4
  91. package/dist/js/internal/components/tooltip.mjs +3 -3
  92. package/dist/js/internal/core/component.mjs +1 -1
  93. package/dist/js/internal/core/utils.mjs +1 -1
  94. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
  95. package/dist/js/modular.mjs +30 -30
  96. package/dist/types/components/appBar.d.ts +1 -1
  97. package/dist/types/components/autocomplete.d.ts +2 -1
  98. package/dist/types/components/datepicker.d.ts +6 -2
  99. package/dist/types/components/menu.d.ts +1 -0
  100. package/dist/types/components/scrollspy.d.ts +5 -4
  101. package/dist/types/components/select.d.ts +7 -1
  102. package/dist/types/components/slider.d.ts +1 -0
  103. package/dist/types/components/snackbar.d.ts +6 -0
  104. package/dist/types/components/timepicker.d.ts +4 -1
  105. package/dist/types/components/tooltip.d.ts +2 -1
  106. package/dist/types/modular.d.ts +1 -1
  107. package/package.json +1 -1
  108. package/src/sass/abstracts/_mixins.scss +19 -11
  109. package/src/sass/components/_buttons.scss +45 -0
  110. package/src/sass/components/_carousel.scss +9 -7
  111. package/src/sass/components/_chips.scss +5 -9
  112. package/src/sass/components/_dialog.scss +0 -7
  113. package/src/sass/components/_navbar.scss +13 -8
  114. package/src/sass/components/_page-footer.scss +0 -11
  115. package/src/sass/components/_progress.scss +25 -6
  116. package/src/sass/components/_snackbar.scss +1 -1
  117. package/src/sass/components/_timepicker.scss +2 -2
  118. package/src/sass/components/_toolbar.scss +1 -1
  119. package/src/sass/components/forms/_checkboxes.scss +2 -2
  120. package/src/sass/components/forms/_fieldset.scss +20 -1
  121. package/src/sass/components/forms/_file-input.scss +11 -3
  122. package/src/sass/components/forms/_input-fields.scss +35 -15
  123. package/src/sass/components/forms/_radio-buttons.scss +2 -2
  124. package/src/sass/components/forms/_select.scss +3 -2
  125. package/src/sass/components/forms/_slider.scss +51 -29
  126. package/src/sass/components/forms/_switches.scss +3 -3
  127. package/src/sass/utilities/_helpers.scss +14 -0
  128. package/src/sass/utilities/_spacing.scss +29 -23
  129. package/src/sass/utilities/_visibility.scss +7 -1
  130. package/dist/js/chunks/chunk-7MM4VJJO.mjs.map +0 -7
  131. package/dist/js/chunks/chunk-AOGFNMXS.mjs.map +0 -7
  132. package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +0 -7
  133. package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +0 -7
  134. package/dist/js/chunks/chunk-G576EP5O.mjs.map +0 -7
  135. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +0 -7
  136. package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +0 -7
  137. package/dist/js/chunks/chunk-JODJAGFS.mjs.map +0 -7
  138. package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +0 -7
  139. package/dist/js/chunks/chunk-QYCYP443.mjs.map +0 -7
  140. package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +0 -7
  141. package/dist/js/chunks/chunk-TZZ24ZQS.mjs +0 -154
  142. package/dist/js/chunks/chunk-TZZ24ZQS.mjs.map +0 -7
  143. package/dist/js/chunks/chunk-YFXEJ7GR.mjs.map +0 -7
  144. package/dist/js/chunks/chunk-ZAOYQ6SY.mjs +0 -7
  145. package/dist/js/chunks/chunk-ZZBZI2XN.mjs.map +0 -7
  146. /package/dist/js/chunks/{chunk-A3BJA7V4.mjs.map → chunk-6WLSDZ4O.mjs.map} +0 -0
  147. /package/dist/js/chunks/{chunk-KR44BSYQ.mjs.map → chunk-DLWYKFEI.mjs.map} +0 -0
  148. /package/dist/js/chunks/{chunk-SLFNPY5M.mjs.map → chunk-EC63CHXU.mjs.map} +0 -0
  149. /package/dist/js/chunks/{chunk-ZIZVUWRL.mjs.map → chunk-HNFSMIBY.mjs.map} +0 -0
  150. /package/dist/js/chunks/{chunk-VAS6JQ6P.mjs.map → chunk-PIJ2TAR3.mjs.map} +0 -0
  151. /package/dist/js/chunks/{chunk-JR24UB4X.mjs.map → chunk-PSSHQWCX.mjs.map} +0 -0
  152. /package/dist/js/chunks/{chunk-PIIAEYAJ.mjs.map → chunk-QDAL4IYN.mjs.map} +0 -0
  153. /package/dist/js/chunks/{chunk-N3UHGN3N.mjs.map → chunk-QVVEWBOF.mjs.map} +0 -0
  154. /package/dist/js/chunks/{chunk-TYM6U5DY.mjs.map → chunk-UAEAQBRC.mjs.map} +0 -0
  155. /package/dist/js/chunks/{chunk-7UXHSYIA.mjs.map → chunk-UBLRRJ7N.mjs.map} +0 -0
  156. /package/dist/js/chunks/{chunk-JNPIWFJT.mjs.map → chunk-UNEMYWEW.mjs.map} +0 -0
  157. /package/dist/js/chunks/{chunk-XO5WX3TK.mjs.map → chunk-YDCS5S3J.mjs.map} +0 -0
@@ -271,12 +271,7 @@ var _Utils = class _Utils {
271
271
  button.type = "button";
272
272
  button.tabIndex = !!visibility ? 0 : -1;
273
273
  button.innerText = text;
274
- if (typeof callback === "function") {
275
- button.addEventListener("click", callback);
276
- button.addEventListener("keypress", (e) => {
277
- if (e.key === _Utils.keys.ENTER) callback(e);
278
- });
279
- }
274
+ if (typeof callback === "function") button.addEventListener("click", callback);
280
275
  container.append(button);
281
276
  }
282
277
  static _setAbsolutePosition(origin, container, position, margin, transitionMovement, align = "center") {
@@ -315,6 +310,13 @@ var _Utils = class _Utils {
315
310
  transitionMovement,
316
311
  align
317
312
  );
313
+ const parent = container.offsetParent;
314
+ if (parent && (parent !== document.body || getComputedStyle(parent).position !== "static")) {
315
+ const rect = parent.getBoundingClientRect();
316
+ const root = parent === document.scrollingElement;
317
+ newCoordinates.x -= rect.left + _Utils.getDocumentScrollLeft() + parent.clientLeft - (root ? 0 : parent.scrollLeft);
318
+ newCoordinates.y -= rect.top + _Utils.getDocumentScrollTop() + parent.clientTop - (root ? 0 : parent.scrollTop);
319
+ }
318
320
  container.style.top = newCoordinates.y + "px";
319
321
  container.style.left = newCoordinates.x + "px";
320
322
  return { x: xMovement, y: yMovement };
@@ -396,7 +398,7 @@ var Component = class {
396
398
  let instances = null;
397
399
  if (els instanceof Element) {
398
400
  instances = new classDef(els, options);
399
- } else if (!!els && els.length) {
401
+ } else if (els) {
400
402
  instances = [];
401
403
  for (let i = 0; i < els.length; i++) {
402
404
  instances.push(new classDef(els[i], options));
@@ -784,6 +786,7 @@ var _Menu = class _Menu extends Component {
784
786
  super(el, options, _Menu);
785
787
  this._pendingTimers = /* @__PURE__ */ new Set();
786
788
  this._transition = 0;
789
+ this._menuClickTargets = /* @__PURE__ */ new WeakMap();
787
790
  this._handleClick = (e) => {
788
791
  e.preventDefault();
789
792
  if (this.isOpen) {
@@ -812,11 +815,15 @@ var _Menu = class _Menu extends Component {
812
815
  }
813
816
  };
814
817
  this._handleDocumentClick = (e) => {
815
- const target = e.target;
818
+ const path = e.composedPath();
819
+ const menuTarget = this._menuClickTargets.get(e);
820
+ this._menuClickTargets.delete(e);
821
+ const target = menuTarget ?? (path[0] || e.target);
822
+ const inside = !!menuTarget || path.includes(this.menuEl) || this.menuEl?.contains(target);
816
823
  if (this._isSubmenuTriggerClick(target)) return;
817
- if (this.options.closeOnClick && this.menuEl?.contains(target) && !this.isTouchMoving) {
824
+ if (this.options.closeOnClick && inside && !this.isTouchMoving) {
818
825
  this.close();
819
- } else if (!this.menuEl?.contains(target)) {
826
+ } else if (!inside) {
820
827
  this._schedule(() => {
821
828
  if (this.isOpen) {
822
829
  this.close();
@@ -834,12 +841,13 @@ var _Menu = class _Menu extends Component {
834
841
  };
835
842
  this._handleDocumentTouchmove = (e) => {
836
843
  const target = e.target;
837
- if (this.menuEl?.contains(target)) {
844
+ if (e.composedPath().includes(this.menuEl) || this.menuEl?.contains(target)) {
838
845
  this.isTouchMoving = true;
839
846
  }
840
847
  };
841
848
  this._handleMenuClick = (e) => {
842
849
  const target = e.target;
850
+ this._menuClickTargets.set(e, target);
843
851
  const li = target.closest("li");
844
852
  if (li?.matches('.disabled, [aria-disabled="true"]')) {
845
853
  e.preventDefault();
@@ -1006,7 +1014,7 @@ var _Menu = class _Menu extends Component {
1006
1014
  this._animateOut();
1007
1015
  this._removeTemporaryEventHandlers();
1008
1016
  this.el.ariaExpanded = "false";
1009
- if (this.options.autoFocus && (root.activeElement === focused || !root.activeElement || root.activeElement === document.body)) {
1017
+ if (this.options.autoFocus && this.menuEl.contains(focused) && (root.activeElement === focused || this.el.ownerDocument.activeElement === this.el.ownerDocument.body)) {
1010
1018
  this.el.focus();
1011
1019
  }
1012
1020
  };
@@ -1098,6 +1106,7 @@ var _Menu = class _Menu extends Component {
1098
1106
  }
1099
1107
  _setupTemporaryEventHandlers() {
1100
1108
  document.body.addEventListener("click", this._handleDocumentClick);
1109
+ this.menuEl?.addEventListener("touchmove", this._handleDocumentTouchmove, { passive: true });
1101
1110
  document.body.addEventListener("touchmove", this._handleDocumentTouchmove, {
1102
1111
  passive: true
1103
1112
  });
@@ -1106,6 +1115,7 @@ var _Menu = class _Menu extends Component {
1106
1115
  }
1107
1116
  _removeTemporaryEventHandlers() {
1108
1117
  document.body.removeEventListener("click", this._handleDocumentClick);
1118
+ this.menuEl?.removeEventListener("touchmove", this._handleDocumentTouchmove);
1109
1119
  document.body.removeEventListener("touchmove", this._handleDocumentTouchmove);
1110
1120
  this.menuEl?.removeEventListener("keydown", this._handleMenuKeydown);
1111
1121
  window.removeEventListener("resize", this._handleWindowResize);
@@ -1455,12 +1465,12 @@ var _Autocomplete = class _Autocomplete extends Component {
1455
1465
  this._resetAutocomplete();
1456
1466
  }
1457
1467
  };
1458
- this._handleInputKeyup = (e) => {
1459
- if (e.type === "keyup") _Autocomplete._keydown = false;
1468
+ this._handleInputKeyup = () => {
1469
+ _Autocomplete._keydown = false;
1470
+ };
1471
+ this._handleInput = () => {
1460
1472
  this.count = 0;
1461
1473
  const actualValue = this.el.value.toLocaleLowerCase();
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")
1463
- return;
1464
1474
  if (this.oldVal !== actualValue && this.el.matches(":focus-visible")) {
1465
1475
  this.open();
1466
1476
  }
@@ -1539,7 +1549,6 @@ var _Autocomplete = class _Autocomplete extends Component {
1539
1549
  const inputText = this.el.value.toLocaleLowerCase();
1540
1550
  this._resetAutocomplete();
1541
1551
  if (inputText.length >= this.options.minLength) {
1542
- this.isOpen = true;
1543
1552
  this._renderMenu();
1544
1553
  this._announce(this.menuItems.length ? this.options.i18n.results(this.menuItems.length) : this.options.i18n.noResults);
1545
1554
  }
@@ -1633,6 +1642,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1633
1642
  }
1634
1643
  this._removeEventHandlers();
1635
1644
  this.menu.destroy();
1645
+ this.isOpen = false;
1636
1646
  this._removeMenu();
1637
1647
  this._statusInfo.remove();
1638
1648
  this._announcer.remove();
@@ -1640,6 +1650,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1640
1650
  }
1641
1651
  _setupEventHandlers() {
1642
1652
  this.el.addEventListener("blur", this._handleInputBlur);
1653
+ this.el.addEventListener("input", this._handleInput);
1643
1654
  this.el.addEventListener("keyup", this._handleInputKeyup);
1644
1655
  this.el.addEventListener("focus", this._handleInputFocus);
1645
1656
  this.el.addEventListener("keydown", this._handleInputKeydown);
@@ -1650,6 +1661,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1650
1661
  }
1651
1662
  _removeEventHandlers() {
1652
1663
  this.el.removeEventListener("blur", this._handleInputBlur);
1664
+ this.el.removeEventListener("input", this._handleInput);
1653
1665
  this.el.removeEventListener("keyup", this._handleInputKeyup);
1654
1666
  this.el.removeEventListener("focus", this._handleInputFocus);
1655
1667
  this.el.removeEventListener("keydown", this._handleInputKeydown);
@@ -1678,6 +1690,16 @@ var _Autocomplete = class _Autocomplete extends Component {
1678
1690
  ..._Autocomplete.defaults.menuOptions,
1679
1691
  ...this.options.menuOptions
1680
1692
  };
1693
+ const userOnOpenStart = menuOptions.onOpenStart;
1694
+ const userOnCloseStart = menuOptions.onCloseStart;
1695
+ menuOptions.onOpenStart = (el) => {
1696
+ this.isOpen = true;
1697
+ if (typeof userOnOpenStart === "function") userOnOpenStart.call(this.menu, el);
1698
+ };
1699
+ menuOptions.onCloseStart = (el) => {
1700
+ this.isOpen = false;
1701
+ if (typeof userOnCloseStart === "function") userOnCloseStart.call(this.menu, el);
1702
+ };
1681
1703
  const userOnItemClick = menuOptions.onItemClick;
1682
1704
  menuOptions.onItemClick = (li) => {
1683
1705
  if (!li) return;
@@ -1690,10 +1712,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1690
1712
  const label = this.el.parentElement.querySelector("label");
1691
1713
  if (label) this.el.after(label);
1692
1714
  this.el.removeEventListener("click", this.menu._handleClick);
1693
- if (!this.options.isMultiSelect && !(this.options.selected.length === 0)) {
1694
- const selectedValue = this.menuItems.filter((value) => value.id === this.selectedValues[0].id);
1695
- this.el.value = selectedValue[0].text;
1696
- }
1715
+ if (!this.options.isMultiSelect) this._refreshInputText();
1697
1716
  if (this.el.value) this.selectOption(this.el.value);
1698
1717
  const div = document.createElement("div");
1699
1718
  div.classList.add("status-info");
@@ -1721,7 +1740,6 @@ var _Autocomplete = class _Autocomplete extends Component {
1721
1740
  this.container.replaceChildren();
1722
1741
  this._resetCurrentElementPosition();
1723
1742
  this.oldVal = null;
1724
- this.isOpen = false;
1725
1743
  this._pointerDown = false;
1726
1744
  }
1727
1745
  _highlightPartialText(input, label) {
@@ -1839,7 +1857,7 @@ var _Autocomplete = class _Autocomplete extends Component {
1839
1857
  }
1840
1858
  }
1841
1859
  _triggerChanged() {
1842
- this.el.dispatchEvent(new Event("change"));
1860
+ this.el.dispatchEvent(new Event("change", { bubbles: true, cancelable: true, composed: true }));
1843
1861
  if (typeof this.options.onAutocomplete === "function")
1844
1862
  this.options.onAutocomplete.call(this, this.selectedValues);
1845
1863
  }
@@ -1948,7 +1966,7 @@ var _Chips = class _Chips extends Component {
1948
1966
  this._handleInputKeydown = (e) => {
1949
1967
  _Chips._keydown = true;
1950
1968
  if (e.key === Utils.keys.ENTER) {
1951
- if (this.hasAutocomplete && this.autocomplete && this.autocomplete.isOpen) {
1969
+ if (this.hasAutocomplete && this.autocomplete?.isOpen && this.autocomplete.container.querySelector('[role="option"]')) {
1952
1970
  return;
1953
1971
  }
1954
1972
  e.preventDefault();
@@ -2014,6 +2032,9 @@ var _Chips = class _Chips extends Component {
2014
2032
  return this.chipsData;
2015
2033
  }
2016
2034
  destroy() {
2035
+ if (this.autocomplete && Autocomplete.getInstance(this._input) === this.autocomplete) {
2036
+ this.autocomplete.destroy();
2037
+ }
2017
2038
  if (this.options.allowUserInput) {
2018
2039
  this._removeEventHandlers();
2019
2040
  }
@@ -2079,7 +2100,7 @@ var _Chips = class _Chips extends Component {
2079
2100
  }
2080
2101
  }
2081
2102
  _renderChip(chip) {
2082
- if (!chip.id) return;
2103
+ if (!chip.id && chip.id !== 0) return;
2083
2104
  const label = chip.text || chip.id;
2084
2105
  const renderedChip = document.createElement("span");
2085
2106
  renderedChip.classList.add("chip");
@@ -2113,14 +2134,16 @@ var _Chips = class _Chips extends Component {
2113
2134
  }
2114
2135
  _setupAutocomplete() {
2115
2136
  this.options.autocompleteOptions.onAutocomplete = (items) => {
2116
- if (items.length > 0)
2137
+ if (_Chips.getInstance(this.el) !== this) return;
2138
+ if (items.length > 0) {
2117
2139
  this.addChip({
2118
2140
  id: items[0].id,
2119
2141
  text: items[0].text,
2120
2142
  image: items[0].image
2121
2143
  });
2122
- this._input.value = "";
2123
- this._input.focus();
2144
+ this._input.value = "";
2145
+ this._input.focus();
2146
+ }
2124
2147
  };
2125
2148
  this.autocomplete = Autocomplete.init(this._input, this.options.autocompleteOptions);
2126
2149
  }
@@ -2141,6 +2164,7 @@ var _Chips = class _Chips extends Component {
2141
2164
  if (this._label && this._input) this._label.setAttribute("for", this._input.getAttribute("id"));
2142
2165
  }
2143
2166
  _setPlaceholder() {
2167
+ if (!this._input) return;
2144
2168
  if (this.chipsData !== void 0 && !this.chipsData.length && this.options.placeholder) {
2145
2169
  this._input.placeholder = this.options.placeholder;
2146
2170
  } else if ((this.chipsData === void 0 || !!this.chipsData.length) && this.options.secondaryPlaceholder) {
@@ -2148,7 +2172,7 @@ var _Chips = class _Chips extends Component {
2148
2172
  }
2149
2173
  }
2150
2174
  _isValidAndNotExist(chip) {
2151
- const isValid = !!chip.id;
2175
+ const isValid = !!chip.id || chip.id === 0;
2152
2176
  const doesNotExist = !this.chipsData.some((item) => item.id == chip.id);
2153
2177
  return isValid && doesNotExist;
2154
2178
  }
@@ -2161,7 +2185,8 @@ var _Chips = class _Chips extends Component {
2161
2185
  const renderedChip = this._renderChip(chip);
2162
2186
  this._chips.push(renderedChip);
2163
2187
  this.chipsData.push(chip);
2164
- this._input.before(renderedChip);
2188
+ if (this._input) this._input.before(renderedChip);
2189
+ else this.el.append(renderedChip);
2165
2190
  this._setPlaceholder();
2166
2191
  if (typeof this.options.onChipAdd === "function") {
2167
2192
  this.options.onChipAdd(this.el, renderedChip);
@@ -2232,6 +2257,7 @@ var Chips = _Chips;
2232
2257
 
2233
2258
  // src/ts/components/slider.ts
2234
2259
  var _defaults6 = {};
2260
+ var _authored = /* @__PURE__ */ new WeakMap();
2235
2261
  var Slider = class _Slider extends Component {
2236
2262
  constructor(el, options) {
2237
2263
  super(el, options, _Slider);
@@ -2300,6 +2326,18 @@ var Slider = class _Slider extends Component {
2300
2326
  this._removeEventHandlers();
2301
2327
  this._removeThumb();
2302
2328
  this.el["Expressive_Slider"] = void 0;
2329
+ const host = this._host();
2330
+ for (const el of [this.el, host]) {
2331
+ for (const name in _authored.get(el)) el.style.setProperty(name, _authored.get(el)[name]);
2332
+ _authored.delete(el);
2333
+ }
2334
+ host?.querySelectorAll('input[type="range"]').forEach((el) => el["Expressive_Slider"]?._sync());
2335
+ }
2336
+ _set(el, name, value) {
2337
+ const authored = _authored.get(el) ?? {};
2338
+ _authored.set(el, authored);
2339
+ authored[name] ?? (authored[name] = el.style.getPropertyValue(name));
2340
+ el.style.setProperty(name, value);
2303
2341
  }
2304
2342
  // Eleven listeners used to cover four stages, because each one was written
2305
2343
  // twice - once for mouse, once for touch. One of the touch spellings,
@@ -2370,25 +2408,28 @@ var Slider = class _Slider extends Component {
2370
2408
  const handle = parseFloat(style.getPropertyValue("--md-comp-slider-handle-width")) || 4;
2371
2409
  const length = vertical ? height : width;
2372
2410
  const position = handle / 2 + percent * (length - handle);
2373
- this.el.style.setProperty("--md-comp-slider-active-fraction", fraction);
2374
- this.el.style.setProperty("--md-comp-slider-active-position", `${position}px`);
2411
+ this._set(this.el, "--md-comp-slider-active-fraction", fraction);
2412
+ this._set(this.el, "--md-comp-slider-active-position", `${position}px`);
2375
2413
  const host = this._host();
2376
2414
  const peers = host?.querySelectorAll('input[type="range"]');
2377
2415
  if (host && peers && peers.length === 2) {
2378
2416
  const nums = Array.from(peers).map((el) => this._fraction(el));
2379
- host.style.setProperty("--md-comp-slider-start-fraction", `${Math.min(...nums) * 100}%`);
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`);
2417
+ this._set(host, "--md-comp-slider-start-fraction", `${Math.min(...nums) * 100}%`);
2418
+ this._set(host, "--md-comp-slider-end-fraction", `${Math.max(...nums) * 100}%`);
2419
+ this._set(host, "--md-comp-slider-start-position", `${handle / 2 + Math.min(...nums) * (length - handle)}px`);
2420
+ this._set(host, "--md-comp-slider-end-position", `${handle / 2 + Math.max(...nums) * (length - handle)}px`);
2383
2421
  }
2384
2422
  if (host?.classList.contains("stops")) {
2385
2423
  const parsedMax = parseFloat(this.el.max);
2386
2424
  const max = Number.isNaN(parsedMax) ? 100 : parsedMax;
2387
2425
  const min = parseFloat(this.el.min) || 0;
2388
2426
  const step = parseFloat(this.el.step);
2389
- if (step > 0 && Number.isFinite(step)) {
2390
- const n = Math.round((max - min) / step) + 1;
2391
- host.style.setProperty("--md-comp-slider-stop-count", String(Math.max(2, n)));
2427
+ const stops = step > 0 && Number.isFinite(step) && max > min;
2428
+ this._set(host, "--md-comp-slider-stop-count", stops ? String(Math.floor((max - min) / step + 1e-9) + 1) : "");
2429
+ this._set(host, "--md-comp-slider-stop-spacing", stops ? `${(length - handle) * step / (max - min)}px` : "");
2430
+ if (peers?.length === 1) {
2431
+ this._set(host, "--md-comp-slider-active-position", `${position}px`);
2432
+ this._set(host, "--md-comp-slider-track-center", `${top + height / 2}px`);
2392
2433
  }
2393
2434
  }
2394
2435
  this.value.textContent = this.el.value;
@@ -2481,6 +2522,7 @@ var Dialogs = _Dialogs;
2481
2522
  // src/ts/behaviors/sheetDrag.ts
2482
2523
  var DISMISS_DISTANCE = 96;
2483
2524
  var DISMISS_VELOCITY = 0.5;
2525
+ var FLICK_TIMEOUT = 100;
2484
2526
  var DRAG_SLOP = 4;
2485
2527
  function installSheetDrag(config) {
2486
2528
  const coord = (event) => config.axis === "x" ? event.clientX : event.clientY;
@@ -2517,6 +2559,7 @@ function installSheetDrag(config) {
2517
2559
  start: coord(event),
2518
2560
  last: coord(event),
2519
2561
  lastT: Date.now(),
2562
+ velocity: 0,
2520
2563
  shift: 0
2521
2564
  };
2522
2565
  observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ["open"], attributeOldValue: true });
@@ -2529,8 +2572,12 @@ function installSheetDrag(config) {
2529
2572
  }
2530
2573
  const delta = coord(event) - drag.start;
2531
2574
  drag.shift = drag.direction === 1 ? Math.max(0, delta) : Math.min(0, delta);
2532
- drag.last = coord(event);
2533
- drag.lastT = Date.now();
2575
+ if (coord(event) !== drag.last) {
2576
+ const now = Date.now();
2577
+ drag.velocity = (coord(event) - drag.last) / Math.max(1, now - drag.lastT);
2578
+ drag.last = coord(event);
2579
+ drag.lastT = now;
2580
+ }
2534
2581
  drag.dialog.style.setProperty(config.property, `${drag.shift}px`);
2535
2582
  };
2536
2583
  const onUp = (event) => {
@@ -2540,13 +2587,14 @@ function installSheetDrag(config) {
2540
2587
  onCancel();
2541
2588
  return;
2542
2589
  }
2590
+ onMove(event);
2543
2591
  drag = null;
2544
2592
  observer.disconnect();
2545
2593
  held.dialog.style.transition = "";
2546
- const dt = Math.max(1, Date.now() - held.lastT);
2547
- const velocity = (coord(event) - held.last) / dt;
2548
- config.onRelease?.(Math.abs(held.shift) > DRAG_SLOP);
2549
- const dismiss = held.direction === 1 ? held.shift > DISMISS_DISTANCE || velocity > DISMISS_VELOCITY : held.shift < -DISMISS_DISTANCE || velocity < -DISMISS_VELOCITY;
2594
+ const velocity = Date.now() - held.lastT < FLICK_TIMEOUT ? held.velocity : 0;
2595
+ const dragged = Math.abs(held.shift) > DRAG_SLOP;
2596
+ config.onRelease?.(dragged);
2597
+ const dismiss = dragged && (held.direction === 1 ? held.shift > DISMISS_DISTANCE || velocity > DISMISS_VELOCITY : held.shift < -DISMISS_DISTANCE || velocity < -DISMISS_VELOCITY);
2550
2598
  if (dismiss && held.dialog.open) held.dialog.close();
2551
2599
  held.dialog.style.setProperty(config.property, "0px");
2552
2600
  };
@@ -2741,7 +2789,10 @@ var AppBar = class _AppBar extends Component {
2741
2789
  this._onIntersect = (entries) => {
2742
2790
  const entry = entries[0];
2743
2791
  if (!entry) return;
2744
- this.el.classList.toggle("collapsed", !entry.isIntersecting);
2792
+ this.el.classList.toggle(
2793
+ "collapsed",
2794
+ !entry.isIntersecting && entry.boundingClientRect.top < this.el.getBoundingClientRect().top
2795
+ );
2745
2796
  };
2746
2797
  this._onSearchViewClose = () => {
2747
2798
  this._searchOpen = this._view.open;
@@ -2788,8 +2839,8 @@ var AppBar = class _AppBar extends Component {
2788
2839
  if (typeof IntersectionObserver === "undefined") return;
2789
2840
  this._sentinel = document.createElement("span");
2790
2841
  this._sentinel.setAttribute("aria-hidden", "true");
2791
- this._sentinel.style.cssText = "display:block;width:100%;height:1px;margin-top:-1px;pointer-events:none;visibility:hidden";
2792
- this.el.insertAdjacentElement("beforebegin", this._sentinel);
2842
+ this._sentinel.style.cssText = "display:block;height:0;position:relative;top:-64px;pointer-events:none;visibility:hidden";
2843
+ this.el.insertAdjacentElement("afterend", this._sentinel);
2793
2844
  this._observer = new IntersectionObserver(this._onIntersect);
2794
2845
  this._observer.observe(this._sentinel);
2795
2846
  }
@@ -3216,10 +3267,6 @@ var _Carousel = class _Carousel extends Component {
3216
3267
  this._dragStartX = e.clientX;
3217
3268
  this._dragStartY = e.clientY;
3218
3269
  this._dragStartScroll = this._vertical ? this._scroller.scrollTop : this._scroller.scrollLeft;
3219
- try {
3220
- this._scroller.setPointerCapture(e.pointerId);
3221
- } catch {
3222
- }
3223
3270
  };
3224
3271
  this._handleTrackPointerMove = (e) => {
3225
3272
  if (!this.pressed || e.pointerId !== this._dragPointerId) return;
@@ -3231,6 +3278,10 @@ var _Carousel = class _Carousel extends Component {
3231
3278
  if (Math.abs(primaryDelta) < 6 || Math.abs(primaryDelta) <= Math.abs(crossDelta)) return;
3232
3279
  this.dragged = true;
3233
3280
  this.el.classList.add("dragging");
3281
+ try {
3282
+ this._scroller.setPointerCapture(e.pointerId);
3283
+ } catch {
3284
+ }
3234
3285
  }
3235
3286
  if (this._vertical) this._scroller.scrollTop = this._dragStartScroll - deltaY;
3236
3287
  else this._scroller.scrollLeft = this._dragStartScroll - deltaX;
@@ -3260,7 +3311,7 @@ var _Carousel = class _Carousel extends Component {
3260
3311
  e.stopImmediatePropagation();
3261
3312
  };
3262
3313
  this._handleTrackDragStart = (e) => {
3263
- if (e.target.closest("img, picture, video")) e.preventDefault();
3314
+ if (e.target.closest("a, img, picture, video")) e.preventDefault();
3264
3315
  };
3265
3316
  this._handleItemResize = (e) => {
3266
3317
  if (this._alignAfterResize && !this.pressed && e.propertyName === "flex-basis" && this.images.includes(e.target)) {
@@ -3316,7 +3367,7 @@ var _Carousel = class _Carousel extends Component {
3316
3367
  if (!this._started || !this.images.length) return;
3317
3368
  this._syncAdaptiveMode();
3318
3369
  this._syncLayoutRoles(this.center);
3319
- this._scrollToIndex(this.center, false);
3370
+ if (!this.pressed) this._scrollToIndex(this.center, false);
3320
3371
  this._updateParallax();
3321
3372
  };
3322
3373
  this._finishScroll = () => {
@@ -3325,7 +3376,7 @@ var _Carousel = class _Carousel extends Component {
3325
3376
  this._scroller.removeEventListener("scrollend", this._handleScrollEnd);
3326
3377
  };
3327
3378
  this._handleScrollEnd = () => {
3328
- if (!this.images.some((item) => item.getAnimations().some((animation) => animation.playState === "running"))) {
3379
+ if (this._nearestIndex() === this.center && !this.images.some((item) => item.getAnimations().some((animation) => animation.playState === "running"))) {
3329
3380
  this._finishScroll();
3330
3381
  }
3331
3382
  };
@@ -3500,9 +3551,9 @@ var _Carousel = class _Carousel extends Component {
3500
3551
  });
3501
3552
  this._scroller.addEventListener("pointerdown", this._handleTrackPointerDown);
3502
3553
  this._scroller.addEventListener("wheel", this._handleNativeScroll, { passive: true });
3503
- this._scroller.addEventListener("pointermove", this._handleTrackPointerMove);
3504
- this._scroller.addEventListener("pointerup", this._handleTrackPointerUp);
3505
- this._scroller.addEventListener("pointercancel", this._handleTrackPointerUp);
3554
+ document.addEventListener("pointermove", this._handleTrackPointerMove);
3555
+ document.addEventListener("pointerup", this._handleTrackPointerUp);
3556
+ document.addEventListener("pointercancel", this._handleTrackPointerUp);
3506
3557
  this._scroller.addEventListener("click", this._handleTrackClick, true);
3507
3558
  this._scroller.addEventListener("dragstart", this._handleTrackDragStart);
3508
3559
  this._scroller.addEventListener("transitionend", this._handleItemResize);
@@ -3521,9 +3572,9 @@ var _Carousel = class _Carousel extends Component {
3521
3572
  this._scroller.removeEventListener("scroll", this._handleTrackScroll);
3522
3573
  this._scroller.removeEventListener("pointerdown", this._handleTrackPointerDown);
3523
3574
  this._scroller.removeEventListener("wheel", this._handleNativeScroll);
3524
- this._scroller.removeEventListener("pointermove", this._handleTrackPointerMove);
3525
- this._scroller.removeEventListener("pointerup", this._handleTrackPointerUp);
3526
- this._scroller.removeEventListener("pointercancel", this._handleTrackPointerUp);
3575
+ document.removeEventListener("pointermove", this._handleTrackPointerMove);
3576
+ document.removeEventListener("pointerup", this._handleTrackPointerUp);
3577
+ document.removeEventListener("pointercancel", this._handleTrackPointerUp);
3527
3578
  this._scroller.removeEventListener("click", this._handleTrackClick, true);
3528
3579
  this._scroller.removeEventListener("dragstart", this._handleTrackDragStart);
3529
3580
  this._scroller.removeEventListener("transitionend", this._handleItemResize);
@@ -3874,14 +3925,41 @@ var _defaults12 = {
3874
3925
  var FormSelect = class _FormSelect extends Component {
3875
3926
  constructor(el, options) {
3876
3927
  super(el, options, _FormSelect);
3928
+ this._originalLabels = /* @__PURE__ */ new Map();
3929
+ this._validationMessage = null;
3877
3930
  this._handleSelectChange = () => {
3878
3931
  this._setValueToInput();
3879
3932
  this._setSelectedStates();
3933
+ this._syncValidationError();
3934
+ };
3935
+ this._handleInvalid = (e) => {
3936
+ if (e.defaultPrevented) return;
3937
+ if (!this._validationMessage) {
3938
+ this._validationMessage = document.createElement("small");
3939
+ this._validationMessage.id = this.input.id + "-error";
3940
+ this._validationMessage.className = "supporting-text";
3941
+ this._validationMessage.style.color = "var(--md-sys-color-error)";
3942
+ this.wrapper.append(this._validationMessage);
3943
+ this.input.setAttribute(
3944
+ "aria-describedby",
3945
+ [this.input.getAttribute("aria-describedby"), this._validationMessage.id].filter(Boolean).join(" ")
3946
+ );
3947
+ }
3948
+ this.input.ariaInvalid = "true";
3949
+ this._syncValidationError();
3880
3950
  };
3951
+ // Native reporting chooses the control; static checks never focus. Wait until
3952
+ // reporting finishes so Firefox dismisses its native popup when focus moves.
3953
+ this._handleNativeFocus = () => queueMicrotask(() => {
3954
+ if (_FormSelect.getInstance(this.el) === this && this.el.matches(":focus")) this.input.focus();
3955
+ });
3881
3956
  this._handleReset = (e) => {
3882
3957
  clearTimeout(this._resetTimer);
3883
3958
  this._resetTimer = setTimeout(() => {
3884
- if (!e.defaultPrevented) this._handleSelectChange();
3959
+ if (!e.defaultPrevented) {
3960
+ this._handleSelectChange();
3961
+ this._clearValidationError();
3962
+ }
3885
3963
  }, 0);
3886
3964
  };
3887
3965
  // Named rather than inline so that _removeEventHandlers can actually detach
@@ -3918,7 +3996,6 @@ var FormSelect = class _FormSelect extends Component {
3918
3996
  this.el.tabIndex = -1;
3919
3997
  this._values = [];
3920
3998
  this._createdWrapper = false;
3921
- this._originalLabelFor = null;
3922
3999
  this._setupMenu();
3923
4000
  this._setupEventHandlers();
3924
4001
  }
@@ -3938,6 +4015,7 @@ var FormSelect = class _FormSelect extends Component {
3938
4015
  }
3939
4016
  destroy() {
3940
4017
  this._removeEventHandlers();
4018
+ this._clearValidationError();
3941
4019
  this.menu?.destroy();
3942
4020
  this._removeMenu();
3943
4021
  this.el.tabIndex = this.nativeTabIndex;
@@ -3972,6 +4050,8 @@ var FormSelect = class _FormSelect extends Component {
3972
4050
  _setupEventHandlers() {
3973
4051
  this._setupOptionHandlers();
3974
4052
  this.el.addEventListener("change", this._handleSelectChange);
4053
+ this.el.addEventListener("invalid", this._handleInvalid);
4054
+ this.el.addEventListener("focus", this._handleNativeFocus);
3975
4055
  this.input.addEventListener("click", this._handleInputClick);
3976
4056
  this.menuEl.addEventListener("focusin", this._handleOptionFocus);
3977
4057
  this._bindForm();
@@ -3984,6 +4064,8 @@ var FormSelect = class _FormSelect extends Component {
3984
4064
  _removeEventHandlers() {
3985
4065
  this._removeOptionHandlers();
3986
4066
  this.el.removeEventListener("change", this._handleSelectChange);
4067
+ this.el.removeEventListener("invalid", this._handleInvalid);
4068
+ this.el.removeEventListener("focus", this._handleNativeFocus);
3987
4069
  this.input?.removeEventListener("click", this._handleInputClick);
3988
4070
  this.menuEl?.removeEventListener("focusin", this._handleOptionFocus);
3989
4071
  this._form?.removeEventListener("reset", this._handleReset);
@@ -4001,6 +4083,21 @@ var FormSelect = class _FormSelect extends Component {
4001
4083
  el.removeEventListener("keydown", this._handleOptionKeydown);
4002
4084
  });
4003
4085
  }
4086
+ _syncValidationError() {
4087
+ if (!this._validationMessage) return;
4088
+ if (this.el.willValidate && !this.el.validity.valid) {
4089
+ this._validationMessage.textContent = this.el.validationMessage;
4090
+ } else this._clearValidationError();
4091
+ }
4092
+ _clearValidationError() {
4093
+ if (!this._validationMessage) return;
4094
+ const descriptions = this.input.getAttribute("aria-describedby")?.split(/\s+/).filter((id) => id !== this._validationMessage.id).join(" ");
4095
+ if (descriptions) this.input.setAttribute("aria-describedby", descriptions);
4096
+ else this.input.removeAttribute("aria-describedby");
4097
+ this.input.ariaInvalid = this.el.ariaInvalid;
4098
+ this._validationMessage.remove();
4099
+ this._validationMessage = null;
4100
+ }
4004
4101
  _arraysEqual(a, b) {
4005
4102
  if (a === b) return true;
4006
4103
  if (a == null || b == null) return false;
@@ -4032,6 +4129,13 @@ var FormSelect = class _FormSelect extends Component {
4032
4129
  }
4033
4130
  _setupMenu() {
4034
4131
  this.labelEl = this.el.labels?.[0] ?? null;
4132
+ Array.from(this.el.labels ?? []).forEach((label) => {
4133
+ this._originalLabels.set(label, { for: label.getAttribute("for"), id: label.getAttribute("id") });
4134
+ });
4135
+ if (this.labelEl && !this.el.closest("label")) {
4136
+ this._labelPlaceholder = document.createComment("");
4137
+ this.labelEl.before(this._labelPlaceholder);
4138
+ }
4035
4139
  this._setupWrapper();
4036
4140
  this._hideNativeSelect();
4037
4141
  if (this.el.matches(":disabled")) this.wrapper.classList.add("disabled");
@@ -4047,7 +4151,7 @@ var FormSelect = class _FormSelect extends Component {
4047
4151
  this._buildCaret();
4048
4152
  this._initMenu();
4049
4153
  this._setSelectedStates();
4050
- if (this.labelEl) this.input.after(this.labelEl);
4154
+ if (this._labelPlaceholder) this.input.after(this.labelEl);
4051
4155
  }
4052
4156
  _setupWrapper() {
4053
4157
  const parent = this.el.parentElement;
@@ -4068,9 +4172,10 @@ var FormSelect = class _FormSelect extends Component {
4068
4172
  _hideNativeSelect() {
4069
4173
  const hiddenDiv = document.createElement("div");
4070
4174
  hiddenDiv.classList.add("hide-select");
4175
+ hiddenDiv.ariaHidden = "true";
4071
4176
  this.el.before(hiddenDiv);
4072
4177
  hiddenDiv.appendChild(this.el);
4073
- this.wrapper.append(hiddenDiv);
4178
+ if (this._createdWrapper) this.wrapper.append(hiddenDiv);
4074
4179
  }
4075
4180
  _buildInput() {
4076
4181
  this.input = document.createElement("input");
@@ -4093,9 +4198,14 @@ var FormSelect = class _FormSelect extends Component {
4093
4198
  this.input.ariaExpanded = "false";
4094
4199
  this.input.setAttribute("aria-controls", this.menuEl.id);
4095
4200
  this.input.placeholder = " ";
4096
- if (this.labelEl) {
4097
- this._originalLabelFor = this.labelEl.htmlFor;
4098
- this.labelEl.htmlFor = this.input.id;
4201
+ this._originalLabels.forEach((_, label) => {
4202
+ label.htmlFor = this.input.id;
4203
+ });
4204
+ if (this._labelPlaceholder && this._originalLabels.size > 1 && !this.input.getAttribute("aria-label") && !this.input.getAttribute("aria-labelledby")) {
4205
+ this.input.setAttribute("aria-labelledby", Array.from(this._originalLabels.keys(), (label, index) => {
4206
+ if (!label.id) label.id = `${this.input.id}-label-${index}`;
4207
+ return label.id;
4208
+ }).join(" "));
4099
4209
  }
4100
4210
  this.wrapper.prepend(this.input);
4101
4211
  this._setValueToInput();
@@ -4190,9 +4300,13 @@ var FormSelect = class _FormSelect extends Component {
4190
4300
  this.menuEl?.remove();
4191
4301
  const hide = this.el.parentElement;
4192
4302
  if (hide?.classList.contains("hide-select")) hide.replaceWith(this.el);
4193
- if (this.labelEl && this._originalLabelFor !== null) {
4194
- this.labelEl.htmlFor = this._originalLabelFor;
4195
- }
4303
+ this._originalLabels.forEach((original, label) => {
4304
+ for (const name of ["for", "id"]) {
4305
+ if (original[name] === null) label.removeAttribute(name);
4306
+ else label.setAttribute(name, original[name]);
4307
+ }
4308
+ });
4309
+ this._labelPlaceholder?.replaceWith(this.labelEl);
4196
4310
  if (!this.wrapper) return;
4197
4311
  if (this._createdWrapper) {
4198
4312
  this.wrapper.replaceWith(this.el);
@@ -4270,8 +4384,7 @@ var FormSelect = class _FormSelect extends Component {
4270
4384
  this._values.forEach((value) => this._deselectValue(value));
4271
4385
  }
4272
4386
  _isValueSelected(value) {
4273
- const realValues = this.getSelectedValues();
4274
- return realValues.some((realValue) => realValue === value.el.value);
4387
+ return value.el.selected;
4275
4388
  }
4276
4389
  _toggleEntryFromArray(value) {
4277
4390
  if (this._isValueSelected(value)) this._deselectValue(value);
@@ -4496,9 +4609,7 @@ var _Datepicker = class _Datepicker extends Component {
4496
4609
  this._randId = null;
4497
4610
  this._focusedDate = null;
4498
4611
  this._handleInputClick = (e) => {
4499
- if (e.type == "date") {
4500
- e.preventDefault();
4501
- }
4612
+ if (e.target.type == "date" && (this.options.openByDefault || this.options.container)) e.preventDefault();
4502
4613
  this._batchDraws(() => {
4503
4614
  this.setDateFromInput(e.target);
4504
4615
  this.draw();
@@ -4608,26 +4719,8 @@ var _Datepicker = class _Datepicker extends Component {
4608
4719
  this.gotoYear(e.target.value);
4609
4720
  };
4610
4721
  this._handleInputChange = (e) => {
4611
- let date;
4612
- const el = e.target;
4613
4722
  if (e["detail"]?.firedBy === this) return;
4614
- if (el == this.endDateEl && !this.date) return;
4615
- if (this.options.parse) {
4616
- date = this.options.parse(
4617
- e.target.value,
4618
- typeof this.options.format === "function" ? this.options.format(new Date(this.el.value)) : this.options.format
4619
- );
4620
- } else {
4621
- date = new Date(Date.parse(e.target.value));
4622
- }
4623
- if (_Datepicker._isDate(date)) {
4624
- if (el == this.endDateEl && date < this.date) return this.setInputValue(el, this.endDate);
4625
- this.setDate(date, false, el == this.endDateEl, true);
4626
- if (e.type == "date") {
4627
- this.setDataDate(e, date);
4628
- this.setInputValues();
4629
- }
4630
- }
4723
+ this.setDateFromInput(e.target);
4631
4724
  };
4632
4725
  this._finishSelection = () => {
4633
4726
  this.setInputValues();
@@ -4659,7 +4752,7 @@ var _Datepicker = class _Datepicker extends Component {
4659
4752
  this._insertHTMLIntoDOM();
4660
4753
  this._setupEventHandlers();
4661
4754
  if (!this.options.defaultDate) {
4662
- this.options.defaultDate = new Date(Date.parse(this.el.value));
4755
+ this.options.defaultDate = this._parseInput(this.el.value);
4663
4756
  }
4664
4757
  const defDate = this.options.defaultDate;
4665
4758
  if (_Datepicker._isDate(defDate)) {
@@ -4712,6 +4805,19 @@ var _Datepicker = class _Datepicker extends Component {
4712
4805
  static _isDate(obj) {
4713
4806
  return /Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
4714
4807
  }
4808
+ static _parseDate(value) {
4809
+ value = value.trim();
4810
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return new Date(Date.parse(value));
4811
+ const date = /* @__PURE__ */ new Date(value + "T00:00:00");
4812
+ return date.getDate() === Number(value.slice(-2)) ? date : /* @__PURE__ */ new Date(NaN);
4813
+ }
4814
+ _parseInput(value) {
4815
+ if (!value.trim() || !this.options.parse) return _Datepicker._parseDate(value);
4816
+ return this.options.parse(
4817
+ value,
4818
+ typeof this.options.format === "string" ? this.options.format : ""
4819
+ );
4820
+ }
4715
4821
  static _isWeekend(date) {
4716
4822
  const day = date.getDay();
4717
4823
  return day === 0 || day === 6;
@@ -4821,8 +4927,22 @@ var _Datepicker = class _Datepicker extends Component {
4821
4927
  * Sets date from input field.
4822
4928
  */
4823
4929
  setDateFromInput(el) {
4824
- const date = new Date(Date.parse(el.value));
4825
- this.setDate(date, false, el == this.endDateEl, true);
4930
+ if (el.type === "date") this.setDataDate(el, _Datepicker._parseDate(el.value));
4931
+ if ((this.options.isDateRange || !this.options.isMultipleSelection) && !el.value.trim()) {
4932
+ this.setSingleDate(null, el === this.endDateEl);
4933
+ this.draw();
4934
+ return;
4935
+ }
4936
+ const parsedDate = this._parseInput(el.value);
4937
+ if (!_Datepicker._isDate(parsedDate)) return;
4938
+ const date = new Date(parsedDate.getTime());
4939
+ _Datepicker._setToStartOfDay(date);
4940
+ const isEndDate = el === this.endDateEl;
4941
+ if (this.options.isDateRange && (isEndDate ? this.date && date < this.date : this.endDate && date > this.endDate)) {
4942
+ this.setInputValue(el, isEndDate ? this.endDate : this.date);
4943
+ return;
4944
+ }
4945
+ this.setDate(date, false, isEndDate, true);
4826
4946
  }
4827
4947
  /**
4828
4948
  * Set a date on the datepicker.
@@ -4850,7 +4970,7 @@ var _Datepicker = class _Datepicker extends Component {
4850
4970
  return this.draw();
4851
4971
  }
4852
4972
  if (typeof date === "string") {
4853
- date = new Date(Date.parse(date));
4973
+ date = _Datepicker._parseDate(date);
4854
4974
  }
4855
4975
  if (!_Datepicker._isDate(date)) {
4856
4976
  return;
@@ -4894,7 +5014,7 @@ var _Datepicker = class _Datepicker extends Component {
4894
5014
  * Sets the data-date attribute on the date input field
4895
5015
  */
4896
5016
  setDataDate(el, date) {
4897
- el.setAttribute("data-date", this.toString(date));
5017
+ el.setAttribute("data-date", _Datepicker._isDate(date) ? this.toString(date) : "");
4898
5018
  }
4899
5019
  /**
4900
5020
  * Sets dates on the input values.
@@ -4920,16 +5040,15 @@ var _Datepicker = class _Datepicker extends Component {
4920
5040
  */
4921
5041
  setInputValue(el, date) {
4922
5042
  if (!el) return;
5043
+ if (el.type == "date") this.setDataDate(el, date);
4923
5044
  if (!_Datepicker._isDate(date)) {
4924
5045
  el.value = "";
4925
- if (el.type === "date") el.setAttribute("data-date", "");
4926
5046
  } else if (el.type == "date") {
4927
- this.setDataDate(el, date);
4928
5047
  el.value = this.formatDate(date, "yyyy-mm-dd");
4929
5048
  } else {
4930
5049
  el.value = this.toString(date);
4931
5050
  }
4932
- this.el.dispatchEvent(
5051
+ el.dispatchEvent(
4933
5052
  new CustomEvent("change", {
4934
5053
  bubbles: true,
4935
5054
  cancelable: true,
@@ -5020,7 +5139,7 @@ var _Datepicker = class _Datepicker extends Component {
5020
5139
  cells += 7 - after;
5021
5140
  let isWeekSelected = false;
5022
5141
  for (let i = 0, r = 0; i < cells; i++) {
5023
- const day = new Date(year, month, 1 + (i - before)), isToday = _Datepicker._compareDates(day, now), hasEvent = this.options.events.indexOf(day.toDateString()) !== -1, isEmpty = i < before || i >= days + before, isStartRange = this.options.startRange && _Datepicker._compareDates(this.options.startRange, day), isEndRange = this.options.endRange && _Datepicker._compareDates(this.options.endRange, day), isInRange = this.options.startRange && this.options.endRange && this.options.startRange < day && day < this.options.endRange, isDisabled = this.options.minDate && day < this.options.minDate || this.options.maxDate && day > this.options.maxDate || this.options.disableWeekends && _Datepicker._isWeekend(day) || this.options.disableDayFn && this.options.disableDayFn(day), isDateRangeStart = this.options.isDateRange && this.date && this.endDate && _Datepicker._compareDates(this.date, day), isDateRangeEnd = this.options.isDateRange && this.endDate && _Datepicker._compareDates(this.endDate, day), isDateRange = this.options.isDateRange && _Datepicker._isDate(this.endDate) && _Datepicker._compareWithinRange(day, this.date, this.endDate);
5142
+ const day = new Date(year, month, 1 + (i - before)), isToday = _Datepicker._compareDates(day, now), hasEvent = this.options.events.indexOf(day.toDateString()) !== -1, isEmpty = i < before || i >= days + before, isStartRange = this.options.startRange && _Datepicker._compareDates(this.options.startRange, day), isEndRange = this.options.endRange && _Datepicker._compareDates(this.options.endRange, day), isInRange = this.options.startRange && this.options.endRange && this.options.startRange < day && day < this.options.endRange, isDisabled = this.options.minDate && day < this.options.minDate || this.options.maxDate && day > this.options.maxDate || this.options.disableWeekends && _Datepicker._isWeekend(day) || this.options.disableDayFn && this.options.disableDayFn(day), isDateRangeStart = this.options.isDateRange && this.date && this.endDate && _Datepicker._compareDates(this.date, day), isDateRangeEnd = this.options.isDateRange && this.endDate && _Datepicker._compareDates(this.endDate, day), isDateRange = this.options.isDateRange && _Datepicker._isDate(this.date) && _Datepicker._isDate(this.endDate) && _Datepicker._compareWithinRange(day, this.date, this.endDate);
5024
5143
  let dayNumber = 1 + (i - before), monthNumber = month, yearNumber = year;
5025
5144
  let isSelected = false;
5026
5145
  if (_Datepicker._isDate(this.date)) {
@@ -5455,6 +5574,7 @@ var _Datepicker = class _Datepicker extends Component {
5455
5574
  createDateInput() {
5456
5575
  const dateInput = this.el.cloneNode(true);
5457
5576
  dateInput.removeAttribute("id");
5577
+ dateInput.classList.add("no-autoinit");
5458
5578
  dateInput.addEventListener("click", this._handleInputClick);
5459
5579
  dateInput.addEventListener("keydown", this._handleInputKeydown);
5460
5580
  dateInput.addEventListener("change", this._handleInputChange);
@@ -5840,18 +5960,31 @@ var _defaults16 = {
5840
5960
  var _ScrollSpy = class _ScrollSpy extends Component {
5841
5961
  constructor(el, options) {
5842
5962
  super(el, options, _ScrollSpy);
5963
+ this._ratio = 0;
5964
+ this._link = null;
5843
5965
  this.el["Expressive_ScrollSpy"] = this;
5844
5966
  this.options = {
5845
5967
  ..._ScrollSpy.defaults,
5846
5968
  ...options
5847
5969
  };
5970
+ this._offset = this.el.style.getPropertyValue("--md-comp-scrollspy-offset");
5971
+ this._offsetPriority = this.el.style.getPropertyPriority("--md-comp-scrollspy-offset");
5848
5972
  this.el.style.setProperty(
5849
5973
  "--md-comp-scrollspy-offset",
5850
5974
  `${this.options.scrollOffset}px`
5851
5975
  );
5852
5976
  _ScrollSpy._elements.push(this);
5853
- _ScrollSpy._ensureObserver(this.options.scrollOffset);
5854
- _ScrollSpy._observer?.observe(this.el);
5977
+ if (typeof IntersectionObserver !== "undefined") {
5978
+ this._observer = new IntersectionObserver((entries) => {
5979
+ if (_ScrollSpy.getInstance(this.el) !== this) return;
5980
+ for (const entry of entries) this._ratio = entry.isIntersecting ? entry.intersectionRatio : 0;
5981
+ _ScrollSpy._syncActive(this.options.getActiveElement);
5982
+ }, {
5983
+ rootMargin: `-${this.options.scrollOffset}px 0px -45% 0px`,
5984
+ threshold: [0, 0.1, 0.25, 0.5, 0.75, 1]
5985
+ });
5986
+ this._observer.observe(this.el);
5987
+ }
5855
5988
  }
5856
5989
  static get defaults() {
5857
5990
  return _defaults16;
@@ -5864,66 +5997,44 @@ var _ScrollSpy = class _ScrollSpy extends Component {
5864
5997
  }
5865
5998
  destroy() {
5866
5999
  const index = _ScrollSpy._elements.indexOf(this);
5867
- if (index >= 0) _ScrollSpy._elements.splice(index, 1);
5868
- _ScrollSpy._ratios.delete(this.el);
5869
- _ScrollSpy._observer?.unobserve(this.el);
5870
- const link = _ScrollSpy._linkFor(this.el.id, this.options);
5871
- if (link && link === _ScrollSpy._active) {
5872
- _ScrollSpy._clearActive(this.options);
5873
- } else {
5874
- link?.classList.remove(this.options.activeClass);
5875
- link?.removeAttribute("aria-current");
5876
- }
5877
- if (_ScrollSpy._elements.length === 0) {
5878
- _ScrollSpy._observer?.disconnect();
5879
- _ScrollSpy._observer = null;
5880
- _ScrollSpy._ratios.clear();
5881
- _ScrollSpy._active = null;
5882
- } else {
5883
- _ScrollSpy._syncActive();
5884
- }
6000
+ if (index < 0) return;
6001
+ _ScrollSpy._elements.splice(index, 1);
6002
+ this._observer?.disconnect();
6003
+ const resolver = this.options.getActiveElement;
6004
+ if (_ScrollSpy._active.get(resolver) === this) _ScrollSpy._clearActive(resolver);
6005
+ this.el.style.setProperty("--md-comp-scrollspy-offset", this._offset, this._offsetPriority);
5885
6006
  this.el["Expressive_ScrollSpy"] = void 0;
6007
+ _ScrollSpy._syncActive(resolver);
5886
6008
  }
5887
- static _ensureObserver(offset) {
5888
- if (_ScrollSpy._observer) return;
5889
- if (typeof IntersectionObserver === "undefined") return;
5890
- _ScrollSpy._observer = new IntersectionObserver(_ScrollSpy._onIntersect, {
5891
- rootMargin: `-${offset}px 0px -45% 0px`,
5892
- threshold: [0, 0.1, 0.25, 0.5, 0.75, 1]
5893
- });
5894
- }
5895
- static _syncActive() {
5896
- if (!_ScrollSpy._elements.length) return;
5897
- const options = _ScrollSpy._elements[0].options;
6009
+ static _syncActive(resolver) {
6010
+ const elements = _ScrollSpy._elements.filter((spy) => spy.options.getActiveElement === resolver);
5898
6011
  let best = null;
5899
6012
  let bestRatio = 0;
5900
- for (const spy of _ScrollSpy._elements) {
5901
- const ratio = _ScrollSpy._ratios.get(spy.el) ?? 0;
6013
+ for (const spy of elements) {
6014
+ const ratio = spy._ratio;
5902
6015
  if (ratio > bestRatio) {
5903
6016
  bestRatio = ratio;
5904
6017
  best = spy;
5905
6018
  }
5906
6019
  }
5907
6020
  if (!best) {
5908
- if (options.keepTopElementActive) {
5909
- best = _ScrollSpy._nearestAbove() ?? _ScrollSpy._elements[0];
5910
- } else {
5911
- _ScrollSpy._clearActive(options);
5912
- return;
5913
- }
6021
+ const retained = elements.filter((spy) => spy.options.keepTopElementActive);
6022
+ best = _ScrollSpy._nearestAbove(retained) ?? retained[0];
5914
6023
  }
5915
- const next = _ScrollSpy._linkFor(best.el.id, best.options);
5916
- if (next === _ScrollSpy._active) return;
5917
- _ScrollSpy._clearActive(options);
6024
+ const next = best ? _ScrollSpy._linkFor(best.el.id, best.options) : null;
6025
+ const active = _ScrollSpy._active.get(resolver);
6026
+ if (active === best && active?._link === next) return;
6027
+ _ScrollSpy._clearActive(resolver);
5918
6028
  if (!next) return;
5919
6029
  next.classList.add(best.options.activeClass);
5920
6030
  next.setAttribute("aria-current", "true");
5921
- _ScrollSpy._active = next;
6031
+ best._link = next;
6032
+ _ScrollSpy._active.set(resolver, best);
5922
6033
  }
5923
- static _nearestAbove() {
6034
+ static _nearestAbove(elements) {
5924
6035
  let best = null;
5925
6036
  let bestTop = -Infinity;
5926
- for (const spy of _ScrollSpy._elements) {
6037
+ for (const spy of elements) {
5927
6038
  const top = spy.el.getBoundingClientRect().top;
5928
6039
  if (top <= 0 && top >= bestTop) {
5929
6040
  bestTop = top;
@@ -5932,11 +6043,13 @@ var _ScrollSpy = class _ScrollSpy extends Component {
5932
6043
  }
5933
6044
  return best;
5934
6045
  }
5935
- static _clearActive(options) {
5936
- if (!_ScrollSpy._active) return;
5937
- _ScrollSpy._active.classList.remove(options.activeClass);
5938
- _ScrollSpy._active.removeAttribute("aria-current");
5939
- _ScrollSpy._active = null;
6046
+ static _clearActive(resolver) {
6047
+ const active = _ScrollSpy._active.get(resolver);
6048
+ if (!active) return;
6049
+ active._link?.classList.remove(active.options.activeClass);
6050
+ active._link?.removeAttribute("aria-current");
6051
+ active._link = null;
6052
+ _ScrollSpy._active.delete(resolver);
5940
6053
  }
5941
6054
  /**
5942
6055
  * Default lookup compares href attributes (no interpolated selector).
@@ -5960,19 +6073,7 @@ var _ScrollSpy = class _ScrollSpy extends Component {
5960
6073
  }
5961
6074
  };
5962
6075
  _ScrollSpy._elements = [];
5963
- _ScrollSpy._observer = null;
5964
- _ScrollSpy._ratios = /* @__PURE__ */ new Map();
5965
- _ScrollSpy._active = null;
5966
- _ScrollSpy._onIntersect = (entries) => {
5967
- for (const entry of entries) {
5968
- if (entry.isIntersecting && entry.intersectionRatio > 0) {
5969
- _ScrollSpy._ratios.set(entry.target, entry.intersectionRatio);
5970
- } else {
5971
- _ScrollSpy._ratios.delete(entry.target);
5972
- }
5973
- }
5974
- _ScrollSpy._syncActive();
5975
- };
6076
+ _ScrollSpy._active = /* @__PURE__ */ new Map();
5976
6077
  var ScrollSpy = _ScrollSpy;
5977
6078
 
5978
6079
  // src/ts/components/navigationRail.ts
@@ -6036,8 +6137,19 @@ var NavigationRail = class _NavigationRail extends Component {
6036
6137
  }
6037
6138
  };
6038
6139
  this._onKeyDown = (e) => {
6039
- if (e.key !== "Escape") return;
6040
- if (this.isExpanded && this._isModal()) this.collapse();
6140
+ if (e.key !== "Escape" || e.defaultPrevented) return;
6141
+ if (this.isExpanded && this._isModal()) {
6142
+ const root = this.el.getRootNode();
6143
+ const restoreFocus = this.el.contains(root.activeElement);
6144
+ let focused = root.activeElement;
6145
+ while (focused?.shadowRoot?.activeElement) focused = focused.shadowRoot.activeElement;
6146
+ this.collapse();
6147
+ let active = root.activeElement;
6148
+ while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
6149
+ if (!this.isExpanded && restoreFocus && active === focused) {
6150
+ this._toggle?.focus();
6151
+ }
6152
+ }
6041
6153
  };
6042
6154
  this.el["Expressive_NavigationRail"] = this;
6043
6155
  this.options = {
@@ -6115,14 +6227,13 @@ var Tabs = class _Tabs extends Component {
6115
6227
  }
6116
6228
  if (tabLink.hasAttribute("target")) return;
6117
6229
  if (this.options.swipeable) {
6118
- const panel = tabLink.hash && document.querySelector(tabLink.hash);
6230
+ const panel = tabLink.hash && document.getElementById(tabLink.hash.slice(1));
6119
6231
  const index = this._tabsCarousel.images.indexOf(panel);
6120
6232
  if (index >= 0) this._tabsCarousel.set(index);
6121
6233
  e.preventDefault();
6122
6234
  return;
6123
6235
  }
6124
6236
  const _oldContent = this._content;
6125
- if (tabLink.hash) this._content = document.querySelector(tabLink.hash);
6126
6237
  this._tabLinks = this._queryTabLinks();
6127
6238
  const prevIndex = this._index;
6128
6239
  this._setActiveTabLink(tabLink);
@@ -6149,7 +6260,7 @@ var Tabs = class _Tabs extends Component {
6149
6260
  this._tabLinks.forEach((link) => {
6150
6261
  this._originalLinks.set(link, { active: link.classList.contains("active"), current: link.getAttribute("aria-current") });
6151
6262
  if (link.hasAttribute("target")) return;
6152
- const panel = link.hash && document.querySelector(link.hash);
6263
+ const panel = link.hash && document.getElementById(link.hash.slice(1));
6153
6264
  if (panel) this._originalPanels.set(panel, {
6154
6265
  display: panel.style.display,
6155
6266
  priority: panel.style.getPropertyPriority("display"),
@@ -6270,7 +6381,7 @@ var Tabs = class _Tabs extends Component {
6270
6381
  const tabsContent = [];
6271
6382
  this._tabLinks.forEach((a) => {
6272
6383
  if (a.hash && !a.hasAttribute("target")) {
6273
- const currContent = document.querySelector(a.hash);
6384
+ const currContent = document.getElementById(a.hash.slice(1));
6274
6385
  if (!currContent) return;
6275
6386
  currContent.classList.add("carousel-item");
6276
6387
  tabsContent.push(currContent);
@@ -6310,7 +6421,7 @@ var Tabs = class _Tabs extends Component {
6310
6421
  Array.from(this._tabLinks).forEach((a) => {
6311
6422
  if (a === this._activeTabLink || a.hasAttribute("target")) return;
6312
6423
  if (a.hash) {
6313
- const currContent = document.querySelector(a.hash);
6424
+ const currContent = document.getElementById(a.hash.slice(1));
6314
6425
  if (currContent) currContent.style.display = "none";
6315
6426
  }
6316
6427
  });
@@ -6398,6 +6509,7 @@ var _Timepicker = class _Timepicker extends Component {
6398
6509
  /** Whether the dial (ticks + SVG + AM/PM buttons) has been built yet. */
6399
6510
  this._clockBuilt = false;
6400
6511
  this._handleInputClick = () => {
6512
+ this._updateTimeFromInput();
6401
6513
  this._ensureClockBuilt();
6402
6514
  if (this.displayPlugin) this.displayPlugin.show();
6403
6515
  this.inputHours.focus();
@@ -6406,10 +6518,7 @@ var _Timepicker = class _Timepicker extends Component {
6406
6518
  this._handleInputKeydown = (e) => {
6407
6519
  if (e.key === Utils.keys.ENTER) {
6408
6520
  e.preventDefault();
6409
- this._ensureClockBuilt();
6410
- if (this.displayPlugin) this.displayPlugin.show();
6411
- this.inputHours.focus();
6412
- if (typeof this.options.onInputInteraction === "function") this.options.onInputInteraction.call(this);
6521
+ this._handleInputClick();
6413
6522
  }
6414
6523
  };
6415
6524
  this._handleClockClickStart = (e) => {
@@ -6453,7 +6562,9 @@ var _Timepicker = class _Timepicker extends Component {
6453
6562
  this.inputMinutes.focus();
6454
6563
  this.showView("minutes", this.options.duration / 2);
6455
6564
  } else {
6456
- setTimeout(() => {
6565
+ clearTimeout(this._autoSubmitTimer);
6566
+ this._autoSubmitTimer = setTimeout(() => {
6567
+ this._autoSubmitTimer = null;
6457
6568
  if (this.options.autoSubmit) this.done();
6458
6569
  }, this.options.duration / 2);
6459
6570
  }
@@ -6505,6 +6616,7 @@ var _Timepicker = class _Timepicker extends Component {
6505
6616
  const input = event.target;
6506
6617
  const isHours = input === this.inputHours;
6507
6618
  if (!isHours && input !== this.inputMinutes) return;
6619
+ this._cancelClockReset();
6508
6620
  const value = Number(input.value);
6509
6621
  const min = isHours && this.options.twelveHour ? 1 : 0;
6510
6622
  const max = isHours ? this.options.twelveHour ? 12 : 23 : 59;
@@ -6573,6 +6685,10 @@ var _Timepicker = class _Timepicker extends Component {
6573
6685
  return el["Expressive_Timepicker"];
6574
6686
  }
6575
6687
  destroy() {
6688
+ clearTimeout(this._autoSubmitTimer);
6689
+ clearTimeout(this.toggleViewTimer);
6690
+ clearTimeout(this.vibrateTimer);
6691
+ this._cancelClockReset();
6576
6692
  this._removeEventHandlers();
6577
6693
  this.displayPlugin?.destroy();
6578
6694
  this.containerEl.remove();
@@ -6759,6 +6875,7 @@ var _Timepicker = class _Timepicker extends Component {
6759
6875
  }
6760
6876
  }
6761
6877
  _updateTimeFromInput() {
6878
+ this._cancelClockReset();
6762
6879
  let value = ((this.el.value || this.options.defaultTime || "") + "").trim().toUpperCase().split(":");
6763
6880
  const period = value[1]?.match(/AM|PM/)?.[0];
6764
6881
  value[1] = value[1]?.replace(/AM|PM/, "");
@@ -6776,12 +6893,17 @@ var _Timepicker = class _Timepicker extends Component {
6776
6893
  this.inputMinutes.value = _Timepicker._addLeadingZero(this.minutes);
6777
6894
  this._updateAmPmView();
6778
6895
  }
6896
+ _cancelClockReset() {
6897
+ clearTimeout(this._clockResetTimer);
6898
+ this._clockResetTimer = null;
6899
+ this._canvas?.classList.remove("timepicker-canvas-out");
6900
+ }
6779
6901
  resetClock(delay) {
6902
+ this._cancelClockReset();
6780
6903
  const view = this.currentView, value = this[view], isHours = view === "hours", unit = Math.PI / (isHours ? 6 : 30), radian = value * unit, radius = isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius, x = Math.sin(radian) * radius, y = -Math.cos(radian) * radius;
6781
6904
  if (delay) {
6782
6905
  this._canvas?.classList.add("timepicker-canvas-out");
6783
- setTimeout(() => {
6784
- this._canvas?.classList.remove("timepicker-canvas-out");
6906
+ this._clockResetTimer = setTimeout(() => {
6785
6907
  this.setHand(x, y);
6786
6908
  }, delay);
6787
6909
  } else {
@@ -6800,6 +6922,7 @@ var _Timepicker = class _Timepicker extends Component {
6800
6922
  this.setClockAttributes(radian, radius);
6801
6923
  }
6802
6924
  setHand(x, y, roundBy5 = false) {
6925
+ this._cancelClockReset();
6803
6926
  const isHours = this.currentView === "hours", unit = Math.PI / (isHours || roundBy5 ? 6 : 30), z = Math.sqrt(x * x + y * y), inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2;
6804
6927
  let radian = Math.atan2(x, -y), radius = inner ? this.options.innerRadius : this.options.outerRadius;
6805
6928
  if (this.options.twelveHour) {
@@ -6920,6 +7043,7 @@ var _Snackbar = class _Snackbar {
6920
7043
  constructor(options = {}) {
6921
7044
  this._dismissed = false;
6922
7045
  this._returnFocus = null;
7046
+ this._restoreElement = null;
6923
7047
  this.options = {
6924
7048
  ..._Snackbar.defaults,
6925
7049
  ...options
@@ -6934,22 +7058,20 @@ var _Snackbar = class _Snackbar {
6934
7058
  while (_Snackbar._snackbars.length > 0) {
6935
7059
  const snackbar = _Snackbar._snackbars.shift();
6936
7060
  snackbar._dismissed = true;
6937
- clearTimeout(snackbar.counterTimeout);
6938
- snackbar._restoreFocus();
6939
- snackbar.el.remove();
7061
+ snackbar._restoreFocus(true);
6940
7062
  }
6941
7063
  let focused = document.activeElement;
6942
7064
  while (focused?.shadowRoot?.activeElement) focused = focused.shadowRoot.activeElement;
6943
7065
  this._returnFocus = focused instanceof HTMLElement ? focused : null;
7066
+ this.el = this._createSnackbar();
6944
7067
  const root = Utils.portalRoot(this.options.root ?? document.body);
6945
7068
  if (!_Snackbar._container || !_Snackbar._container.isConnected || _Snackbar._container.parentNode !== root) {
6946
7069
  if (_Snackbar._container) _Snackbar._removeContainer();
6947
7070
  _Snackbar._createContainer(root);
6948
7071
  }
7072
+ _Snackbar._container.appendChild(this.el);
7073
+ this.el["Expressive_Snackbar"] = this;
6949
7074
  _Snackbar._snackbars.push(this);
6950
- const snackbarElement = this._createSnackbar();
6951
- snackbarElement["Expressive_Snackbar"] = this;
6952
- this.el = snackbarElement;
6953
7075
  this._animateIn();
6954
7076
  this._setTimer();
6955
7077
  }
@@ -6991,6 +7113,7 @@ var _Snackbar = class _Snackbar {
6991
7113
  snackbar.el.style.transition = "";
6992
7114
  _Snackbar._dragPointerId = e.pointerId;
6993
7115
  snackbar.startingXPos = e.clientX;
7116
+ snackbar.velocityX = 0;
6994
7117
  snackbar.time = Date.now();
6995
7118
  snackbar.xPos = e.clientX;
6996
7119
  }
@@ -7019,7 +7142,8 @@ var _Snackbar = class _Snackbar {
7019
7142
  snackbar.el.classList.remove("panning");
7020
7143
  const totalDeltaX = snackbar.xPos - snackbar.startingXPos;
7021
7144
  const activationDistance = snackbar.el.offsetWidth * snackbar.options.activationPercent;
7022
- const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || snackbar.velocityX > 1;
7145
+ const velocity = Date.now() - snackbar.time < 100 ? snackbar.velocityX : 0;
7146
+ const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || velocity > 1;
7023
7147
  if (shouldBeDismissed) {
7024
7148
  snackbar.wasSwiped = true;
7025
7149
  snackbar.dismiss();
@@ -7063,7 +7187,23 @@ var _Snackbar = class _Snackbar {
7063
7187
  if (snackbar instanceof HTMLTemplateElement) {
7064
7188
  const node = snackbar.content.cloneNode(true);
7065
7189
  snackbar = node.firstElementChild;
7190
+ } else if (snackbar && this.options.snackbarId) {
7191
+ const placeholder = document.createComment("");
7192
+ snackbar.before(placeholder);
7193
+ const children = [...snackbar.childNodes];
7194
+ const attributes = ["class", "style", "role", "aria-live", "aria-atomic", "inert"].map((name) => [name, snackbar.getAttribute(name)]);
7195
+ this._restoreElement = () => {
7196
+ snackbar.replaceChildren(...children);
7197
+ for (const [name, value] of attributes) {
7198
+ if (value === null) snackbar.removeAttribute(name);
7199
+ else snackbar.setAttribute(name, value);
7200
+ }
7201
+ placeholder.replaceWith(snackbar);
7202
+ };
7066
7203
  }
7204
+ if (!snackbar) throw new Error("Snackbar body not found");
7205
+ this._events = new (snackbar.ownerDocument.defaultView ?? window).AbortController();
7206
+ const listenerOptions = { signal: this._events.signal };
7067
7207
  snackbar.classList.add("snackbar");
7068
7208
  snackbar.setAttribute("role", "status");
7069
7209
  snackbar.setAttribute("aria-live", "polite");
@@ -7074,16 +7214,19 @@ var _Snackbar = class _Snackbar {
7074
7214
  this._returnFocus = e.relatedTarget;
7075
7215
  }
7076
7216
  this._pauseTimer();
7077
- });
7217
+ }, listenerOptions);
7078
7218
  snackbar.addEventListener("keydown", (e) => {
7079
7219
  if (e.key !== "Escape" || e.defaultPrevented || this._dismissed) return;
7080
7220
  e.preventDefault();
7081
7221
  e.stopPropagation();
7082
7222
  this.dismiss();
7083
- });
7084
- snackbar.addEventListener("focusout", () => setTimeout(() => this._resumeTimer(), 0));
7085
- snackbar.addEventListener("pointerenter", () => this._pauseTimer());
7086
- snackbar.addEventListener("pointerleave", () => this._resumeTimer());
7223
+ }, listenerOptions);
7224
+ snackbar.addEventListener("focusout", () => {
7225
+ clearTimeout(this._focusTimer);
7226
+ this._focusTimer = setTimeout(() => this._resumeTimer(), 0);
7227
+ }, listenerOptions);
7228
+ snackbar.addEventListener("pointerenter", () => this._pauseTimer(), listenerOptions);
7229
+ snackbar.addEventListener("pointerleave", () => this._resumeTimer(), listenerOptions);
7087
7230
  if (this.options.classes.length > 0) {
7088
7231
  snackbar.classList.add(...this.options.classes.split(" ").filter(Boolean));
7089
7232
  }
@@ -7104,7 +7247,7 @@ var _Snackbar = class _Snackbar {
7104
7247
  } finally {
7105
7248
  this.dismiss();
7106
7249
  }
7107
- });
7250
+ }, listenerOptions);
7108
7251
  snackbar.appendChild(action);
7109
7252
  }
7110
7253
  if (this.options.dismissible) {
@@ -7120,12 +7263,32 @@ var _Snackbar = class _Snackbar {
7120
7263
  close.addEventListener("click", (e) => {
7121
7264
  e.stopPropagation();
7122
7265
  this.dismiss();
7123
- });
7266
+ }, listenerOptions);
7124
7267
  snackbar.appendChild(close);
7125
7268
  }
7126
- _Snackbar._container.appendChild(snackbar);
7127
7269
  return snackbar;
7128
7270
  }
7271
+ _remove() {
7272
+ if (this._events.signal.aborted) return;
7273
+ this._events.abort();
7274
+ clearTimeout(this.counterTimeout);
7275
+ clearTimeout(this._transitionTimer);
7276
+ clearTimeout(this._dismissTimer);
7277
+ clearTimeout(this._focusTimer);
7278
+ this.counterTimeout = null;
7279
+ if (_Snackbar._draggedSnackbar === this) {
7280
+ _Snackbar._draggedSnackbar = null;
7281
+ _Snackbar._dragPointerId = null;
7282
+ }
7283
+ this.el["Expressive_Snackbar"] = void 0;
7284
+ if (this._restoreElement) this._restoreElement();
7285
+ else this.el.remove();
7286
+ const index = _Snackbar._snackbars.indexOf(this);
7287
+ if (index >= 0) _Snackbar._snackbars.splice(index, 1);
7288
+ if (!_Snackbar._snackbars.length && _Snackbar._container?.childElementCount === 0) {
7289
+ _Snackbar._removeContainer();
7290
+ }
7291
+ }
7129
7292
  _animateIn() {
7130
7293
  this.el.style.display = "";
7131
7294
  this.el.style.opacity = "0";
@@ -7134,7 +7297,7 @@ var _Snackbar = class _Snackbar {
7134
7297
  transform ${this.options.inDuration}ms ease,
7135
7298
  opacity ${this.options.inDuration}ms ease
7136
7299
  `;
7137
- setTimeout(() => {
7300
+ this._transitionTimer = setTimeout(() => {
7138
7301
  this.el.style.transform = "";
7139
7302
  this.el.style.opacity = "1";
7140
7303
  }, 1);
@@ -7163,12 +7326,12 @@ var _Snackbar = class _Snackbar {
7163
7326
  if (this._dismissed || this.panning || this.el.matches(":hover, :focus-within") || this.counterTimeout != null) return;
7164
7327
  this._setTimer();
7165
7328
  }
7166
- _restoreFocus() {
7329
+ _restoreFocus(remove = false) {
7167
7330
  const focused = this.el.getRootNode().activeElement;
7168
- if (focused && this.el.contains(focused) && this._returnFocus?.isConnected) {
7169
- this._returnFocus.focus({ preventScroll: true });
7170
- }
7331
+ const returnFocus = focused && this.el.contains(focused) ? this._returnFocus : null;
7171
7332
  this.el.inert = true;
7333
+ if (remove) this._remove();
7334
+ if (returnFocus?.isConnected) returnFocus.focus({ preventScroll: true });
7172
7335
  }
7173
7336
  /**
7174
7337
  * Dismiss snackbar with animation.
@@ -7179,6 +7342,7 @@ var _Snackbar = class _Snackbar {
7179
7342
  clearTimeout(this.counterTimeout);
7180
7343
  this.counterTimeout = null;
7181
7344
  this._restoreFocus();
7345
+ if (this._events.signal.aborted) return;
7182
7346
  const activationDistance = this.el.offsetWidth * this.options.activationPercent;
7183
7347
  if (this.wasSwiped) {
7184
7348
  this.el.style.transition = "transform .05s, opacity .05s";
@@ -7188,22 +7352,16 @@ var _Snackbar = class _Snackbar {
7188
7352
  this.el.style.transition = `
7189
7353
  margin ${this.options.outDuration}ms ease,
7190
7354
  opacity ${this.options.outDuration}ms ease`;
7191
- setTimeout(() => {
7355
+ clearTimeout(this._transitionTimer);
7356
+ this._transitionTimer = setTimeout(() => {
7192
7357
  this.el.style.opacity = "0";
7193
7358
  this.el.style.marginTop = "-40px";
7194
7359
  }, 1);
7195
- setTimeout(() => {
7360
+ this._dismissTimer = setTimeout(() => {
7361
+ this._remove();
7196
7362
  if (typeof this.options.completeCallback === "function") {
7197
7363
  this.options.completeCallback();
7198
7364
  }
7199
- if (this.el.id != this.options.snackbarId) {
7200
- this.el.remove();
7201
- const index = _Snackbar._snackbars.indexOf(this);
7202
- if (index >= 0) _Snackbar._snackbars.splice(index, 1);
7203
- if (_Snackbar._snackbars.length === 0 && _Snackbar._container && _Snackbar._container.childElementCount === 0) {
7204
- _Snackbar._removeContainer();
7205
- }
7206
- }
7207
7365
  }, this.options.outDuration);
7208
7366
  }
7209
7367
  };
@@ -7232,9 +7390,8 @@ var Tooltip = class _Tooltip extends Component {
7232
7390
  /**
7233
7391
  * Show tooltip.
7234
7392
  */
7235
- this.open = (isManual) => {
7393
+ this.open = (isManual = true) => {
7236
7394
  if (this.isOpen) return;
7237
- isManual = isManual === void 0 ? true : void 0;
7238
7395
  clearTimeout(this._exitDelayTimeout);
7239
7396
  clearTimeout(this._animationTimeout);
7240
7397
  this.isOpen = true;
@@ -7318,8 +7475,21 @@ var Tooltip = class _Tooltip extends Component {
7318
7475
  this.isOpen = false;
7319
7476
  this.isHovered = false;
7320
7477
  this.isFocused = false;
7321
- if (this.el.getAttribute("aria-describedby") === this.tooltipEl.id) {
7322
- this.el.removeAttribute("aria-describedby");
7478
+ const descriptions = this.el.getAttribute("aria-describedby")?.split(/\s+/);
7479
+ if (descriptions?.includes(this.tooltipEl.id)) {
7480
+ const remaining = descriptions.filter((id) => id && id !== this.tooltipEl.id).join(" ");
7481
+ if (remaining) this.el.setAttribute("aria-describedby", remaining);
7482
+ else this.el.removeAttribute("aria-describedby");
7483
+ }
7484
+ if (this._originalContent) {
7485
+ const { el, marker, display, priority, hidden, contentClass } = this._originalContent;
7486
+ el.style.setProperty("display", display, priority);
7487
+ if (hidden === null) el.removeAttribute("hidden");
7488
+ else el.setAttribute("hidden", hidden);
7489
+ el.classList.toggle("tooltip-content", contentClass);
7490
+ if (!el.className) el.removeAttribute("class");
7491
+ marker.replaceWith(el);
7492
+ this._originalContent = null;
7323
7493
  }
7324
7494
  this.tooltipEl.remove();
7325
7495
  this._removeEventHandlers();
@@ -7330,10 +7500,21 @@ var Tooltip = class _Tooltip extends Component {
7330
7500
  this.tooltipEl.classList.add("tooltip");
7331
7501
  this.tooltipEl.id = `tooltip-${Utils.guid()}`;
7332
7502
  this.tooltipEl.setAttribute("role", "tooltip");
7333
- this.el.setAttribute("aria-describedby", this.tooltipEl.id);
7503
+ this.el.setAttribute("aria-describedby", [this.el.getAttribute("aria-describedby"), this.tooltipEl.id].filter(Boolean).join(" "));
7334
7504
  const tooltipContentEl = this.options.tooltipId ? Utils.getElementById(this.el, this.options.tooltipId) : document.createElement("div");
7335
7505
  if (this.options.tooltipId) {
7336
7506
  this.tooltipEl.classList.add("rich");
7507
+ const marker = document.createComment("");
7508
+ tooltipContentEl.before(marker);
7509
+ this._originalContent = {
7510
+ el: tooltipContentEl,
7511
+ marker,
7512
+ display: tooltipContentEl.style.display,
7513
+ priority: tooltipContentEl.style.getPropertyPriority("display"),
7514
+ hidden: tooltipContentEl.getAttribute("hidden"),
7515
+ contentClass: tooltipContentEl.classList.contains("tooltip-content")
7516
+ };
7517
+ tooltipContentEl.removeAttribute("hidden");
7337
7518
  }
7338
7519
  tooltipContentEl.style.display = "";
7339
7520
  tooltipContentEl.classList.add("tooltip-content");
@@ -7531,7 +7712,7 @@ function AutoInit(context = document.body, options) {
7531
7712
  }
7532
7713
 
7533
7714
  // src/ts/modular.ts
7534
- var version = "0.10.1";
7715
+ var version = "0.12.0";
7535
7716
 
7536
7717
  // src/ts/index.ts
7537
7718
  Forms.Init();