Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
feat(overlay): Adds pinnedChanged output and isOverlayPinned property.
Browse files Browse the repository at this point in the history
  • Loading branch information
rowa-audil authored and thomaspink committed Jun 2, 2021
1 parent 37e5cab commit bbadf67
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 18 deletions.
32 changes: 21 additions & 11 deletions libs/barista-components/overlay/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ dismissed as well.
| `dtOverlay` | `TemplateRef`  | - | Overlay pane containing the content.  |
| `dtOverlayConfig` | `DtOverlayConfig`  | - | Overlay configuration; see properties below.  |

## Outputs

| Name | Type | Description |
| --------------- | -------------------- | --------------------------------------------------------- |
| `pinnedChanged` | `EventEmitter<void>` | Will notify by firing every time the pinned state changes |

### Methods

| Name | Type | Description |
Expand All @@ -72,24 +78,27 @@ constructor(private _dtOverlay: DtOverlay) {}

The `DtOverlay` service has the following two methods:

| Method | Parameters | Return value | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `create()` | `origin: ElementRef`<br>`componentOrTemplateRef: ComponentType<T> \| TemplateRef<T>`<br>`config?: DtOverlayConfig` | `DtOverlayRef` (see details below) | Creates a overlay connected to the origin and containing the given component or templateRef. |
| `dismiss()` |  - |  `void` |  Dismisses the currently open overlay. This method can be used if the overlay needs to be dismissed programatically. |
| Method | Parameters | Return value | Description |
| ----------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `create()` | `origin: DtOverlayOrigin`<br>`componentOrTemplateRef: ComponentType<T> \| TemplateRef<T>`<br>`config?: DtOverlayConfig` | `DtOverlayRef` (see details below) | Creates a overlay connected to the origin and containing the given component or templateRef. |
| `dismiss()` |  - |  `void` |  Dismisses the currently open overlay. This method can be used if the overlay needs to be dismissed programatically. |

<ba-live-example name="DtExampleOverlayProgrammatic"></ba-live-example>

### DtOverlayRef
## DtOverlayRef

The DtOverlay service `create` method returns an instance of `DtOverlayRef`.
This reference can be used to perform updates on the position, pinning the
overlay or dismissing it.

| Method | Parameters | Return value | Description |
| ------------------ | ---------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pin()` | `value: boolean` |  `void` | Either pins or unpins the overlay.  |
| `dismiss()` | - |  `void` | Dismisses the overlay.  |
| `updatePosition()` | `offsetX: number` <br> `offsetY: number` |  `void` | Sets an offset to the overlay's position. Can be used e.g. in a mousemove eventhandler to update the overlays position depending on the MouseEvent.  |
### Methods

| Method | Parameters | Return value | Description |
| ------------------------- | ---------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pin()` | `value: boolean` |  `void` | Either pins or unpins the overlay.  |
| `dismiss()` | - |  `void` | Dismisses the overlay.  |
| `updatePosition()` | `offsetX: number` <br> `offsetY: number` |  `void` | Sets an offset to the overlay's position. Can be used e.g. in a mousemove eventhandler to update the overlays position depending on the MouseEvent.  |
| `updateImplicitContext()` | `data: any` | `void` | Updates the implicit context on the template portal if one exists |

## DtOverlayConfig

Expand All @@ -99,9 +108,10 @@ the following properties:

