• 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

6.56
/src/segment/segment.component.ts
1
import {
2
    ChangeDetectionStrategy,
3
    ChangeDetectorRef,
4
    Component,
5
    DestroyRef,
6
    ViewEncapsulation,
7
    numberAttribute,
8
    inject,
9
    input,
10
    signal,
11
    effect,
12
    output,
13
    contentChildren
1✔
14
} from '@angular/core';
UNCOV
15
import { ThumbAnimationProps } from 'ngx-tethys/core';
×
UNCOV
16
import { thumbMotion } from 'ngx-tethys/core';
×
UNCOV
17
import { ThySegmentItem } from './segment-item.component';
×
UNCOV
18
import { IThySegmentComponent, THY_SEGMENTED_COMPONENT } from './segment.token';
×
UNCOV
19
import { ThySegmentEvent } from './types';
×
UNCOV
20
import { AnimationEvent } from '@angular/animations';
×
UNCOV
21

×
UNCOV
22
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
×
UNCOV
23
import { coerceBooleanProperty } from 'ngx-tethys/util';
×
UNCOV
24

×
UNCOV
25
export type ThySegmentSize = 'xs' | 'sm' | 'md' | 'default';
×
UNCOV
26

×
UNCOV
27
export type ThySegmentMode = 'block' | 'inline';
×
UNCOV
28

×
UNCOV
29
/**
×
30
 * 分段控制器组件
UNCOV
31
 * @name thy-segment
×
UNCOV
32
 */
×
UNCOV
33
@Component({
×
UNCOV
34
    selector: 'thy-segment',
×
UNCOV
35
    templateUrl: './segment.component.html',
×
UNCOV
36
    exportAs: 'thySegment',
×
37
    animations: [thumbMotion],
38
    encapsulation: ViewEncapsulation.None,
UNCOV
39
    changeDetection: ChangeDetectionStrategy.OnPush,
×
40
    providers: [
41
        {
42
            provide: THY_SEGMENTED_COMPONENT,
UNCOV
43
            useExisting: ThySegment
×
UNCOV
44
        }
×
UNCOV
45
    ],
×
UNCOV
46
    host: {
×
47
        class: 'thy-segment',
UNCOV
48
        '[class.thy-segment-xs]': `thySize() === 'xs'`,
×
UNCOV
49
        '[class.thy-segment-sm]': `thySize() === 'sm'`,
×
50
        '[class.thy-segment-md]': `thySize() === 'md'`,
51
        '[class.thy-segment-default]': `!thySize() || thySize() === 'default'`,
52
        '[class.thy-segment-block]': `thyMode() === 'block'`,
UNCOV
53
        '[class.disabled]': 'thyDisabled()'
×
UNCOV
54
    },
×
55
    imports: []
56
})
×
57
export class ThySegment implements IThySegmentComponent {
UNCOV
58
    private cdr = inject(ChangeDetectorRef);
×
UNCOV
59
    private destroyRef = inject(DestroyRef);
×
UNCOV
60

×
61
    /**
62
     * @internal
63
     */
UNCOV
64
    readonly options = contentChildren(ThySegmentItem);
×
UNCOV
65

×
UNCOV
66
    /**
×
67
     * 大小
UNCOV
68
     * @type xs | sm | md | default
×
69
     */
70
    readonly thySize = input<ThySegmentSize>('default');
UNCOV
71

×
UNCOV
72
    /**
×
UNCOV
73
     * 模式
×
UNCOV
74
     * @type block | inline
×
UNCOV
75
     */
×
76
    readonly thyMode = input<ThySegmentMode>('block');
77

78
    /**
1✔
79
     * 是否禁用分段控制器
1✔
80
     */
81
    readonly thyDisabled = input(false, { transform: coerceBooleanProperty });
82

83
    /**
84
     * 选中选项的索引
85
     */
86
    readonly thyActiveIndex = input(undefined, { transform: numberAttribute });
87

88
    /**
1✔
89
     * 选项被选中的回调事件
90
     */
91
    readonly thySelectChange = output<ThySegmentEvent>();
92

93
    public selectedItem: ThySegmentItem;
94

95
    private newActiveIndex: number;
96

97
    private activeIndex: number;
98

99
    public animationState = signal<{ value: string; params: ThumbAnimationProps }>(null);
100

101
    public transitionedTo: any = null;
102

103
    constructor() {
104
        effect(() => {
105
            const value = this.thyActiveIndex();
106
            this.newActiveIndex = value;
107
            if (value < 0 || value === this.activeIndex) {
108
                return;
109
            }
110
            setTimeout(() => {
111
                const options = this.options();
112
                const selectedItem = options?.[this.activeIndex];
113
                if (selectedItem) {
114
                    selectedItem.unselect();
115
                    this.changeSelectedItem(options?.[value]);
116
                } else {
UNCOV
117
                    this.activeIndex = value;
×
118
                }
119
            });
120
        });
121

122
        effect(() => {
123
            const options = this.options();
124
            (options || []).forEach(item => {
125
                item.unselect();
126
            });
127
            this.selectedItem = options?.[this.newActiveIndex] || options?.[0];
128
            this.selectedItem?.select();
129
        });
130
    }
131

132
    public changeSelectedItem(item: ThySegmentItem, event?: Event): void {
133
        const options = this.options();
134
        this.animationState.set({
135
            value: 'from',
136
            params: getThumbAnimationProps(options?.[this.activeIndex || 0]?.elementRef.nativeElement!)
137
        });
138
        this.selectedItem = null;
139
        this.cdr.detectChanges();
140

141
        this.animationState.set({
142
            value: 'to',
143
            params: getThumbAnimationProps(item.elementRef.nativeElement!)
144
        });
145
        this.transitionedTo = item;
146
        this.activeIndex = options.findIndex(option => {
147
            return option.thyValue() === item?.thyValue();
148
        });
149
        this.thySelectChange.emit({ event: event, value: item.thyValue(), activeIndex: this.activeIndex });
150
    }
151

152
    public handleThumbAnimationDone(event: AnimationEvent): void {
153
        if (event.fromState === 'from') {
154
            this.selectedItem = this.transitionedTo;
155
            this.selectedItem?.select();
156
            this.transitionedTo = null;
157
            this.animationState.set(null);
158
        }
159
    }
160
}
161

162
function getThumbAnimationProps(element: HTMLElement): ThumbAnimationProps {
163
    return {
164
        transform: element.offsetLeft,
165
        width: element.clientWidth
166
    };
167
}
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