• 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

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';
15
import { ThumbAnimationProps } from 'ngx-tethys/core';
×
16
import { thumbMotion } from 'ngx-tethys/core';
×
17
import { ThySegmentItem } from './segment-item.component';
×
18
import { IThySegmentComponent, THY_SEGMENTED_COMPONENT } from './segment.token';
×
19
import { ThySegmentEvent } from './types';
×
20
import { AnimationEvent } from '@angular/animations';
×
21

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

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

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

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

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

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

×
72
    /**
×
73
     * 模式
×
74
     * @type block | inline
×
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 {
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