1+ /* eslint-disable no-restricted-properties */
2+
13/* eslint-disable no-restricted-globals */
24export const canUseDOM = ! ! (
35 typeof window !== 'undefined' &&
@@ -20,18 +22,54 @@ export function composeEventHandlers<E extends { defaultPrevented: boolean }>(
2022 } ;
2123}
2224
23- export function getOwnerWindow ( element : Element | null | undefined ) {
25+ export function getOwnerWindow ( element : Node | null | undefined ) {
2426 if ( ! canUseDOM ) {
2527 throw new Error ( 'Cannot access window outside of the DOM' ) ;
2628 }
2729 // eslint-disable-next-line no-restricted-globals
2830 return element ?. ownerDocument ?. defaultView ?? window ;
2931}
3032
31- export function getOwnerDocument ( element : Element | null | undefined ) {
33+ export function getOwnerDocument ( element : Node | null | undefined ) {
3234 if ( ! canUseDOM ) {
3335 throw new Error ( 'Cannot access document outside of the DOM' ) ;
3436 }
3537 // eslint-disable-next-line no-restricted-globals
3638 return element ?. ownerDocument ?? document ;
3739}
40+
41+ /**
42+ * Lifted from https://github.com/ariakit/ariakit/blob/main/packages/ariakit-core/src/utils/dom.ts#L37
43+ * MIT License, Copyright (c) AriaKit.
44+ */
45+ export function getActiveElement (
46+ node : Node | null | undefined ,
47+ activeDescendant = false
48+ ) : HTMLElement | null {
49+ const { activeElement } = getOwnerDocument ( node ) ;
50+ if ( ! activeElement ?. nodeName ) {
51+ // `activeElement` might be an empty object if we're interacting with elements
52+ // inside of an iframe.
53+ return null ;
54+ }
55+
56+ if ( isFrame ( activeElement ) && activeElement . contentDocument ) {
57+ return getActiveElement ( activeElement . contentDocument . body , activeDescendant ) ;
58+ }
59+
60+ if ( activeDescendant ) {
61+ const id = activeElement . getAttribute ( 'aria-activedescendant' ) ;
62+ if ( id ) {
63+ const element = getOwnerDocument ( activeElement ) . getElementById ( id ) ;
64+ if ( element ) {
65+ return element ;
66+ }
67+ }
68+ }
69+
70+ return activeElement as HTMLElement | null ;
71+ }
72+
73+ export function isFrame ( element : Element ) : element is HTMLIFrameElement {
74+ return element . tagName === 'IFRAME' ;
75+ }
0 commit comments