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

atinc / ngx-tethys / 68ef226c-f83e-44c1-b8ed-e420a83c5d84

28 May 2025 10:31AM UTC coverage: 10.352% (-80.0%) from 90.316%
68ef226c-f83e-44c1-b8ed-e420a83c5d84

Pull #3460

circleci

pubuzhixing8
chore: xxx
Pull Request #3460: refactor(icon): migrate signal input #TINFR-1476

132 of 6823 branches covered (1.93%)

Branch coverage included in aggregate %.

10 of 14 new or added lines in 1 file covered. (71.43%)

11648 existing lines in 344 files now uncovered.

2078 of 14525 relevant lines covered (14.31%)

6.69 hits per line

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

5.19
/src/popover/popover.directive.ts
1
import {
2
    Directive,
3
    ElementRef,
4
    NgZone,
5
    OnDestroy,
6
    Input,
7
    TemplateRef,
8
    OnInit,
9
    ViewContainerRef,
10
    HostBinding,
11
    ChangeDetectorRef,
12
    numberAttribute,
13
    inject,
14
    input,
1✔
15
    effect
UNCOV
16
} from '@angular/core';
×
17
import { Platform } from '@angular/cdk/platform';
18
import { OverlayRef } from '@angular/cdk/overlay';
UNCOV
19
import { FocusMonitor } from '@angular/cdk/a11y';
×
UNCOV
20
import { ThyOverlayDirectiveBase, ThyOverlayTrigger, ThyPlacement } from 'ngx-tethys/core';
×
UNCOV
21
import { ThyPopover } from './popover.service';
×
UNCOV
22
import { ComponentType } from '@angular/cdk/portal';
×
UNCOV
23
import { ThyPopoverRef } from './popover-ref';
×
UNCOV
24
import { ThyPopoverConfig } from './popover.config';
×
UNCOV
25
import { coerceBooleanProperty } from 'ngx-tethys/util';
×
UNCOV
26

×
UNCOV
27
/**
×
UNCOV
28
 * 弹出悬浮层指令
×
UNCOV
29
 * @name thyPopover
×
UNCOV
30
 * @order 50
×
UNCOV
31
 */
