@angular/cdk 19.1.0-next.3 → 19.1.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2024 Google LLC.
3
+ Copyright (c) 2025 Google LLC.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/a11y/index.d.ts CHANGED
@@ -318,8 +318,6 @@ export declare class FocusKeyManager<T> extends ListKeyManager<FocusableOption &
318
318
  export declare class FocusMonitor implements OnDestroy {
319
319
  private _ngZone;
320
320
  private _platform;
321
- private _renderer;
322
- private _cleanupWindowFocus;
323
321
  private readonly _inputModalityDetector;
324
322
  /** The focus origin that the next focus event is a result of. */
325
323
  private _origin;
@@ -346,7 +344,7 @@ export declare class FocusMonitor implements OnDestroy {
346
344
  * handlers differently from the rest of the events, because the browser won't emit events
347
345
  * to the document when focus moves inside of a shadow root.
348
346
  */
349
- private _rootNodeFocusListeners;
347
+ private _rootNodeFocusListenerCount;
350
348
  /**
351
349
  * The specified detection mode, used for attributing the origin of a focus
352
350
  * event.
@@ -410,6 +408,8 @@ export declare class FocusMonitor implements OnDestroy {
410
408
  ngOnDestroy(): void;
411
409
  /** Access injected document if available or fallback to global document reference */
412
410
  private _getDocument;
411
+ /** Use defaultView of injected document if available or fallback to global window reference */
412
+ private _getWindow;
413
413
  private _getFocusOrigin;
414
414
  /**
415
415
  * Returns whether the focus event should be attributed to touch. Recall that in IMMEDIATE mode, a
@@ -788,7 +788,6 @@ export declare type InputModality = 'keyboard' | 'mouse' | 'touch' | null;
788
788
  */
789
789
  export declare class InputModalityDetector implements OnDestroy {
790
790
  private readonly _platform;
791
- private readonly _listenerCleanups;
792
791
  /** Emits whenever an input modality is detected. */
793
792
  readonly modalityDetected: Observable<InputModality>;
794
793
  /** Emits when the input modality changes. */
@@ -582,8 +582,6 @@ export declare class DragDropRegistry<_ = unknown, __ = unknown> implements OnDe
582
582
  private _ngZone;
583
583
  private _document;
584
584
  private _styleLoader;
585
- private _renderer;
586
- private _cleanupDocumentTouchmove;
587
585
  /** Registered drop container instances. */
588
586
  private _dropInstances;
589
587
  /** Registered drag item instances. */
@@ -701,8 +699,6 @@ export declare class DragRef<T = any> {
701
699
  private _viewportRuler;
702
700
  private _dragDropRegistry;
703
701
  private _renderer;
704
- private _rootElementCleanups;
705
- private _cleanupShadowRootSelectStart;
706
702
  /** Element displayed next to the user's pointer while the element is dragged. */
707
703
  private _preview;
708
704
  /** Container into which to insert the preview. */
package/fesm2022/a11y.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DOCUMENT } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, APP_ID, Injectable, signal, QueryList, isSignal, effect, InjectionToken, afterNextRender, NgZone, Injector, ElementRef, booleanAttribute, Directive, Input, RendererFactory2, EventEmitter, Output, NgModule } from '@angular/core';
4
- import { Platform, _getFocusedElementPierceShadowDom, _getEventTarget, _bindEventWithOptions, _getShadowRoot } from '@angular/cdk/platform';
3
+ import { inject, APP_ID, Injectable, signal, QueryList, isSignal, effect, InjectionToken, afterNextRender, NgZone, Injector, ElementRef, booleanAttribute, Directive, Input, EventEmitter, Output, NgModule } from '@angular/core';
4
+ import { Platform, _getFocusedElementPierceShadowDom, normalizePassiveListenerOptions, _getEventTarget, _getShadowRoot } from '@angular/cdk/platform';
5
5
  import { _CdkPrivateStyleLoader, _VisuallyHiddenLoader } from '@angular/cdk/private';
6
6
  import { A, Z, ZERO, NINE, hasModifierKey, PAGE_DOWN, PAGE_UP, END, HOME, LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, TAB, ALT, CONTROL, MAC_META, META, SHIFT } from '@angular/cdk/keycodes';
7
7
  import { Subject, Subscription, isObservable, of, BehaviorSubject } from 'rxjs';
@@ -1994,10 +1994,10 @@ const TOUCH_BUFFER_MS = 650;
1994
1994
  * Event listener options that enable capturing and also mark the listener as passive if the browser
1995
1995
  * supports it.
1996
1996
  */
1997
- const modalityEventListenerOptions = {
1997
+ const modalityEventListenerOptions = normalizePassiveListenerOptions({
1998
1998
  passive: true,
1999
1999
  capture: true,
2000
- };
2000
+ });
2001
2001
  /**
2002
2002
  * Service that detects the user's input modality.
2003
2003
  *
@@ -2014,7 +2014,6 @@ const modalityEventListenerOptions = {
2014
2014
  */
2015
2015
  class InputModalityDetector {
2016
2016
  _platform = inject(Platform);
2017
- _listenerCleanups;
2018
2017
  /** Emits whenever an input modality is detected. */
2019
2018
  modalityDetected;
2020
2019
  /** Emits when the input modality changes. */
@@ -2097,19 +2096,20 @@ class InputModalityDetector {
2097
2096
  // If we're not in a browser, this service should do nothing, as there's no relevant input
2098
2097
  // modality to detect.
2099
2098
  if (this._platform.isBrowser) {
2100
- const renderer = inject(RendererFactory2).createRenderer(null, null);
2101
- this._listenerCleanups = ngZone.runOutsideAngular(() => {
2102
- return [
2103
- _bindEventWithOptions(renderer, document, 'keydown', this._onKeydown, modalityEventListenerOptions),
2104
- _bindEventWithOptions(renderer, document, 'mousedown', this._onMousedown, modalityEventListenerOptions),
2105
- _bindEventWithOptions(renderer, document, 'touchstart', this._onTouchstart, modalityEventListenerOptions),
2106
- ];
2099
+ ngZone.runOutsideAngular(() => {
2100
+ document.addEventListener('keydown', this._onKeydown, modalityEventListenerOptions);
2101
+ document.addEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);
2102
+ document.addEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);
2107
2103
  });
2108
2104
  }
2109
2105
  }
2110
2106
  ngOnDestroy() {
2111
2107
  this._modality.complete();
2112
- this._listenerCleanups?.forEach(cleanup => cleanup());
2108
+ if (this._platform.isBrowser) {
2109
+ document.removeEventListener('keydown', this._onKeydown, modalityEventListenerOptions);
2110
+ document.removeEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);
2111
+ document.removeEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);
2112
+ }
2113
2113
  }
2114
2114
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: InputModalityDetector, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2115
2115
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: InputModalityDetector, providedIn: 'root' });
@@ -2343,16 +2343,14 @@ const FOCUS_MONITOR_DEFAULT_OPTIONS = new InjectionToken('cdk-focus-monitor-defa
2343
2343
  * Event listener options that enable capturing and also
2344
2344
  * mark the listener as passive if the browser supports it.
2345
2345
  */
2346
- const captureEventListenerOptions = {
2346
+ const captureEventListenerOptions = normalizePassiveListenerOptions({
2347
2347
  passive: true,
2348
2348
  capture: true,
2349
- };
2349
+ });
2350
2350
  /** Monitors mouse and keyboard events to determine the cause of focus events. */
2351
2351
  class FocusMonitor {
2352
2352
  _ngZone = inject(NgZone);
2353
2353
  _platform = inject(Platform);
2354
- _renderer = inject(RendererFactory2).createRenderer(null, null);
2355
- _cleanupWindowFocus;
2356
2354
  _inputModalityDetector = inject(InputModalityDetector);
2357
2355
  /** The focus origin that the next focus event is a result of. */
2358
2356
  _origin = null;
@@ -2379,7 +2377,7 @@ class FocusMonitor {
2379
2377
  * handlers differently from the rest of the events, because the browser won't emit events
2380
2378
  * to the document when focus moves inside of a shadow root.
2381
2379
  */
2382
- _rootNodeFocusListeners = new Map();
2380
+ _rootNodeFocusListenerCount = new Map();
2383
2381
  /**
2384
2382
  * The specified detection mode, used for attributing the origin of a focus
2385
2383
  * event.
@@ -2487,6 +2485,11 @@ class FocusMonitor {
2487
2485
  _getDocument() {
2488
2486
  return this._document || document;
2489
2487
  }
2488
+ /** Use defaultView of injected document if available or fallback to global window reference */
2489
+ _getWindow() {
2490
+ const doc = this._getDocument();
2491
+ return doc.defaultView || window;
2492
+ }
2490
2493
  _getFocusOrigin(focusEventTarget) {
2491
2494
  if (this._origin) {
2492
2495
  // If the origin was realized via a touch interaction, we need to perform additional checks
@@ -2623,28 +2626,21 @@ class FocusMonitor {
2623
2626
  return;
2624
2627
  }
2625
2628
  const rootNode = elementInfo.rootNode;
2626
- const listeners = this._rootNodeFocusListeners.get(rootNode);
2627
- if (listeners) {
2628
- listeners.count++;
2629
- }
2630
- else {
2629
+ const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;
2630
+ if (!rootNodeFocusListeners) {
2631
2631
  this._ngZone.runOutsideAngular(() => {
2632
- this._rootNodeFocusListeners.set(rootNode, {
2633
- count: 1,
2634
- cleanups: [
2635
- _bindEventWithOptions(this._renderer, rootNode, 'focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions),
2636
- _bindEventWithOptions(this._renderer, rootNode, 'blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions),
2637
- ],
2638
- });
2632
+ rootNode.addEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2633
+ rootNode.addEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2639
2634
  });
2640
2635
  }
2636
+ this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1);
2641
2637
  // Register global listeners when first element is monitored.
2642
2638
  if (++this._monitoredElementCount === 1) {
2643
2639
  // Note: we listen to events in the capture phase so we
2644
2640
  // can detect them even if the user stops propagation.
2645
2641
  this._ngZone.runOutsideAngular(() => {
2646
- this._cleanupWindowFocus?.();
2647
- this._cleanupWindowFocus = this._renderer.listen('window', 'focus', this._windowFocusListener);
2642
+ const window = this._getWindow();
2643
+ window.addEventListener('focus', this._windowFocusListener);
2648
2644
  });
2649
2645
  // The InputModalityDetector is also just a collection of global listeners.
2650
2646
  this._inputModalityDetector.modalityDetected
@@ -2655,19 +2651,22 @@ class FocusMonitor {
2655
2651
  }
2656
2652
  }
2657
2653
  _removeGlobalListeners(elementInfo) {
2658
- const listeners = this._rootNodeFocusListeners.get(elementInfo.rootNode);
2659
- if (listeners) {
2660
- if (listeners.count > 1) {
2661
- listeners.count--;
2654
+ const rootNode = elementInfo.rootNode;
2655
+ if (this._rootNodeFocusListenerCount.has(rootNode)) {
2656
+ const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode);
2657
+ if (rootNodeFocusListeners > 1) {
2658
+ this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);
2662
2659
  }
2663
2660
  else {
2664
- listeners.cleanups.forEach(cleanup => cleanup());
2665
- this._rootNodeFocusListeners.delete(elementInfo.rootNode);
2661
+ rootNode.removeEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2662
+ rootNode.removeEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2663
+ this._rootNodeFocusListenerCount.delete(rootNode);
2666
2664
  }
2667
2665
  }
2668
2666
  // Unregister global listeners when last element is unmonitored.
2669
2667
  if (!--this._monitoredElementCount) {
2670
- this._cleanupWindowFocus?.();
2668
+ const window = this._getWindow();
2669
+ window.removeEventListener('focus', this._windowFocusListener);
2671
2670
  // Equivalently, stop our InputModalityDetector subscription.
2672
2671
  this._stopInputModalityDetector.next();
2673
2672
  // Clear timeouts for all potentially pending timeouts to prevent the leaks.