• 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

95.65
/src/breadcrumb/breadcrumb.component.ts
1
import { Component, ChangeDetectionStrategy, TemplateRef, numberAttribute, input, contentChild, Signal, computed } from '@angular/core';
2
import { ThyIcon } from 'ngx-tethys/icon';
3
import { NgClass, NgTemplateOutlet } from '@angular/common';
4
import { ThyBreadcrumbItem } from './breadcrumb-item.component';
5
import { SafeAny } from 'ngx-tethys/types';
6
import { ThyDropdownDirective, ThyDropdownMenuComponent, ThyDropdownMenuItemDirective } from 'ngx-tethys/dropdown';
7
import { ThyAction } from 'ngx-tethys/action';
8
import { coerceBooleanProperty } from 'ngx-tethys/util';
9

10
const THY_BREADCRUMB_ITEM_ELLIPSIS_ID = 'THY_BREADCRUMB_ITEM_ELLIPSIS_ID';
1✔
11

12
const ELLIPSIS_ITEM = { _id: THY_BREADCRUMB_ITEM_ELLIPSIS_ID };
1✔
13

14
/**
15
 * 面包屑组件
16
 * @name thy-breadcrumb
17
 * @order 10
18
 */
19
@Component({
20
    selector: 'thy-breadcrumb',
21
    templateUrl: './breadcrumb.component.html',
22
    exportAs: 'ThyBreadcrumb',
23
    changeDetection: ChangeDetectionStrategy.OnPush,
24
    host: {
25
        class: 'thy-breadcrumb',
26
        '[class.thy-breadcrumb-separator]': '!!thySeparator()',
27
        '[class.thy-breadcrumb-separator-slash]': 'thySeparator() === "slash"',
28
        '[class.thy-breadcrumb-separator-backslash]': 'thySeparator() === "backslash"',
29
        '[class.thy-breadcrumb-separator-vertical-line]': 'thySeparator() === "vertical-line"'
30
    },
31
    imports: [
32
        ThyIcon,
33
        NgClass,
34
        ThyBreadcrumbItem,
35
        NgTemplateOutlet,
36
        ThyAction,
37
        ThyDropdownDirective,
38
        ThyDropdownMenuItemDirective,
39
        ThyDropdownMenuComponent,
40
        ThyIcon
41
    ]
42
})
43
export class ThyBreadcrumb {
1✔
44
    /**
45
     * 面包屑的前缀 展示图标,如 folder-fill
46
     */
47
    readonly thyIcon = input<string>();
15✔
48

49
    iconClasses: Signal<string[] | null> = computed(() => {
15✔
50
        const icon = this.thyIcon();
11✔
51
        if (icon && icon.includes('wtf')) {
11✔
52
            const classes = icon.split(' ');
1✔
53
            if (classes.length === 1) {
1!
54
                classes.unshift('wtf');
×
55
            }
56
            return classes;
1✔
57
        } else {
58
            return null;
10✔
59
        }
60
    });
61

62
    svgIconName: Signal<string | null> = computed(() => {
15✔
63
        const icon = this.thyIcon();
15✔
64
        if (icon && !icon.includes('wtf')) {
15✔
65
            return icon;
4✔
66
        } else {
67
            return null;
11✔
68
        }
69
    });
70

71
    /**
72
     * 面包屑的分隔符,不传值默认为 ">"
73
     * @type slash | backslash | vertical-line
74
     */
75
    readonly thySeparator = input<'slash' | 'backslash' | 'vertical-line'>();
15✔
76

77
    /**
78
     * 面包屑的每一项数据
79
     */
80
    readonly items = input<SafeAny[]>(undefined, { alias: 'thyItems' });
15✔
81

82
    /**
83
     * 最大显示数量,超出此数量后,面包屑会被省略, 0 表示不省略(仅当传入 thyItems 时有效)
84
     */
85
    readonly thyMaxCount = input(4, { transform: numberAttribute });
15✔
86

87
    /**
88
     * 是否可点击弹出已被省略的面包屑项(仅当传入 thyItems 时有效)
89
     */
90
    readonly thyExpandable = input(true, { transform: coerceBooleanProperty });
15✔
91

92
    /**
93
     * 面包屑的每一项模板(仅当传入 thyItems 时有效)
94
     */
95
    readonly itemTemplate = contentChild<TemplateRef<SafeAny>>('item');
15✔
96

97
    public ellipsisItemId = THY_BREADCRUMB_ITEM_ELLIPSIS_ID;
15✔
98

99
    public readonly processedItems: Signal<
15✔
100
        | {
101
              ellipsisItems: SafeAny[];
102
              showItems: SafeAny[];
103
          }
17✔
104
        | undefined
17✔
105
    > = computed(() => {
11✔
106
        const items = this.items();
107
        if (!items?.length) {
6✔
108
            return;
6✔
109
        }
4✔
110
        const thyMaxCount = this.thyMaxCount();
4✔
111
        if (thyMaxCount && items.length > thyMaxCount) {
112
            const ellipsisIndex = items.length - thyMaxCount + 2;
113
            return {
114
                ellipsisItems: items.slice(1, ellipsisIndex),
115
                showItems: [items[0], ELLIPSIS_ITEM, ...items.slice(ellipsisIndex)]
2✔
116
            };
117
        } else {
118
            return {
119
                ellipsisItems: [],
120
                showItems: [...items]
121
            };
122
        }
123
    });
124
}
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