diff --git a/goldens/cdk/platform/index.api.md b/goldens/cdk/platform/index.api.md index 11fa92af5272..21144f237ded 100644 --- a/goldens/cdk/platform/index.api.md +++ b/goldens/cdk/platform/index.api.md @@ -5,10 +5,6 @@ ```ts import * as i0 from '@angular/core'; -import { Renderer2 } from '@angular/core'; - -// @public -export function _bindEventWithOptions(renderer: Renderer2, target: EventTarget, eventName: string, callback: (event: any) => boolean | void, options: _ListenerOptions): () => void; // @public export function _getEventTarget(event: Event): T | null; @@ -28,16 +24,6 @@ export function getSupportedInputTypes(): Set; // @public export function _isTestEnvironment(): boolean; -// @public -export interface _ListenerOptions { - // (undocumented) - capture?: boolean; - // (undocumented) - once?: boolean; - // (undocumented) - passive?: boolean; -} - // @public export function normalizePassiveListenerOptions(options: AddEventListenerOptions): AddEventListenerOptions | boolean; diff --git a/src/cdk-experimental/popover-edit/table-directives.ts b/src/cdk-experimental/popover-edit/table-directives.ts index 5ab67b5ee5d7..34130fa89c65 100644 --- a/src/cdk-experimental/popover-edit/table-directives.ts +++ b/src/cdk-experimental/popover-edit/table-directives.ts @@ -35,7 +35,6 @@ import { withLatestFrom, } from 'rxjs/operators'; -import {_bindEventWithOptions} from '@angular/cdk/platform'; import {CELL_SELECTOR, EDIT_PANE_CLASS, EDIT_PANE_SELECTOR, ROW_SELECTOR} from './constants'; import {EditEventDispatcher, HoverContentState} from './edit-event-dispatcher'; import {EditRef} from './edit-ref'; @@ -136,9 +135,7 @@ export class CdkEditable implements AfterViewInit, OnDestroy { ) { return new Observable(subscriber => { const handler = (event: T) => subscriber.next(event); - const cleanup = options - ? _bindEventWithOptions(this._renderer, element, name, handler, options) - : this._renderer.listen(element, name, handler, options); + const cleanup = this._renderer.listen(element, name, handler, options); return () => { cleanup(); subscriber.complete(); diff --git a/src/cdk/a11y/input-modality/input-modality-detector.ts b/src/cdk/a11y/input-modality/input-modality-detector.ts index 58252f742be5..9054b5e8632f 100644 --- a/src/cdk/a11y/input-modality/input-modality-detector.ts +++ b/src/cdk/a11y/input-modality/input-modality-detector.ts @@ -15,7 +15,7 @@ import { inject, RendererFactory2, } from '@angular/core'; -import {Platform, _bindEventWithOptions, _getEventTarget} from '../../platform'; +import {Platform, _getEventTarget} from '../../platform'; import {DOCUMENT} from '@angular/common'; import {BehaviorSubject, Observable} from 'rxjs'; import {distinctUntilChanged, skip} from 'rxjs/operators'; @@ -205,27 +205,9 @@ export class InputModalityDetector implements OnDestroy { this._listenerCleanups = ngZone.runOutsideAngular(() => { return [ - _bindEventWithOptions( - renderer, - document, - 'keydown', - this._onKeydown, - modalityEventListenerOptions, - ), - _bindEventWithOptions( - renderer, - document, - 'mousedown', - this._onMousedown, - modalityEventListenerOptions, - ), - _bindEventWithOptions( - renderer, - document, - 'touchstart', - this._onTouchstart, - modalityEventListenerOptions, - ), + renderer.listen(document, 'keydown', this._onKeydown, modalityEventListenerOptions), + renderer.listen(document, 'mousedown', this._onMousedown, modalityEventListenerOptions), + renderer.listen(document, 'touchstart', this._onTouchstart, modalityEventListenerOptions), ]; }); } diff --git a/src/cdk/drag-drop/drag-drop-registry.ts b/src/cdk/drag-drop/drag-drop-registry.ts index 9fdc66b75e5d..ef81bab708d3 100644 --- a/src/cdk/drag-drop/drag-drop-registry.ts +++ b/src/cdk/drag-drop/drag-drop-registry.ts @@ -10,6 +10,7 @@ import { ChangeDetectionStrategy, Component, Injectable, + ListenerOptions, NgZone, OnDestroy, RendererFactory2, @@ -19,7 +20,6 @@ import { signal, } from '@angular/core'; import {DOCUMENT} from '@angular/common'; -import {_bindEventWithOptions, _ListenerOptions} from '../platform'; import {_CdkPrivateStyleLoader} from '../private'; import {Observable, Observer, Subject, merge} from 'rxjs'; import type {DropListRef} from './drop-list-ref'; @@ -123,8 +123,7 @@ export class DragDropRegistry implements OnDestroy { // The event handler has to be explicitly active, // because newer browsers make it passive by default. this._cleanupDocumentTouchmove?.(); - this._cleanupDocumentTouchmove = _bindEventWithOptions( - this._renderer, + this._cleanupDocumentTouchmove = this._renderer.listen( this._document, 'touchmove', this._persistentTouchmoveListener, @@ -170,7 +169,7 @@ export class DragDropRegistry implements OnDestroy { const isTouchEvent = event.type.startsWith('touch'); const endEventHandler = (e: Event) => this.pointerUp.next(e as TouchEvent | MouseEvent); - const toBind: [name: string, handler: (event: Event) => void, options: _ListenerOptions][] = [ + const toBind: [name: string, handler: (event: Event) => void, options: ListenerOptions][] = [ // Use capturing so that we pick up scroll changes in any scrollable nodes that aren't // the document. See https://github.com/angular/components/issues/17144. ['scroll', (e: Event) => this._scroll.next(e), capturingEventOptions], @@ -203,7 +202,7 @@ export class DragDropRegistry implements OnDestroy { this._ngZone.runOutsideAngular(() => { this._globalListeners = toBind.map(([name, handler, options]) => - _bindEventWithOptions(this._renderer, this._document, name, handler, options), + this._renderer.listen(this._document, name, handler, options), ); }); } @@ -247,8 +246,7 @@ export class DragDropRegistry implements OnDestroy { streams.push( new Observable((observer: Observer) => { return this._ngZone.runOutsideAngular(() => { - const cleanup = _bindEventWithOptions( - this._renderer, + const cleanup = this._renderer.listen( shadowRoot as ShadowRoot, 'scroll', (event: Event) => { diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index 7296c3f59440..45dea4eac3dd 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -9,7 +9,7 @@ import {isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader} from '../a11y'; import {Direction} from '../bidi'; import {coerceElement} from '../coercion'; -import {_getEventTarget, _getShadowRoot, _bindEventWithOptions} from '../platform'; +import {_getEventTarget, _getShadowRoot} from '../platform'; import {ViewportRuler} from '../scrolling'; import { ElementRef, @@ -457,28 +457,11 @@ export class DragRef { if (element !== this._rootElement) { this._removeRootElementListeners(); + const renderer = this._renderer; this._rootElementCleanups = this._ngZone.runOutsideAngular(() => [ - _bindEventWithOptions( - this._renderer, - element, - 'mousedown', - this._pointerDown, - activeEventListenerOptions, - ), - _bindEventWithOptions( - this._renderer, - element, - 'touchstart', - this._pointerDown, - passiveEventListenerOptions, - ), - _bindEventWithOptions( - this._renderer, - element, - 'dragstart', - this._nativeDragStart, - activeEventListenerOptions, - ), + renderer.listen(element, 'mousedown', this._pointerDown, activeEventListenerOptions), + renderer.listen(element, 'touchstart', this._pointerDown, passiveEventListenerOptions), + renderer.listen(element, 'dragstart', this._nativeDragStart, activeEventListenerOptions), ]); this._initialTransform = undefined; this._rootElement = element; @@ -832,8 +815,7 @@ export class DragRef { // In some browsers the global `selectstart` that we maintain in the `DragDropRegistry` // doesn't cross the shadow boundary so we have to prevent it at the shadow root (see #28792). this._ngZone.runOutsideAngular(() => { - this._cleanupShadowRootSelectStart = _bindEventWithOptions( - this._renderer, + this._cleanupShadowRootSelectStart = this._renderer.listen( shadowRoot, 'selectstart', shadowDomSelectStart, diff --git a/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts b/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts index 3aa681fb0532..b66e0259d1ae 100644 --- a/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts +++ b/src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts @@ -7,7 +7,7 @@ */ import {Injectable, NgZone, RendererFactory2, inject} from '@angular/core'; -import {Platform, _bindEventWithOptions, _getEventTarget} from '../../platform'; +import {Platform, _getEventTarget} from '../../platform'; import {BaseOverlayDispatcher} from './base-overlay-dispatcher'; import type {OverlayRef} from '../overlay-ref'; @@ -40,24 +40,13 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher { if (!this._isAttached) { const body = this._document.body; const eventOptions = {capture: true}; + const renderer = this._renderer; this._cleanups = this._ngZone.runOutsideAngular(() => [ - _bindEventWithOptions( - this._renderer, - body, - 'pointerdown', - this._pointerDownListener, - eventOptions, - ), - _bindEventWithOptions(this._renderer, body, 'click', this._clickListener, eventOptions), - _bindEventWithOptions(this._renderer, body, 'auxclick', this._clickListener, eventOptions), - _bindEventWithOptions( - this._renderer, - body, - 'contextmenu', - this._clickListener, - eventOptions, - ), + renderer.listen(body, 'pointerdown', this._pointerDownListener, eventOptions), + renderer.listen(body, 'click', this._clickListener, eventOptions), + renderer.listen(body, 'auxclick', this._clickListener, eventOptions), + renderer.listen(body, 'contextmenu', this._clickListener, eventOptions), ]); // click event is not fired on iOS. To make element "clickable" we are diff --git a/src/cdk/platform/features/backwards-compatibility.ts b/src/cdk/platform/features/backwards-compatibility.ts deleted file mode 100644 index 8be208a78268..000000000000 --- a/src/cdk/platform/features/backwards-compatibility.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {Renderer2, VERSION} from '@angular/core'; - -// TODO(crisbeto): replace interface with the one from core when making breaking changes for v20. -/** Options when binding events manually. */ -export interface _ListenerOptions { - capture?: boolean; - once?: boolean; - passive?: boolean; -} - -// TODO(crisbeto): remove this function when making breaking changes for v20. -/** - * Binds an event listener with specific options in a backwards-compatible way. - * This function is necessary, because `Renderer2.listen` only supports listener options - * after 19.1 and during the v19 period we support any 19.x version. - * @docs-private - */ -export function _bindEventWithOptions( - renderer: Renderer2, - target: EventTarget, - eventName: string, - callback: (event: any) => boolean | void, - options: _ListenerOptions, -): () => void { - const major = parseInt(VERSION.major); - const minor = parseInt(VERSION.minor); - - // Event options in `listen` are only supported in 19.1 and beyond. - // We also allow 0.0.x, because that indicates a build at HEAD. - if (major > 19 || (major === 19 && minor > 0) || (major === 0 && minor === 0)) { - return renderer.listen(target, eventName, callback, options); - } - - target.addEventListener(eventName, callback, options); - - return () => { - target.removeEventListener(eventName, callback, options); - }; -} diff --git a/src/cdk/platform/public-api.ts b/src/cdk/platform/public-api.ts index 9613cc5b04bc..ae1990dee0fe 100644 --- a/src/cdk/platform/public-api.ts +++ b/src/cdk/platform/public-api.ts @@ -13,4 +13,3 @@ export * from './features/passive-listeners'; export * from './features/scrolling'; export * from './features/shadow-dom'; export * from './features/test-environment'; -export * from './features/backwards-compatibility'; diff --git a/src/cdk/text-field/autofill.ts b/src/cdk/text-field/autofill.ts index 26928753351a..5c2506e67fae 100644 --- a/src/cdk/text-field/autofill.ts +++ b/src/cdk/text-field/autofill.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {Platform, _bindEventWithOptions} from '../platform'; +import {Platform} from '../platform'; import { Directive, ElementRef, @@ -111,13 +111,7 @@ export class AutofillMonitor implements OnDestroy { const unlisten = this._ngZone.runOutsideAngular(() => { element.classList.add('cdk-text-field-autofill-monitored'); - return _bindEventWithOptions( - this._renderer, - element, - 'animationstart', - listener, - listenerOptions, - ); + return this._renderer.listen(element, 'animationstart', listener, listenerOptions); }); this._monitoredElements.set(element, {subject, unlisten}); diff --git a/src/material/core/private/ripple-loader.ts b/src/material/core/private/ripple-loader.ts index c098a7e523a6..79e399472170 100644 --- a/src/material/core/private/ripple-loader.ts +++ b/src/material/core/private/ripple-loader.ts @@ -14,7 +14,7 @@ import { RippleTarget, defaultRippleAnimationConfig, } from '../ripple'; -import {Platform, _bindEventWithOptions, _getEventTarget} from '@angular/cdk/platform'; +import {Platform, _getEventTarget} from '@angular/cdk/platform'; import {_CdkPrivateStyleLoader} from '@angular/cdk/private'; import {_animationsDisabled} from '../animation/animation'; @@ -65,17 +65,11 @@ export class MatRippleLoader implements OnDestroy { constructor() { const renderer = inject(RendererFactory2).createRenderer(null, null); - this._eventCleanups = this._ngZone.runOutsideAngular(() => { - return rippleInteractionEvents.map(name => - _bindEventWithOptions( - renderer, - this._document, - name, - this._onInteraction, - eventListenerOptions, - ), - ); - }); + this._eventCleanups = this._ngZone.runOutsideAngular(() => + rippleInteractionEvents.map(name => + renderer.listen(this._document, name, this._onInteraction, eventListenerOptions), + ), + ); } ngOnDestroy(): void { diff --git a/src/material/datepicker/calendar-body.ts b/src/material/datepicker/calendar-body.ts index da7f3d83056d..34af64d8faba 100644 --- a/src/material/datepicker/calendar-body.ts +++ b/src/material/datepicker/calendar-body.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {Platform, _bindEventWithOptions} from '@angular/cdk/platform'; +import {Platform} from '@angular/cdk/platform'; import { ChangeDetectionStrategy, Component, @@ -239,55 +239,13 @@ export class MatCalendarBody implements OnChanges, OnDestroy, AfterView const element = this._elementRef.nativeElement; const cleanups = [ // `touchmove` is active since we need to call `preventDefault`. - _bindEventWithOptions( - renderer, - element, - 'touchmove', - this._touchmoveHandler, - activeCapturingEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'mouseenter', - this._enterHandler, - passiveCapturingEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'focus', - this._enterHandler, - passiveCapturingEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'mouseleave', - this._leaveHandler, - passiveCapturingEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'blur', - this._leaveHandler, - passiveCapturingEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'mousedown', - this._mousedownHandler, - passiveEventOptions, - ), - _bindEventWithOptions( - renderer, - element, - 'touchstart', - this._mousedownHandler, - passiveEventOptions, - ), + renderer.listen(element, 'touchmove', this._touchmoveHandler, activeCapturingEventOptions), + renderer.listen(element, 'mouseenter', this._enterHandler, passiveCapturingEventOptions), + renderer.listen(element, 'focus', this._enterHandler, passiveCapturingEventOptions), + renderer.listen(element, 'mouseleave', this._leaveHandler, passiveCapturingEventOptions), + renderer.listen(element, 'blur', this._leaveHandler, passiveCapturingEventOptions), + renderer.listen(element, 'mousedown', this._mousedownHandler, passiveEventOptions), + renderer.listen(element, 'touchstart', this._mousedownHandler, passiveEventOptions), ]; if (this._platform.isBrowser) { diff --git a/src/material/menu/menu-trigger.ts b/src/material/menu/menu-trigger.ts index 6dcf5aefeb8b..7fd5a475d9bf 100644 --- a/src/material/menu/menu-trigger.ts +++ b/src/material/menu/menu-trigger.ts @@ -39,7 +39,6 @@ import { Renderer2, ViewContainerRef, } from '@angular/core'; -import {_bindEventWithOptions} from '@angular/cdk/platform'; import {merge, Observable, of as observableOf, Subscription} from 'rxjs'; import {filter, take, takeUntil} from 'rxjs/operators'; import {MatMenu, MenuCloseReason} from './menu'; @@ -228,8 +227,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy { const renderer = inject(Renderer2); this._parentMaterialMenu = parentMenu instanceof MatMenu ? parentMenu : undefined; - this._cleanupTouchstart = _bindEventWithOptions( - renderer, + this._cleanupTouchstart = renderer.listen( this._element.nativeElement, 'touchstart', (event: TouchEvent) => { diff --git a/src/material/tabs/paginated-tab-header.ts b/src/material/tabs/paginated-tab-header.ts index c43f349c55e7..6dbde9e09556 100644 --- a/src/material/tabs/paginated-tab-header.ts +++ b/src/material/tabs/paginated-tab-header.ts @@ -10,7 +10,7 @@ import {FocusKeyManager, FocusableOption} from '@angular/cdk/a11y'; import {Direction, Directionality} from '@angular/cdk/bidi'; import {ENTER, SPACE, hasModifierKey} from '@angular/cdk/keycodes'; import {SharedResizeObserver} from '@angular/cdk/observers/private'; -import {Platform, _bindEventWithOptions} from '@angular/cdk/platform'; +import {Platform} from '@angular/cdk/platform'; import {ViewportRuler} from '@angular/cdk/scrolling'; import { AfterContentChecked, @@ -177,15 +177,13 @@ export abstract class MatPaginatedTabHeader // We need to handle these events manually, because we want to bind passive event listeners. this._eventCleanups.push( - _bindEventWithOptions( - this._renderer, + this._renderer.listen( this._previousPaginator.nativeElement, 'touchstart', () => this._handlePaginatorPress('before'), passiveEventListenerOptions, ), - _bindEventWithOptions( - this._renderer, + this._renderer.listen( this._nextPaginator.nativeElement, 'touchstart', () => this._handlePaginatorPress('after'),