@@ -58,6 +58,12 @@ const passiveEventListenerOptions = normalizePassiveListenerOptions({passive: tr
58
58
/** Options that can be used to bind an active event listener. */
59
59
const activeEventListenerOptions = normalizePassiveListenerOptions ( { passive : false } ) ;
60
60
61
+ /** Event options that can be used to bind an active, capturing event. */
62
+ const activeCapturingEventOptions = normalizePassiveListenerOptions ( {
63
+ passive : false ,
64
+ capture : true ,
65
+ } ) ;
66
+
61
67
/**
62
68
* Time in milliseconds for which to ignore mouse events, after
63
69
* receiving a touch event. Used to avoid doing double work for
@@ -496,7 +502,7 @@ export class DragRef<T = any> {
496
502
this . _destroyPreview ( ) ;
497
503
this . _destroyPlaceholder ( ) ;
498
504
this . _dragDropRegistry . removeDragItem ( this ) ;
499
- this . _removeSubscriptions ( ) ;
505
+ this . _removeListeners ( ) ;
500
506
this . beforeStarted . complete ( ) ;
501
507
this . started . complete ( ) ;
502
508
this . released . complete ( ) ;
@@ -608,10 +614,15 @@ export class DragRef<T = any> {
608
614
}
609
615
610
616
/** Unsubscribes from the global subscriptions. */
611
- private _removeSubscriptions ( ) {
617
+ private _removeListeners ( ) {
612
618
this . _pointerMoveSubscription . unsubscribe ( ) ;
613
619
this . _pointerUpSubscription . unsubscribe ( ) ;
614
620
this . _scrollSubscription . unsubscribe ( ) ;
621
+ this . _getShadowRoot ( ) ?. removeEventListener (
622
+ 'selectstart' ,
623
+ shadowDomSelectStart ,
624
+ activeCapturingEventOptions ,
625
+ ) ;
615
626
}
616
627
617
628
/** Destroys the preview element and its ViewRef. */
@@ -741,7 +752,7 @@ export class DragRef<T = any> {
741
752
return ;
742
753
}
743
754
744
- this . _removeSubscriptions ( ) ;
755
+ this . _removeListeners ( ) ;
745
756
this . _dragDropRegistry . stopDragging ( this ) ;
746
757
this . _toggleNativeDragInteractions ( ) ;
747
758
@@ -792,17 +803,28 @@ export class DragRef<T = any> {
792
803
793
804
this . _toggleNativeDragInteractions ( ) ;
794
805
806
+ // Needs to happen before the root element is moved.
807
+ const shadowRoot = this . _getShadowRoot ( ) ;
795
808
const dropContainer = this . _dropContainer ;
796
809
810
+ if ( shadowRoot ) {
811
+ // In some browsers the global `selectstart` that we maintain in the `DragDropRegistry`
812
+ // doesn't cross the shadow boundary so we have to prevent it at the shadow root (see #28792).
813
+ this . _ngZone . runOutsideAngular ( ( ) => {
814
+ shadowRoot . addEventListener (
815
+ 'selectstart' ,
816
+ shadowDomSelectStart ,
817
+ activeCapturingEventOptions ,
818
+ ) ;
819
+ } ) ;
820
+ }
821
+
797
822
if ( dropContainer ) {
798
823
const element = this . _rootElement ;
799
824
const parent = element . parentNode as HTMLElement ;
800
825
const placeholder = ( this . _placeholder = this . _createPlaceholderElement ( ) ) ;
801
826
const anchor = ( this . _anchor = this . _anchor || this . _document . createComment ( '' ) ) ;
802
827
803
- // Needs to happen before the root element is moved.
804
- const shadowRoot = this . _getShadowRoot ( ) ;
805
-
806
828
// Insert an anchor node so that we can restore the element's position in the DOM.
807
829
parent . insertBefore ( anchor , element ) ;
808
830
@@ -888,7 +910,7 @@ export class DragRef<T = any> {
888
910
889
911
// Avoid multiple subscriptions and memory leaks when multi touch
890
912
// (isDragging check above isn't enough because of possible temporal and/or dimensional delays)
891
- this . _removeSubscriptions ( ) ;
913
+ this . _removeListeners ( ) ;
892
914
this . _initialDomRect = this . _rootElement . getBoundingClientRect ( ) ;
893
915
this . _pointerMoveSubscription = this . _dragDropRegistry . pointerMove . subscribe ( this . _pointerMove ) ;
894
916
this . _pointerUpSubscription = this . _dragDropRegistry . pointerUp . subscribe ( this . _pointerUp ) ;
@@ -1617,3 +1639,8 @@ function matchElementSize(target: HTMLElement, sourceRect: DOMRect): void {
1617
1639
target . style . height = `${ sourceRect . height } px` ;
1618
1640
target . style . transform = getTransform ( sourceRect . left , sourceRect . top ) ;
1619
1641
}
1642
+
1643
+ /** Callback invoked for `selectstart` events inside the shadow DOM. */
1644
+ function shadowDomSelectStart ( event : Event ) {
1645
+ event . preventDefault ( ) ;
1646
+ }
0 commit comments