• 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

0.0
/src/tooltip/tooltip-ref.ts
1
import { FlexibleConnectedPositionStrategy, Overlay, OverlayRef, ScrollDispatcher, ScrollStrategy } from '@angular/cdk/overlay';
2
import { ComponentPortal } from '@angular/cdk/portal';
3
import { ElementRef, NgZone, TemplateRef } from '@angular/core';
4
import { isUndefinedOrNull } from '@tethys/cdk/is';
5
import { getFlexiblePositions } from 'ngx-tethys/core';
6
import { SafeAny } from 'ngx-tethys/types';
7
import { isNumber } from 'ngx-tethys/util';
8
import { Subject } from 'rxjs';
9
import { take, takeUntil } from 'rxjs/operators';
10
import { ThyTooltipContent } from './interface';
×
11
import { ThyTooltipComponent } from './tooltip.component';
×
12
import { ThyTooltipConfig } from './tooltip.config';
×
13

×
14
export class ThyTooltipRef {
×
15
    private overlayRef: OverlayRef;
×
16

×
17
    private tooltipInstance: ThyTooltipComponent;
18

19
    private scrollStrategy: ScrollStrategy;
20

21
    private portal: ComponentPortal<ThyTooltipComponent>;
22

×
23
    private readonly dispose$ = new Subject<void>();
×
24

25
    constructor(
×
26
        private host: ElementRef<HTMLElement> | HTMLElement,
27
        private config: ThyTooltipConfig,
×
28
        private overlay: Overlay,
29
        private scrollDispatcher: ScrollDispatcher,
30
        private ngZone: NgZone
31
    ) {
32
        this.scrollStrategy = overlay.scrollStrategies.reposition({
33
            scrollThrottle: this.config.scrollThrottleSeconds
×
34
        });
×
35
    }
×
36

×
37
    /** Create the overlay config and position strategy */
38
    private createOverlay(): OverlayRef {
39
        if (this.overlayRef) {
×
40
            return this.overlayRef;
41
        }
42
        const scrollableAncestors = this.scrollDispatcher.getAncestorScrollContainers(this.host);
43
        // Create connected position strategy that listens for scroll events to reposition.
×
44
        const strategy = this.overlay
45
            .position()
46
            .flexibleConnectedTo(this.host)
47
            .withTransformOriginOn('.thy-tooltip-content')
48
            .withFlexibleDimensions(false)
49
            .withViewportMargin(8);
50

×
51
        strategy.withScrollableContainers(scrollableAncestors);
×
52
        strategy.positionChanges.pipe(takeUntil(this.dispose$)).subscribe(change => {
53
            if (this.tooltipInstance) {
54
                if (change.scrollableViewProperties.isOverlayClipped && this.tooltipInstance.isVisible()) {
×
55
                    // After position changes occur and the overlay is clipped by
×
56
                    // a parent scrollable then close the tooltip.
57
                    this.ngZone.run(() => this.hide(0));
58
                }
59
            }
×
60
        });
×
61
        this.overlayRef = this.overlay.create({
62
            positionStrategy: strategy,
×
63
            panelClass: this.config.panelClass,
64
            scrollStrategy: this.scrollStrategy,
65
            hasBackdrop: this.config.hasBackdrop,
66
            backdropClass: 'thy-tooltip-backdrop'
×
67
        });
×
68

×
69
        this.updatePosition();
70

71
        this.overlayRef
×
72
            .detachments()
×
73
            .pipe(takeUntil(this.dispose$))
74
            .subscribe(() => this.detach());
×
75

76
        this.overlayRef
77
            .backdropClick()
×
78
            .pipe(takeUntil(this.dispose$))
×
79
            .subscribe(() => {
80
                this.overlayRef.detachBackdrop();
×
81
                this.hide(0);
×
82
            });
×
83

×
84
        return this.overlayRef;
85
    }
86

×
87
    /** Updates the position of the current tooltip. */
×
88
    private updatePosition() {
89
        const position = this.overlayRef.getConfig().positionStrategy as FlexibleConnectedPositionStrategy;
×
90
        const connectionPositions = getFlexiblePositions(this.config.placement, this.config.offset, 'thy-tooltip');
×
91
        position.withPositions(connectionPositions);
×
92
    }
×
93

×
94
    private detach() {
95
        if (this.overlayRef && this.overlayRef.hasAttached()) {
96
            this.overlayRef.detach();
×
97
        }
×
98
        this.tooltipInstance = null;
×
99
    }
×
100

101
    show(content: ThyTooltipContent, delay?: number): void;
×
102
    show<T extends Record<SafeAny, SafeAny>>(content: ThyTooltipContent, data: T, delay?: number): void;
×
103
    show<T extends Record<SafeAny, SafeAny>>(content: ThyTooltipContent, dataOrDelay: T | number, delay?: number) {
×
104
        if (!content || (this.isTooltipVisible() && !this.tooltipInstance.showTimeoutId && !this.tooltipInstance.hideTimeoutId)) {
105
            return;
106
        }
107
        let showDelay = null;
×
108
        let initialState = null;
109
        if (isNumber(dataOrDelay)) {
110
            showDelay = dataOrDelay as number;
×
111
        } else {
×
112
            initialState = dataOrDelay;
113
            showDelay = delay;
114
        }
115
        const overlayRef = this.createOverlay();
116
        this.detach();
117
        this.portal = this.portal || new ComponentPortal(ThyTooltipComponent, this.config.viewContainerRef);
×
118
        this.tooltipInstance = overlayRef.attach(this.portal).instance;
×
119
        this.tooltipInstance
×
120
            .afterHidden()
×
121
            .pipe(takeUntil(this.dispose$))
×
122
            .subscribe(() => this.detach());
123
        this.updateTooltipContent(content, initialState);
124
        this.setTooltipClass(this.config.contentClass);
125
        this.tooltipInstance.show(!isUndefinedOrNull(showDelay) ? showDelay : this.config.showDelay);
×
126
    }
×
127

128
    hide(delay: number = 0): void {
129
        if (this.tooltipInstance) {
130
            this.tooltipInstance.hide(!isUndefinedOrNull(delay) ? delay : this.config.hideDelay);
131
        }
132
    }
×
133

134
    getOverlayRef() {
135
        return this.overlayRef;
×
136
    }
×
137

×
138
    setTooltipClass(tooltipClass: string | string[]) {
×
139
        if (this.tooltipInstance) {
×
140
            this.tooltipInstance.setTooltipClass(tooltipClass);
×
141
        }
142
    }
143

144
    updateTooltipContent(content: string | TemplateRef<any>, data?: any) {
145
        // Must wait for the message to be painted to the tooltip so that the overlay can properly
146
        // calculate the correct positioning based on the size of the text.
147
        if (this.tooltipInstance) {
148
            this.tooltipInstance.content = content;
149
            this.tooltipInstance.data = data;
150
            this.tooltipInstance.markForCheck();
151

152
            this.ngZone.onMicrotaskEmpty
153
                .asObservable()
154
                .pipe(take(1), takeUntil(this.dispose$))
155
                .subscribe(() => {
156
                    if (this.tooltipInstance) {
157
                        this.overlayRef.updatePosition();
158
                    }
159
                });
160
        }
161
    }
162

163
    isTooltipVisible(): boolean {
164
        return !!this.tooltipInstance && this.tooltipInstance.isVisible();
165
    }
166

167
    dispose(): void {
168
        this.dispose$.next();
169
        this.dispose$.complete();
170
        this.hide(0);
171
        if (this.overlayRef) {
172
            this.overlayRef.dispose();
173
            this.tooltipInstance = null;
174
        }
175
    }
176
}
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