Skip to content

Commit 79fc1a5

Browse files
committed
feat: add position classes to warpper element
1 parent 6120384 commit 79fc1a5

14 files changed

+163
-40
lines changed

projects/toppy/src/lib/models.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { TemplateRef } from '@angular/core';
22
import { ToppyPosition } from './position/position';
33

4-
export interface PositionCoOrds {
4+
export interface PositionMeta {
55
top?: number;
66
left?: number;
77
bottom?: number;
88
right?: number;
99
height?: number | string;
1010
width?: number | string;
1111
position?: string;
12+
extra?: string;
1213
}
1314

1415
enum p {
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { PositionCoOrds } from '../models';
1+
import { PositionMeta } from '../models';
22
import { ToppyPosition } from './position';
33

44
export class FullscreenPosition extends ToppyPosition {
55
constructor() {
66
super();
77
}
8-
getPositions(): PositionCoOrds {
8+
getPositions(): PositionMeta {
99
return { top: 0, left: 0, width: '100%', height: '100%', position: 'fixed' };
1010
}
1111
}

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ export class GlobalPosition extends ToppyPosition {
3535
}
3636

3737
const props = this.calc(this.config.placement, src, host);
38-
return { ...props, width: this.config.width, height: this.config.height, position: 'fixed' };
38+
return {
39+
...props,
40+
width: this.config.width,
41+
height: this.config.height,
42+
position: 'fixed',
43+
extra: this.config.placement
44+
};
3945
}
4046
private getPercentageToCssPx(max, percentage: string): string {
4147
let number = Number(percentage.slice(0, -1));

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

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OutsidePlacement, PositionCoOrds } from '../models';
1+
import { OutsidePlacement, PositionMeta } from '../models';
22
import { Bus } from '../utils';
33
import { ToppyPosition } from './position';
44

@@ -28,7 +28,7 @@ export class RelativePosition extends ToppyPosition {
2828
if (this.config.autoUpdate) this.listenDrag(tid);
2929
}
3030

31-
getPositions(hostElement: HTMLElement): PositionCoOrds {
31+
getPositions(hostElement: HTMLElement): Pick<PositionMeta, any> {
3232
const s = this.getCoords(this.config.src);
3333
const h = this.getCoords(hostElement);
3434

@@ -45,11 +45,11 @@ export class RelativePosition extends ToppyPosition {
4545
if (typeof this.config.width === 'number') {
4646
h.width = this.config.width;
4747
}
48-
const props = this.calculatePos(this.config.placement, s, h);
49-
return { ...this.round(props), width: this.config.width, height: this.config.height };
48+
const { pos, props } = this.calculatePos(this.config.placement, s, h);
49+
return { ...this.round(props), width: this.config.width, height: this.config.height, extra: pos };
5050
}
5151

52-
private getCoords(elem: HTMLElement): PositionCoOrds {
52+
private getCoords(elem: HTMLElement): PositionMeta {
5353
const box: any = elem.getBoundingClientRect();
5454

5555
return {
@@ -104,16 +104,14 @@ export class RelativePosition extends ToppyPosition {
104104
return this.calc(pos, s, h);
105105
}
106106

107-
private calculatePos(pos, s, h, c = true): object {
107+
private calculatePos(pos, s, h, c = true): { [x: string]: any } {
108108
const props = this.getProps(pos, s, h);
109-
if (!c) {
110-
return props;
111-
}
112-
if (this.config.autoUpdate && this.isOverflowed({ ...props, width: h.width, height: h.height })) {
109+
110+
if (c && this.config.autoUpdate && this.isOverflowed({ ...props, width: h.width, height: h.height })) {
113111
return this.calculatePos(this.nextPosition(pos), s, h, false);
114112
}
115113

116-
return props;
114+
return { pos, props };
117115
}
118116

119117
private isOverflowed(props: { [x: string]: any }): boolean {
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PositionCoOrds, SlidePlacement } from '../models';
1+
import { PositionMeta, SlidePlacement } from '../models';
22
import { ToppyPosition } from './position';
33

44
export class SlidePosition extends ToppyPosition {
@@ -7,8 +7,15 @@ export class SlidePosition extends ToppyPosition {
77
super();
88
this.config = { ...this.config, ...config };
99
}
10-
getPositions(): PositionCoOrds {
10+
getPositions(): PositionMeta {
1111
const props = this.config.placement === SlidePlacement.LEFT ? { left: 0 } : { right: 0 };
12-
return { ...props, top: 0, width: this.config.width, height: '100%', position: 'fixed' };
12+
return {
13+
...props,
14+
top: 0,
15+
width: this.config.width,
16+
height: '100%',
17+
position: 'fixed',
18+
extra: this.config.placement
19+
};
1320
}
1421
}

projects/toppy/src/lib/template.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div class="t-backdrop" *ngIf="config.backdrop"></div>
2-
<div class="t-wrapper" [ngClass]="config.wrapperClass" #wrapperEl>
2+
<div class="t-wrapper" [ngClass]="config.wrapperClass" [class]="extra" #wrapperEl>
33
<ng-container [ngSwitch]="content.type">
44
<ng-container *ngSwitchCase="'s'">
55
<div [class]="content.props.class">{{ content.data }}</div>

projects/toppy/src/lib/toppy.component.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class ToppyComponent implements OnInit, AfterViewInit, OnDestroy {
3333
tid: TID;
3434
el: HTMLElement | any;
3535
wrapperEl: HTMLElement | any;
36-
36+
extra: string;
3737
private die: Subject<1> = new Subject();
3838

3939
constructor(private inj: Injector, private cd: ChangeDetectorRef, private elRef: ElementRef) {}
@@ -91,7 +91,11 @@ export class ToppyComponent implements OnInit, AfterViewInit, OnDestroy {
9191
}
9292

9393
private setPos(): void {
94-
const coords = this.position.getPositions(this.wrapperEl);
94+
const { extra, ...coords } = this.position.getPositions(this.wrapperEl);
95+
if (this.extra !== extra) {
96+
this.extra = extra;
97+
this.cd.detectChanges();
98+
}
9599
Object.assign(coords, { visibility: 'visible', opacity: '1' });
96100
this.wrapperEl.style = toCss(coords);
97101
Bus.send(this.tid, 't_posupdate');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { FullscreenPosition } from '../../lib/position';
2+
3+
describe('@ FullscreenPosition', () => {
4+
describe('#getPositions', () => {
5+
it('should return proper position', () => {
6+
const slidePos = new FullscreenPosition();
7+
expect(slidePos.getPositions()).toEqual({
8+
top: 0,
9+
left: 0,
10+
width: '100%',
11+
height: '100%',
12+
position: 'fixed'
13+
});
14+
});
15+
});
16+
});

projects/toppy/src/tests/positions/global-position.spec.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ describe('@ GlobalPosition', () => {
6565
top: 0,
6666
width: 4,
6767
height: 10,
68-
position: 'fixed'
68+
position: 'fixed',
69+
extra: InsidePlacement.TOP
6970
});
7071
});
7172
it('when exact width and height is provided in negative px', () => {
@@ -79,7 +80,8 @@ describe('@ GlobalPosition', () => {
7980
top: 0,
8081
width: 4,
8182
height: 10,
82-
position: 'fixed'
83+
position: 'fixed',
84+
extra: InsidePlacement.TOP
8385
});
8486
});
8587
it('when exact width and height is provided in percentage', () => {
@@ -93,7 +95,8 @@ describe('@ GlobalPosition', () => {
9395
top: 0,
9496
width: `calc(${ww}px - 50%)`,
9597
height: `calc(${wh}px - 50%)`,
96-
position: 'fixed'
98+
position: 'fixed',
99+
extra: InsidePlacement.TOP
97100
});
98101
});
99102
it('when exact width and height is provided in higher percentage', () => {
@@ -107,7 +110,8 @@ describe('@ GlobalPosition', () => {
107110
top: 0,
108111
width: `calc(${ww}px - 0%)`,
109112
height: `calc(${wh}px - 0%)`,
110-
position: 'fixed'
113+
position: 'fixed',
114+
extra: InsidePlacement.TOP
111115
});
112116
});
113117
it('when no width and height is provided', () => {
@@ -117,7 +121,8 @@ describe('@ GlobalPosition', () => {
117121
top: 0,
118122
width: 100,
119123
height: 100,
120-
position: 'fixed'
124+
position: 'fixed',
125+
extra: InsidePlacement.TOP_RIGHT
121126
});
122127
});
123128
});

projects/toppy/src/tests/positions/relative-position.spec.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ describe('@ RelativePosition', () => {
6161
height: 450
6262
};
6363
expect((relPos as any).calculatePos(OutsidePlacement.TOP, srcCoords, hostElCoords, true)).toEqual({
64-
left: 8 + (srcCoords.width - 4) / 2,
65-
top: srcCoords.top + srcCoords.height
64+
props: {
65+
left: 8 + (srcCoords.width - 4) / 2,
66+
top: srcCoords.top + srcCoords.height
67+
},
68+
pos: OutsidePlacement.BOTTOM
6669
});
6770
});
6871
it('should not switch if it is false', () => {
@@ -78,8 +81,11 @@ describe('@ RelativePosition', () => {
7881
height: 150
7982
};
8083
expect((relPos as any).calculatePos(OutsidePlacement.TOP, srcCoords, hostElCoords, true)).toEqual({
81-
left: 8 + (srcCoords.width - 4) / 2,
82-
top: srcCoords.top - 150
84+
props: {
85+
left: 8 + (srcCoords.width - 4) / 2,
86+
top: srcCoords.top - 150
87+
},
88+
pos: OutsidePlacement.TOP
8389
});
8490
});
8591
});
@@ -99,7 +105,8 @@ describe('@ RelativePosition', () => {
99105
left: Math.round(8 + (targetElement.offsetWidth - 4) / 2),
100106
top: Math.round(srcCoords.top - 10),
101107
width: 4,
102-
height: 10
108+
height: 10,
109+
extra: OutsidePlacement.TOP
103110
});
104111
});
105112
it('when no width and height is provided', () => {
@@ -108,7 +115,8 @@ describe('@ RelativePosition', () => {
108115
left: Math.round(8 + (967 - 967) / 2),
109116
top: Math.round(srcCoords.top - 18),
110117
width: targetElement.offsetWidth,
111-
height: 'auto'
118+
height: 'auto',
119+
extra: OutsidePlacement.TOP
112120
});
113121
});
114122
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/// <reference types="karma-viewport" />
2+
3+
import { SlidePlacement } from '../../lib/models';
4+
import { SlidePosition } from '../../lib/position';
5+
6+
describe('@ SlidePosition', () => {
7+
describe('#getPositions', () => {
8+
it('should return proper position when placement is left', () => {
9+
const slidePos = new SlidePosition({
10+
width: 200,
11+
placement: SlidePlacement.LEFT
12+
});
13+
expect(slidePos.getPositions()).toEqual({
14+
left: 0,
15+
top: 0,
16+
width: 200,
17+
height: '100%',
18+
position: 'fixed',
19+
extra: SlidePlacement.LEFT
20+
});
21+
});
22+
it('should return proper position when placement is right', () => {
23+
const slidePos = new SlidePosition({
24+
width: 500,
25+
placement: SlidePlacement.RIGHT
26+
});
27+
expect(slidePos.getPositions()).toEqual({
28+
right: 0,
29+
top: 0,
30+
width: 500,
31+
height: '100%',
32+
position: 'fixed',
33+
extra: SlidePlacement.RIGHT
34+
});
35+
});
36+
});
37+
});

projects/toppy/src/tests/toppy-control.spec.ts

+22
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,26 @@ describe('@ ToppyControl', () => {
306306
window.dispatchEvent(new Event('resize'));
307307
});
308308
});
309+
describe('#listen', () => {
310+
beforeEach(() => {
311+
toppyControl.tid = 'arui';
312+
toppyControl.config = DefaultConfig;
313+
toppyControl.content = { data: 'One', props: {}, type: ContentType.STRING };
314+
});
315+
afterEach(() => {
316+
toppyControl.close();
317+
});
318+
319+
it('should emit events', done => {
320+
toppyControl
321+
.listen('t_open')
322+
.pipe(take(1))
323+
.subscribe(res => {
324+
expect(res).toBeNull();
325+
done();
326+
});
327+
328+
toppyControl.open();
329+
});
330+
});
309331
});

