@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
@@ -0,0 +1,663 @@
1
+ import {
2
+ Utils
3
+ } from "./chunk-MISGHDUU.mjs";
4
+ import {
5
+ Component
6
+ } from "./chunk-QSQ24FYT.mjs";
7
+
8
+ // src/ts/components/menu.ts
9
+ var MIN_SURFACE_WIDTH = 112;
10
+ var MAX_SURFACE_WIDTH = 280;
11
+ var _defaults = {
12
+ alignment: "left",
13
+ autoFocus: true,
14
+ constrainWidth: true,
15
+ container: null,
16
+ coverTrigger: false,
17
+ closeOnClick: true,
18
+ hover: false,
19
+ inDuration: 150,
20
+ outDuration: 250,
21
+ onOpenStart: null,
22
+ onOpenEnd: null,
23
+ onCloseStart: null,
24
+ onCloseEnd: null,
25
+ onItemClick: null
26
+ };
27
+ var SPACE = " ";
28
+ var _Menu = class _Menu extends Component {
29
+ constructor(el, options) {
30
+ super(el, options, _Menu);
31
+ this._pendingTimers = /* @__PURE__ */ new Set();
32
+ this._transition = 0;
33
+ this._handleClick = (e) => {
34
+ e.preventDefault();
35
+ if (this.isOpen) {
36
+ this.close();
37
+ } else {
38
+ this.open();
39
+ }
40
+ };
41
+ this._handleMouseEnter = () => {
42
+ this.open();
43
+ };
44
+ this._handleMouseLeave = (e) => {
45
+ const toEl = e.relatedTarget;
46
+ if (!toEl) {
47
+ this.close();
48
+ return;
49
+ }
50
+ const leaveToMenuContent = !!(this.menuEl && toEl && this.menuEl.contains(toEl));
51
+ let leaveToActiveMenuTrigger = false;
52
+ const closestTrigger = toEl.closest(".menu-trigger");
53
+ if (closestTrigger && !!closestTrigger["Expressive_Menu"] && closestTrigger["Expressive_Menu"].isOpen) {
54
+ leaveToActiveMenuTrigger = true;
55
+ }
56
+ if (!leaveToActiveMenuTrigger && !leaveToMenuContent) {
57
+ this.close();
58
+ }
59
+ };
60
+ this._handleDocumentClick = (e) => {
61
+ const target = e.target;
62
+ if (this._isSubmenuTriggerClick(target)) return;
63
+ if (this.options.closeOnClick && this.menuEl?.contains(target) && !this.isTouchMoving) {
64
+ this.close();
65
+ } else if (!this.menuEl?.contains(target)) {
66
+ this._schedule(() => {
67
+ if (this.isOpen) {
68
+ this.close();
69
+ }
70
+ }, 0);
71
+ }
72
+ this.isTouchMoving = false;
73
+ };
74
+ this._handleTriggerKeydown = (e) => {
75
+ const opensMenu = e.key === SPACE || e.key === Utils.keys.ENTER || e.key === Utils.keys.ARROW_DOWN || e.key === Utils.keys.ARROW_UP;
76
+ if (opensMenu && !this.isOpen) {
77
+ e.preventDefault();
78
+ this.open();
79
+ }
80
+ };
81
+ this._handleDocumentTouchmove = (e) => {
82
+ const target = e.target;
83
+ if (this.menuEl?.contains(target)) {
84
+ this.isTouchMoving = true;
85
+ }
86
+ };
87
+ this._handleMenuClick = (e) => {
88
+ const target = e.target;
89
+ const li = target.closest("li");
90
+ if (li?.matches('.disabled, [aria-disabled="true"]')) {
91
+ e.preventDefault();
92
+ e.stopPropagation();
93
+ return;
94
+ }
95
+ if (li && this._isSubmenuTriggerClick(target)) {
96
+ e.preventDefault();
97
+ e.stopPropagation();
98
+ this._toggleSubmenu(li);
99
+ return;
100
+ }
101
+ if (li && typeof this.options.onItemClick === "function") {
102
+ this.options.onItemClick.call(this, li);
103
+ }
104
+ };
105
+ this._handleSubmenuAlign = (e) => {
106
+ const target = e.target;
107
+ if (!(target instanceof Element)) return;
108
+ const li = target.closest("li");
109
+ if (li?.querySelector(":scope > menu") && this.menuEl?.contains(li)) {
110
+ this._alignSubmenu(li);
111
+ }
112
+ };
113
+ this._handleMenuKeydown = (e) => {
114
+ if (!this.isOpen || e.ctrlKey || e.metaKey || e.altKey || e.isComposing) return;
115
+ const list = this._containingSubmenu(e) ?? this.menuEl;
116
+ const rtl = getComputedStyle(list).direction === "rtl";
117
+ const openKey = rtl ? Utils.keys.ARROW_LEFT : Utils.keys.ARROW_RIGHT;
118
+ const backKey = rtl ? Utils.keys.ARROW_RIGHT : Utils.keys.ARROW_LEFT;
119
+ if ([openKey, backKey, Utils.keys.ARROW_UP, Utils.keys.ARROW_DOWN, Utils.keys.ESC, Utils.keys.TAB].includes(e.key)) {
120
+ clearTimeout(this.filterTimeout);
121
+ this._resetFilterQuery();
122
+ }
123
+ const arrowUpOrDown = e.key === Utils.keys.ARROW_DOWN || e.key === Utils.keys.ARROW_UP;
124
+ if (e.key === Utils.keys.TAB) {
125
+ e.preventDefault();
126
+ this.close();
127
+ } else if (e.key === openKey) {
128
+ const li = this._focusedRow(e);
129
+ if (li?.querySelector(":scope > menu") && !li.matches('.disabled, [aria-disabled="true"]')) {
130
+ e.preventDefault();
131
+ li.classList.add("open");
132
+ this._alignSubmenu(li);
133
+ this._syncSubmenuAria(li, true);
134
+ const first = Array.from(li.querySelector(":scope > menu").children).find(
135
+ (child) => child instanceof HTMLElement && child.tabIndex !== -1
136
+ );
137
+ if (first) this._focusRow(first);
138
+ }
139
+ } else if (e.key === backKey) {
140
+ const submenu = this._containingSubmenu(e);
141
+ if (submenu) {
142
+ e.preventDefault();
143
+ const parentLi = submenu.parentElement;
144
+ parentLi.classList.remove("open", "submenu-start");
145
+ this._syncSubmenuAria(parentLi, false);
146
+ this._focusRow(parentLi);
147
+ }
148
+ } else if (arrowUpOrDown && this.isOpen) {
149
+ e.preventDefault();
150
+ const direction = e.key === Utils.keys.ARROW_DOWN ? 1 : -1;
151
+ const row = this._focusedRow(e);
152
+ let newFocusedIndex = row ? Array.from(list.children).indexOf(row) : this.focusedIndex;
153
+ let hasFoundNewIndex = false;
154
+ do {
155
+ newFocusedIndex = newFocusedIndex + direction;
156
+ if (!!list.children[newFocusedIndex] && list.children[newFocusedIndex].tabIndex !== -1) {
157
+ hasFoundNewIndex = true;
158
+ break;
159
+ }
160
+ } while (newFocusedIndex < list.children.length && newFocusedIndex >= 0);
161
+ if (hasFoundNewIndex) {
162
+ if (this.focusedIndex >= 0) list.children[this.focusedIndex]?.classList.remove("active");
163
+ const item = list.children[newFocusedIndex];
164
+ item.classList.add("active");
165
+ this._focusRow(item);
166
+ }
167
+ } else if ((e.key === Utils.keys.ENTER || e.key === SPACE) && this.isOpen) {
168
+ const li = this._focusedRow(e);
169
+ e.preventDefault();
170
+ if (li?.matches('.disabled, [aria-disabled="true"]')) return;
171
+ if (li?.querySelector(":scope > menu")) {
172
+ this._toggleSubmenu(li);
173
+ return;
174
+ }
175
+ const focusedElement = li ?? this.menuEl.children[this.focusedIndex];
176
+ const activatableElement = focusedElement?.querySelector(":scope > a, :scope > button");
177
+ if (!!activatableElement) {
178
+ activatableElement.click();
179
+ } else if (focusedElement instanceof HTMLElement) {
180
+ focusedElement.click();
181
+ }
182
+ } else if (e.key === Utils.keys.ESC && this.isOpen) {
183
+ e.preventDefault();
184
+ const openSub = this._containingSubmenu(e)?.parentElement ?? Array.from(this.menuEl.querySelectorAll("li.open")).reverse()[0];
185
+ if (openSub) {
186
+ openSub.classList.remove("open", "submenu-start");
187
+ this._syncSubmenuAria(openSub, false);
188
+ this._focusRow(openSub);
189
+ } else {
190
+ this.close();
191
+ }
192
+ }
193
+ const keyText = e.key.toLowerCase();
194
+ if (e.key.length === 1 && e.key !== SPACE && !e.ctrlKey && !e.metaKey && !e.altKey && !e.isComposing) {
195
+ this.filterQuery.push(keyText);
196
+ const string = this.filterQuery.join("");
197
+ const newOptionEl = Array.from(list.querySelectorAll(":scope > li")).find(
198
+ (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)
199
+ );
200
+ if (newOptionEl) {
201
+ this._focusRow(newOptionEl);
202
+ }
203
+ clearTimeout(this.filterTimeout);
204
+ this.filterTimeout = setTimeout(this._resetFilterQuery, 1e3);
205
+ }
206
+ };
207
+ this._handleWindowResize = () => {
208
+ if (this.el.offsetParent) {
209
+ this.recalculateDimensions();
210
+ }
211
+ };
212
+ this._resetFilterQuery = () => {
213
+ this.filterQuery = [];
214
+ };
215
+ /**
216
+ * Open menu.
217
+ */
218
+ this.open = () => {
219
+ if (this.isOpen || this.el["Expressive_Menu"] !== this) return;
220
+ const transition = this._clearPendingTimers();
221
+ this.isOpen = true;
222
+ if (typeof this.options.onOpenStart === "function") {
223
+ this.options.onOpenStart.call(this, this.el);
224
+ }
225
+ if (transition !== this._transition) return;
226
+ this._resetMenuStyles();
227
+ this.menuEl.style.display = "block";
228
+ this._restoreInert();
229
+ this._placeMenu();
230
+ this._schedule(() => this._setupTemporaryEventHandlers(), 0);
231
+ this._animateIn();
232
+ this.el.ariaExpanded = "true";
233
+ };
234
+ /**
235
+ * Close menu.
236
+ */
237
+ this.close = () => {
238
+ if (!this.isOpen) return;
239
+ const transition = this._clearPendingTimers();
240
+ const root = this.menuEl.getRootNode();
241
+ const focused = root.activeElement;
242
+ this.isOpen = false;
243
+ this.menuEl.setAttribute("inert", "");
244
+ clearTimeout(this.filterTimeout);
245
+ this._resetFilterQuery();
246
+ this.focusedIndex = -1;
247
+ this._closeSubmenus();
248
+ if (typeof this.options.onCloseStart === "function") {
249
+ this.options.onCloseStart.call(this, this.el);
250
+ }
251
+ if (transition !== this._transition) return;
252
+ this._animateOut();
253
+ this._removeTemporaryEventHandlers();
254
+ this.el.ariaExpanded = "false";
255
+ if (this.options.autoFocus && (root.activeElement === focused || !root.activeElement || root.activeElement === document.body)) {
256
+ this.el.focus();
257
+ }
258
+ };
259
+ /**
260
+ * While menu is open, you can recalculate its dimensions if its contents have changed.
261
+ */
262
+ this.recalculateDimensions = () => {
263
+ if (this.isOpen) {
264
+ this._resetMenuPositioningStyles();
265
+ this._placeMenu();
266
+ }
267
+ };
268
+ this.el["Expressive_Menu"] = this;
269
+ _Menu._menus.push(this);
270
+ this.id = Utils.getIdFromTrigger(el);
271
+ this.menuEl = Utils.getElementById(el, this.id);
272
+ this._originalInert = this.menuEl?.getAttribute("inert") ?? null;
273
+ this.options = {
274
+ ..._Menu.defaults,
275
+ ...options
276
+ };
277
+ this.isOpen = false;
278
+ this.isScrollable = false;
279
+ this.isTouchMoving = false;
280
+ this.focusedIndex = -1;
281
+ this.filterQuery = [];
282
+ this.el.ariaExpanded = "false";
283
+ if (!this.el.hasAttribute("aria-haspopup")) this.el.setAttribute("aria-haspopup", "menu");
284
+ if (this.id && !this.el.hasAttribute("aria-controls"))
285
+ this.el.setAttribute("aria-controls", this.id);
286
+ this._moveMenuToElement();
287
+ this._setupAccessibility();
288
+ this._makeMenuFocusable();
289
+ this._setupSubmenus();
290
+ this._setupEventHandlers();
291
+ }
292
+ static get defaults() {
293
+ return _defaults;
294
+ }
295
+ /**
296
+ * Initializes instances of Menu.
297
+ * @param els HTML elements.
298
+ * @param options Component options.
299
+ */
300
+ static init(els, options = {}) {
301
+ return super.init(els, options, _Menu);
302
+ }
303
+ static getInstance(el) {
304
+ return el["Expressive_Menu"];
305
+ }
306
+ destroy() {
307
+ this._clearPendingTimers();
308
+ this.isOpen = false;
309
+ this.el.ariaExpanded = "false";
310
+ clearTimeout(this.filterTimeout);
311
+ this._resetMenuStyles();
312
+ this._restoreInert();
313
+ this._removeEventHandlers();
314
+ this._removeTemporaryEventHandlers();
315
+ const index = _Menu._menus.indexOf(this);
316
+ if (index >= 0) _Menu._menus.splice(index, 1);
317
+ this.el["Expressive_Menu"] = void 0;
318
+ }
319
+ _setupEventHandlers() {
320
+ this.el.addEventListener("keydown", this._handleTriggerKeydown);
321
+ this.menuEl?.addEventListener("click", this._handleMenuClick);
322
+ if (this.menuEl?.querySelector(":scope > li > menu")) {
323
+ this.menuEl.addEventListener("mouseover", this._handleSubmenuAlign);
324
+ }
325
+ if (this.options.hover) {
326
+ this.el.addEventListener("mouseenter", this._handleMouseEnter);
327
+ this.el.addEventListener("mouseleave", this._handleMouseLeave);
328
+ this.menuEl.addEventListener("mouseleave", this._handleMouseLeave);
329
+ } else {
330
+ this.el.addEventListener("click", this._handleClick);
331
+ }
332
+ }
333
+ _removeEventHandlers() {
334
+ this.el.removeEventListener("keydown", this._handleTriggerKeydown);
335
+ this.menuEl?.removeEventListener("click", this._handleMenuClick);
336
+ this.menuEl?.removeEventListener("mouseover", this._handleSubmenuAlign);
337
+ if (this.options.hover) {
338
+ this.el.removeEventListener("mouseenter", this._handleMouseEnter);
339
+ this.el.removeEventListener("mouseleave", this._handleMouseLeave);
340
+ this.menuEl?.removeEventListener("mouseleave", this._handleMouseLeave);
341
+ } else {
342
+ this.el.removeEventListener("click", this._handleClick);
343
+ }
344
+ }
345
+ _setupTemporaryEventHandlers() {
346
+ document.body.addEventListener("click", this._handleDocumentClick);
347
+ document.body.addEventListener("touchmove", this._handleDocumentTouchmove, {
348
+ passive: true
349
+ });
350
+ this.menuEl?.addEventListener("keydown", this._handleMenuKeydown);
351
+ window.addEventListener("resize", this._handleWindowResize);
352
+ }
353
+ _removeTemporaryEventHandlers() {
354
+ document.body.removeEventListener("click", this._handleDocumentClick);
355
+ document.body.removeEventListener("touchmove", this._handleDocumentTouchmove);
356
+ this.menuEl?.removeEventListener("keydown", this._handleMenuKeydown);
357
+ window.removeEventListener("resize", this._handleWindowResize);
358
+ }
359
+ _setupAccessibility() {
360
+ if (!this.menuEl) return;
361
+ if (!this.menuEl.hasAttribute("role")) this.menuEl.setAttribute("role", "menu");
362
+ const menus = [this.menuEl, ...this.menuEl.querySelectorAll("menu")];
363
+ menus.forEach((menu) => {
364
+ if (!menu.hasAttribute("role")) menu.setAttribute("role", "menu");
365
+ if (menu.getAttribute("role") !== "menu") return;
366
+ menu.querySelectorAll(":scope > li").forEach((li) => {
367
+ if (li.classList.contains("divider")) {
368
+ if (!li.hasAttribute("role")) li.setAttribute("role", "separator");
369
+ return;
370
+ }
371
+ if (li.classList.contains("gap")) {
372
+ li.setAttribute("aria-hidden", "true");
373
+ return;
374
+ }
375
+ if (li.classList.contains("label") || li.classList.contains("optgroup")) {
376
+ if (!li.hasAttribute("role")) li.setAttribute("role", "presentation");
377
+ return;
378
+ }
379
+ if (!li.hasAttribute("role")) li.setAttribute("role", "menuitem");
380
+ if (li.classList.contains("disabled") && !li.hasAttribute("aria-disabled")) {
381
+ li.setAttribute("aria-disabled", "true");
382
+ }
383
+ });
384
+ });
385
+ }
386
+ _isSubmenuTriggerClick(target) {
387
+ if (!this.menuEl) return false;
388
+ const li = target.closest("li");
389
+ if (!li || !this.menuEl.contains(li)) return false;
390
+ const submenu = li.querySelector(":scope > menu");
391
+ if (!submenu) return false;
392
+ return !submenu.contains(target);
393
+ }
394
+ _setupSubmenus() {
395
+ this.menuEl?.querySelectorAll("li").forEach((li) => {
396
+ if (!li.querySelector(":scope > menu")) return;
397
+ const trigger = li.querySelector(":scope > a, :scope > button, :scope > span") ?? li;
398
+ trigger.setAttribute("aria-haspopup", "menu");
399
+ trigger.setAttribute("aria-expanded", "false");
400
+ });
401
+ }
402
+ _toggleSubmenu(li) {
403
+ const open = !li.classList.contains("open");
404
+ li.parentElement?.querySelectorAll(":scope > li.open").forEach((other) => {
405
+ if (other !== li) {
406
+ other.classList.remove("open", "submenu-start");
407
+ this._syncSubmenuAria(other, false);
408
+ }
409
+ });
410
+ li.classList.toggle("open", open);
411
+ if (open) this._alignSubmenu(li);
412
+ this._syncSubmenuAria(li, open);
413
+ }
414
+ _syncSubmenuAria(li, open) {
415
+ const trigger = li.querySelector(":scope > a, :scope > button, :scope > span") ?? li;
416
+ trigger.setAttribute("aria-expanded", open ? "true" : "false");
417
+ }
418
+ _alignSubmenu(li) {
419
+ const menu = li.querySelector(":scope > menu");
420
+ if (!menu) return;
421
+ li.classList.remove("submenu-start");
422
+ const rect = menu.getBoundingClientRect();
423
+ if (rect.left < 8 || rect.right > window.innerWidth - 8) li.classList.add("submenu-start");
424
+ }
425
+ _closeSubmenus() {
426
+ this.menuEl?.querySelectorAll("li.open").forEach((li) => {
427
+ li.classList.remove("open", "submenu-start");
428
+ this._syncSubmenuAria(li, false);
429
+ });
430
+ }
431
+ _containingSubmenu(e) {
432
+ const target = e.target;
433
+ if (!(target instanceof Element)) return null;
434
+ const submenu = target.closest("li > menu");
435
+ if (submenu instanceof HTMLElement && this.menuEl?.contains(submenu)) return submenu;
436
+ return null;
437
+ }
438
+ _focusedRow(e) {
439
+ const target = e.target;
440
+ if (!(target instanceof Element)) return null;
441
+ const li = target.closest("li");
442
+ if (li instanceof HTMLElement && this.menuEl?.contains(li)) return li;
443
+ return null;
444
+ }
445
+ _restoreInert() {
446
+ if (this._originalInert === null) this.menuEl?.removeAttribute("inert");
447
+ else this.menuEl?.setAttribute("inert", this._originalInert);
448
+ }
449
+ _focusRow(item) {
450
+ this.focusedIndex = Array.from(item.parentElement.children).indexOf(item);
451
+ item.focus({ preventScroll: true });
452
+ item.scrollIntoView({ block: "nearest", inline: "nearest" });
453
+ }
454
+ _resetMenuStyles() {
455
+ this.menuEl.style.display = "";
456
+ this._resetMenuPositioningStyles();
457
+ this.menuEl.style.transform = "";
458
+ this.menuEl.style.opacity = "";
459
+ }
460
+ _resetMenuPositioningStyles() {
461
+ this.menuEl.style.width = "";
462
+ this.menuEl.style.height = "";
463
+ this.menuEl.style.left = "";
464
+ this.menuEl.style.top = "";
465
+ this.menuEl.style.transformOrigin = "";
466
+ }
467
+ _moveMenuToElement(containerEl = null) {
468
+ if (this.options.container) {
469
+ this.options.container.append(this.menuEl);
470
+ return;
471
+ }
472
+ if (containerEl) {
473
+ if (!containerEl.contains(this.menuEl)) containerEl.append(this.menuEl);
474
+ return;
475
+ }
476
+ this.el.after(this.menuEl);
477
+ }
478
+ _makeMenuFocusable() {
479
+ if (!this.menuEl) return;
480
+ this.menuEl.popover = "";
481
+ this.menuEl.tabIndex = -1;
482
+ this.menuEl.querySelectorAll(":scope li, :scope > hr").forEach((el) => {
483
+ if (el instanceof HTMLHRElement || el.classList.contains("divider") || el.classList.contains("gap") || el.classList.contains("label") || el.classList.contains("optgroup")) {
484
+ el.setAttribute("tabindex", "-1");
485
+ return;
486
+ }
487
+ if (!el.getAttribute("tabindex")) el.setAttribute("tabindex", "0");
488
+ });
489
+ }
490
+ _focusInitialItem() {
491
+ if (!this.menuEl || !this.options.autoFocus) return;
492
+ const first = Array.from(this.menuEl.children).find(
493
+ (child) => child instanceof HTMLElement && child.tabIndex !== -1
494
+ );
495
+ if (!first) return;
496
+ this.focusedIndex = Array.from(this.menuEl.children).indexOf(first);
497
+ first.focus({ preventScroll: true });
498
+ }
499
+ _focusFocusedItem() {
500
+ if (this.focusedIndex >= 0 && this.focusedIndex < this.menuEl.children.length && this.options.autoFocus) {
501
+ this.menuEl.children[this.focusedIndex].focus({
502
+ preventScroll: true
503
+ });
504
+ this.menuEl.children[this.focusedIndex].scrollIntoView({
505
+ behavior: "smooth",
506
+ block: "nearest",
507
+ inline: "nearest"
508
+ });
509
+ }
510
+ }
511
+ _getMenuPosition(closestOverflowParent) {
512
+ const triggerBRect = this.el.getBoundingClientRect();
513
+ const menuBRect = this.menuEl.getBoundingClientRect();
514
+ let idealHeight = menuBRect.height;
515
+ let idealWidth = menuBRect.width;
516
+ let idealXPos = triggerBRect.left - menuBRect.left;
517
+ let idealYPos = triggerBRect.top - menuBRect.top;
518
+ const menuBounds = {
519
+ left: idealXPos,
520
+ top: idealYPos,
521
+ height: idealHeight,
522
+ width: idealWidth
523
+ };
524
+ const alignments = Utils.checkPossibleAlignments(
525
+ this.el,
526
+ closestOverflowParent,
527
+ menuBounds,
528
+ this.options.coverTrigger ? 0 : triggerBRect.height
529
+ );
530
+ let verticalAlignment = "top";
531
+ let horizontalAlignment = this.options.alignment;
532
+ idealYPos += this.options.coverTrigger ? 0 : triggerBRect.height;
533
+ this.isScrollable = false;
534
+ if (!alignments.top) {
535
+ if (alignments.bottom) {
536
+ verticalAlignment = "bottom";
537
+ if (!this.options.coverTrigger) {
538
+ idealYPos -= triggerBRect.height;
539
+ }
540
+ } else {
541
+ this.isScrollable = true;
542
+ idealHeight -= 20;
543
+ if (alignments.spaceOnTop > alignments.spaceOnBottom) {
544
+ verticalAlignment = "bottom";
545
+ idealHeight += alignments.spaceOnTop;
546
+ idealYPos -= this.options.coverTrigger ? alignments.spaceOnTop - 20 : alignments.spaceOnTop - 20 + triggerBRect.height;
547
+ } else {
548
+ idealHeight += alignments.spaceOnBottom;
549
+ }
550
+ }
551
+ }
552
+ if (!alignments[horizontalAlignment]) {
553
+ const oppositeAlignment = horizontalAlignment === "left" ? "right" : "left";
554
+ if (alignments[oppositeAlignment]) {
555
+ horizontalAlignment = oppositeAlignment;
556
+ } else {
557
+ if (alignments.spaceOnLeft > alignments.spaceOnRight) {
558
+ horizontalAlignment = "right";
559
+ idealWidth += alignments.spaceOnLeft;
560
+ idealXPos -= alignments.spaceOnLeft;
561
+ } else {
562
+ horizontalAlignment = "left";
563
+ idealWidth += alignments.spaceOnRight;
564
+ }
565
+ }
566
+ }
567
+ if (verticalAlignment === "bottom") {
568
+ idealYPos = idealYPos - menuBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
569
+ }
570
+ if (horizontalAlignment === "right") {
571
+ idealXPos = idealXPos - menuBRect.width + triggerBRect.width;
572
+ }
573
+ return {
574
+ x: idealXPos,
575
+ y: idealYPos,
576
+ verticalAlignment,
577
+ horizontalAlignment,
578
+ height: idealHeight,
579
+ width: idealWidth
580
+ };
581
+ }
582
+ _schedule(callback, delay) {
583
+ const timer = setTimeout(() => {
584
+ this._pendingTimers.delete(timer);
585
+ callback();
586
+ }, delay);
587
+ this._pendingTimers.add(timer);
588
+ }
589
+ _clearPendingTimers() {
590
+ for (const timer of this._pendingTimers) clearTimeout(timer);
591
+ this._pendingTimers.clear();
592
+ return ++this._transition;
593
+ }
594
+ _animateIn() {
595
+ const transition = this._transition;
596
+ const duration = this.options.inDuration;
597
+ this.menuEl.style.transition = "none";
598
+ this.menuEl.style.opacity = "0";
599
+ this.menuEl.style.transform = "scale(0.85)";
600
+ this._schedule(() => {
601
+ this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
602
+ this.menuEl.style.opacity = "1";
603
+ this.menuEl.style.transform = "scale(1)";
604
+ }, 1);
605
+ this._schedule(() => {
606
+ this._focusInitialItem();
607
+ if (transition !== this._transition) return;
608
+ if (typeof this.options.onOpenEnd === "function") this.options.onOpenEnd.call(this, this.el);
609
+ }, duration);
610
+ }
611
+ _animateOut() {
612
+ const duration = this.options.outDuration;
613
+ this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
614
+ this.menuEl.style.opacity = "0";
615
+ this.menuEl.style.transform = "scale(0.85)";
616
+ this._schedule(() => {
617
+ this._resetMenuStyles();
618
+ if (typeof this.options.onCloseEnd === "function")
619
+ this.options.onCloseEnd.call(this, this.el);
620
+ }, duration);
621
+ }
622
+ _getClosestAncestor(el, condition) {
623
+ let ancestor = el.parentNode;
624
+ while (ancestor !== null && ancestor !== void 0 && ancestor !== document) {
625
+ if (ancestor.nodeType === Node.ELEMENT_NODE && condition(ancestor)) {
626
+ return ancestor;
627
+ }
628
+ ancestor = ancestor.parentNode ?? ancestor.host;
629
+ }
630
+ return null;
631
+ }
632
+ _placeMenu() {
633
+ let closestOverflowParent = this._getClosestAncestor(
634
+ this.menuEl,
635
+ (ancestor) => {
636
+ return !["HTML", "BODY"].includes(ancestor.tagName) && getComputedStyle(ancestor).overflow !== "visible";
637
+ }
638
+ );
639
+ if (!closestOverflowParent) {
640
+ const parent = !!this.menuEl.offsetParent ? this.menuEl.offsetParent : this.menuEl.parentNode;
641
+ closestOverflowParent = parent.host ?? parent;
642
+ }
643
+ if (getComputedStyle(closestOverflowParent).position === "static")
644
+ closestOverflowParent.style.position = "relative";
645
+ const natural = this.menuEl.getBoundingClientRect().width;
646
+ const triggerWidth = this.el.getBoundingClientRect().width;
647
+ const idealWidth = this.options.constrainWidth && triggerWidth >= MIN_SURFACE_WIDTH ? triggerWidth : Math.min(MAX_SURFACE_WIDTH, Math.max(MIN_SURFACE_WIDTH, natural));
648
+ this.menuEl.style.width = idealWidth + "px";
649
+ const positionInfo = this._getMenuPosition(closestOverflowParent);
650
+ this.menuEl.style.left = positionInfo.x + "px";
651
+ this.menuEl.style.top = positionInfo.y + "px";
652
+ this.menuEl.style.height = positionInfo.height + "px";
653
+ this.menuEl.style.width = positionInfo.width + "px";
654
+ this.menuEl.style.transformOrigin = `${positionInfo.horizontalAlignment === "left" ? "0" : "100%"} ${positionInfo.verticalAlignment === "top" ? "0" : "100%"}`;
655
+ }
656
+ };
657
+ _Menu._menus = [];
658
+ var Menu = _Menu;
659
+
660
+ export {
661
+ Menu
662
+ };
663
+ //# sourceMappingURL=chunk-TK6PX2GC.mjs.map