Skip to content

Commit

Permalink
fix(cdk/drag-drop): defer loading reset styles
Browse files Browse the repository at this point in the history
Currently we load the reset styles for the preview up-front which seems to break some Jest tests since Jest's CSS parser does't understand layers.

These changes switch to loading the styles only once dragging has started.

Fixes angular#29053.
  • Loading branch information
crisbeto committed May 16, 2024
1 parent 46bcc21 commit 69b6966
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 55 deletions.
53 changes: 52 additions & 1 deletion src/cdk/drag-drop/drag-drop-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Injectable, NgZone, OnDestroy, Inject} from '@angular/core';
import {
Injectable,
NgZone,
OnDestroy,
Inject,
inject,
ApplicationRef,
EnvironmentInjector,
Component,
ViewEncapsulation,
ChangeDetectionStrategy,
createComponent,
} from '@angular/core';
import {DOCUMENT} from '@angular/common';
import {normalizePassiveListenerOptions} from '@angular/cdk/platform';
import {merge, Observable, Observer, Subject} from 'rxjs';
Expand All @@ -17,6 +29,23 @@ const activeCapturingEventOptions = normalizePassiveListenerOptions({
capture: true,
});

/** Keeps track of the apps currently containing badges. */
const activeApps = new Set<ApplicationRef>();

/**
* Component used to load the drag&drop reset styles.
* @docs-private
*/
@Component({
standalone: true,
styleUrl: 'resets.css',
encapsulation: ViewEncapsulation.None,
template: '',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {'cdk-drag-resets-container': ''},
})
export class _ResetsLoader {}

/**
* Service that keeps track of all the drag item and drop container
* instances, and manages global event listeners on the `document`.
Expand All @@ -28,6 +57,8 @@ const activeCapturingEventOptions = normalizePassiveListenerOptions({
@Injectable({providedIn: 'root'})
export class DragDropRegistry<I extends {isDragging(): boolean}, C> implements OnDestroy {
private _document: Document;
private _appRef = inject(ApplicationRef);
private _environmentInjector = inject(EnvironmentInjector);

/** Registered drop container instances. */
private _dropInstances = new Set<C>();
Expand Down Expand Up @@ -136,6 +167,7 @@ export class DragDropRegistry<I extends {isDragging(): boolean}, C> implements O
return;
}

this._loadResets();
this._activeDragInstances.push(drag);

if (this._activeDragInstances.length === 1) {
Expand Down Expand Up @@ -276,4 +308,23 @@ export class DragDropRegistry<I extends {isDragging(): boolean}, C> implements O

this._globalListeners.clear();
}

// TODO(crisbeto): abstract this away into something reusable.
/** Loads the CSS resets needed for the module to work correctly. */
private _loadResets() {
if (!activeApps.has(this._appRef)) {
activeApps.add(this._appRef);

const componentRef = createComponent(_ResetsLoader, {
environmentInjector: this._environmentInjector,
});

this._appRef.onDestroy(() => {
activeApps.delete(this._appRef);
if (activeApps.size === 0) {
componentRef.destroy();
}
});
}
}
}
54 changes: 1 addition & 53 deletions src/cdk/drag-drop/drag-drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {
Injectable,
Inject,
NgZone,
ElementRef,
Component,
ViewEncapsulation,
ChangeDetectionStrategy,
ApplicationRef,
inject,
createComponent,
EnvironmentInjector,
} from '@angular/core';
import {Injectable, Inject, NgZone, ElementRef} from '@angular/core';
import {DOCUMENT} from '@angular/common';
import {ViewportRuler} from '@angular/cdk/scrolling';
import {DragRef, DragRefConfig} from './drag-ref';
Expand All @@ -31,31 +19,11 @@ const DEFAULT_CONFIG = {
pointerDirectionChangeThreshold: 5,
};

/** Keeps track of the apps currently containing badges. */
const activeApps = new Set<ApplicationRef>();

/**
* Component used to load the drag&drop reset styles.
* @docs-private
*/
@Component({
standalone: true,
styleUrl: 'resets.css',
encapsulation: ViewEncapsulation.None,
template: '',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {'cdk-drag-resets-container': ''},
})
export class _ResetsLoader {}

/**
* Service that allows for drag-and-drop functionality to be attached to DOM elements.
*/
@Injectable({providedIn: 'root'})
export class DragDrop {
private _appRef = inject(ApplicationRef);
private _environmentInjector = inject(EnvironmentInjector);

constructor(
@Inject(DOCUMENT) private _document: any,
private _ngZone: NgZone,
Expand All @@ -72,7 +40,6 @@ export class DragDrop {
element: ElementRef<HTMLElement> | HTMLElement,
config: DragRefConfig = DEFAULT_CONFIG,
): DragRef<T> {
this._loadResets();
return new DragRef<T>(
element,
config,
Expand All @@ -96,23 +63,4 @@ export class DragDrop {
this._viewportRuler,
);
}

// TODO(crisbeto): abstract this away into something reusable.
/** Loads the CSS resets needed for the module to work correctly. */
private _loadResets() {
if (!activeApps.has(this._appRef)) {
activeApps.add(this._appRef);

const componentRef = createComponent(_ResetsLoader, {
environmentInjector: this._environmentInjector,
});

this._appRef.onDestroy(() => {
activeApps.delete(this._appRef);
if (activeApps.size === 0) {
componentRef.destroy();
}
});
}
}
}
2 changes: 1 addition & 1 deletion src/cdk/drag-drop/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export {CDK_DRAG_PARENT} from './drag-parent';
export * from './drag-events';
export * from './drag-utils';
export * from './drag-drop-module';
export * from './drag-drop-registry';
export {DragDropRegistry} from './drag-drop-registry';

export {CdkDropList} from './directives/drop-list';
export * from './directives/config';
Expand Down

0 comments on commit 69b6966

Please sign in to comment.