projects/toppy/src/tests/toppy.component.spec.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ describe('@ ToppyComponent', () => {
4242
beforeEach(() => {
4343
toppyComp.tid = 'abc';
4444
toppyComp.config = { ...DefaultConfig, bodyClass: 'zzz' };
45-
toppyComp.position = { getClassName: () => 'relative', getPositions: c => ({ left: 45, top: 79 }) } as any;
45+
toppyComp.position = {
46+
getClassName: () => 'relative',
47+
getPositions: c => ({ left: 45, top: 79, extra: 't' })
48+
} as any;
4649
});
4750

4851
afterEach(() => {
@@ -125,6 +128,7 @@ describe('@ ToppyComponent', () => {
125128
expect(fixture.debugElement.query(By.css('test-comp')).nativeElement.textContent).toBe('Hello Peter');
126129
});
127130
});
131+
128132
describe('#updateTextContent', () => {
129133
it('should not change the text if the content is not string', () => {
130134
toppyComp.content = {
@@ -174,6 +178,7 @@ describe('@ ToppyComponent', () => {
174178
expect(spy.calls.count()).toEqual(2);
175179
});
176180
});
181+
177182
describe('#listenPos', () => {
178183
it('should return new position', done => {
179184
fixture.detectChanges();
@@ -226,5 +231,10 @@ describe('@ ToppyComponent', () => {
226231
toppyComp['setPos']();
227232
expect(spy.calls.count()).toEqual(3);
228233
});
234+
it('should set extra class to wrapper element', () => {
235+
fixture.detectChanges();
236+
toppyComp['setPos']();
237+
expect(el.querySelector('.t-wrapper').classList.value).toEqual('t-wrapper t');
238+
});
229239
});
230240
});

0 commit comments

Comments
 (0)