@@ -157,230 +157,208 @@ export default class BasicDropdownContent<
157157 },
158158 );
159159
160- respondToEvents = modifier (
161- (dropdownElement : Element ): (() => void ) => {
162- if (this .args .dropdown ?.actions ?.registerDropdownElement ) {
163- this .args .dropdown .actions .registerDropdownElement (
164- dropdownElement as HTMLElement ,
165- );
166- }
160+ respondToEvents = modifier ((dropdownElement : Element ): (() => void ) => {
161+ if (this .args .dropdown ?.actions ?.registerDropdownElement ) {
162+ this .args .dropdown .actions .registerDropdownElement (
163+ dropdownElement as HTMLElement ,
164+ );
165+ }
167166
168- const selector = ` [data-ebd-id=${this .args .dropdown ?.uniqueId }-trigger] ` ;
169- let triggerElement: HTMLElement | null = null ;
167+ const selector = ` [data-ebd-id=${this .args .dropdown ?.uniqueId }-trigger] ` ;
168+ let triggerElement: HTMLElement | null = null ;
169+ if (typeof this .args .dropdown ?.actions ?.getTriggerElement === ' function' ) {
170+ triggerElement = this .args .dropdown ?.actions ?.getTriggerElement ();
171+ }
172+ if (! triggerElement ) {
173+ triggerElement = document .querySelector (selector ) as HTMLElement ;
174+ }
175+ this .handleRootMouseDown = (e : MouseEvent | TouchEvent ): void => {
176+ const target = (e .composedPath ?.()[0 ] || e .target ) as Element ;
177+ if (target === null ) return ;
170178 if (
171- typeof this .args .dropdown ?.actions ?.getTriggerElement === ' function'
179+ hasMoved (e as TouchEvent , this .touchMoveEvent ) ||
180+ dropdownElement .contains (target ) ||
181+ (triggerElement && triggerElement .contains (target ))
172182 ) {
173- triggerElement = this .args .dropdown ?.actions ?.getTriggerElement ();
183+ this .touchMoveEvent = undefined ;
184+ return ;
174185 }
175- if (! triggerElement ) {
176- triggerElement = document .querySelector (selector ) as HTMLElement ;
186+
187+ if (dropdownIsValidParent (triggerElement , target , this .dropdownId )) {
188+ this .touchMoveEvent = undefined ;
189+ return ;
177190 }
178- this .handleRootMouseDown = (e : MouseEvent | TouchEvent ): void => {
179- const target = (e .composedPath ?.()[0 ] || e .target ) as Element ;
180- if (target === null ) return ;
181- if (
182- hasMoved (e as TouchEvent , this .touchMoveEvent ) ||
183- dropdownElement .contains (target ) ||
184- (triggerElement && triggerElement .contains (target ))
185- ) {
186- this .touchMoveEvent = undefined ;
187- return ;
188- }
189191
190- if (dropdownIsValidParent (triggerElement , target , this .dropdownId )) {
191- this .touchMoveEvent = undefined ;
192- return ;
193- }
192+ if (this .args .dropdown ?.actions ?.close ) {
193+ this .args .dropdown .actions .close (e , true );
194+ }
195+ };
196+ document .addEventListener (
197+ this .args .rootEventType || ' click' ,
198+ this .handleRootMouseDown ,
199+ true ,
200+ );
194201
195- if (this .args .dropdown ?.actions ?.close ) {
196- this .args .dropdown .actions .close (e , true );
197- }
198- };
199- document .addEventListener (
202+ // We need to register closing event on shadow dom element, otherwise all clicks inside a shadow dom are not closing the dropdown
203+ // In additional store the rootElement for outside clicks (ensure that we do removeEventListener on correct element)
204+ if (
205+ this ._contentWormhole &&
206+ this ._contentWormhole .getRootNode () instanceof ShadowRoot
207+ ) {
208+ this .rootElement = this ._contentWormhole .getRootNode () as HTMLElement ;
209+ } else {
210+ this .rootElement = undefined ;
211+ }
212+
213+ if (this .rootElement ) {
214+ this .rootElement .addEventListener (
200215 this .args .rootEventType || ' click' ,
201216 this .handleRootMouseDown ,
202217 true ,
203218 );
219+ }
204220
205- // We need to register closing event on shadow dom element, otherwise all clicks inside a shadow dom are not closing the dropdown
206- // In additional store the rootElement for outside clicks (ensure that we do removeEventListener on correct element)
207- if (
208- this ._contentWormhole &&
209- this . _contentWormhole . getRootNode () instanceof ShadowRoot
210- ) {
211- this .rootElement = this . _contentWormhole . getRootNode () as HTMLElement ;
212- } else {
213- this . rootElement = undefined ;
214- }
221+ window . addEventListener ( ' resize ' , this . repositionBound );
222+ window . addEventListener ( ' orientationchange ' , this . repositionBound );
223+
224+ if ( this .isTouchDevice ) {
225+ document . addEventListener (
226+ ' touchstart ' ,
227+ this .touchStartHandlerBound ,
228+ true ,
229+ ) ;
230+ document . addEventListener ( ' touchend ' , this . handleRootMouseDown , true );
215231
216232 if (this .rootElement ) {
217233 this .rootElement .addEventListener (
218- this .args .rootEventType || ' click' ,
234+ ' touchstart' ,
235+ this .touchStartHandlerBound ,
236+ true ,
237+ );
238+ this .rootElement .addEventListener (
239+ ' touchend' ,
219240 this .handleRootMouseDown ,
220241 true ,
221242 );
222243 }
244+ }
245+ if (
246+ triggerElement !== null &&
247+ ! (triggerElement .getRootNode () instanceof ShadowRoot )
248+ ) {
249+ this .scrollableAncestors = getScrollableAncestors (triggerElement );
250+ }
251+ this .addScrollHandling (dropdownElement );
252+ return () => {
253+ this .removeGlobalEvents ();
254+ this .removeScrollHandling ();
255+ this .scrollableAncestors = [];
223256
224- window .addEventListener (' resize' , this .repositionBound );
225- window .addEventListener (' orientationchange' , this .repositionBound );
257+ document .removeEventListener (
258+ this .args .rootEventType || ' click' ,
259+ this .handleRootMouseDown as RootMouseDownHandler ,
260+ true ,
261+ );
262+
263+ if (this .rootElement ) {
264+ this .rootElement .removeEventListener (
265+ this .args .rootEventType || ' click' ,
266+ this .handleRootMouseDown as RootMouseDownHandler ,
267+ true ,
268+ );
269+ }
226270
227271 if (this .isTouchDevice ) {
228- document .addEventListener (
272+ document .removeEventListener (
229273 ' touchstart' ,
230274 this .touchStartHandlerBound ,
231275 true ,
232276 );
233- document .addEventListener (' touchend' , this .handleRootMouseDown , true );
234-
235- if (this .rootElement ) {
236- this .rootElement .addEventListener (
237- ' touchstart' ,
238- this .touchStartHandlerBound ,
239- true ,
240- );
241- this .rootElement .addEventListener (
242- ' touchend' ,
243- this .handleRootMouseDown ,
244- true ,
245- );
246- }
247- }
248- if (
249- triggerElement !== null &&
250- ! (triggerElement .getRootNode () instanceof ShadowRoot )
251- ) {
252- this .scrollableAncestors = getScrollableAncestors (triggerElement );
253- }
254- this .addScrollHandling (dropdownElement );
255- return () => {
256- this .removeGlobalEvents ();
257- this .removeScrollHandling ();
258- this .scrollableAncestors = [];
259-
260277 document .removeEventListener (
261- this . args . rootEventType || ' click ' ,
278+ ' touchend ' ,
262279 this .handleRootMouseDown as RootMouseDownHandler ,
263280 true ,
264281 );
265282
266283 if (this .rootElement ) {
267284 this .rootElement .removeEventListener (
268- this .args .rootEventType || ' click' ,
269- this .handleRootMouseDown as RootMouseDownHandler ,
270- true ,
271- );
272- }
273-
274- if (this .isTouchDevice ) {
275- document .removeEventListener (
276285 ' touchstart' ,
277286 this .touchStartHandlerBound ,
278287 true ,
279288 );
280- document .removeEventListener (
289+ this . rootElement .removeEventListener (
281290 ' touchend' ,
282291 this .handleRootMouseDown as RootMouseDownHandler ,
283292 true ,
284293 );
285-
286- if (this .rootElement ) {
287- this .rootElement .removeEventListener (
288- ' touchstart' ,
289- this .touchStartHandlerBound ,
290- true ,
291- );
292- this .rootElement .removeEventListener (
293- ' touchend' ,
294- this .handleRootMouseDown as RootMouseDownHandler ,
295- true ,
296- );
297- }
298294 }
299- };
300- },
301- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
302- // @ts-ignore
303- { eager: false },
304- );
295+ }
296+ };
297+ });
305298
306- initiallyReposition = modifier (
307- () => {
308- // Escape autotracking frame and avoid backtracking re-render
309- void Promise .resolve ().then (() => {
310- this .args .dropdown ?.actions .reposition ();
311- });
312- },
313- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
314- // @ts-ignore
315- { eager: false },
316- );
299+ initiallyReposition = modifier (() => {
300+ // Escape autotracking frame and avoid backtracking re-render
301+ void Promise .resolve ().then (() => {
302+ this .args .dropdown ?.actions .reposition ();
303+ });
304+ });
317305
318- animateInAndOut = modifier (
319- (dropdownElement : Element ): (() => void ) => {
320- if (! this .animationEnabled ) return () => {};
321- waitForAnimations (dropdownElement , () => {
322- this .animationClass = this .transitionedInClass ;
306+ animateInAndOut = modifier ((dropdownElement : Element ): (() => void ) => {
307+ if (! this .animationEnabled ) return () => {};
308+ waitForAnimations (dropdownElement , () => {
309+ this .animationClass = this .transitionedInClass ;
310+ });
311+ return () => {
312+ if (! this .animationEnabled ) return ;
313+ let parentElement =
314+ dropdownElement .parentElement ?? this .destinationElement ;
315+ if (parentElement === null ) return ;
316+ if (this .args .renderInPlace ) {
317+ parentElement = parentElement .parentElement ;
318+ }
319+ if (parentElement === null ) return ;
320+ const clone = dropdownElement .cloneNode (true ) as Element ;
321+ clone .id = ` ${clone .id }--clone ` ;
322+ clone .classList .remove (... this .transitioningInClass .split (' ' ));
323+ clone .classList .add (... this .transitioningOutClass .split (' ' ));
324+ parentElement .appendChild (clone );
325+ this .animationClass = this .transitioningInClass ;
326+ waitForAnimations (clone , function () {
327+ (parentElement as HTMLElement ).removeChild (clone );
323328 });
324- return () => {
325- if (! this .animationEnabled ) return ;
326- let parentElement =
327- dropdownElement .parentElement ?? this .destinationElement ;
328- if (parentElement === null ) return ;
329- if (this .args .renderInPlace ) {
330- parentElement = parentElement .parentElement ;
331- }
332- if (parentElement === null ) return ;
333- const clone = dropdownElement .cloneNode (true ) as Element ;
334- clone .id = ` ${clone .id }--clone ` ;
335- clone .classList .remove (... this .transitioningInClass .split (' ' ));
336- clone .classList .add (... this .transitioningOutClass .split (' ' ));
337- parentElement .appendChild (clone );
338- this .animationClass = this .transitioningInClass ;
339- waitForAnimations (clone , function () {
340- (parentElement as HTMLElement ).removeChild (clone );
341- });
342- };
343- },
344- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
345- // @ts-ignore
346- { eager: false },
347- );
329+ };
330+ });
348331
349- observeMutations = modifier (
350- (dropdownElement : Element ): (() => void ) => {
351- this .mutationObserver = new MutationObserver ((mutations ) => {
352- let shouldReposition = mutations .some (
353- (record : MutationRecord ) =>
354- containsRelevantMutation (record .addedNodes ) ||
355- containsRelevantMutation (record .removedNodes ),
356- );
332+ observeMutations = modifier ((dropdownElement : Element ): (() => void ) => {
333+ this .mutationObserver = new MutationObserver ((mutations ) => {
334+ let shouldReposition = mutations .some (
335+ (record : MutationRecord ) =>
336+ containsRelevantMutation (record .addedNodes ) ||
337+ containsRelevantMutation (record .removedNodes ),
338+ );
357339
358- if (shouldReposition && this .args .shouldReposition ) {
359- shouldReposition = this .args .shouldReposition (
360- mutations ,
361- this .args .dropdown ,
362- );
363- }
340+ if (shouldReposition && this .args .shouldReposition ) {
341+ shouldReposition = this .args .shouldReposition (
342+ mutations ,
343+ this .args .dropdown ,
344+ );
345+ }
364346
365- if (shouldReposition ) {
366- this .reposition ();
367- }
368- });
369- this .mutationObserver .observe (dropdownElement , {
370- childList: true ,
371- subtree: true ,
372- });
373- return () => {
374- if (this .mutationObserver !== undefined ) {
375- this .mutationObserver .disconnect ();
376- this .mutationObserver = undefined ;
377- }
378- };
379- },
380- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
381- // @ts-ignore
382- { eager: false },
383- );
347+ if (shouldReposition ) {
348+ this .reposition ();
349+ }
350+ });
351+ this .mutationObserver .observe (dropdownElement , {
352+ childList: true ,
353+ subtree: true ,
354+ });
355+ return () => {
356+ if (this .mutationObserver !== undefined ) {
357+ this .mutationObserver .disconnect ();
358+ this .mutationObserver = undefined ;
359+ }
360+ };
361+ });
384362
385363 @action
386364 touchStartHandler(): void {
0 commit comments