Skip to content

Commit

Permalink
refactor: improve support for shadow root
Browse files Browse the repository at this point in the history
  • Loading branch information
segunadebayo committed Sep 24, 2024
1 parent cdeaed6 commit d463198
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 17 deletions.
5 changes: 2 additions & 3 deletions packages/utilities/dom-query/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ export function getWindow(el: Node | ShadowRoot | Document | null | undefined) {
return window
}

export function getActiveElement(el: HTMLElement): HTMLElement | null {
const doc = getDocument(el)
let activeElement = doc.activeElement as HTMLElement | null
export function getActiveElement(rootNode: Document | ShadowRoot): HTMLElement | null {
let activeElement = rootNode.activeElement as HTMLElement | null

while (activeElement?.shadowRoot) {
const el = activeElement.shadowRoot.activeElement as HTMLElement | null
Expand Down
4 changes: 2 additions & 2 deletions packages/utilities/dom-query/src/scope.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getDocument } from "./env"
import { getActiveElement, getDocument } from "./env"

export interface ScopeContext {
getRootNode?(): Document | ShadowRoot | Node
Expand All @@ -9,7 +9,7 @@ export function createScope<T>(methods: T) {
getRootNode: (ctx: ScopeContext) => (ctx.getRootNode?.() ?? document) as Document | ShadowRoot,
getDoc: (ctx: ScopeContext) => getDocument(dom.getRootNode(ctx)),
getWin: (ctx: ScopeContext) => dom.getDoc(ctx).defaultView ?? window,
getActiveElement: (ctx: ScopeContext) => dom.getRootNode(ctx).activeElement,
getActiveElement: (ctx: ScopeContext) => getActiveElement(dom.getRootNode(ctx)),
isActiveElement: (ctx: ScopeContext, elem: HTMLElement | null) => elem === dom.getActiveElement(ctx),
getById: <T extends Element = HTMLElement>(ctx: ScopeContext, id: string) =>
dom.getRootNode(ctx).getElementById(id) as T | null,
Expand Down
22 changes: 10 additions & 12 deletions packages/utilities/focus-visible/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Credit: Huge props to the team at Adobe for inspiring this implementation.
* https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/interactions/src/useFocusVisible.ts
*/
import { getDocument, getWindow, isMac } from "@zag-js/dom-query"
import { getDocument, getEventTarget, getWindow, isMac } from "@zag-js/dom-query"

function isVirtualClick(event: MouseEvent | PointerEvent): boolean {
if ((event as any).mozInputSource === 0 && event.isTrusted) return true
Expand All @@ -23,23 +23,19 @@ function isValidKey(e: KeyboardEvent) {
const nonTextInputTypes = new Set(["checkbox", "radio", "range", "color", "file", "image", "button", "submit", "reset"])

function isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent) {
const IHTMLInputElement =
typeof window !== "undefined" ? getWindow(e?.target as Element).HTMLInputElement : HTMLInputElement
const IHTMLTextAreaElement =
typeof window !== "undefined" ? getWindow(e?.target as Element).HTMLTextAreaElement : HTMLTextAreaElement
const IHTMLElement = typeof window !== "undefined" ? getWindow(e?.target as Element).HTMLElement : HTMLElement
const IKeyboardEvent = typeof window !== "undefined" ? getWindow(e?.target as Element).KeyboardEvent : KeyboardEvent
const target = e ? getEventTarget<Element>(e) : null
const win = getWindow(target)

isTextInput =
isTextInput ||
(e?.target instanceof IHTMLInputElement && !nonTextInputTypes.has(e?.target?.type)) ||
e?.target instanceof IHTMLTextAreaElement ||
(e?.target instanceof IHTMLElement && e?.target.isContentEditable)
(target instanceof win.HTMLInputElement && !nonTextInputTypes.has(target?.type)) ||
target instanceof win.HTMLTextAreaElement ||
(target instanceof win.HTMLElement && target.isContentEditable)

return !(
isTextInput &&
modality === "keyboard" &&
e instanceof IKeyboardEvent &&
e instanceof win.KeyboardEvent &&
!Reflect.has(FOCUS_VISIBLE_INPUT_KEYS, e.key)
)
}
Expand Down Expand Up @@ -108,7 +104,9 @@ function handleFocusEvent(e: FocusEvent) {
// Firefox fires two extra focus events when the user first clicks into an iframe:
// first on the window, then on the document. We ignore these events so they don't
// cause keyboard focus rings to appear.
if (e.target === getWindow(e.target as Element) || e.target === getDocument(e.target as Element)) {
const target = getEventTarget(e)

if (target === getWindow(target as Element) || target === getDocument(target as Element)) {
return
}

Expand Down

0 comments on commit d463198

Please sign in to comment.