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

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

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

9.59
/src/tabs/tabs.component.ts
1
import {
2
    AfterContentInit,
3
    ChangeDetectionStrategy,
4
    ChangeDetectorRef,
5
    Component,
6
    ContentChildren,
7
    ElementRef,
8
    EventEmitter,
9
    Input,
10
    OnChanges,
11
    OnInit,
12
    Output,
1✔
13
    QueryList,
14
    SimpleChanges,
15
    TemplateRef
16
} from '@angular/core';
17
import { Constructor, InputBoolean, MixinBase, mixinUnsubscribe, ThyUnsubscribe } from 'ngx-tethys/core';
1✔
18
import { isString } from 'ngx-tethys/util';
19
import { fromEvent } from 'rxjs';
×
20
import { takeUntil } from 'rxjs/operators';
×
21
import { ThyTabComponent } from './tab.component';
×
22
import { ThyActiveTabInfo, ThyTabActiveEvent } from './types';
23
import { ThyTabContentComponent } from './tab-content.component';
24
import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
×
25
import { ThyNavComponent, ThyNavItemDirective } from 'ngx-tethys/nav';
×
26

27
export type ThyTabsSize = 'lg' | 'md' | 'sm';
28

29
export type ThyTabsType = 'pulled' | 'tabs' | 'pills' | 'lite';
×
30

×
31
export type ThyTabsPosition = 'top' | 'left';
×
32

×
33
const _MixinBase: Constructor<ThyUnsubscribe> & typeof MixinBase = mixinUnsubscribe(MixinBase);
×
34

×
35
/**
×
36
 * 选项卡切换组件
×
37
 * @name thy-tabs
×
38
 */
×
39
@Component({
×
40
    selector: 'thy-tabs',
×
41
    templateUrl: './tabs.component.html',
42
    changeDetection: ChangeDetectionStrategy.OnPush,
43
    host: {
×
44
        class: 'thy-tabs',
×
45
        '[class.thy-tabs-top]': `thyPosition === 'top'`,
46
        '[class.thy-tabs-left]': `thyPosition === 'left'`,
47
        '[style.overflow]': `transitionStarted ? "hidden" : null`
×
48
    },
×
49
    standalone: true,
50
    imports: [ThyNavComponent, NgFor, ThyNavItemDirective, NgIf, NgTemplateOutlet, ThyTabContentComponent]
51
})
52
export class ThyTabsComponent extends _MixinBase implements OnInit, OnChanges, AfterContentInit {
×
53
    @ContentChildren(ThyTabComponent, { descendants: true }) tabs = new QueryList<ThyTabComponent>();
×
54

×
55
    /**
×
56
     * 标签类型
×
57
     * @type 'pulled' | 'tabs' | 'pills' | 'lite'
58
     */
59
    @Input() thyType: ThyTabsType = 'tabs';
60

×
61
    /**
×
62
     * 选项卡的大小
×
63
     * @type 'lg' | 'md' | 'sm'
64
     */
65
    @Input() thySize: ThyTabsSize = 'md';
66

×
67
    /**
68
     * 激活的项
69
     */
×
70
    @Input()
×
71
    set thyActiveTab(value: ThyActiveTabInfo) {
72
        if (isString(value)) {
×
73
            this.activeTabId = value;
74
            this.activeTabIndex = undefined;
75
        } else {
×
76
            this.activeTabIndex = value;
×
77
            this.activeTabId = undefined;
78
        }
×
79
    }
×
80

×
81
    /**
×
82
     * 附加操作
×
83
     */
84
    @Input() thyExtra: TemplateRef<unknown>;
85

×
86
    /**
87
     * 选项卡的位置
1✔
88
     * @type 'top' | 'left'
89
     */
90
    @Input() thyPosition: ThyTabsPosition = 'top';
91

1✔
92
    /**
93
     * 是否使用动画切换 Tabs
94
     */
95
    @Input() @InputBoolean() thyAnimated: boolean = false;
96

97
    /**
98
     * 响应式,自动计算宽度存放 thyNavItem,并添加更多弹框
99
     */
100
    @Input() @InputBoolean() thyResponsive: boolean = false;
101

102
    /**
103
     * 激活的项发生改变时的回调
1✔
104
     */
105
    @Output() thyActiveTabChange: EventEmitter<ThyTabActiveEvent> = new EventEmitter<ThyTabActiveEvent>();
106

107
    activeTabIndex: number = 0;
1✔
108

109
    activeTabId: string;
110

111
    transitionStarted: boolean = false;
1✔
112

113
    constructor(private cd: ChangeDetectorRef, private el: ElementRef) {
114
        super();
115
    }
116

117
    ngOnInit(): void {
118
        const tabsContent = this.el.nativeElement.querySelector('.thy-tabs-content');
119
        fromEvent(tabsContent, 'transitionend')
120
            .pipe(takeUntil(this.ngUnsubscribe$))
121
            .subscribe(() => {
122
                this.transitionStarted = false;
123
                this.cd.markForCheck();
124
            });
125
    }
126

127
    ngOnChanges(changes: SimpleChanges): void {
128
        const { thyActiveTab } = changes;
129
        if (thyActiveTab && !thyActiveTab.firstChange && this.thyAnimated) {
130
            const index = thyActiveTab?.currentValue?.index || Array.from(this.tabs).findIndex(k => k.id === thyActiveTab?.currentValue.id);
131
            this.transitionStarted = this.activeTabIndex !== index;
132
            this.activeTabIndex = index;
133
        }
134
    }
135

136
    ngAfterContentInit() {
137
        this.tabs.changes.pipe(takeUntil(this.ngUnsubscribe$)).subscribe(data => {
138
            this.thyAnimated && (this.transitionStarted = true);
139
            this.activeTabIndex = data.length - 1;
140
        });
141
    }
142

143
    get tabPaneAnimated(): boolean {
144
        return this.thyPosition === 'top' && this.thyAnimated;
145
    }
146

147
    getTabContentMarginLeft(): string {
148
        if (this.tabPaneAnimated) {
149
            return `${-(this.activeTabIndex || 0) * 100}%`;
150
        }
151
        return '';
152
    }
153

154
    activeTab(tab: ThyTabComponent, index: number) {
155
        if (tab.thyDisabled) {
156
            return;
157
        }
158
        this.activeTabId = tab.id || null;
159
        this.thyAnimated && (this.transitionStarted = this.activeTabIndex !== index);
160
        this.activeTabIndex = index;
161
        const activeTab = tab.id ? tab.id : index;
162
        this.thyActiveTabChange.emit(activeTab);
163
    }
164

165
    tabTrackBy(index: number, item: ThyTabComponent) {
166
        return index;
167
    }
168
}
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