diff --git a/src/aria/private/accordion/BUILD.bazel b/src/aria/private/accordion/BUILD.bazel index 50e04123df05..6fface1302fd 100644 --- a/src/aria/private/accordion/BUILD.bazel +++ b/src/aria/private/accordion/BUILD.bazel @@ -14,6 +14,7 @@ ts_project( "//src/aria/private/behaviors/list-navigation", "//src/aria/private/behaviors/list-selection", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/accordion/accordion.ts b/src/aria/private/accordion/accordion.ts index c3db0cecd4d1..9cd9fc8935e4 100644 --- a/src/aria/private/accordion/accordion.ts +++ b/src/aria/private/accordion/accordion.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {KeyboardEventManager, ClickEventManager} from '../behaviors/event-manager'; import {ExpansionItem, ListExpansion, ListExpansionInputs} from '../behaviors/expansion/expansion'; import {ListFocus, ListFocusInputs, ListFocusItem} from '../behaviors/list-focus/list-focus'; @@ -82,7 +83,7 @@ export class AccordionGroupPattern { /** The click event manager for the accordion trigger. */ readonly click = computed(() => { return new ClickEventManager().on((e: PointerEvent) => { - const item = this._findTriggerPattern(e.target as Element); + const item = this._findTriggerPattern(_getEventTarget(e)); if (!item) return; this.navigationBehavior.goto(item); @@ -102,7 +103,7 @@ export class AccordionGroupPattern { /** Handles focus events on the trigger. This ensures the tabbing changes the active index. */ onFocus(event: FocusEvent): void { - const item = this._findTriggerPattern(event.target as Element); + const item = this._findTriggerPattern(_getEventTarget(event)); if (!item) return; if (!this.focusBehavior.isFocusable(item)) return; diff --git a/src/aria/private/combobox/BUILD.bazel b/src/aria/private/combobox/BUILD.bazel index 4b8ec2562657..49e2edad35bd 100644 --- a/src/aria/private/combobox/BUILD.bazel +++ b/src/aria/private/combobox/BUILD.bazel @@ -14,6 +14,7 @@ ts_project( "//src/aria/private/behaviors/expansion", "//src/aria/private/behaviors/list", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/combobox/combobox.spec.ts b/src/aria/private/combobox/combobox.spec.ts index 844864f7b94a..be922258905b 100644 --- a/src/aria/private/combobox/combobox.spec.ts +++ b/src/aria/private/combobox/combobox.spec.ts @@ -154,6 +154,7 @@ describe('ComboboxPattern', () => { const deleteEvent = new InputEvent('input', {inputType: 'deleteContentBackward'}); Object.defineProperty(deleteEvent, 'target', {value: element}); + Object.defineProperty(deleteEvent, 'composedPath', {value: null}); pattern.onInput(deleteEvent as Event); expect(pattern.isDeleting()).toBe(true); diff --git a/src/aria/private/combobox/combobox.ts b/src/aria/private/combobox/combobox.ts index 444b44127455..f5ff59d1ca8b 100644 --- a/src/aria/private/combobox/combobox.ts +++ b/src/aria/private/combobox/combobox.ts @@ -6,8 +6,9 @@ * found in the LICENSE file at https://angular.dev/license */ -import {KeyboardEventManager, ClickEventManager, Modifier} from '../behaviors/event-manager'; import {computed, signal, untracked} from '@angular/core'; +import {_getEventTarget} from '@angular/cdk/platform'; +import {KeyboardEventManager, ClickEventManager, Modifier} from '../behaviors/event-manager'; import {SignalLike, WritableSignalLike} from '../behaviors/signal-like/signal-like'; import {ExpansionItem} from '../behaviors/expansion/expansion'; @@ -231,11 +232,11 @@ export class ComboboxPattern { /** Handles input events for the combobox. */ onInput(event: Event) { - if (!(event.target instanceof HTMLInputElement)) return; - if (this.disabled() || this.readonly()) return; + const target = _getEventTarget(event); + if (!(target instanceof HTMLInputElement) || this.disabled() || this.readonly()) return; this.inputs.expanded.set(true); - this.value.set(event.target.value); + this.value.set(target.value); this.isDeleting.set(event instanceof InputEvent && !!event.inputType.match(/^delete/)); } diff --git a/src/aria/private/grid/BUILD.bazel b/src/aria/private/grid/BUILD.bazel index 8e86c4872d33..662b52da7bed 100644 --- a/src/aria/private/grid/BUILD.bazel +++ b/src/aria/private/grid/BUILD.bazel @@ -18,6 +18,7 @@ ts_project( "//src/aria/private/behaviors/list-navigation", "//src/aria/private/behaviors/signal-like", "//src/aria/private/utils", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/grid/cell.ts b/src/aria/private/grid/cell.ts index de913f595da0..22b009366542 100644 --- a/src/aria/private/grid/cell.ts +++ b/src/aria/private/grid/cell.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import { computed, signal, @@ -125,7 +126,7 @@ export class GridCellPattern implements GridCell { onFocusIn(event: FocusEvent): void { this.isFocused.set(true); - const focusTarget = event.target as Element | null; + const focusTarget = _getEventTarget(event); const widget = this.inputs.getWidget(focusTarget); if (!widget) return; @@ -135,7 +136,7 @@ export class GridCellPattern implements GridCell { /** Handles focusout events for the cell. */ onFocusOut(event: FocusEvent): void { - const blurTarget = event.target as Element | null; + const blurTarget = _getEventTarget(event); const widget = this.inputs.getWidget(blurTarget); // Pass down focusout event to the widget. diff --git a/src/aria/private/grid/grid.ts b/src/aria/private/grid/grid.ts index 6c2b746c3c0e..18ceecac99d7 100644 --- a/src/aria/private/grid/grid.ts +++ b/src/aria/private/grid/grid.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {SignalLike, computed, signal, untracked} from '../behaviors/signal-like/signal-like'; import {KeyboardEventManager, ClickEventManager, Modifier} from '../behaviors/event-manager'; import {NavOptions, Grid, GridInputs as GridBehaviorInputs} from '../behaviors/grid'; @@ -146,7 +147,7 @@ export class GridPattern { // Navigation without selection. if (!this.inputs.enableSelection()) { manager.on(e => { - const cell = this.inputs.getCell(e.target as Element); + const cell = this.inputs.getCell(_getEventTarget(e)); if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return; this.gridBehavior.gotoCell(cell); @@ -156,7 +157,7 @@ export class GridPattern { // Navigation with selection. if (this.inputs.enableSelection()) { manager.on(e => { - const cell = this.inputs.getCell(e.target as Element); + const cell = this.inputs.getCell(_getEventTarget(e)); if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return; this.gridBehavior.gotoCell(cell, { @@ -169,7 +170,7 @@ export class GridPattern { // Selection with modifier keys. if (this.inputs.multi()) { manager.on([Modifier.Ctrl, Modifier.Meta], e => { - const cell = this.inputs.getCell(e.target as Element); + const cell = this.inputs.getCell(_getEventTarget(e)); if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return; this.gridBehavior.gotoCell(cell, {toggle: true}); @@ -233,7 +234,7 @@ export class GridPattern { this.hasBeenInteracted.set(true); // Cell that receives focus. - const cell = this.inputs.getCell(event.target as Element | null); + const cell = this.inputs.getCell(_getEventTarget(event)); if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return; // Pass down the focusin event to the cell. @@ -249,7 +250,7 @@ export class GridPattern { /** Handles focusout events on the grid. */ onFocusOut(event: FocusEvent) { // Pass down focusout event to the cell that loses focus. - const blurTarget = event.target as Element | null; + const blurTarget = _getEventTarget(event); const cell = this.inputs.getCell(blurTarget); // Pass down the focusout event to the cell. diff --git a/src/aria/private/grid/widget.ts b/src/aria/private/grid/widget.ts index 56480bf55582..d45386ade1bb 100644 --- a/src/aria/private/grid/widget.ts +++ b/src/aria/private/grid/widget.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {KeyboardEventManager, Modifier} from '../behaviors/event-manager'; import { SignalLike, @@ -133,7 +134,7 @@ export class GridCellWidgetPattern { if (this.inputs.widgetType() === 'simple') return; // Set activate state if the focus is inside of widget. - const focusTarget = event.target as Element; + const focusTarget = _getEventTarget(event); if (this.widgetHost().contains(focusTarget) && this.widgetHost() !== focusTarget) { this.activate(event); } diff --git a/src/aria/private/listbox/BUILD.bazel b/src/aria/private/listbox/BUILD.bazel index 5c5fe8ecf3cc..bcd06ec1229c 100644 --- a/src/aria/private/listbox/BUILD.bazel +++ b/src/aria/private/listbox/BUILD.bazel @@ -13,6 +13,7 @@ ts_project( "//src/aria/private/behaviors/event-manager", "//src/aria/private/behaviors/list", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/listbox/listbox.ts b/src/aria/private/listbox/listbox.ts index 12562c9a02a6..8baf9b6a0df0 100644 --- a/src/aria/private/listbox/listbox.ts +++ b/src/aria/private/listbox/listbox.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {OptionPattern} from './option'; import {KeyboardEventManager, Modifier, ClickEventManager} from '../behaviors/event-manager'; import {computed, signal, SignalLike} from '../behaviors/signal-like/signal-like'; @@ -292,11 +293,12 @@ export class ListboxPattern { } protected _getItem(e: PointerEvent) { - if (!e.target) { + const target = _getEventTarget(e); + if (!target) { return; } - const element = (e.target as Element).closest('[role="option"]'); + const element = target.closest('[role="option"]'); return this.inputs.items().find(i => i.element() === element); } } diff --git a/src/aria/private/menu/BUILD.bazel b/src/aria/private/menu/BUILD.bazel index dc1c20d548aa..8259dc2fe55f 100644 --- a/src/aria/private/menu/BUILD.bazel +++ b/src/aria/private/menu/BUILD.bazel @@ -13,6 +13,7 @@ ts_project( "//src/aria/private/behaviors/expansion", "//src/aria/private/behaviors/list", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/menu/menu.ts b/src/aria/private/menu/menu.ts index 70657833c7ec..9d6ed70cc538 100644 --- a/src/aria/private/menu/menu.ts +++ b/src/aria/private/menu/menu.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {KeyboardEventManager} from '../behaviors/event-manager'; import {computed, signal, SignalLike} from '../behaviors/signal-like/signal-like'; import {List, ListInputs, ListItem} from '../behaviors/list/list'; @@ -229,7 +230,7 @@ export class MenuPattern { } this.hasBeenHovered.set(true); - const item = this.inputs.items().find(i => i.element()?.contains(event.target as Node)); + const item = this.inputs.items().find(i => i.element()?.contains(_getEventTarget(event))); if (!item) { return; @@ -309,7 +310,7 @@ export class MenuPattern { /** Handles click events for the menu. */ onClick(event: MouseEvent) { - const relatedTarget = event.target as Node | null; + const relatedTarget = _getEventTarget(event); const item = this.inputs.items().find(i => i.element()?.contains(relatedTarget)); if (item) { @@ -552,7 +553,7 @@ export class MenuBarPattern { /** Handles click events for the menu bar. */ onClick(event: MouseEvent) { - const item = this.inputs.items().find(i => i.element()?.contains(event.target as Node)); + const item = this.inputs.items().find(i => i.element()?.contains(_getEventTarget(event))); if (!item) { return; @@ -564,7 +565,7 @@ export class MenuBarPattern { /** Handles mouseover events for the menu bar. */ onMouseOver(event: MouseEvent) { - const item = this.inputs.items().find(i => i.element()?.contains(event.target as Node)); + const item = this.inputs.items().find(i => i.element()?.contains(_getEventTarget(event))); if (item) { this.goto(item, {focusElement: this.isFocused()}); diff --git a/src/aria/private/tabs/BUILD.bazel b/src/aria/private/tabs/BUILD.bazel index 891074f610e6..4a22eda8836b 100644 --- a/src/aria/private/tabs/BUILD.bazel +++ b/src/aria/private/tabs/BUILD.bazel @@ -15,6 +15,7 @@ ts_project( "//src/aria/private/behaviors/list-focus", "//src/aria/private/behaviors/list-navigation", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/tabs/tabs.ts b/src/aria/private/tabs/tabs.ts index 028c07efc098..85a82d8496a1 100644 --- a/src/aria/private/tabs/tabs.ts +++ b/src/aria/private/tabs/tabs.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {KeyboardEventManager, ClickEventManager} from '../behaviors/event-manager'; import {ExpansionItem, ListExpansion, ListExpansionInputs} from '../behaviors/expansion/expansion'; import { @@ -296,11 +297,12 @@ export class TabListPattern { /** Returns the tab item associated with the given pointer event. */ private _getItem(e: PointerEvent) { - if (!e.target) { + const target = _getEventTarget(e); + if (!target) { return; } - const element = (e.target as Element).closest('[role="tab"]'); + const element = target.closest('[role="tab"]'); return this.inputs.items().find(i => i.element() === element); } } diff --git a/src/aria/private/toolbar/BUILD.bazel b/src/aria/private/toolbar/BUILD.bazel index 6c2dd3d6221b..f74e0e585ce2 100644 --- a/src/aria/private/toolbar/BUILD.bazel +++ b/src/aria/private/toolbar/BUILD.bazel @@ -14,6 +14,7 @@ ts_project( "//src/aria/private/behaviors/event-manager", "//src/aria/private/behaviors/list", "//src/aria/private/behaviors/signal-like", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/toolbar/toolbar.ts b/src/aria/private/toolbar/toolbar.ts index 0e0124f92e09..1fab0665c4a2 100644 --- a/src/aria/private/toolbar/toolbar.ts +++ b/src/aria/private/toolbar/toolbar.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import {computed, signal, SignalLike} from '../behaviors/signal-like/signal-like'; import {KeyboardEventManager} from '../behaviors/event-manager'; import {List, ListInputs} from '../behaviors/list/list'; @@ -139,7 +140,7 @@ export class ToolbarPattern { /** Navigates to the widget targeted by a pointer event. */ private _goto(e: MouseEvent) { - const item = this.inputs.getItem(e.target as Element); + const item = this.inputs.getItem(_getEventTarget(e) as Element); if (item) { this.listBehavior.goto(item); diff --git a/src/aria/private/tree/BUILD.bazel b/src/aria/private/tree/BUILD.bazel index 287f3d90787e..d4dadbc9da1e 100644 --- a/src/aria/private/tree/BUILD.bazel +++ b/src/aria/private/tree/BUILD.bazel @@ -13,6 +13,7 @@ ts_project( "//src/aria/private/behaviors/expansion", "//src/aria/private/behaviors/signal-like", "//src/aria/private/behaviors/tree", + "//src/cdk/platform", ], ) diff --git a/src/aria/private/tree/tree.ts b/src/aria/private/tree/tree.ts index f235040eaecd..1a8f60690c79 100644 --- a/src/aria/private/tree/tree.ts +++ b/src/aria/private/tree/tree.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ +import {_getEventTarget} from '@angular/cdk/platform'; import { SignalLike, computed, @@ -479,10 +480,11 @@ export class TreePattern implements TreeInputs { /** Retrieves the TreeItemPattern associated with a DOM event, if any. */ protected _getItem(event: Event): TreeItemPattern | undefined { - if (!event.target) { + const target = _getEventTarget(event); + if (!target) { return; } - const element = (event.target as Element).closest('[role="treeitem"]'); + const element = target.closest('[role="treeitem"]'); return this.inputs.items().find(i => i.element() === element); } }