| Name | Type | Default | Description |
| -------------------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pinnable` | `boolean` | `-` | enables pinning of the overlay on click or by keyboard when the trigger is focused. |
| `pinnable` | `boolean` | - | enables pinning of the overlay on click or by keyboard when the trigger is focused. |
| `originY` | `center \| edge` | `center` | The originY defines the vertical attachment point for the overlay. By default `center` is set. `edge` defines that the vertical attachment point is set to the bottom edge if the overlay fits below the origin element and the top edge otherwise. |
| `movementConstraint` |  `xAxis \| yAxis` | - | The movementConstraint locks the movement of the overlay to a given axis. No constraint is set by default. |
| `data` | `any` | - | The data passed to the overlay as the $implicit context object |

## Fullscreen support

Expand Down
8 changes: 7 additions & 1 deletion libs/barista-components/overlay/src/overlay-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export class DtOverlayRef<T> {
return coerceBooleanProperty(this._config.pinnable);
}

/** Subject for notifying the user that the overlays pinned state has changed */
pinnedChanged = new Subject<boolean>();

/** Subject for notifying the user that the overlay has finished exiting. */
private readonly _afterExit = new Subject<void>();

Expand Down Expand Up @@ -86,9 +89,10 @@ export class DtOverlayRef<T> {

/** Pins the overlay */
pin(value: boolean): void {
if (!this._config.pinnable) {
if (!this._config.pinnable || this._pinned === value) {
return;
}

this._pinned = value;
if (this._overlayRef.backdropElement) {
if (value) {
Expand All @@ -113,6 +117,7 @@ export class DtOverlayRef<T> {
this._backDropClickSub.unsubscribe();
}
}
this.pinnedChanged.next(value);
}

/** Update the implicit context on the template portal if one exists. */
Expand All @@ -129,6 +134,7 @@ export class DtOverlayRef<T> {
this._disposableFns.forEach((fn) => {
fn();
});
this.pinnedChanged.next(false);
}

/**
Expand Down
55 changes: 55 additions & 0 deletions libs/barista-components/overlay/src/overlay-trigger.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,55 @@ describe('DtOverlayTrigger', () => {
expect(overlay).not.toBeNull();
}));

it('should fire pinnedChanged when pinned', fakeAsync(() => {
fixture.componentInstance.config = { pinnable: true };
fixture.detectChanges();
initOverlay(fixture, trigger);

dispatchMouseEvent(trigger, 'click');
fixture.detectChanges();
flush();

expect(fixture.componentInstance.pinned).toBeTruthy();
}));

it('should not fire pinnedChanged on subsequent mouseenter', fakeAsync(() => {
fixture.componentInstance.config = { pinnable: true };
fixture.detectChanges();
initOverlay(fixture, trigger);

dispatchMouseEvent(trigger, 'click');
fixture.detectChanges();
flush();

expect(fixture.componentInstance.pinned).toBeTruthy();

dispatchMouseEvent(trigger, 'mouseleave');
dispatchMouseEvent(trigger, 'mouseenter');
dispatchMouseEvent(trigger, 'mousemove');
fixture.detectChanges();

expect(fixture.componentInstance.pinned).toBeTruthy();
}));

it('should fire pinnedChanged when pinned then overlay is dismissed', fakeAsync(() => {
fixture.componentInstance.config = { pinnable: true };
fixture.detectChanges();
initOverlay(fixture, trigger);

dispatchMouseEvent(trigger, 'click');
fixture.detectChanges();
flush();

expect(fixture.componentInstance.pinned).toBeTruthy();

fixture.componentInstance.showTrigger = false;
fixture.detectChanges();
flush();

expect(fixture.componentInstance.pinned).toBeFalsy();
}));

it('should stay pinned on subsequent mouseenter', fakeAsync(() => {
fixture.componentInstance.config = { pinnable: true };
fixture.detectChanges();
Expand Down Expand Up @@ -337,6 +386,7 @@ function getOverlayPane(overlayContainerElement: HTMLElement): HTMLElement {
[dtOverlay]="overlay"
[dtOverlayConfig]="config"
[disabled]="disabled"
(pinnedChanged)="handlePinnedChanged($event)"
>
trigger
</div>
Expand All @@ -348,4 +398,9 @@ class TestComponent {
config: DtOverlayConfig = {};
disabled = false;
showTrigger = true;
pinned: boolean = false;

handlePinnedChanged(event: boolean): void {
this.pinned = event;
}
}
29 changes: 26 additions & 3 deletions libs/barista-components/overlay/src/overlay-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import {
Attribute,
Directive,
ElementRef,
EventEmitter,
Input,
NgZone,
OnDestroy,
Output,
TemplateRef,
} from '@angular/core';
import { Subscription, fromEvent } from 'rxjs';
import { Subscription, fromEvent, EMPTY } from 'rxjs';

import {
CanDisable,
Expand Down Expand Up @@ -84,6 +86,17 @@ export class DtOverlayTrigger<T>
this._config = value;
}

/** Emits on every pinned state change */
@Output()
pinnedChanged = new EventEmitter<boolean>();

/** Whether the underlying overlay is pinned or not */
get isOverlayPinned(): boolean | undefined {
return this._dtOverlayRef?.pinned;
}

private _pinnedChangedSubscribtion: Subscription = EMPTY.subscribe();

constructor(
private elementRef: ElementRef<Element>,
private _dtOverlayService: DtOverlay,
Expand All @@ -101,7 +114,7 @@ export class DtOverlayTrigger<T>
ngOnDestroy(): void {
this._moveSub.unsubscribe();
if (this._dtOverlayRef) {
this._dtOverlayRef.dismiss();
this._dismissOverlay();
}
}

Expand Down Expand Up @@ -133,7 +146,7 @@ export class DtOverlayTrigger<T>
event.stopPropagation();
this._moveSub.unsubscribe();
if (this._dtOverlayRef && !this._dtOverlayRef.pinned) {
this._dtOverlayRef.dismiss();
this._dismissOverlay();
}
}

Expand Down Expand Up @@ -190,6 +203,16 @@ export class DtOverlayTrigger<T>
this._dtOverlayRef = null;
});
this._dtOverlayRef = ref;
this._pinnedChangedSubscribtion = this._dtOverlayRef.pinnedChanged.subscribe(
(pinnedChanged) => {
this.pinnedChanged.emit(pinnedChanged);
},
);
}
}

private _dismissOverlay(): void {
this._dtOverlayRef?.dismiss();
this._pinnedChangedSubscribtion.unsubscribe();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<span [dtOverlay]="overlay" style="cursor: pointer" [dtOverlayConfig]="config">
<span
[dtOverlay]="overlay"
style="cursor: pointer"
[dtOverlayConfig]="config"
(pinnedChanged)="handle($event)"
>
Hover me
</span>
<ng-template #overlay>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
* limitations under the License.
*/

import { Component } from '@angular/core';
import { Component, ViewChild } from '@angular/core';

import { DtOverlayConfig } from '@dynatrace/barista-components/overlay';
import {
DtOverlayConfig,
DtOverlay,
} from '@dynatrace/barista-components/overlay';

@Component({
selector: 'dt-example-overlay-default',
Expand All @@ -27,4 +30,10 @@ export class DtExampleOverlayDefault {
pinnable: true,
originY: 'center',
};

@ViewChild(DtOverlay, { static: false }) overlay;

handle(event): void {
console.log(event, this.overlay);
}
}

0 comments on commit bbadf67

Please sign in to comment.