Skip to content

Commit

Permalink
feat(popover, tooltip): add shown state api (#1998)
Browse files Browse the repository at this point in the history
  • Loading branch information
yggg committed Oct 7, 2019
1 parent d8689c1 commit 6dbce1d
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { NbDynamicOverlay } from './dynamic-overlay';
import { NbOverlayContent } from '../overlay-service';
import { NbDynamicOverlayChange, NbDynamicOverlayHandler } from './dynamic-overlay-handler';
import { NbTrigger, NbTriggerStrategy, NbTriggerStrategyBuilderService } from '../overlay-trigger';
import { NbOverlayConfig } from '@nebular/theme/components/cdk/overlay/mapping';

@Component({ template: '' })
export class NbDynamicOverlayMockComponent implements NbRenderableContainer {
Expand All @@ -43,18 +44,21 @@ export class NbMockDynamicOverlay {
_context: Object = {};
_content: NbOverlayContent;
_positionStrategy: NbAdjustableConnectedPositionStrategy;
_overlayConfig: NbOverlayConfig;

constructor() {}

create(componentType: Type<NbRenderableContainer>,
content: NbOverlayContent,
context: Object,
positionStrategy: NbAdjustableConnectedPositionStrategy) {
positionStrategy: NbAdjustableConnectedPositionStrategy,
overlayConfig: NbOverlayConfig) {

this.setContext(context);
this.setContent(content);
this.setComponent(componentType);
this.setPositionStrategy(positionStrategy);
this.setOverlayConfig(overlayConfig);

return this;
}
Expand All @@ -71,6 +75,10 @@ export class NbMockDynamicOverlay {
this._componentType = componentType;
}

setOverlayConfig(overlayConfig: NbOverlayConfig) {
this._overlayConfig = overlayConfig;
}

setContentAndContext(content: NbOverlayContent, context: Object) {
this._content = content;
this._context = context;
Expand Down Expand Up @@ -516,4 +524,15 @@ describe('dynamic-overlay-handler', () => {
expect(positionBuilder._position).toBe(NbPosition.LEFT);
expect(positionBuilder._adjustment).toBe(NbAdjustment.HORIZONTAL);
});

it('should set and update overlay config', () => {
let overlayConfig: NbOverlayConfig = { panelClass: 'custom-class' };

let dynamic = configure().overlayConfig(overlayConfig).build();
expect(dynamic._overlayConfig).toEqual(jasmine.objectContaining(overlayConfig));

overlayConfig = { panelClass: 'other-custom-class' };
dynamic = configure().overlayConfig(overlayConfig).rebuild();
expect(dynamic._overlayConfig).toEqual(jasmine.objectContaining(overlayConfig));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { NbRenderableContainer } from '../overlay-container';
import { NbOverlayContent } from '../overlay-service';
import { NbDynamicOverlay } from './dynamic-overlay';
import { NbOverlayConfig } from '../mapping';

export class NbDynamicOverlayChange extends SimpleChange {

Expand All @@ -33,6 +34,7 @@ export class NbDynamicOverlayHandler {
protected _position: NbPosition = NbPosition.TOP;
protected _adjustment: NbAdjustment = NbAdjustment.NOOP;
protected _offset: number = 15;
protected _overlayConfig: NbOverlayConfig = {};

protected dynamicOverlay: NbDynamicOverlay;
protected triggerStrategy: NbTriggerStrategy;
Expand Down Expand Up @@ -94,6 +96,12 @@ export class NbDynamicOverlayHandler {
return this;
}

overlayConfig(overlayConfig: NbOverlayConfig) {
this.changes.overlayConfig = new NbDynamicOverlayChange(this._overlayConfig, overlayConfig);
this._overlayConfig = overlayConfig;
return this;
}

build() {
if (!this._componentType || !this._host) {
throw Error(`NbDynamicOverlayHandler: at least 'componentType' and 'host' should be
Expand All @@ -104,6 +112,7 @@ export class NbDynamicOverlayHandler {
this._content,
this._context,
this.createPositionStrategy(),
this._overlayConfig,
);

this.connect();
Expand Down Expand Up @@ -139,6 +148,10 @@ export class NbDynamicOverlayHandler {
this.dynamicOverlay.setComponent(this._componentType);
}

if (this.isOverlayConfigUpdateRequired()) {
this.dynamicOverlay.setOverlayConfig(this._overlayConfig);
}

this.clearChanges();
return this.dynamicOverlay;
}
Expand Down Expand Up @@ -203,6 +216,10 @@ export class NbDynamicOverlayHandler {
return this.isComponentTypeUpdated();
}

private isOverlayConfigUpdateRequired(): boolean {
return this.isOverlayConfigUpdated();
}

protected isComponentTypeUpdated(): boolean {
return this.changes.componentType && this.changes.componentType.isChanged();
}
Expand Down Expand Up @@ -235,6 +252,10 @@ export class NbDynamicOverlayHandler {
return this.changes.offset && this.changes.offset.isChanged();
}

protected isOverlayConfigUpdated(): boolean {
return this.changes.overlayConfig && this.changes.overlayConfig.isChanged();
}

protected clearChanges() {
this.changes = {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,16 @@ describe('dynamic-overlay', () => {
expect(instance.content).toBe(newContent);
});

it('should set overlay config', () => {
const overlayConfig: NbOverlayConfig = { panelClass: 'additional-overlay-class' };
const createOverlaySpy = spyOn(overlayService, 'create').and.callThrough();

dynamicOverlay.setOverlayConfig(overlayConfig);
dynamicOverlay.show();

expect(createOverlaySpy).toHaveBeenCalledWith(jasmine.objectContaining(overlayConfig));
});

it('should return container', () => {
dynamicOverlay.show();
expect(dynamicOverlay.getContainer()).toBe(container as any);
Expand Down Expand Up @@ -319,29 +329,25 @@ describe('dynamic-overlay', () => {
});

it('should set component', () => {
const detachSpy = spyOn(ref, 'detach').and.callThrough();
const disposeSpy = spyOn(ref, 'dispose').and.callThrough();
const attachSpy = spyOn(ref, 'attach').and.callThrough();
const hasAttacheSpy = spyOn(ref, 'hasAttached');

dynamicOverlay.setComponent(NbDynamicOverlayMock2Component);

expect(detachSpy).toHaveBeenCalledTimes(0);
expect(disposeSpy).toHaveBeenCalledTimes(0);
expect(attachSpy).toHaveBeenCalledTimes(0);

dynamicOverlay.show();
hasAttacheSpy.and.returnValue(true);

expect(ref.portal.component).toBe(NbDynamicOverlayMock2Component);
expect(detachSpy).toHaveBeenCalledTimes(0);
expect(disposeSpy).toHaveBeenCalledTimes(0);
expect(attachSpy).toHaveBeenCalledTimes(1);

dynamicOverlay.setComponent(NbDynamicOverlayMockComponent);

expect(ref.portal.component).toBe(NbDynamicOverlayMockComponent);
expect(detachSpy).toHaveBeenCalledTimes(1);
expect(disposeSpy).toHaveBeenCalledTimes(1);
expect(attachSpy).toHaveBeenCalledTimes(2);

Expand All @@ -350,7 +356,6 @@ describe('dynamic-overlay', () => {

dynamicOverlay.setComponent(NbDynamicOverlayMock2Component);

expect(detachSpy).toHaveBeenCalledTimes(3);
expect(disposeSpy).toHaveBeenCalledTimes(2);
expect(attachSpy).toHaveBeenCalledTimes(2);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentFactoryResolver, ComponentRef, Injectable, NgZone, Type } from '@angular/core';
import { filter, takeUntil, takeWhile } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { filter, takeUntil, takeWhile, distinctUntilChanged } from 'rxjs/operators';
import { Subject, BehaviorSubject, Observable } from 'rxjs';

import {
NbAdjustableConnectedPositionStrategy,
Expand All @@ -9,7 +9,7 @@ import {

import { NbRenderableContainer } from '../overlay-container';
import { createContainer, NbOverlayContent, NbOverlayService, patch } from '../overlay-service';
import { NbOverlayRef, NbOverlayContainer } from '../mapping';
import { NbOverlayRef, NbOverlayContainer, NbOverlayConfig } from '../mapping';

export interface NbDynamicOverlayController {
show();
Expand All @@ -27,14 +27,20 @@ export class NbDynamicOverlay {
protected context: Object = {};
protected content: NbOverlayContent;
protected positionStrategy: NbAdjustableConnectedPositionStrategy;
protected overlayConfig: NbOverlayConfig = {};

protected positionStrategyChange$ = new Subject();
protected isShown$ = new BehaviorSubject<boolean>(false);
protected alive = true;

get isAttached(): boolean {
return this.ref && this.ref.hasAttached();
}

get isShown(): Observable<boolean> {
return this.isShown$.pipe(distinctUntilChanged());
}

constructor(
protected overlay: NbOverlayService,
protected componentFactoryResolver: ComponentFactoryResolver,
Expand All @@ -45,11 +51,13 @@ export class NbDynamicOverlay {
create(componentType: Type<NbRenderableContainer>,
content: NbOverlayContent,
context: Object,
positionStrategy: NbAdjustableConnectedPositionStrategy) {
positionStrategy: NbAdjustableConnectedPositionStrategy,
overlayConfig: NbOverlayConfig = {}) {

this.setContentAndContext(content, context);
this.setComponent(componentType);
this.setPositionStrategy(positionStrategy);
this.setOverlayConfig(overlayConfig);

return this;
}
Expand Down Expand Up @@ -82,11 +90,10 @@ export class NbDynamicOverlay {
this.componentType = componentType;

// in case the component is shown we recreate it and show it back
if (this.ref && this.isAttached) {
this.dispose();
const wasAttached = this.isAttached;
this.disposeOverlayRef();
if (wasAttached) {
this.show();
} else if (this.ref && !this.isAttached) {
this.dispose();
}
}

Expand All @@ -108,6 +115,16 @@ export class NbDynamicOverlay {
}
}

setOverlayConfig(overlayConfig: NbOverlayConfig) {
this.overlayConfig = overlayConfig;

const wasAttached = this.isAttached;
this.disposeOverlayRef();
if (wasAttached) {
this.show();
}
}

show() {
if (!this.ref) {
this.createOverlay();
Expand All @@ -120,6 +137,8 @@ export class NbDynamicOverlay {
this.disposeOverlayRef();
return this.show();
}

this.isShown$.next(true);
}

hide() {
Expand All @@ -129,6 +148,8 @@ export class NbDynamicOverlay {

this.ref.detach();
this.container = null;

this.isShown$.next(false);
}

toggle() {
Expand All @@ -143,6 +164,8 @@ export class NbDynamicOverlay {
this.alive = false;
this.hide();
this.disposeOverlayRef();
this.isShown$.complete();
this.positionStrategyChange$.complete();
}

getContainer() {
Expand All @@ -153,6 +176,7 @@ export class NbDynamicOverlay {
this.ref = this.overlay.create({
positionStrategy: this.positionStrategy,
scrollStrategy: this.overlay.scrollStrategies.reposition(),
...this.overlayConfig,
});
this.updatePositionWhenStable();
}
Expand Down
Loading

0 comments on commit 6dbce1d

Please sign in to comment.