×
UNCOV
32
@Directive({
×
UNCOV
33
    selector: '[thyPopover]'
×
UNCOV
34
})
×
UNCOV
35
export class ThyPopoverDirective extends ThyOverlayDirectiveBase implements OnInit, OnDestroy {
×
UNCOV
36
    elementRef: ElementRef;
×
UNCOV
37
    private popover = inject(ThyPopover);
×
UNCOV
38
    private viewContainerRef = inject(ViewContainerRef);
×
39
    private cdr = inject(ChangeDetectorRef);
UNCOV
40

×
UNCOV
41
    @HostBinding(`class.thy-popover-opened`) popoverOpened = false;
×
42

UNCOV
43
    /**
×
UNCOV
44
     * 悬浮组件或者模板
×
45
     */
46
    readonly content = input<ComponentType<any> | TemplateRef<any>>(undefined, { alias: 'thyPopover' });
47

UNCOV
48
    /**
×
49
     * 弹出悬浮层的触发方式
50
     */
UNCOV
51
    readonly thyTrigger = input<ThyOverlayTrigger>('click');
×
52

53
    /**
×
54
     * 弹出悬浮层的位置
55
     * @type top | topLeft | topRight | bottom | bottomLeft | bottomRight | left | leftTop | leftBottom | right |  rightTop | rightBottom
56
     */
57
    readonly thyPlacement = input<ThyPlacement>('bottom');
58

UNCOV
59
    /**
×
UNCOV
60
     * 弹出悬浮层的偏移量
×
UNCOV
61
     */
×
62
    readonly thyOffset = input<number, unknown>(0, { transform: numberAttribute });
UNCOV
63

×
64
    /**
65
     * 弹出悬浮层的配置
×
UNCOV
66
     */
×
UNCOV
67
    readonly thyConfig = input<ThyPopoverConfig>(undefined);
×
UNCOV
68

×
69
    /**
UNCOV
70
     * 显示延迟时间
×
UNCOV
71
     */
×
72
    readonly thyShowDelay = input<number, unknown>(0, { transform: numberAttribute });
UNCOV
73

×
UNCOV
74
    /**
×
75
     * 隐藏延迟时间
UNCOV
76
     */
×
UNCOV
77
    readonly thyHideDelay = input<number, unknown>(0, { transform: numberAttribute });
×
UNCOV
78

×
UNCOV
79
    /**
×
UNCOV
80
     * 自动适配内容变化重新计算位置
×
UNCOV
81
     */
×
82
    readonly thyAutoAdaptive = input(false, { transform: coerceBooleanProperty });
UNCOV
83

×
84
    /**
85
     * 是否禁用打开悬浮层
86
     * @default false
×
UNCOV
87
     */
×
UNCOV
88
    @Input({ transform: coerceBooleanProperty }) set thyDisabled(value: boolean) {
×
UNCOV
89
        this.disabled = value;
×
90
    }
UNCOV
91

×
UNCOV
92
    private popoverRef: ThyPopoverRef<any>;
×
UNCOV
93

×
UNCOV
94
    constructor() {
×
95
        const elementRef = inject(ElementRef);
UNCOV
96
        const platform = inject(Platform);
×
97
        const focusMonitor = inject(FocusMonitor);
98
        const ngZone = inject(NgZone);
99
        super(elementRef, platform, focusMonitor, ngZone, true);
UNCOV
100
        this.elementRef = elementRef;
×
101

102
        effect(() => {
1✔
103
            this.trigger = this.thyTrigger();
1✔
104
        });
105
        effect(() => {
106
            this.showDelay = this.thyShowDelay();
107
        });
108
        effect(() => {
109
            this.hideDelay = this.thyHideDelay();
110
        });
111
    }
112

113
    ngOnInit(): void {
114
        this.initialize();
115
    }
116

1✔
117
    createOverlay(): OverlayRef {
118
        const config = Object.assign(
119
            {
120
                origin: this.elementRef.nativeElement,
121
                hasBackdrop: this.trigger === 'click' || this.trigger === 'focus',
122
                viewContainerRef: this.viewContainerRef,
123
                placement: this.thyPlacement(),
124
                offset: this.thyOffset(),
125
                autoAdaptive: this.thyAutoAdaptive()
126
            },
127
            this.thyConfig()
128
        );
129
        this.popoverRef = this.popover.open(this.content(), config);
130

131
        this.popoverRef.afterClosed().subscribe(() => {
132
            this.popoverOpened = false;
133
        });
134

135
        return this.popoverRef.getOverlayRef();
136
    }
137

138
    show(delay: number = this.showDelay) {
139
        if (this.hideTimeoutId) {
140
            clearTimeout(this.hideTimeoutId);
141
            this.hideTimeoutId = null;
142
        }
143

144
        if (this.disabled || (this.overlayRef && this.overlayRef.hasAttached())) {
145
            return;
146
        }
147
        if (this.trigger !== 'hover') {
148
            delay = 0;
149
        }
150

151
        this.showTimeoutId = setTimeout(() => {
152
            if (!this.disabled) {
153
                const overlayRef = this.createOverlay();
154
                this.overlayRef = overlayRef;
155
                this.popoverOpened = true;
156
                this.cdr.markForCheck();
157
            }
158
            this.showTimeoutId = null;
159
        }, delay);
160
    }
161

162
    hide(delay: number = this.hideDelay) {
163
        if (this.showTimeoutId) {
164
            clearTimeout(this.showTimeoutId);
165
            this.showTimeoutId = null;
166
        }
167

168
        this.hideTimeoutId = setTimeout(() => {
169
            if (this.popoverRef) {
170
                this.popoverRef.close();
171
                this.cdr.markForCheck();
172
            }
173
            this.hideTimeoutId = null;
174
        }, delay);
175
    }
176

177
    ngOnDestroy() {
178
        this.dispose();
179
    }
180
}
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