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

atinc / ngx-tethys / #55

30 Jul 2025 07:08AM UTC coverage: 9.866% (-80.4%) from 90.297%
#55

push

why520crazy
feat(empty): add setMessage for update display text #TINFR-2616

92 of 6794 branches covered (1.35%)

Branch coverage included in aggregate %.

2014 of 14552 relevant lines covered (13.84%)

6.15 hits per line

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

4.26
/src/progress/progress-circle.component.ts
1
import { isNumber, isString } from 'ngx-tethys/util';
2
import { Component, TemplateRef, ViewEncapsulation, numberAttribute, input, effect, computed } from '@angular/core';
3
import { useHostRenderer } from '@tethys/cdk/dom';
4
import { ThyProgressGapPositionType, ThyProgressShapeType, ThyProgressStackedValue, ThyProgressType } from './interfaces';
5
import { NgClass, NgStyle } from '@angular/common';
6
import { ThyTooltipDirective } from 'ngx-tethys/tooltip';
7

8
/**
9
 * @private
10
 */
11
@Component({
12
    selector: 'thy-progress-circle',
1✔
13
    templateUrl: './progress-circle.component.html',
14
    encapsulation: ViewEncapsulation.None,
×
15
    host: {
×
16
        class: 'progress-circle'
×
17
    },
×
18
    imports: [ThyTooltipDirective, NgClass, NgStyle]
×
19
})
×
20
export class ThyProgressCircle {
×
21
    private hostRenderer = useHostRenderer();
×
22

×
23
    readonly thyType = input<ThyProgressType>(undefined);
×
24

×
25
    readonly thySize = input<string | number>(undefined);
×
26

27
    readonly thyValue = input<number | ThyProgressStackedValue[]>(undefined);
×
28

×
29
    readonly thyMax = input<number, unknown>(undefined, { transform: numberAttribute });
×
30

×
31
    readonly thyTips = input<string | TemplateRef<unknown>>(undefined);
32

×
33
    readonly thyShape = input<ThyProgressShapeType>('strip');
34

×
35
    readonly thyGapDegree = input<number, unknown>(undefined, { transform: numberAttribute });
×
36

×
37
    readonly thyGapPosition = input<ThyProgressGapPositionType>('top');
×
38

39
    readonly thyStrokeWidth = input<number, unknown>(undefined, { transform: numberAttribute });
×
40

41
    readonly strokeWidth = computed(() => {
×
42
        return this.thyStrokeWidth() || 6;
×
43
    });
×
44

×
45
    readonly progressSize = computed(() => {
×
46
        const size = this.thySize();
×
47
        if (size && isString(size)) {
×
48
            return `progress-circle-inner-${size}`;
×
49
        }
×
50
        return '';
51
    });
52

53
    readonly width = computed(() => {
×
54
        const size = this.thySize();
55
        if (size && isNumber(size)) {
×
56
            return size;
×
57
        }
×
58
        return 112;
×
59
    });
×
60

×
61
    readonly circle = computed(() => {
×
62
        let values: ThyProgressStackedValue[] = [];
×
63

×
64
        const thyValue = this.thyValue();
65
        if (Array.isArray(thyValue)) {
×
66
            let totalValue = 0;
×
67
            values = (thyValue as ThyProgressStackedValue[]).map((item, index) => {
×
68
                totalValue += item.value;
×
69
                const currentValue = +((totalValue / this.thyMax()) * 100).toFixed(2);
×
70
                return { ...item, value: currentValue };
71
            });
×
72
        } else {
×
73
            values = [{ value: thyValue }];
×
74
        }
×
75

×
76
        const radius = 50 - this.strokeWidth() / 2;
77
        const gapPosition = this.thyGapPosition() || 'top';
×
78
        const len = Math.PI * 2 * radius;
×
79
        const gapDegree = this.thyGapDegree() || 0;
×
80

81
        let beginPositionX = 0;
82
        let beginPositionY = -radius;
×
83
        let endPositionX = 0;
×
84
        let endPositionY = radius * -2;
85

86
        switch (gapPosition) {
87
            case 'left':
88
                beginPositionX = -radius;
×
89
                beginPositionY = 0;
90
                endPositionX = radius * 2;
×
91
                endPositionY = 0;
92
                break;
93
            case 'right':
×
94
                beginPositionX = radius;
95
                beginPositionY = 0;
×
96
                endPositionX = radius * -2;
97
                endPositionY = 0;
×
98
                break;
99
            case 'bottom':
100
                beginPositionY = radius;
101
                endPositionY = radius * 2;
102
                break;
103
            default:
×
104
        }
105

×
106
        const pathString = `M 50,50 m ${beginPositionX},${beginPositionY} a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY} a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
×
107

×
108
        const trailPathStyle = {
109
            strokeDasharray: `${len - gapDegree}px ${len}px`,
110
            strokeDashoffset: `-${gapDegree / 2}px`,
1✔
111
            transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s'
1✔
112
        };
113

114
        const progressCirclePath = values
115
            .map((item, index) => {
116
                return {
117
                    stroke: '',
118
                    value: +item.value,
119
                    className: item.type ? `progress-circle-path-${item.type}` : null,
120
                    strokePathStyle: {
121
                        stroke: item?.color ? item?.color : null,
122
                        transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s',
123
                        strokeDasharray: `${((item.value || 0) / 100) * (len - gapDegree)}px ${len}px`,
1✔
124
                        strokeDashoffset: `-${gapDegree / 2}px`
125
                    }
126
                };
127
            })
128
            .reverse();
129
        return { pathString, trailPathStyle, progressCirclePath };
130
    });
131

132
    constructor() {
133
        effect(() => {
134
            const type = this.thyType();
135
            this.hostRenderer.updateClass(type ? [`progress-circle-${type}`] : []);
136
        });
137
    }
138
}
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