@@ -23,18 +23,8 @@ interface CloseWatcherOptions {
2323}
2424
2525type TriggerType = 'hover' | 'focus' | 'click' | 'manual' ;
26-
27- type LastOf < T > = UnionToIntersection < T extends any ? ( ) => T : never > extends ( ) => infer R ? R : never ;
28- type Push < T extends any [ ] , V > = [ ...T , V ] ;
29- type UnionToIntersection < U > = ( U extends any ? ( k : U ) => void : never ) extends ( k : infer I ) => void ? I : never ;
30-
31- type TriggerCombinationHelper < T extends TriggerType , U extends TriggerType [ ] = [ ] > = {
32- [ K in T ] : K extends LastOf < U >
33- ? TriggerCombinationHelper < Exclude < T , K > , Push < U , K > >
34- : `${U extends [ ] ? '' : `${U [ number ] } `} ${K } ` | TriggerCombinationHelper < Exclude < T , K > , Push < U , K > > ;
35- } [ T ] ;
36-
37- type Triggers = TriggerCombinationHelper < TriggerType > ;
26+ type Combine < T extends string , U extends string = T > = T extends any ? T | `${T } ${Combine < Exclude < U , T > > } ` : never ;
27+ type Triggers = Combine < TriggerType > ;
3828
3929declare global {
4030 interface HTMLElementTagNameMap {
@@ -247,24 +237,23 @@ export class GlPopover extends GlElement {
247237
248238 private handleTriggerBlur = ( e : FocusEvent ) => {
249239 if ( this . open && this . hasTrigger ( 'focus' ) ) {
250- const composedPath = e . composedPath ( ) ;
251- if ( composedPath . includes ( this ) ) return ;
240+ if ( e . relatedTarget && this . contains ( e . relatedTarget as Node ) ) return ;
252241
253242 void this . hide ( ) ;
254243 }
255244 } ;
256245
257246 private handleTriggerClick = ( ) => {
258247 if ( this . hasTrigger ( 'click' ) ) {
259- if ( this . open ) {
248+ if ( this . open && this . _triggeredBy !== 'hover' ) {
260249 if ( this . _skipHideOnClick ) {
261250 this . _skipHideOnClick = false ;
262251 return ;
263252 }
264253
265254 void this . hide ( ) ;
266255 } else {
267- void this . show ( ) ;
256+ void this . show ( 'click' ) ;
268257 }
269258 }
270259 } ;
@@ -280,7 +269,11 @@ export class GlPopover extends GlElement {
280269
281270 private handleTriggerFocus = ( ) => {
282271 if ( this . hasTrigger ( 'focus' ) ) {
283- void this . show ( ) ;
272+ if ( this . open && this . _triggeredBy !== 'hover' && ! this . hasPopupFocus ( ) ) {
273+ void this . hide ( ) ;
274+ } else {
275+ void this . show ( 'focus' ) ;
276+ }
284277 }
285278 } ;
286279
@@ -303,12 +296,19 @@ export class GlPopover extends GlElement {
303296 void this . hide ( ) ;
304297 } ;
305298
299+ private handleWebviewMouseDown = ( e : MouseEvent ) => {
300+ const composedPath = e . composedPath ( ) ;
301+ if ( ! composedPath . includes ( this ) ) {
302+ void this . hide ( ) ;
303+ }
304+ } ;
305+
306306 private handleMouseOver = ( ) => {
307307 if ( this . hasTrigger ( 'hover' ) ) {
308308 clearTimeout ( this . hoverTimeout ) ;
309309
310310 const delay = parseDuration ( getComputedStyle ( this ) . getPropertyValue ( '--show-delay' ) ) ;
311- this . hoverTimeout = setTimeout ( ( ) => this . show ( ) , delay ) ;
311+ this . hoverTimeout = setTimeout ( ( ) => this . show ( 'hover' ) , delay ) ;
312312 }
313313 } ;
314314
@@ -319,7 +319,7 @@ export class GlPopover extends GlElement {
319319 const composedPath = e . composedPath ( ) ;
320320 if ( composedPath [ composedPath . length - 2 ] === this ) return ;
321321
322- if ( this . hasPopupFocus ( ) ) return ;
322+ if ( this . hasPopupFocus ( ) || this . _triggeredBy !== 'hover' ) return ;
323323
324324 const delay = parseDuration ( getComputedStyle ( this ) . getPropertyValue ( '--hide-delay' ) ) ;
325325 this . hoverTimeout = setTimeout ( ( ) => this . hide ( ) , delay ) ;
@@ -353,6 +353,10 @@ export class GlPopover extends GlElement {
353353 document . addEventListener ( 'focusin' , this . handlePopupBlur ) ;
354354 window . addEventListener ( 'webview-blur' , this . handleWebviewBlur , false ) ;
355355
356+ if ( this . hasTrigger ( 'click' ) || this . hasTrigger ( 'focus' ) ) {
357+ document . addEventListener ( 'mousedown' , this . handleWebviewMouseDown ) ;
358+ }
359+
356360 this . body . hidden = false ;
357361 this . popup . active = true ;
358362 this . popup . reposition ( ) ;
@@ -361,6 +365,7 @@ export class GlPopover extends GlElement {
361365 } else {
362366 document . removeEventListener ( 'focusin' , this . handlePopupBlur ) ;
363367 window . removeEventListener ( 'webview-blur' , this . handleWebviewBlur , false ) ;
368+ document . removeEventListener ( 'mousedown' , this . handleWebviewMouseDown ) ;
364369
365370 // Hide
366371
@@ -390,8 +395,12 @@ export class GlPopover extends GlElement {
390395 }
391396 }
392397
398+ private _triggeredBy : TriggerType | undefined ;
393399 /** Shows the popover. */
394- async show ( ) {
400+ async show ( triggeredBy ?: TriggerType ) {
401+ if ( this . _triggeredBy == null || triggeredBy !== 'hover' ) {
402+ this . _triggeredBy = triggeredBy ;
403+ }
395404 if ( this . open ) return undefined ;
396405
397406 this . open = true ;
@@ -400,6 +409,7 @@ export class GlPopover extends GlElement {
400409
401410 /** Hides the popover */
402411 async hide ( ) {
412+ this . _triggeredBy = undefined ;
403413 if ( ! this . open ) return undefined ;
404414
405415 this . open = false ;
0 commit comments