Skip to content

Commit abbfc8f

Browse files
authored
feat: fade in content only after final position is updated
2 parents 6c8f45e + 3520ef6 commit abbfc8f

File tree

9 files changed

+107
-71
lines changed

9 files changed

+107
-71
lines changed

projects/toppy/src/lib/host-container.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
import { ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, EmbeddedViewRef, Injectable, Injector, TemplateRef, ViewRef } from "@angular/core";
2-
import { ComponentInstance } from "./component-ins";
3-
import { CurrentOverlay } from "./current-overlay";
4-
import { HostArgs, HostContentType } from "./models";
5-
import { ToppyRef } from "./toppy-ref";
1+
import {
2+
ApplicationRef,
3+
ComponentFactory,
4+
ComponentFactoryResolver,
5+
ComponentRef,
6+
EmbeddedViewRef,
7+
Injectable,
8+
Injector,
9+
TemplateRef,
10+
ViewRef
11+
} from '@angular/core';
12+
import { ComponentInstance } from './component-ins';
13+
import { CurrentOverlay } from './current-overlay';
14+
import { HostArgs, HostContentType } from './models';
15+
import { ToppyRef } from './toppy-ref';
616

717
@Injectable()
818
export class HostContainer {
@@ -13,12 +23,16 @@ export class HostContainer {
1323
private _contentProps: { [key: string]: any };
1424
private _content: any;
1525
toppyRef: (id: string) => ToppyRef;
16-
constructor(private appRef: ApplicationRef, private compFacResolver: ComponentFactoryResolver, private injector: Injector) {}
26+
constructor(
27+
private appRef: ApplicationRef,
28+
private compFacResolver: ComponentFactoryResolver,
29+
private injector: Injector
30+
) {}
1731

1832
configure(
1933
{ contentType, content, props }: HostArgs = {
20-
content: "hello",
21-
contentType: "STRING"
34+
content: 'hello',
35+
contentType: 'STRING'
2236
}
2337
) {
2438
this._contentType = contentType;
@@ -53,18 +67,18 @@ export class HostContainer {
5367
let view: any = null;
5468
let viewEl = null;
5569
switch (this._contentType) {
56-
case "COMPONENT":
70+
case 'COMPONENT':
5771
view = this.createViewFromComponent(this._content, this._contentProps);
5872
this.appRef.attachView(view);
5973
viewEl = this.getComponentViewEl();
6074
break;
61-
case "TEMPLATEREF":
75+
case 'TEMPLATEREF':
6276
view = this.createViewFromTemplate(this._content);
6377
this.appRef.attachView(view);
6478
viewEl = view.rootNodes[0];
6579
break;
66-
case "STRING":
67-
const el = document.createElement("div");
80+
case 'STRING':
81+
const el = document.createElement('div');
6882
el.innerHTML = this._content;
6983
return el as any;
7084
default:

projects/toppy/src/lib/overlay-instance.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,26 @@ export class OverlayInstance implements OnDestroy {
2525
this._overlayID = overlayID;
2626
}
2727

28+
changePosition(newPosition) {
29+
this._position = newPosition;
30+
}
31+
32+
updatePositionConfig(positionConfig) {
33+
this._position.updateConfig(positionConfig);
34+
}
35+
2836
create() {
2937
this._containerEl = this._dom.createElement('div', {
3038
'data-overlay-id': this._overlayID,
3139
class: this.config.containerClass + ' ' + this._position.getClassName(),
32-
style: `left:0;position: fixed;top: 0;width: 100%;height: 100%;${!this.config.dismissOnDocumentClick ? 'pointer-events:none' : ''}`
40+
style: `left:0;position: fixed;top: 0;width: 100%;height: 100%;${
41+
!this.config.dismissOnDocumentClick ? 'pointer-events:none' : ''
42+
}`
3343
});
3444

3545
this._wrapperEl = this._dom.createElement('div', {
3646
class: this.config.wrapperClass,
37-
style: 'position: absolute;transition:all 0.2s ease;'
47+
style: 'position: absolute;visibility:hidden;opacity:0;transition:opacity 0.5s ease;'
3848
});
3949

4050
if (this.config.backdrop) {
@@ -84,13 +94,20 @@ export class OverlayInstance implements OnDestroy {
8494
this._containerEl = this._wrapperEl = this._backdropEl = this._viewEl = null;
8595
}
8696

87-
private _setPosition(): void {
97+
private _setPosition(show = false): void {
8898
const coords = this._position.getPositions(this._wrapperEl);
8999
this._dom.setPositions(this._wrapperEl, coords);
100+
101+
if (show) {
102+
this._wrapperEl.style.visibility = 'visible';
103+
this._wrapperEl.style.opacity = '1';
104+
}
90105
this._eventBus.post({ name: 'POSITION_UPDATED', data: null });
91106
}
92107

93108
private _watchPositionChange(): void {
94-
this._positionSubscription = this.computePosition.subscribe(_ => this._setPosition());
109+
this._positionSubscription = this.computePosition.subscribe(_ => {
110+
this._setPosition(true);
111+
});
95112
}
96113
}

projects/toppy/src/lib/position/default-position.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export class DefaultPosition extends Position {
55
constructor() {
66
super();
77
}
8+
updateConfig(newConfig) {
9+
return null;
10+
}
811
getPositions(hostElement?: HTMLElement): PositionCoOrds {
912
return {};
1013
}

projects/toppy/src/lib/position/fullscreen-position.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export class FullscreenPosition extends Position {
55
constructor() {
66
super();
77
}
8+
updateConfig(newConfig) {
9+
return null;
10+
}
811
getPositions(): PositionCoOrds {
912
return { top: 0, left: 0, width: '100%', height: '100%', position: 'fixed' };
1013
}

projects/toppy/src/lib/position/global-position.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@ export interface Config {
99
}
1010
export class GlobalPosition extends Position {
1111
private size;
12-
placement: InsidePlacement;
13-
hostWidth: string | number;
14-
hostHeight: string | number;
15-
offset: number;
16-
constructor({ placement = InsidePlacement.CENTER, hostWidth = 500, hostHeight = 500, offset = 0 }: Config) {
12+
private _config: Config = { placement: InsidePlacement.CENTER, hostWidth: 500, hostHeight: 500, offset: 0 };
13+
constructor(config: Config) {
1714
super();
18-
this.placement = placement;
19-
this.hostWidth = hostWidth;
20-
this.hostHeight = hostHeight;
21-
this.offset = offset;
15+
this._config = { ...this._config, ...config };
16+
}
17+
updateConfig(newConfig) {
18+
this._config = { ...this._config, ...newConfig };
2219
}
2320
getPositions(hostElement?: HTMLElement) {
2421
const host = hostElement.getBoundingClientRect();
@@ -27,7 +24,7 @@ export class GlobalPosition extends Position {
2724
width: (window as any).innerWidth,
2825
height: (window as any).innerHeight
2926
};
30-
switch (this.placement) {
27+
switch (this._config.placement) {
3128
case InsidePlacement.TOP:
3229
props = this.calculateTop(src, host);
3330
break;
@@ -58,27 +55,27 @@ export class GlobalPosition extends Position {
5855
default:
5956
break;
6057
}
61-
return { ...props, width: this.hostWidth, height: this.hostHeight, position: 'fixed' };
58+
return { ...props, width: this._config.hostWidth, height: this._config.hostHeight, position: 'fixed' };
6259
}
6360

6461
private calculateTop(src, host) {
65-
const top = this.offset;
62+
const top = this._config.offset;
6663
const left = (src.width - host.width) / 2;
6764
return { left, top };
6865
}
6966
private calculateBottom(src, host) {
70-
const bottom = this.offset;
67+
const bottom = this._config.offset;
7168
const left = (src.width - host.width) / 2;
7269
return { left, bottom };
7370
}
7471
private calculateLeft(src, host) {
7572
const top = (src.height - host.height) / 2;
76-
const left = this.offset;
73+
const left = this._config.offset;
7774
return { left, top };
7875
}
7976
private calculateRight(src, host) {
8077
const top = (src.height - host.height) / 2;
81-
const right = this.offset;
78+
const right = this._config.offset;
8279
return { right, top };
8380
}
8481
private calculateCenter(src, host) {
@@ -87,23 +84,23 @@ export class GlobalPosition extends Position {
8784
return { left, top };
8885
}
8986
private calculateTopLeft(src, host) {
90-
const top = this.offset;
91-
const left = this.offset;
87+
const top = this._config.offset;
88+
const left = this._config.offset;
9289
return { left, top };
9390
}
9491
private calculateTopRight(src, host) {
95-
const top = this.offset;
96-
const right = this.offset;
92+
const top = this._config.offset;
93+
const right = this._config.offset;
9794
return { right, top };
9895
}
9996
private calculateBottomLeft(src, host) {
100-
const bottom = this.offset;
101-
const left = this.offset;
97+
const bottom = this._config.offset;
98+
const left = this._config.offset;
10299
return { left, bottom };
103100
}
104101
private calculateBottomRight(src, host) {
105-
const bottom = this.offset;
106-
const right = this.offset;
102+
const bottom = this._config.offset;
103+
const right = this._config.offset;
107104
return { right, bottom };
108105
}
109106
}

projects/toppy/src/lib/position/position.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
export abstract class Position {
44
abstract getPositions(host: HTMLElement): any;
5+
abstract updateConfig(config: object): any;
56
getClassName(): string {
67
return this.constructor.name.replace('Position', '-position').toLocaleLowerCase();
78
}

projects/toppy/src/lib/position/relative-position.ts

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,33 @@ export interface Config {
1010
}
1111

1212
export class RelativePosition extends Position {
13-
src: HTMLElement;
14-
private placement: OutsidePlacement;
15-
private autoUpdate: boolean;
16-
private hostWidth: string | number;
17-
private hostHeight: string | number;
18-
constructor({
19-
src,
20-
placement = OutsidePlacement.TOP,
21-
autoUpdate = false,
22-
hostWidth = '100%',
23-
hostHeight = '100%'
24-
}: Config) {
13+
private _config: Config = {
14+
src: null,
15+
placement: OutsidePlacement.TOP,
16+
autoUpdate: false,
17+
hostWidth: '100%',
18+
hostHeight: '100%'
19+
};
20+
constructor(config: Config) {
2521
super();
26-
this.src = src;
27-
this.placement = placement;
28-
this.hostWidth = hostWidth;
29-
this.hostHeight = hostHeight;
30-
this.autoUpdate = autoUpdate;
22+
this._config = { ...this._config, ...config };
23+
}
24+
updateConfig(config) {
25+
this._config = { ...this._config, ...config };
3126
}
3227
getPositions(hostElement: HTMLElement): PositionCoOrds {
33-
const s = this.getCoords(this.src);
28+
const s = this.getCoords(this._config.src);
3429
const h = this.getCoords(hostElement);
3530

36-
if (this.hostWidth === '100%') {
37-
this.hostWidth = s.width;
31+
if (this._config.hostWidth === '100%') {
32+
this._config.hostWidth = s.width;
3833
}
3934

40-
if (this.hostHeight === '100%') {
41-
this.hostHeight = 'auto';
35+
if (this._config.hostHeight === '100%') {
36+
this._config.hostHeight = 'auto';
4237
}
43-
const props = this.calculatePos(this.placement, s, h);
44-
return { ...this.round(props), width: this.hostWidth, height: this.hostHeight };
38+
const props = this.calculatePos(this._config.placement, s, h);
39+
return { ...this.round(props), width: this._config.hostWidth, height: this._config.hostHeight };
4540
}
4641

4742
private getSize(el): { x: number; y: number } {
@@ -197,7 +192,7 @@ export class RelativePosition extends Position {
197192
if (!c) {
198193
return props;
199194
}
200-
if (this.autoUpdate && this.isOverflowed({ ...props, width: h.width, height: h.height })) {
195+
if (this._config.autoUpdate && this.isOverflowed({ ...props, width: h.width, height: h.height })) {
201196
return this.calculatePos(this.nextPosition(pos), s, h, false);
202197
}
203198

projects/toppy/src/lib/position/slide-position.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import { PositionCoOrds, SlidePlacement } from '../models';
22
import { Position } from './position';
33

44
export class SlidePosition extends Position {
5-
private placement: SlidePlacement;
6-
private width: string;
7-
constructor({ placement = SlidePlacement.LEFT, width = '30%' }: any) {
5+
private _config: { placement: SlidePlacement; width: string } = { placement: SlidePlacement.LEFT, width: '30%' };
6+
constructor(config) {
87
super();
9-
this.placement = placement;
10-
this.width = width;
8+
this._config = { ...this._config, ...config };
9+
}
10+
updateConfig(newConfig) {
11+
this._config = { ...this._config, ...newConfig };
1112
}
1213
getPositions(): PositionCoOrds {
13-
const props = this.placement === SlidePlacement.LEFT ? { left: 0 } : { right: 0 };
14-
return { ...props, top: 0, width: this.width, height: '100%', position: 'fixed' };
14+
const props = this._config.placement === SlidePlacement.LEFT ? { left: 0 } : { right: 0 };
15+
return { ...props, top: 0, width: this._config.width, height: '100%', position: 'fixed' };
1516
}
1617
}

projects/toppy/src/lib/toppy-ref.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class ToppyRef {
5454
map((e: any) => e.target),
5555
skipWhile(() => !this._config.dismissOnDocumentClick),
5656
filter(this._overlay.isHostElement.bind(this._overlay)),
57+
tap(_ => this._config.docClickCallback.call(null)),
5758
tap(() => this.close())
5859
);
5960
}
@@ -73,6 +74,10 @@ export class ToppyRef {
7374
);
7475
}
7576

77+
updatePosition(positionConfig) {
78+
this._overlay.updatePositionConfig(positionConfig);
79+
}
80+
7681
private _cleanup() {
7782
this._alive.next(true);
7883
}

0 commit comments

Comments
 (0)