@foxeltech/angular-ui 0.3.1 → 0.7.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/archivo/archivo-400-latin-ext.woff2 +0 -0
- package/archivo/archivo-400-latin.woff2 +0 -0
- package/archivo/archivo-400-vietnamese.woff2 +0 -0
- package/archivo/archivo-500-latin-ext.woff2 +0 -0
- package/archivo/archivo-500-latin.woff2 +0 -0
- package/archivo/archivo-500-vietnamese.woff2 +0 -0
- package/archivo/archivo-600-latin-ext.woff2 +0 -0
- package/archivo/archivo-600-latin.woff2 +0 -0
- package/archivo/archivo-600-vietnamese.woff2 +0 -0
- package/archivo/archivo-700-latin-ext.woff2 +0 -0
- package/archivo/archivo-700-latin.woff2 +0 -0
- package/archivo/archivo-700-vietnamese.woff2 +0 -0
- package/components.css +12 -12
- package/dialogs.css +2 -2
- package/fesm2022/foxeltech-angular-ui-chart.mjs +560 -0
- package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui-flow.mjs +211 -0
- package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs +156 -0
- package/fesm2022/foxeltech-angular-ui-rich-text.mjs.map +1 -0
- package/fesm2022/foxeltech-angular-ui.mjs +1580 -1409
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/fonts.css +462 -138
- package/fx-icons.svg +97 -0
- package/ibm-plex-mono/ibm-plex-mono-400-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-400-vietnamese.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-500-vietnamese.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-cyrillic-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-cyrillic.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-latin-ext.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-latin.woff2 +0 -0
- package/ibm-plex-mono/ibm-plex-mono-600-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-400-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-500-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-600-vietnamese.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-cyrillic-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-cyrillic.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-greek.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-latin-ext.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-latin.woff2 +0 -0
- package/jetbrains-mono/jetbrains-mono-700-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-400-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-400-latin.woff2 +0 -0
- package/newsreader/newsreader-400-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-500-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-500-latin.woff2 +0 -0
- package/newsreader/newsreader-500-vietnamese.woff2 +0 -0
- package/newsreader/newsreader-600-latin-ext.woff2 +0 -0
- package/newsreader/newsreader-600-latin.woff2 +0 -0
- package/newsreader/newsreader-600-vietnamese.woff2 +0 -0
- package/package.json +18 -9
- package/source-serif-4/source-serif-4-400-cyrillic-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-cyrillic.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-greek.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-latin-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-latin.woff2 +0 -0
- package/source-serif-4/source-serif-4-400-vietnamese.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-cyrillic-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-cyrillic.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-greek.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-latin-ext.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-latin.woff2 +0 -0
- package/source-serif-4/source-serif-4-600-vietnamese.woff2 +0 -0
- package/src/lib/styles/components.css +12 -12
- package/src/lib/styles/dialogs.css +2 -2
- package/src/lib/styles/fonts.css +462 -138
- package/src/lib/styles/tailwind.css +1 -2
- package/src/lib/styles/theme.css +596 -69
- package/src/lib/styles/tokens.css +56 -19
- package/src/lib/styles/utilities.css +4 -1
- package/src/lib/ui/components/bar-list/bar-list.component.html +29 -0
- package/src/lib/ui/components/button/button.component.html +20 -18
- package/src/lib/ui/components/checkbox/checkbox.component.html +3 -3
- package/src/lib/ui/components/circle-progress-bar/circle-progress-bar.component.html +2 -2
- package/src/lib/ui/components/code-block/code-block.component.html +8 -0
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.html +49 -27
- package/src/lib/ui/components/datetime-picker/datetime-picker.component.scss +25 -137
- package/src/lib/ui/components/dnd-upload/dnd-upload.component.html +3 -3
- package/src/lib/ui/components/drawer/drawer.component.html +36 -13
- package/src/lib/ui/components/drawer/drawer.component.scss +104 -18
- package/src/lib/ui/components/empty-state/empty-state.component.html +2 -2
- package/src/lib/ui/components/facets-rail/facets-rail.component.html +42 -0
- package/src/lib/ui/components/filter-pills/filter-pills.component.html +16 -0
- package/src/lib/ui/components/hero-icon/hero-icon.component.html +10 -9
- package/src/lib/ui/components/info-field/info-field.component.html +1 -1
- package/src/lib/ui/components/input/input.component.html +6 -6
- package/src/lib/ui/components/kanban-board/kanban-board.component.html +1 -1
- package/src/lib/ui/components/kanban-board/kanban-board.component.scss +9 -9
- package/src/lib/ui/components/list-row/list-row.component.html +20 -0
- package/src/lib/ui/components/loading-panel/loading-panel.component.html +1 -1
- package/src/lib/ui/components/master-detail/master-detail.component.css +22 -0
- package/src/lib/ui/components/master-detail/master-detail.component.html +42 -10
- package/src/lib/ui/components/menu/menu.component.html +27 -0
- package/src/lib/ui/components/pending-badge/pending-badge.component.html +15 -0
- package/src/lib/ui/components/pipeline-stepper/pipeline-stepper.component.html +45 -0
- package/src/lib/ui/components/project-card/project-card.component.html +102 -0
- package/src/lib/ui/components/radio-button/radio-button.component.html +4 -4
- package/src/lib/ui/components/radio-button-toggle/radio-button-toggle.component.html +4 -4
- package/src/lib/ui/components/sample-frame/sample-frame.component.html +18 -0
- package/src/lib/ui/components/score-badge/score-badge.component.html +7 -0
- package/src/lib/ui/components/screenshot-frame/screenshot-frame.component.html +40 -0
- package/src/lib/ui/components/search-bar/search-bar.component.html +1 -1
- package/src/lib/ui/components/section-card/section-card.component.html +19 -6
- package/src/lib/ui/components/segmented/segmented.component.html +42 -0
- package/src/lib/ui/components/segmented/segmented.component.scss +12 -0
- package/src/lib/ui/components/select/select.component.html +6 -6
- package/src/lib/ui/components/skeleton-detail/skeleton-detail.component.html +2 -2
- package/src/lib/ui/components/skeleton-list/skeleton-list.component.html +1 -1
- package/src/lib/ui/components/skeleton-table-loading/skeleton-table-loading.component.html +5 -5
- package/src/lib/ui/components/slider/slider.component.html +8 -8
- package/src/lib/ui/components/sparkbar/sparkbar.component.html +14 -0
- package/src/lib/ui/components/stage-dots/stage-dots.component.html +13 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +45 -12
- package/src/lib/ui/components/status-dot/status-dot.component.html +13 -0
- package/src/lib/ui/components/switch/switch.component.html +1 -1
- package/src/lib/ui/components/tab-group/tab-group.component.html +41 -12
- package/src/lib/ui/components/tab-group/tab-group.component.scss +41 -1
- package/src/lib/ui/components/table-cell/table-cell.component.html +2 -2
- package/src/lib/ui/components/tag/tag.component.html +4 -4
- package/src/lib/ui/components/theme-picker/theme-picker.component.html +44 -0
- package/src/lib/ui/components/toast/toast.component.html +7 -7
- package/src/lib/ui/components/toast-container/toast-container.component.html +1 -0
- package/src/lib/ui/components/tree-diagram/tree-diagram.component.html +5 -5
- package/tailwind.css +1 -2
- package/theme.css +596 -69
- package/tokens.css +56 -19
- package/types/foxeltech-angular-ui-chart.d.ts +65 -0
- package/types/foxeltech-angular-ui-flow.d.ts +96 -0
- package/types/foxeltech-angular-ui-rich-text.d.ts +35 -0
- package/types/foxeltech-angular-ui.d.ts +1018 -395
- package/utilities.css +4 -1
- package/BeVietnamPro/BeVietnamPro-Bold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-ExtraLight.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Light.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Medium.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Regular.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-SemiBold.woff2 +0 -0
- package/BeVietnamPro/BeVietnamPro-Thin.woff2 +0 -0
- package/SpaceMono-Regular.woff2 +0 -0
- package/dm-sans/DMSans-Bold.woff2 +0 -0
- package/dm-sans/DMSans-Light.woff2 +0 -0
- package/dm-sans/DMSans-Medium.woff2 +0 -0
- package/dm-sans/DMSans-Regular.woff2 +0 -0
- package/dm-sans/DMSans-SemiBold.woff2 +0 -0
- package/dm-sans/DMSans-Thin.woff2 +0 -0
- package/orbitron/Orbitron-Bold.woff2 +0 -0
- package/orbitron/Orbitron-Medium.woff2 +0 -0
- package/orbitron/Orbitron-Regular.woff2 +0 -0
- package/orbitron/Orbitron-SemiBold.woff2 +0 -0
- package/roboto/Roboto-Black.woff2 +0 -0
- package/roboto/Roboto-BlackItalic.woff2 +0 -0
- package/roboto/Roboto-Bold.woff2 +0 -0
- package/roboto/Roboto-BoldCondensed.woff2 +0 -0
- package/roboto/Roboto-BoldCondensedItalic.woff2 +0 -0
- package/roboto/Roboto-BoldItalic.woff2 +0 -0
- package/roboto/Roboto-Condensed.woff2 +0 -0
- package/roboto/Roboto-CondensedItalic.woff2 +0 -0
- package/roboto/Roboto-Italic.woff2 +0 -0
- package/roboto/Roboto-Light.woff2 +0 -0
- package/roboto/Roboto-LightItalic.woff2 +0 -0
- package/roboto/Roboto-Medium.woff2 +0 -0
- package/roboto/Roboto-MediumItalic.woff2 +0 -0
- package/roboto/Roboto-Regular.woff2 +0 -0
- package/roboto/Roboto-Thin.woff2 +0 -0
- package/roboto/Roboto-ThinItalic.woff2 +0 -0
- package/src/lib/ui/components/chart/chart.component.html +0 -20
- package/src/lib/ui/components/chart/chart.component.scss +0 -49
- package/src/lib/ui/components/flow-connection/flow-connection.component.html +0 -10
- package/src/lib/ui/components/flow-connection/flow-connection.component.scss +0 -0
- package/src/lib/ui/components/rich-text-area/rich-text-area.component.html +0 -3
- package/src/lib/ui/components/rich-text-area/rich-text-area.component.scss +0 -18
|
@@ -6,11 +6,75 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.drawer-host-wrapper {
|
|
9
|
-
|
|
9
|
+
/* Column flex: logo (fixed) + container (flex-1). The container was h-full
|
|
10
|
+
UNDER a 60px logo -> the drawer overflowed the viewport by 60px and the
|
|
11
|
+
footer (account block) sagged below the fold; opening its menu then
|
|
12
|
+
scroll-jumped the page. */
|
|
13
|
+
/* Nền SECONDARY (--og-page-bg) đặt ở WRAPPER chứ không ở .drawer-container:
|
|
14
|
+
hàng brand nằm ngoài container, nếu tô ở container thì 60px trên cùng
|
|
15
|
+
lộ nền của trang. Sáng: drawer xám, nội dung trắng; tối: drawer tối hơn
|
|
16
|
+
surface — đúng quy ước sidebar của cả hai chiều. */
|
|
17
|
+
@apply relative h-full border-r border-border-default flex flex-col bg-page;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Brand row — phải thẳng hàng với icon của nav item.
|
|
21
|
+
Icon nav nằm ở 24px tính từ mép drawer: 8px của .drawer-container (px-2)
|
|
22
|
+
+ 16px padding-left inline của .drawer-item. Brand nằm NGOÀI container
|
|
23
|
+
nên phải tự cộng đủ 24px (trước đây p-4 + ml-5 = 36px → lệch 12px). */
|
|
24
|
+
.drawer-brand {
|
|
25
|
+
@apply h-[60px] shrink-0 flex items-center gap-3 no-underline overflow-hidden;
|
|
26
|
+
padding-left: 24px;
|
|
27
|
+
padding-right: 8px;
|
|
28
|
+
transition: padding 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
29
|
+
/* max-width là BẮT BUỘC: .drawer-host-wrapper là flex column có width auto
|
|
30
|
+
nên bề rộng của nó = max bề rộng các con. Chỉ .drawer-container được
|
|
31
|
+
animate 70/260px, còn hàng brand thì tự do — một tagline dài (VD "Binary
|
|
32
|
+
Exploit Intelligence Platform") sẽ NỚI RỘNG cả drawer thay vì xuống dòng.
|
|
33
|
+
Hai con số dưới đây phải khớp trigger drawerExpand trong drawer.component.ts. */
|
|
34
|
+
max-width: 260px;
|
|
35
|
+
|
|
36
|
+
/* Thu gọn: drawer rộng 70px, icon nav (20px @ 24px) có tâm 34px ≈ tâm
|
|
37
|
+
drawer 35px → căn giữa là khớp, không cần trừ bì. */
|
|
38
|
+
&.is-collapsed {
|
|
39
|
+
@apply justify-center;
|
|
40
|
+
padding-left: 0;
|
|
41
|
+
padding-right: 0;
|
|
42
|
+
max-width: 70px;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.drawer-brand-mark {
|
|
47
|
+
@apply h-[20px] w-auto shrink-0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Cột chữ: title + subtitle xếp dọc. min-w-0 để truncate hoạt động khi
|
|
51
|
+
drawer bị bóp — thiếu nó thì chữ đẩy tràn ra ngoài thay vì cắt. */
|
|
52
|
+
.drawer-brand-copy {
|
|
53
|
+
@apply flex flex-col min-w-0 leading-tight;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Wordmark: dùng CHỮ THẬT chứ không phải ảnh text_logo.png — ảnh đó là
|
|
57
|
+
navy đặc nên chìm hẳn trên theme dark; chữ ăn --og-text nên đúng cả 6. */
|
|
58
|
+
.drawer-brand-text {
|
|
59
|
+
@apply truncate text-[15px] font-semibold text-text-primary select-none;
|
|
60
|
+
font-family: var(--og-font-display);
|
|
61
|
+
letter-spacing: -0.01em;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Subtitle: 11px muted, cùng cỡ với .drawer-version và caption
|
|
65
|
+
ADMINISTRATION nên không tự sinh ra một bậc typography mới. */
|
|
66
|
+
/* line-clamp-2 chứ không phải truncate: tagline dài (VD "Binary Exploit
|
|
67
|
+
Intelligence Platform") không lọt một dòng trong cột chữ ~188px của drawer
|
|
68
|
+
260px, truncate sẽ cắt mất chữ. Hai dòng vẫn nằm gọn trong 60px của
|
|
69
|
+
.drawer-brand (18.75 + 1 + 27.5 = 47px). */
|
|
70
|
+
.drawer-brand-subtext {
|
|
71
|
+
@apply line-clamp-2 text-[11px] text-text-placeholder select-none mt-[1px];
|
|
72
|
+
letter-spacing: var(--og-tracking-label);
|
|
10
73
|
}
|
|
11
74
|
|
|
12
75
|
.drawer-container {
|
|
13
|
-
|
|
76
|
+
/* Nền do .drawer-host-wrapper lo — container để trong suốt. */
|
|
77
|
+
@apply px-2 flex-1 min-h-0 flex flex-col overflow-hidden;
|
|
14
78
|
transition: width 300ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
15
79
|
}
|
|
16
80
|
|
|
@@ -33,6 +97,10 @@
|
|
|
33
97
|
}
|
|
34
98
|
}
|
|
35
99
|
|
|
100
|
+
.drawer-footer-nav {
|
|
101
|
+
@apply border-t border-border-default pt-2 pb-1 px-0;
|
|
102
|
+
}
|
|
103
|
+
|
|
36
104
|
.drawer-nav {
|
|
37
105
|
@apply flex-1 overflow-y-auto overflow-x-hidden py-2;
|
|
38
106
|
|
|
@@ -54,6 +122,15 @@
|
|
|
54
122
|
}
|
|
55
123
|
}
|
|
56
124
|
|
|
125
|
+
.drawer-section-label {
|
|
126
|
+
@apply px-large pt-4 pb-1 text-[11px] font-semibold uppercase text-faint select-none;
|
|
127
|
+
letter-spacing: var(--og-tracking-label);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.drawer-section-rule {
|
|
131
|
+
@apply mx-3 my-3 border-t border-border-default;
|
|
132
|
+
}
|
|
133
|
+
|
|
57
134
|
.drawer-item-wrapper {
|
|
58
135
|
@apply relative;
|
|
59
136
|
}
|
|
@@ -62,15 +139,35 @@
|
|
|
62
139
|
@apply flex items-center mt-1 w-full min-h-8 py-2 px-large border-none bg-transparent cursor-pointer no-underline text-text-primary relative rounded;
|
|
63
140
|
transition: all 200ms ease;
|
|
64
141
|
|
|
142
|
+
/* Hover = glass mờ hơn: chỉ translucent, chưa có viền/shadow, để không
|
|
143
|
+
nhầm với hàng đang chọn. */
|
|
65
144
|
&:hover {
|
|
66
|
-
@apply
|
|
145
|
+
@apply text-text-primary scale-95;
|
|
146
|
+
background: rgb(var(--og-surface-raised) / 0.5);
|
|
67
147
|
}
|
|
68
148
|
|
|
149
|
+
/* Hàng đang chọn = GLASS, KHÔNG dùng màu primary (anh Tú chốt 31/08):
|
|
150
|
+
một tấm surface trong suốt nổi trên nền secondary của drawer + viền
|
|
151
|
+
hairline + shadow nhẹ. Chữ/icon giữ màu text thường.
|
|
152
|
+
- surface-RAISED (không phải surface) vì ở charcoal raised (#211c1b)
|
|
153
|
+
sáng hơn page-bg (#0e0e10) nên tấm kính vẫn nổi; ở porcelain cả hai
|
|
154
|
+
đều là trắng nên không khác gì.
|
|
155
|
+
- Viền vẽ bằng inset box-shadow chứ không phải `border`: .drawer-item
|
|
156
|
+
khai border-none, thêm border thật sẽ đẩy layout 1px.
|
|
157
|
+
- backdrop-blur chỉ có tác dụng khi nền sau có hoạ tiết/gradient; nền
|
|
158
|
+
phẳng thì hiệu ứng đến từ độ trong + viền + shadow. */
|
|
69
159
|
&.active {
|
|
70
|
-
@apply
|
|
160
|
+
@apply text-text-primary font-medium;
|
|
161
|
+
background: rgb(var(--og-surface-raised) / 0.8);
|
|
162
|
+
backdrop-filter: blur(12px);
|
|
163
|
+
/* shadow viết literal chứ không dùng var(--shadow-sm): biến đó do @theme
|
|
164
|
+
của Tailwind sinh, không chắc có mặt trong scope của component SCSS. */
|
|
165
|
+
box-shadow:
|
|
166
|
+
inset 0 0 0 1px rgb(var(--og-border)),
|
|
167
|
+
0 1px 2px 0 rgb(var(--shadow-color) / 0.05);
|
|
71
168
|
|
|
72
|
-
|
|
73
|
-
|
|
169
|
+
&:hover {
|
|
170
|
+
background: rgb(var(--og-surface-raised) / 0.95);
|
|
74
171
|
}
|
|
75
172
|
}
|
|
76
173
|
|
|
@@ -114,21 +211,10 @@
|
|
|
114
211
|
|
|
115
212
|
.drawer-version {
|
|
116
213
|
@apply flex items-center justify-center py-3 px-4 text-text-placeholder text-[11px] border-t border-border-default select-none;
|
|
117
|
-
font-family:
|
|
214
|
+
font-family: var(--og-font-mono);
|
|
118
215
|
}
|
|
119
216
|
|
|
120
217
|
.drawer-version-dot {
|
|
121
218
|
@apply block w-1.5 h-1.5 rounded-full bg-text-placeholder;
|
|
122
219
|
}
|
|
123
220
|
|
|
124
|
-
/* Collapsed mode: center the icons */
|
|
125
|
-
.drawer-container[style*='width: 64px'] {
|
|
126
|
-
.drawer-item {
|
|
127
|
-
@apply justify-center;
|
|
128
|
-
padding-left: 16px !important;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.item-content {
|
|
132
|
-
@apply justify-center;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<div
|
|
2
2
|
class="flex flex-col items-center justify-center gap-small w-full"
|
|
3
|
-
[style.minHeight]="height"
|
|
3
|
+
[style.minHeight]="height()"
|
|
4
4
|
>
|
|
5
5
|
@if (icon) {
|
|
6
6
|
<fx-ui-hero-icon class="text-text-placeholder" [icon]="icon" [size]="24"></fx-ui-hero-icon>
|
|
7
7
|
}
|
|
8
|
-
<div class="txt-default text-text-placeholder">{{ message }}</div>
|
|
8
|
+
<div class="txt-default text-text-placeholder">{{ message() }}</div>
|
|
9
9
|
</div>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<div class="flex flex-col gap-large">
|
|
2
|
+
@if (hasSelection()) {
|
|
3
|
+
<button type="button" class="txt-link self-end" (click)="reset()">
|
|
4
|
+
{{ resetLabel() }}
|
|
5
|
+
</button>
|
|
6
|
+
}
|
|
7
|
+
@for (group of groups(); track group.id) {
|
|
8
|
+
<div role="group" [attr.aria-label]="group.label">
|
|
9
|
+
<div
|
|
10
|
+
class="txt-table-header uppercase mb-small"
|
|
11
|
+
[style.letter-spacing]="'var(--og-tracking-label)'"
|
|
12
|
+
>
|
|
13
|
+
{{ group.label }}
|
|
14
|
+
</div>
|
|
15
|
+
<div class="flex flex-col gap-xs">
|
|
16
|
+
@for (option of group.options; track option.value) {
|
|
17
|
+
<button
|
|
18
|
+
type="button"
|
|
19
|
+
(click)="toggle(group, option)"
|
|
20
|
+
[attr.aria-pressed]="isSelected(group, option)"
|
|
21
|
+
class="flex items-center gap-normal px-normal py-small rounded-control text-left transition-colors"
|
|
22
|
+
[ngClass]="
|
|
23
|
+
isSelected(group, option)
|
|
24
|
+
? 'bg-accent-soft text-accent-soft-fg font-medium'
|
|
25
|
+
: 'text-body hover:bg-surface-sunken'
|
|
26
|
+
"
|
|
27
|
+
>
|
|
28
|
+
@if (option.tone) {
|
|
29
|
+
<fx-ui-status-dot [tone]="option.tone" [size]="7" />
|
|
30
|
+
}
|
|
31
|
+
<span class="text-sm truncate flex-1">{{ option.label }}</span>
|
|
32
|
+
@if (option.count !== undefined) {
|
|
33
|
+
<span class="txt-tag-label text-faint" style="font-family: var(--og-font-figure)">
|
|
34
|
+
{{ option.count }}
|
|
35
|
+
</span>
|
|
36
|
+
}
|
|
37
|
+
</button>
|
|
38
|
+
}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
}
|
|
42
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="flex flex-wrap items-center gap-small">
|
|
2
|
+
@for (option of options(); track option.value) {
|
|
3
|
+
<button
|
|
4
|
+
type="button"
|
|
5
|
+
[attr.aria-pressed]="isActive(option)"
|
|
6
|
+
class="flex items-center gap-small px-semi py-xs rounded-full border txt-utility-caption font-bold cursor-pointer transition-colors"
|
|
7
|
+
[ngClass]="pillClass(option)"
|
|
8
|
+
(click)="valueChange.emit(option.value)"
|
|
9
|
+
>
|
|
10
|
+
{{ option.label }}
|
|
11
|
+
@if (option.count !== null && option.count !== undefined) {
|
|
12
|
+
<span [ngClass]="countClass(option)" style="font-family: var(--og-font-figure)">{{ option.count }}</span>
|
|
13
|
+
}
|
|
14
|
+
</button>
|
|
15
|
+
}
|
|
16
|
+
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
<
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
6
|
-
[
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/>
|
|
1
|
+
<svg
|
|
2
|
+
[attr.width]="size() || 24"
|
|
3
|
+
[attr.height]="size() || 24"
|
|
4
|
+
[attr.stroke-width]="solid() ? null : stroke()"
|
|
5
|
+
[style.color]="color() || null"
|
|
6
|
+
[class]="class()"
|
|
7
|
+
aria-hidden="true"
|
|
8
|
+
>
|
|
9
|
+
<use [attr.href]="href" />
|
|
10
|
+
</svg>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<div class="mb-4 text-left w-full text-text-primary" [class]="class">
|
|
1
|
+
<div class="mb-4 text-left w-full text-text-primary" [class]="class()">
|
|
2
2
|
@if (label) {
|
|
3
3
|
<label class="block txt-field-label" [attr.for]="fieldId">
|
|
4
4
|
{{ label }}
|
|
5
|
-
@if (required) {
|
|
5
|
+
@if (required()) {
|
|
6
6
|
<span class="txt-required" aria-hidden="true">*</span>
|
|
7
7
|
}
|
|
8
8
|
@if (tooltip) {
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
[appTrimOnBlurCollapse]="true"
|
|
25
25
|
[id]="fieldId"
|
|
26
26
|
[type]="displayType"
|
|
27
|
-
[placeholder]="placeholder"
|
|
27
|
+
[placeholder]="placeholder()"
|
|
28
28
|
[disabled]="disabled"
|
|
29
29
|
[value]="value"
|
|
30
30
|
(input)="onInput($event)"
|
|
31
31
|
(blur)="onBlur()"
|
|
32
32
|
(focus)="onFocus()"
|
|
33
|
-
[attr.maxlength]="maxlength"
|
|
33
|
+
[attr.maxlength]="maxlength()"
|
|
34
34
|
[attr.aria-invalid]="invalid || null"
|
|
35
35
|
[attr.aria-describedby]="invalid ? fieldId + '-error' : null"
|
|
36
|
-
[attr.aria-required]="required ? true : null"
|
|
36
|
+
[attr.aria-required]="required() ? true : null"
|
|
37
37
|
[class]="type === 'otp' ? 'input-otp' : 'input-default'"
|
|
38
38
|
[class.input-invalid]="invalid"
|
|
39
39
|
[class.pr-8]="type === 'password' || suffixIcon"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
[attr.aria-label]="
|
|
49
49
|
type === 'password'
|
|
50
50
|
? (showPassword ? 'Hide password' : 'Show password')
|
|
51
|
-
: (suffixAriaLabel || null)
|
|
51
|
+
: (suffixAriaLabel() || null)
|
|
52
52
|
"
|
|
53
53
|
[attr.aria-pressed]="type === 'password' ? showPassword : null"
|
|
54
54
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="kanban-board">
|
|
2
2
|
<div class="kanban-columns">
|
|
3
|
-
@for (column of columns; track column.id) {
|
|
3
|
+
@for (column of columns(); track column.id) {
|
|
4
4
|
<div class="kanban-column">
|
|
5
5
|
<div class="kanban-column-header">
|
|
6
6
|
<h3 class="kanban-column-title">{{ column.title }}</h3>
|
|
@@ -10,20 +10,20 @@
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
.kanban-column {
|
|
13
|
-
@apply flex flex-col min-w-[300px] bg-
|
|
13
|
+
@apply flex flex-col min-w-[300px] bg-surface-sunken rounded-lg;
|
|
14
14
|
flex-shrink: 0;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
.kanban-column-header {
|
|
18
|
-
@apply flex items-center justify-between p-4 border-b border-
|
|
18
|
+
@apply flex items-center justify-between p-4 border-b border-border;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
.kanban-column-title {
|
|
22
|
-
@apply text-lg font-semibold text-
|
|
22
|
+
@apply text-lg font-semibold text-strong m-0;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
.kanban-column-count {
|
|
26
|
-
@apply px-2 py-1 text-sm font-medium bg-
|
|
26
|
+
@apply px-2 py-1 text-sm font-medium bg-neutral-soft text-neutral-soft-fg rounded-full;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.kanban-column-content {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.kanban-item {
|
|
35
|
-
@apply bg-
|
|
35
|
+
@apply bg-surface-raised rounded-lg shadow-sm border border-border;
|
|
36
36
|
@apply transition-shadow duration-200;
|
|
37
37
|
cursor: move;
|
|
38
38
|
|
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
.kanban-item-default {
|
|
45
|
-
@apply p-4 text-
|
|
45
|
+
@apply p-4 text-strong;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.kanban-item-placeholder {
|
|
49
|
-
@apply bg-
|
|
49
|
+
@apply bg-neutral-soft rounded-lg border-2 border-dashed border-border-strong;
|
|
50
50
|
@apply opacity-50;
|
|
51
51
|
min-height: 60px;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
.kanban-column-empty {
|
|
55
|
-
@apply flex items-center justify-center h-32 text-
|
|
56
|
-
@apply border-2 border-dashed border-
|
|
55
|
+
@apply flex items-center justify-center h-32 text-faint text-sm;
|
|
56
|
+
@apply border-2 border-dashed border-border rounded-lg;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// CDK Drag and Drop Styles
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<div class="flex items-center gap-normal min-w-0">
|
|
2
|
+
@if (dotTone() !== undefined) {
|
|
3
|
+
<fx-ui-status-dot [tone]="dotTone() ?? null" [pulse]="dotPulse()" />
|
|
4
|
+
}
|
|
5
|
+
<span class="txt-body-medium-01 truncate flex-1">{{ title() }}</span>
|
|
6
|
+
@for (badge of badges(); track badge.label) {
|
|
7
|
+
<span
|
|
8
|
+
class="txt-tag-label px-normal py-[1px] rounded-pill whitespace-nowrap"
|
|
9
|
+
[ngClass]="badgeClass(badge)"
|
|
10
|
+
>
|
|
11
|
+
{{ badge.label }}
|
|
12
|
+
</span>
|
|
13
|
+
}
|
|
14
|
+
</div>
|
|
15
|
+
@if (meta()) {
|
|
16
|
+
<div class="txt-utility-description mt-xs truncate" [class.ml-large]="dotTone() !== undefined">
|
|
17
|
+
{{ meta() }}
|
|
18
|
+
</div>
|
|
19
|
+
}
|
|
20
|
+
<ng-content></ng-content>
|
|
@@ -9,3 +9,25 @@
|
|
|
9
9
|
flex-shrink: 0;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
+
|
|
13
|
+
/* Facets rail: full-width when stacked; fixed narrow column on lg+. */
|
|
14
|
+
.fx-md-facets {
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (min-width: 1080px) {
|
|
19
|
+
.fx-md-facets {
|
|
20
|
+
width: 230px;
|
|
21
|
+
flex-shrink: 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* prevnext style: the Material paginator stays as the paging engine but is
|
|
26
|
+
visually removed (display:none would break its measurements on re-show). */
|
|
27
|
+
.fx-md-paginator-hidden {
|
|
28
|
+
position: absolute !important;
|
|
29
|
+
width: 1px;
|
|
30
|
+
height: 1px;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
clip-path: inset(50%);
|
|
33
|
+
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
<div class="flex flex-col lg:flex-row items-start gap-xl" [style.--fx-md-list-width]="listWidth">
|
|
1
|
+
<div class="flex flex-col lg:flex-row items-start gap-xl" [style.--fx-md-list-width]="listWidth()">
|
|
2
|
+
<!-- Facets rail (V2 3-column lookup) — wrapper always rendered so ng-content
|
|
3
|
+
stays unconditional; hidden when the host projects nothing. -->
|
|
4
|
+
<div class="fx-md-facets card-common bg-surface" [class.hidden]="!hasFacets">
|
|
5
|
+
<ng-content select="[mdFacets]"></ng-content>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
2
8
|
<!-- Master: list pane -->
|
|
3
9
|
<div class="fx-md-list card-common">
|
|
4
10
|
<ng-content select="[mdHeader]"></ng-content>
|
|
5
11
|
<ng-content select="[mdFilters]"></ng-content>
|
|
6
12
|
<div
|
|
7
13
|
class="flex flex-col gap-normal overflow-auto pr-xs"
|
|
8
|
-
[style.maxHeight]="maxListHeight"
|
|
14
|
+
[style.maxHeight]="maxListHeight()"
|
|
9
15
|
role="listbox"
|
|
10
|
-
[attr.aria-label]="listLabel || null"
|
|
16
|
+
[attr.aria-label]="listLabel() || null"
|
|
11
17
|
>
|
|
12
18
|
@if (table.loading) {
|
|
13
19
|
<fx-ui-skeleton-list [rows]="table.pageSize"></fx-ui-skeleton-list>
|
|
@@ -24,18 +30,18 @@
|
|
|
24
30
|
class="text-left rounded-lg border p-semi transition-colors"
|
|
25
31
|
[ngClass]="
|
|
26
32
|
isSelected(row)
|
|
27
|
-
? 'border-
|
|
33
|
+
? 'border-accent bg-accent-soft/60'
|
|
28
34
|
: 'border-border-default hover:border-border-interactive bg-bg-primary'
|
|
29
35
|
"
|
|
30
36
|
>
|
|
31
37
|
<ng-container
|
|
32
|
-
[ngTemplateOutlet]="rowTemplate"
|
|
38
|
+
[ngTemplateOutlet]="rowTemplate()"
|
|
33
39
|
[ngTemplateOutletContext]="{ $implicit: row, selected: isSelected(row) }"
|
|
34
40
|
></ng-container>
|
|
35
41
|
</button>
|
|
36
42
|
}
|
|
37
43
|
@if (!table.dataSource.data.length) {
|
|
38
|
-
<fx-ui-empty-state [message]="emptyMessage"></fx-ui-empty-state>
|
|
44
|
+
<fx-ui-empty-state [message]="emptyMessage()"></fx-ui-empty-state>
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
47
|
</div>
|
|
@@ -44,26 +50,52 @@
|
|
|
44
50
|
wires page events — a binding here would double-fetch every change. -->
|
|
45
51
|
<mat-paginator
|
|
46
52
|
class="mt-normal"
|
|
53
|
+
[class.fx-md-paginator-hidden]="paginationStyle() === 'prevnext'"
|
|
47
54
|
[length]="table.total"
|
|
48
55
|
[pageSize]="table.pageSize"
|
|
49
|
-
[pageSizeOptions]="pageSizeOptions"
|
|
56
|
+
[pageSizeOptions]="pageSizeOptions()"
|
|
50
57
|
></mat-paginator>
|
|
58
|
+
@if (paginationStyle() === 'prevnext') {
|
|
59
|
+
<div class="flex items-center justify-between mt-normal">
|
|
60
|
+
<span class="txt-utility-description" style="font-family: var(--og-font-figure)">
|
|
61
|
+
{{ rangeText() }}
|
|
62
|
+
</span>
|
|
63
|
+
<div class="flex gap-small">
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
class="btn-alternative !h-8 !px-semi text-sm"
|
|
67
|
+
[disabled]="!paginator().hasPreviousPage()"
|
|
68
|
+
(click)="paginator().previousPage()"
|
|
69
|
+
>
|
|
70
|
+
{{ prevLabel() }}
|
|
71
|
+
</button>
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
class="btn-alternative !h-8 !px-semi text-sm"
|
|
75
|
+
[disabled]="!paginator().hasNextPage()"
|
|
76
|
+
(click)="paginator().nextPage()"
|
|
77
|
+
>
|
|
78
|
+
{{ nextLabel() }}
|
|
79
|
+
</button>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
}
|
|
51
83
|
</div>
|
|
52
84
|
|
|
53
85
|
<!-- Detail pane -->
|
|
54
86
|
<div class="w-full lg:flex-1 min-w-0">
|
|
55
87
|
@if (table.selected) {
|
|
56
88
|
@if (table.detailBusy) {
|
|
57
|
-
<fx-ui-skeleton-detail [cards]="skeletonCards"></fx-ui-skeleton-detail>
|
|
89
|
+
<fx-ui-skeleton-detail [cards]="skeletonCards()"></fx-ui-skeleton-detail>
|
|
58
90
|
} @else {
|
|
59
91
|
<ng-container
|
|
60
|
-
[ngTemplateOutlet]="detailTemplate"
|
|
92
|
+
[ngTemplateOutlet]="detailTemplate()"
|
|
61
93
|
[ngTemplateOutletContext]="{ $implicit: table.detail, selected: table.selected }"
|
|
62
94
|
></ng-container>
|
|
63
95
|
}
|
|
64
96
|
} @else {
|
|
65
97
|
<div class="card-common flex items-center justify-center h-[300px]">
|
|
66
|
-
<fx-ui-empty-state [message]="emptyMessage"></fx-ui-empty-state>
|
|
98
|
+
<fx-ui-empty-state [message]="emptyMessage()"></fx-ui-empty-state>
|
|
67
99
|
</div>
|
|
68
100
|
}
|
|
69
101
|
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<button
|
|
2
|
+
type="button"
|
|
3
|
+
class="inline-flex items-center justify-center rounded-lg p-1 hover:bg-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
4
|
+
[matMenuTriggerFor]="menu"
|
|
5
|
+
[disabled]="disabled()"
|
|
6
|
+
[attr.aria-label]="ariaLabel()"
|
|
7
|
+
>
|
|
8
|
+
<ng-content></ng-content>
|
|
9
|
+
</button>
|
|
10
|
+
|
|
11
|
+
<mat-menu #menu="matMenu">
|
|
12
|
+
@for (item of items(); track item.label) {
|
|
13
|
+
<button
|
|
14
|
+
mat-menu-item
|
|
15
|
+
type="button"
|
|
16
|
+
[disabled]="item.disabled"
|
|
17
|
+
(click)="select.emit(item)"
|
|
18
|
+
>
|
|
19
|
+
<span class="flex items-center gap-normal" [class]="toneClass(item)">
|
|
20
|
+
@if (item.icon) {
|
|
21
|
+
<fx-ui-hero-icon [icon]="item.icon" [size]="18"></fx-ui-hero-icon>
|
|
22
|
+
}
|
|
23
|
+
<span>{{ item.label }}</span>
|
|
24
|
+
</span>
|
|
25
|
+
</button>
|
|
26
|
+
}
|
|
27
|
+
</mat-menu>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@if (variant() === 'dot') {
|
|
2
|
+
<span
|
|
3
|
+
class="inline-block w-[7px] h-[7px] rounded-full bg-warning/70 align-middle"
|
|
4
|
+
[attr.title]="tooltip"
|
|
5
|
+
[attr.aria-label]="tooltip"
|
|
6
|
+
></span>
|
|
7
|
+
} @else {
|
|
8
|
+
<span
|
|
9
|
+
class="inline-flex items-center gap-xs px-small py-[1px] rounded-pill border border-dashed border-warning/60 bg-warning/10 text-warning txt-tag-label whitespace-nowrap align-middle"
|
|
10
|
+
[attr.title]="tooltip"
|
|
11
|
+
>
|
|
12
|
+
<fx-ui-hero-icon icon="clock" [size]="11" class="flex" />
|
|
13
|
+
{{ label() }}
|
|
14
|
+
</span>
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<ol class="flex items-start overflow-x-auto pb-small" role="list">
|
|
2
|
+
@for (stage of stages(); track stage.id; let i = $index; let last = $last) {
|
|
3
|
+
<li class="flex items-start" [class.flex-1]="!last" [attr.aria-current]="stateOf(stage) === 'active' ? 'step' : null">
|
|
4
|
+
<button
|
|
5
|
+
type="button"
|
|
6
|
+
class="flex flex-col items-center gap-xs min-w-20 px-xs"
|
|
7
|
+
[class.cursor-pointer]="canClick(stage)"
|
|
8
|
+
[class.cursor-default]="!canClick(stage)"
|
|
9
|
+
[tabindex]="canClick(stage) ? 0 : -1"
|
|
10
|
+
(click)="onStageClick(stage, i)"
|
|
11
|
+
>
|
|
12
|
+
<span
|
|
13
|
+
class="w-8 h-8 rounded-full border-2 flex items-center justify-center text-sm font-semibold transition-colors"
|
|
14
|
+
[ngClass]="circleClass(stage)"
|
|
15
|
+
>
|
|
16
|
+
@switch (stateOf(stage)) {
|
|
17
|
+
@case ('done') {
|
|
18
|
+
<fx-ui-hero-icon icon="check" [size]="16" class="flex" />
|
|
19
|
+
}
|
|
20
|
+
@case ('error') {
|
|
21
|
+
<fx-ui-hero-icon icon="exclamation-triangle" [size]="16" class="flex" />
|
|
22
|
+
}
|
|
23
|
+
@default {
|
|
24
|
+
{{ i + 1 }}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
</span>
|
|
28
|
+
<span class="text-xs text-center whitespace-nowrap" [ngClass]="labelClass(stage)">
|
|
29
|
+
{{ stage.label }}
|
|
30
|
+
</span>
|
|
31
|
+
@if (stage.description) {
|
|
32
|
+
<span class="txt-utility-description text-center whitespace-nowrap">
|
|
33
|
+
{{ stage.description }}
|
|
34
|
+
</span>
|
|
35
|
+
}
|
|
36
|
+
</button>
|
|
37
|
+
@if (!last) {
|
|
38
|
+
<div class="flex-1 h-[2px] mt-4 mx-xs rounded-pill min-w-6" [ngClass]="connectorClass(stage)"></div>
|
|
39
|
+
}
|
|
40
|
+
</li>
|
|
41
|
+
}
|
|
42
|
+
</ol>
|
|
43
|
+
<div class="mt-large">
|
|
44
|
+
<ng-content></ng-content>
|
|
45
|
+
</div>
|