@@ -17,14 +17,6 @@ import {FocusableTreeTraverser} from './utils/focusable_tree_traverser.js';
1717 */
1818export type ReturnEphemeralFocus = ( ) => void ;
1919
20- /**
21- * Type declaration for an optional callback to observe when an element with
22- * ephemeral focus has its DOM focus changed before ephemeral focus is returned.
23- *
24- * See FocusManager.takeEphemeralFocus for more details.
25- */
26- export type EphemeralFocusChangedInDom = ( hasDomFocus : boolean ) => void ;
27-
2820/**
2921 * Represents an IFocusableTree that has been registered for focus management in
3022 * FocusManager.
@@ -86,10 +78,7 @@ export class FocusManager {
8678 private previouslyFocusedNode : IFocusableNode | null = null ;
8779 private registeredTrees : Array < TreeRegistration > = [ ] ;
8880
89- private ephemerallyFocusedElement : HTMLElement | SVGElement | null = null ;
90- private ephemeralDomFocusChangedCallback : EphemeralFocusChangedInDom | null =
91- null ;
92- private ephemerallyFocusedElementCurrentlyHasFocus : boolean = false ;
81+ private currentlyHoldsEphemeralFocus : boolean = false ;
9382 private lockFocusStateChanges : boolean = false ;
9483 private recentlyLostAllFocus : boolean = false ;
9584 private isUpdatingFocusedNode : boolean = false ;
@@ -129,21 +118,6 @@ export class FocusManager {
129118 } else {
130119 this . defocusCurrentFocusedNode ( ) ;
131120 }
132-
133- const ephemeralFocusElem = this . ephemerallyFocusedElement ;
134- if ( ephemeralFocusElem ) {
135- const hadFocus = this . ephemerallyFocusedElementCurrentlyHasFocus ;
136- const hasFocus =
137- ! ! element &&
138- element instanceof Node &&
139- ephemeralFocusElem . contains ( element ) ;
140- if ( hadFocus !== hasFocus ) {
141- this . ephemerallyFocusedElementCurrentlyHasFocus = hasFocus ;
142- if ( this . ephemeralDomFocusChangedCallback ) {
143- this . ephemeralDomFocusChangedCallback ( hasFocus ) ;
144- }
145- }
146- }
147121 } ;
148122
149123 // Register root document focus listeners for tracking when focus leaves all
@@ -339,7 +313,7 @@ export class FocusManager {
339313 */
340314 focusNode ( focusableNode : IFocusableNode ) : void {
341315 this . ensureManagerIsUnlocked ( ) ;
342- const mustRestoreUpdatingNode = ! this . ephemerallyFocusedElement ;
316+ const mustRestoreUpdatingNode = ! this . currentlyHoldsEphemeralFocus ;
343317 if ( mustRestoreUpdatingNode ) {
344318 // Disable state syncing from DOM events since possible calls to focus()
345319 // below will loop a call back to focusNode().
@@ -421,7 +395,7 @@ export class FocusManager {
421395 this . removeHighlight ( nextTreeRoot ) ;
422396 }
423397
424- if ( ! this . ephemerallyFocusedElement ) {
398+ if ( ! this . currentlyHoldsEphemeralFocus ) {
425399 // Only change the actively focused node if ephemeral state isn't held.
426400 this . activelyFocusNode ( nodeToFocus , prevTree ?? null ) ;
427401 }
@@ -449,50 +423,24 @@ export class FocusManager {
449423 * the returned lambda is called. Additionally, only 1 ephemeral focus context
450424 * can be active at any given time (attempting to activate more than one
451425 * simultaneously will result in an error being thrown).
452- *
453- * Important details regarding the onFocusChangedInDom callback:
454- * - This method will be called initially with a value of 'true' indicating
455- * that the ephemeral element has been focused, so callers can rely on that,
456- * if needed, for initialization logic.
457- * - It's safe to end ephemeral focus in this callback (and is encouraged for
458- * callers that wish to automatically end ephemeral focus when the user
459- * directs focus outside of the element).
460- * - The element AND all of its descendants are tracked for focus. That means
461- * the callback will ONLY be called with a value of 'false' if focus
462- * completely leaves the DOM tree for the provided focusable element.
463- * - It's invalid to return focus on the very first call to the callback,
464- * however this is expected to be impossible, anyway, since this method
465- * won't return until after the first call to the callback (thus there will
466- * be no means to return ephemeral focus).
467- *
468- * @param focusableElement The element that should be focused until returned.
469- * @param onFocusChangedInDom An optional callback which will be notified
470- * whenever the provided element's focus changes before ephemeral focus is
471- * returned. See the details above for specifics.
472- * @returns A ReturnEphemeralFocus that must be called when ephemeral focus
473- * should end.
474426 */
475427 takeEphemeralFocus (
476428 focusableElement : HTMLElement | SVGElement ,
477- onFocusChangedInDom : EphemeralFocusChangedInDom | null = null ,
478429 ) : ReturnEphemeralFocus {
479430 this . ensureManagerIsUnlocked ( ) ;
480- if ( this . ephemerallyFocusedElement ) {
431+ if ( this . currentlyHoldsEphemeralFocus ) {
481432 throw Error (
482433 `Attempted to take ephemeral focus when it's already held, ` +
483434 `with new element: ${ focusableElement } .` ,
484435 ) ;
485436 }
486- this . ephemerallyFocusedElement = focusableElement ;
487- this . ephemeralDomFocusChangedCallback = onFocusChangedInDom ;
437+ this . currentlyHoldsEphemeralFocus = true ;
488438
489439 if ( this . focusedNode ) {
490440 this . passivelyFocusNode ( this . focusedNode , null ) ;
491441 }
492442 focusableElement . focus ( ) ;
493- this . ephemerallyFocusedElementCurrentlyHasFocus = true ;
494443
495- const focusedNodeAtStart = this . focusedNode ;
496444 let hasFinishedEphemeralFocus = false ;
497445 return ( ) => {
498446 if ( hasFinishedEphemeralFocus ) {
@@ -502,22 +450,9 @@ export class FocusManager {
502450 ) ;
503451 }
504452 hasFinishedEphemeralFocus = true ;
505- this . ephemerallyFocusedElement = null ;
506- this . ephemeralDomFocusChangedCallback = null ;
507-
508- const hadEphemeralFocusAtEnd =
509- this . ephemerallyFocusedElementCurrentlyHasFocus ;
510- this . ephemerallyFocusedElementCurrentlyHasFocus = false ;
511-
512- // If the user forced away DOM focus during ephemeral focus, then
513- // determine whether focus should be restored back to a focusable node
514- // after ephemeral focus ends. Generally it shouldn't be, but in some
515- // cases (such as the user focusing an actual focusable node) it then
516- // should be.
517- const hasNewFocusedNode = focusedNodeAtStart !== this . focusedNode ;
518- const shouldRestoreToNode = hasNewFocusedNode || hadEphemeralFocusAtEnd ;
519-
520- if ( this . focusedNode && shouldRestoreToNode ) {
453+ this . currentlyHoldsEphemeralFocus = false ;
454+
455+ if ( this . focusedNode ) {
521456 this . activelyFocusNode ( this . focusedNode , null ) ;
522457
523458 // Even though focus was restored, check if it's lost again. It's
@@ -535,11 +470,6 @@ export class FocusManager {
535470 this . focusNode ( capturedNode ) ;
536471 }
537472 } , 0 ) ;
538- } else {
539- // If the ephemeral element lost focus then do not force it back since
540- // that likely will override the user's own attempt to move focus away
541- // from the ephemeral experience.
542- this . defocusCurrentFocusedNode ( ) ;
543473 }
544474 } ;
545475 }
@@ -548,7 +478,7 @@ export class FocusManager {
548478 * @returns whether something is currently holding ephemeral focus
549479 */
550480 ephemeralFocusTaken ( ) : boolean {
551- return ! ! this . ephemerallyFocusedElement ;
481+ return this . currentlyHoldsEphemeralFocus ;
552482 }
553483
554484 /**
@@ -586,7 +516,7 @@ export class FocusManager {
586516 // The current node will likely be defocused while ephemeral focus is held,
587517 // but internal manager state shouldn't change since the node should be
588518 // restored upon exiting ephemeral focus mode.
589- if ( this . focusedNode && ! this . ephemerallyFocusedElement ) {
519+ if ( this . focusedNode && ! this . currentlyHoldsEphemeralFocus ) {
590520 this . passivelyFocusNode ( this . focusedNode , null ) ;
591521 this . updateFocusedNode ( null ) ;
592522 }
0 commit comments