• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.25
/src/slide/slide-container.component.ts
1
import { ThyAbstractOverlayContainer } from 'ngx-tethys/core';
2
import { helpers } from 'ngx-tethys/util';
3
import { Observable, Subject } from 'rxjs';
4
import { filter, startWith, takeUntil } from 'rxjs/operators';
5
import { useHostRenderer } from '@tethys/cdk/dom';
6
import { AnimationEvent } from '@angular/animations';
7
import { ViewportRuler } from '@angular/cdk/overlay';
8
import { CdkPortalOutlet, PortalModule } from '@angular/cdk/portal';
9
import { DOCUMENT } from '@angular/common';
10
import { NgZone, ChangeDetectorRef, Component, ElementRef, Inject, OnDestroy, Renderer2, ViewChild } from '@angular/core';
11

12
import { thySlideAnimations } from './slide-animations';
13
import { slideAbstractOverlayOptions, ThySlideConfig, ThySlideFromTypes } from './slide.config';
14

15
/**
16
 * @private
1✔
17
 */
18
@Component({
×
19
    selector: 'thy-slide-container',
20
    template: ` <ng-template cdkPortalOutlet></ng-template> `,
21
    animations: [thySlideAnimations.slideContainer],
×
22
    host: {
23
        class: 'thy-slide-container',
24
        '[class.thy-slide-push]': 'isPush',
×
25
        '[class.thy-slide-side]': 'isSide',
26
        '[class.thy-slide-over]': '!isPush && !isSide',
27
        tabindex: '-1',
×
28
        '[attr.role]': `'slide'`,
×
29
        '[@slideContainer]': 'animationState',
×
30
        '(@slideContainer.start)': 'onAnimationStart($event)',
31
        '(@slideContainer.done)': 'onAnimationDone($event)',
32
        '[style.width.px]': 'slideContainerStyles.width',
×
33
        '[style.height.px]': 'slideContainerStyles.height',
34
        '[style.max-height.px]': 'slideContainerStyles.height'
×
35
    },
36
    standalone: true,
37
    imports: [PortalModule]
×
38
})
39
export class ThySlideContainerComponent extends ThyAbstractOverlayContainer implements OnDestroy {
×
40
    @ViewChild(CdkPortalOutlet, { static: true })
41
    portalOutlet: CdkPortalOutlet;
×
42

43
    animationOpeningDone: Observable<AnimationEvent>;
×
44

45
    animationClosingDone: Observable<AnimationEvent>;
×
46

47
    animationState: ThySlideFromTypes = 'void';
48

49
    slideContainerStyles: { width?: number; height?: number } = {};
×
50

51
    private drawerContainerElement: HTMLElement;
52

×
53
    private ngUnsubscribe$ = new Subject<void>();
×
54

×
55
    private hostRenderer = useHostRenderer();
×
56

×
57
    get isPush() {
×
58
        return this.config.mode === 'push' && !!this.drawerContainerElement;
×
59
    }
×
60

×
61
    get isSide() {
×
62
        return this.config.mode === 'side' && !!this.drawerContainerElement;
×
63
    }
×
64

×
65
    private get isLeftOrRight(): boolean {
66
        return this.config.from === 'left' || this.config.from === 'right';
×
67
    }
×
68

69
    private get hostOffset() {
×
70
        let offset = 0;
×
71
        if (this.isLeftOrRight) {
×
72
            offset = this.elementRef.nativeElement.clientWidth + this.config.offset || 0;
73
        } else {
74
            offset = this.elementRef.nativeElement.clientHeight + this.config.offset || 0;
×
75
        }
×
76
        return offset;
77
    }
×
78

×
79
    private get transform() {
80
        switch (this.config.from) {
×
81
            case 'left':
×
82
                return `translateX(${this.hostOffset}px)`;
83
            case 'right':
84
                return `translateX(-${this.hostOffset}px)`;
85
            case 'top':
86
                return `translateY(${this.hostOffset}px)`;
×
87
            case 'bottom':
×
88
                return `translateY(${this.hostOffset}px)`;
×
89
        }
×
90
    }
×
91

92
    private get drawerContainerElementClass() {
93
        return `thy-slide-${this.config.mode}-drawer-container`;
×
94
    }
×
95

×
96
    constructor(
97
        private elementRef: ElementRef,
×
98
        @Inject(DOCUMENT) private document: any,
99
        public config: ThySlideConfig,
100
        changeDetectorRef: ChangeDetectorRef,
101
        private renderer: Renderer2,
102
        private viewportRuler: ViewportRuler,
103
        private readonly ngZone: NgZone
×
104
    ) {
105
        super(slideAbstractOverlayOptions, changeDetectorRef);
106
        this.animationOpeningDone = this.animationStateChanged.pipe(
107
            filter((event: AnimationEvent) => {
×
108
                return event.phaseName === 'done' && event.toState === this.animationState;
109
            })
110
        );
111
        this.animationClosingDone = this.animationStateChanged.pipe(
×
112
            filter((event: AnimationEvent) => {
×
113
                return event.phaseName === 'done' && event.toState === 'exit';
114
            })
115
        );
116
        this.setDrawerContainerElement();
×
117
        this.checkContainerWithinViewport();
×
118
        this.addDrawerContainerElementClass();
119
    }
120

121
    private setDrawerContainerElement() {
×
122
        if (typeof this.config.drawerContainer === 'string') {
×
123
            this.drawerContainerElement = this.config.drawerContainer && document.querySelector(this.config.drawerContainer);
124
        }
×
125
        if (this.config.drawerContainer instanceof ElementRef) {
×
126
            this.drawerContainerElement = this.config.drawerContainer.nativeElement;
127
        }
128
        if (this.config.drawerContainer instanceof HTMLElement) {
129
            this.drawerContainerElement = this.config.drawerContainer as HTMLElement;
×
130
        }
×
131
    }
132

×
133
    private setSlideContainerStyles() {
×
134
        let width, height, top, left;
135
        const drawerContainerElementRect = (this.drawerContainerElement || document.body).getBoundingClientRect();
136
        if (this.isLeftOrRight) {
137
            height = drawerContainerElementRect.height;
×
138
            top = drawerContainerElementRect.top;
×
139
            this.hostRenderer.setStyle('top', `${top}px`);
×
140
        } else {
141
            width = drawerContainerElementRect.width;
142
            left = drawerContainerElementRect.left;
×
143
            this.hostRenderer.setStyle('left', `${left}px`);
144
        }
×
145
        this.slideContainerStyles = {
146
            width: width,
147
            height: height
×
148
        };
149
    }
150

×
151
    private checkContainerWithinViewport() {
152
        this.viewportRuler
153
            .change(100)
×
154
            .pipe(startWith(null), takeUntil(this.ngUnsubscribe$))
155
            .subscribe(() => {
156
                this.ngZone.run(() => this.setSlideContainerStyles());
×
157
            });
×
158
    }
×
159

×
160
    private addDrawerContainerElementClass() {
161
        if (this.drawerContainerElement) {
1✔
162
            this.renderer.addClass(this.drawerContainerElement, this.drawerContainerElementClass);
163
        }
164
    }
165

166
    private removeDrawerContainerElementClass() {
167
        if (this.drawerContainerElement) {
168
            this.renderer.removeClass(this.drawerContainerElement, this.drawerContainerElementClass);
169
        }
170
    }
1✔
171

172
    private setDrawerContainerElementStyle() {
173
        if (this.isSide) {
174
            this.renderer.setStyle(this.drawerContainerElement, `margin-${this.config.from}`, `${this.hostOffset}px`);
1✔
175
        } else if (this.isPush) {
176
            this.renderer.setStyle(this.drawerContainerElement, `transform`, this.transform);
177
        }
178
    }
179

180
    private removeDrawerContainerElementStyle() {
181
        if (this.isSide) {
182
            this.renderer.removeStyle(this.drawerContainerElement, `margin-${this.config.from}`);
183
        } else if (this.isPush) {
184
            this.renderer.removeStyle(this.drawerContainerElement, `transform`);
185
        }
186
    }
187

188
    beforeAttachPortal(): void {
189
        if (this.config.offset) {
190
            this.hostRenderer.setStyle(this.config.from, `${this.config.offset}px`);
191
            this.animationState = helpers.camelCase(['offset', this.config.from]) as ThySlideFromTypes;
192
        } else {
193
            this.animationState = this.config.from;
194
        }
195
        this.setDrawerContainerElementStyle();
196
    }
197

198
    beforeDetachPortal(): void {
199
        this.removeDrawerContainerElementStyle();
200
    }
201

202
    onAnimationDone(event: AnimationEvent) {
203
        this.animationStateChanged.emit(event);
204
    }
205

206
    onAnimationStart(event: AnimationEvent) {
207
        this.animationStateChanged.emit(event);
208
    }
209

210
    ngOnDestroy() {
211
        super.destroy();
212
        this.removeDrawerContainerElementClass();
213
        this.ngUnsubscribe$.next();
214
        this.ngUnsubscribe$.complete();
215
    }
216
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc