Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/overlay #679

Merged
merged 4 commits into from
Sep 10, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"@angular/cli": "^6.0.0",
"@angular/compiler-cli": "6.0.0",
"@angular/language-service": "6.0.0",
"@angular/cdk": "6.0.0",
"@types/gulp": "3.8.36",
"@types/highlight.js": "9.12.2",
"@types/jasmine": "2.8.3",
Expand Down
3 changes: 3 additions & 0 deletions scripts/gulp/tasks/bundle/rollup-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const ROLLUP_GLOBALS = {
'@angular/core/testing': 'ng.core.testing',
'@angular/common/testing': 'ng.common.testing',
'@angular/common/http/testing': 'ng.common.http.testing',
'@angular/cdk/overlay': 'ng.cdk.overlay',
'@angular/cdk/platform': 'ng.cdk.platform',
'@angular/cdk/portal': 'ng.cdk.portal',


// RxJS dependencies
Expand Down
17 changes: 17 additions & 0 deletions src/framework/theme/components/cdk/adapter/adapter.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { OverlayContainer, ScrollDispatcher } from '@angular/cdk/overlay';

import { NbOverlayContainerAdapter } from './overlay-container-adapter';
import { NbScrollDispatcherAdapter } from './scroll-dispatcher-adapter';
import { NbViewportRulerAdapter } from './viewport-ruler-adapter';


@NgModule({
providers: [
NbViewportRulerAdapter,
{ provide: OverlayContainer, useClass: NbOverlayContainerAdapter },
{ provide: ScrollDispatcher, useClass: NbScrollDispatcherAdapter },
],
})
export class NbAdapterModule {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NbCdkAdapter maybe? As NbAdapterModule is too abstract to me

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';

import { NbOverlayContainer } from '../overlay/mapping';


@Injectable()
export class NbOverlayContainerAdapter extends NbOverlayContainer {
protected _createContainer(): void {
const container = this._document.createElement('div');

container.classList.add('cdk-overlay-container');
this._document.querySelector('nb-layout').appendChild(container);
this._containerElement = container;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Injectable, NgZone } from '@angular/core';
import { CdkScrollable, ScrollDispatcher } from '@angular/cdk/overlay';
import { Observable } from 'rxjs';

import { NbPlatform } from '../overlay/mapping';
import { NbLayoutScrollService } from '../../../services/scroll.service';

@Injectable()
export class NbScrollDispatcherAdapter extends ScrollDispatcher {
constructor(_ngZone: NgZone, _platform: NbPlatform, protected scrollService: NbLayoutScrollService) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why _?

super(_ngZone, _platform);
}

scrolled(auditTimeInMs?: number): Observable<CdkScrollable | void> {
return this.scrollService.onScroll();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Injectable, NgZone } from '@angular/core';
import { ViewportRuler } from '@angular/cdk/overlay';
import { map } from 'rxjs/operators';

import { NbPlatform } from '../overlay/mapping';
import { NbLayoutRulerService } from '../../../services/ruler.service';
import { NbLayoutScrollService, NbScrollPosition } from '../../../services/scroll.service';


@Injectable()
export class NbViewportRulerAdapter extends ViewportRuler {
constructor(_platform: NbPlatform, ngZone: NgZone,
protected ruler: NbLayoutRulerService,
protected scroll: NbLayoutScrollService) {
super(_platform, ngZone);
}

getViewportSize(): Readonly<{ width: number; height: number; }> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add a comment why this is a synchronous operation

let res;
this.ruler.getDimensions()
.pipe(map(dimensions => ({ width: dimensions.clientWidth, height: dimensions.clientHeight })))
.subscribe(rect => res = rect);
return res;
}

getViewportScrollPosition(): { left: number; top: number } {
let res;
this.scroll.getPosition()
.pipe(map((position: NbScrollPosition) => ({ top: position.y, left: position.x })))
.subscribe(position => res = position);
return res;
}
}
2 changes: 2 additions & 0 deletions src/framework/theme/components/cdk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './overlay/mapping';
export * from './overlay';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@mixin nb-overlay-theme {
.overlay-backdrop {
background: rgba(0, 0, 0, 0.288);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a theme variable to me

}
}
6 changes: 6 additions & 0 deletions src/framework/theme/components/cdk/overlay/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './overlay.module';
export * from './overlay';
export * from './overlay-position';
export * from './overlay-container';
export * from './overlay-trigger';
export * from './mapping';
82 changes: 82 additions & 0 deletions src/framework/theme/components/cdk/overlay/mapping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Directive, Injectable, NgModule, TemplateRef, ViewContainerRef } from '@angular/core';
import { CdkPortal, ComponentPortal, Portal, PortalModule, TemplatePortal } from '@angular/cdk/portal';
import {
ComponentType,
ConnectedOverlayPositionChange,
ConnectedPosition,
ConnectionPositionPair,
FlexibleConnectedPositionStrategy,
GlobalPositionStrategy,
Overlay,
OverlayContainer,
OverlayModule,
OverlayPositionBuilder,
OverlayRef,
PositionStrategy,
} from '@angular/cdk/overlay';
import { Platform } from '@angular/cdk/platform';


@Directive({ selector: '[nbPortal]' })
export class NbPortalDirective extends CdkPortal {
}

@Injectable()
export class NbOverlayService extends Overlay {
}

@Injectable()
export class NbPlatform extends Platform {
}

@Injectable()
export class NbOverlayPositionBuilder extends OverlayPositionBuilder {
}

export class NbComponentPortal<T = any> extends ComponentPortal<T> {
}

export class NbTemplatePortal<T = any> extends TemplatePortal<T> {
constructor(template: TemplateRef<T>, viewContainerRef?: ViewContainerRef, context?: T) {
super(template, viewContainerRef, context);
}
}

export class NbOverlayContainer extends OverlayContainer {
}

export class NbFlexibleConnectedPositionStrategy extends FlexibleConnectedPositionStrategy {
}

export type NbPortal<T = any> = Portal<T>;
export type NbOverlayRef = OverlayRef;
export type NbComponentType<T = any> = ComponentType<T>;
export type NbGlobalPositionStrategy = GlobalPositionStrategy;
export type NbPositionStrategy = PositionStrategy;
export type NbConnectedPosition = ConnectedPosition;
export type NbConnectedOverlayPositionChange = ConnectedOverlayPositionChange;
export type NbConnectionPositionPair = ConnectionPositionPair;

const CDK_MODULES = [OverlayModule, PortalModule];

const CDK_PROVIDERS = [
NbOverlayService,
NbPlatform,
NbOverlayPositionBuilder,
];

/**
* This module helps us to keep all angular/cdk deps inside our cdk module via providing aliases.
* Approach will help us move cdk in separate npm package and refactor nebular/theme code.
* */
@NgModule({
imports: [...CDK_MODULES],
exports: [
...CDK_MODULES,
NbPortalDirective,
],
declarations: [NbPortalDirective],
providers: [...CDK_PROVIDERS],
})
export class NbCdkMappingModule {
}
90 changes: 90 additions & 0 deletions src/framework/theme/components/cdk/overlay/overlay-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { ChangeDetectorRef, Component, HostBinding, Input, TemplateRef, Type, ViewChild } from '@angular/core';
import { NgComponentOutlet } from '@angular/common';

import { NbPosition } from './overlay-position';

export abstract class NbPositionedContainer {
@Input() position: NbPosition;

@HostBinding('class.top')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make this class more specific? That would be safer

get top(): boolean {
return this.position === NbPosition.TOP
}

@HostBinding('class.right')
get right(): boolean {
return this.position === NbPosition.RIGHT
}

@HostBinding('class.bottom')
get bottom(): boolean {
return this.position === NbPosition.BOTTOM
}

@HostBinding('class.left')
get left(): boolean {
return this.position === NbPosition.LEFT
}
}

@Component({
selector: 'nb-overlay-container',
template: `
<ng-container *ngIf="isTemplate">
<ng-container *ngTemplateOutlet="content; context: context"></ng-container>
</ng-container>
<ng-container *ngIf="isComponent" [ngComponentOutlet]="content"></ng-container>
<ng-container *ngIf="isPrimitive">
<div class="primitive-overlay">{{content}}</div>
</ng-container>
`,
})
export class NbOverlayContainerComponent {
@Input()
content: any;

@Input()
context: Object;

constructor(private cd: ChangeDetectorRef) {
}

@ViewChild(NgComponentOutlet)
set componentOutlet(el) {
if (this.isComponent) {
Object.assign(el._componentRef.instance, this.context);
/**
* Change detection have to performed here, because another way applied context
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have -> has to be

* will be rendered on the next change detection loop and
* we'll have incorrect positioning. Because rendered component may change its size
* based on the context.
* */
this.cd.detectChanges();
}
}

/**
* Check that content is a TemplateRef.
*
* @return boolean
* */
get isTemplate(): boolean {
return this.content instanceof TemplateRef;
}

/**
* Check that content is an angular component.
*
* @return boolean
* */
get isComponent(): boolean {
return this.content instanceof Type;
}

/**
* Check that if content is not a TemplateRef or an angular component it means a primitive.
* */
get isPrimitive(): boolean {
return !this.isTemplate && !this.isComponent;
}
}
Loading