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

atinc / ngx-tethys / #102

26 May 2026 08:11AM UTC coverage: 91.111% (+0.7%) from 90.407%
#102

push

web-flow
build: bump docgeni to 2.8.0-next.5 (#3809)

4571 of 5491 branches covered (83.25%)

Branch coverage included in aggregate %.

13141 of 13949 relevant lines covered (94.21%)

966.75 hits per line

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

83.78
/src/stepper/stepper.component.ts
1
import {
2
    Component,
3
    numberAttribute,
4
    viewChildren,
5
    output,
6
    contentChildren,
7
    input,
8
    computed,
9
    effect,
10
    ChangeDetectionStrategy,
11
    signal,
12
    untracked
13
} from '@angular/core';
14
import { ThyStep, IThyStepperComponent, THY_STEPPER_COMPONENT } from './step.component';
15
import { ThyStepHeader } from './step-header.component';
16
import { NgTemplateOutlet } from '@angular/common';
17
import { coerceBooleanProperty } from 'ngx-tethys/util';
18

19
/**
20
 * 步骤条组件
21
 * @name thy-stepper
22
 * @order 10
23
 */
24
@Component({
25
    selector: 'thy-stepper',
26
    templateUrl: 'stepper.component.html',
27
    providers: [{ provide: THY_STEPPER_COMPONENT, useExisting: ThyStepper }],
28
    imports: [ThyStepHeader, NgTemplateOutlet],
29
    changeDetection: ChangeDetectionStrategy.OnPush,
30
    host: { class: 'thy-stepper' }
31
})
32
export class ThyStepper implements IThyStepperComponent {
1✔
33
    /**
34
     * 当前处于激活状态的步骤 index
35
     */
36
    readonly thySelectedIndex = input<number, unknown>(0, { transform: numberAttribute });
8✔
37

38
    /**
39
     * 当前处于激活状态的步骤实例
40
     */
41
    readonly thySelected = input<ThyStep>();
8✔
42

43
    /**
44
     * 步骤条导航是否展示,默认展示
45
     */
46
    readonly thyShowStepHeader = input(true, { transform: coerceBooleanProperty });
8✔
47

48
    readonly selectionChange = output<any>();
8✔
49

50
    readonly steps = contentChildren(ThyStep);
8✔
51

52
    readonly selectedIndex = signal(0);
8✔
53

54
    protected readonly selected = computed(() => this.steps()?.[this.selectedIndex()]);
13✔
55

56
    constructor() {
57
        effect(() => {
8✔
58
            const newIndex = this.thySelectedIndex();
9✔
59
            if (newIndex) {
9!
60
                untracked(() => {
×
61
                    this.updateSelectedIndex(newIndex);
×
62
                });
63
            }
64
        });
65

66
        effect(() => {
8✔
67
            const selected = this.thySelected();
9✔
68
            if (selected) {
9✔
69
                untracked(() => {
1✔
70
                    const index = this.steps()?.indexOf(selected);
1✔
71
                    if (index > -1) {
1✔
72
                        this.updateSelectedIndex(index);
1✔
73
                    }
74
                });
75
            }
76
        });
77
    }
78

79
    private updateSelectedIndex(newIndex: number): void {
80
        if (!this.steps()?.[newIndex]) {
5!
81
            return;
×
82
        }
83
        const previouslySelectedIndex = this.selectedIndex();
5✔
84
        const previouslySelectedStep = this.steps() ? this.steps()[previouslySelectedIndex] : null;
5!
85
        this.selectedIndex.set(newIndex);
5✔
86
        this.selectionChange.emit({
5✔
87
            selectedIndex: newIndex,
88
            previouslySelectedIndex: previouslySelectedIndex,
89
            selectedStep: this.selected(),
90
            previouslySelectedStep: previouslySelectedStep
91
        });
92
    }
93

94
    updateSelected(step: ThyStep): void {
95
        const index = this.steps().indexOf(step);
1✔
96
        this.updateSelectedIndex(index);
1✔
97
    }
98

99
    to(index: number): void {
100
        this.updateSelectedIndex(Math.min(index, this.steps().length - 1));
1✔
101
    }
102

103
    next(): void {
104
        this.updateSelectedIndex(Math.min(this.selectedIndex() + 1, this.steps().length - 1));
1✔
105
    }
106

107
    /** Selects and focuses the previous step in list. */
108
    previous(): void {
109
        this.updateSelectedIndex(Math.max(this.selectedIndex() - 1, 0));
1✔
110
    }
111
}
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