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

atinc / ngx-tethys / e7e93139-40c1-43df-89af-590c74472c57

15 May 2025 08:03AM UTC coverage: 90.284% (+0.007%) from 90.277%
e7e93139-40c1-43df-89af-590c74472c57

push

circleci

web-flow
refactor(copy): migrate to signal for copy #TINFR-1461 (#3383)

5607 of 6871 branches covered (81.6%)

Branch coverage included in aggregate %.

5 of 6 new or added lines in 1 file covered. (83.33%)

4 existing lines in 1 file now uncovered.

13404 of 14186 relevant lines covered (94.49%)

920.14 hits per line

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

74.47
/src/copy/copy.directive.ts
1
import { Directive, ElementRef, HostListener, OnDestroy, OnInit, Signal, inject, input, output } from '@angular/core';
2
import { DOCUMENT } from '@angular/common';
3
import { coerceElement } from '@angular/cdk/coercion';
4
import { ThyNotifyService } from 'ngx-tethys/notify';
5
import { ThyTooltipDirective } from 'ngx-tethys/tooltip';
6
import { coerceBooleanProperty } from 'ngx-tethys/util';
7
import { injectLocale, ThyCopyLocale } from 'ngx-tethys/i18n';
8

9
export interface ThyCopyEvent {
10
    isSuccess: boolean;
11
    event: Event;
12
}
13

1✔
14
/**
15
 * @name thyCopy
22✔
16
 */
22✔
17
@Directive({
22✔
18
    selector: '[thyCopy]',
22✔
19
    hostDirectives: [ThyTooltipDirective]
22✔
20
})
22✔
21
export class ThyCopyDirective implements OnInit, OnDestroy {
22✔
22
    private document = inject(DOCUMENT);
22✔
23
    tooltipDirective = inject(ThyTooltipDirective);
22✔
24
    private notifyService = inject(ThyNotifyService);
22✔
25
    private locale: Signal<ThyCopyLocale> = injectLocale('copy');
26

27
    /**
22✔
28
     * 默认为点击标签,可传复制目标标签
22✔
29
     */
22✔
30
    readonly thyCopy = output<ThyCopyEvent>();
31

32
    /**
2✔
33
     * 复制成功时的文案
2!
34
     */
2✔
35
    readonly thyCopySuccessText = input<string>(this.locale().success);
36

UNCOV
37
    /**
×
UNCOV
38
     * 提示文案
×
39
     */
40
    readonly thyCopyTips = input<string>(this.locale().tips);
41

42
    /**
2✔
43
     * 偏移量
2✔
44
     */
2✔
45
    readonly thyCopyTipsOffset = input<number>(undefined);
2✔
46

2✔
47
    /**
2✔
48
     * 当为 string 时,复制的是传入的内容;当为 ElementRef | HTMLElement 时,复制的是 dom 节点的 value 或者 textContent
2✔
49
     */
2✔
50
    readonly thyCopyContent = input<string | ElementRef | HTMLElement>(undefined);
1✔
51

52
    /**
53
     * 是否展示通知
UNCOV
54
     */
×
NEW
55
    readonly thyShowNotify = input(true, { transform: coerceBooleanProperty });
×
UNCOV
56

×
57
    ngOnInit() {
58
        const thyCopyTips = this.thyCopyTips();
59
        this.tooltipDirective.content = thyCopyTips ? thyCopyTips : this.locale().tips;
60
        this.tooltipDirective.tooltipOffset = this.thyCopyTipsOffset();
2✔
61
    }
62

63
    private getContent(event: Event) {
64
        const thyCopyContent = this.thyCopyContent();
22✔
65
        if (typeof thyCopyContent === 'string') {
66
            return thyCopyContent;
1✔
67
        } else {
68
            const target = thyCopyContent ? coerceElement(thyCopyContent) : event.target;
69
            return target.value || target.textContent;
70
        }
71
    }
72

73
    @HostListener('click', ['$event'])
74
    public onClick(event: Event) {
75
        const textarea = this.document.createElement('textarea');
76
        this.document.body.appendChild(textarea);
1✔
77
        textarea.value = this.getContent(event);
78
        textarea.select();
79
        try {
80
            document.execCommand('copy', false, null);
81
            this.thyCopy.emit({ isSuccess: true, event });
82
            if (this.thyShowNotify()) {
83
                this.notifyService.success(this.thyCopySuccessText());
84
            }
85
        } catch (err) {
86
            this.thyCopy.emit({ isSuccess: false, event });
87
            if (this.thyShowNotify()) {
88
                this.notifyService.error(this.locale().error);
89
            }
90
        } finally {
91
            textarea.remove();
92
        }
93
    }
94

95
    ngOnDestroy() {
96
        this.tooltipDirective.hide();
97
    }
98
}
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

© 2026 Coveralls, Inc