@libs-ui/components-badge 0.2.355-9 → 0.2.356-0
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/README.md +146 -80
- package/badge.component.d.ts +67 -0
- package/esm2022/badge.component.mjs +92 -8
- package/esm2022/interfaces/badge.interface.mjs +1 -1
- package/esm2022/interfaces/mode.type.mjs +1 -1
- package/fesm2022/libs-ui-components-badge.mjs +91 -7
- package/fesm2022/libs-ui-components-badge.mjs.map +1 -1
- package/interfaces/badge.interface.d.ts +33 -0
- package/interfaces/mode.type.d.ts +15 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,114 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @libs-ui/components-badge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Component hiển thị số lượng/đếm (badge) với nhiều chế độ định dạng cho Angular.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Giới thiệu
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`LibsUiComponentsBadgeComponent` là một standalone Angular component để hiển thị số lượng với các tính năng:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- ✅ Nhiều chế độ hiển thị (x, 0x, x+, +x, k)
|
|
10
|
+
- ✅ Rút gọn số lớn tự động (1K, 1.5K, 1M)
|
|
11
|
+
- ✅ Hiển thị dạng "99+" khi vượt giới hạn
|
|
12
|
+
- ✅ Hỗ trợ trạng thái active với màu sắc khác
|
|
13
|
+
- ✅ Tích hợp Popover tooltip
|
|
14
|
+
- ✅ OnPush Change Detection cho hiệu năng cao
|
|
15
|
+
- ✅ Sử dụng Angular Signals
|
|
13
16
|
|
|
14
17
|
## Cài đặt
|
|
15
18
|
|
|
16
|
-
### Yêu cầu
|
|
17
|
-
|
|
18
|
-
- Angular 18.0.0 trở lên
|
|
19
|
-
- Tailwind CSS 3.3.0 trở lên
|
|
20
|
-
|
|
21
|
-
Để cài đặt component `badge`, sử dụng npm hoặc yarn:
|
|
22
|
-
|
|
23
19
|
```bash
|
|
20
|
+
# npm
|
|
24
21
|
npm install @libs-ui/components-badge
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
hoặc
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
# yarn
|
|
30
24
|
yarn add @libs-ui/components-badge
|
|
31
25
|
```
|
|
32
26
|
|
|
33
27
|
## Sử dụng
|
|
34
28
|
|
|
35
|
-
###
|
|
29
|
+
### Import Component
|
|
36
30
|
|
|
37
31
|
```typescript
|
|
38
32
|
import { Component } from '@angular/core';
|
|
39
|
-
import { LibsUiComponentsBadgeComponent } from '@libs-ui/components-badge';
|
|
33
|
+
import { LibsUiComponentsBadgeComponent, TYPE_BADGE_MODE } from '@libs-ui/components-badge';
|
|
40
34
|
|
|
41
35
|
@Component({
|
|
42
36
|
selector: 'app-example',
|
|
43
37
|
standalone: true,
|
|
44
38
|
imports: [LibsUiComponentsBadgeComponent],
|
|
45
39
|
template: `
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
<div class="flex items-center gap-2">
|
|
41
|
+
<span>Tin nhắn</span>
|
|
42
|
+
<libs_ui-components-badge
|
|
43
|
+
[count]="messageCount"
|
|
44
|
+
[mode]="'0x'"
|
|
45
|
+
[active]="hasUnread"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
`
|
|
52
49
|
})
|
|
53
50
|
export class ExampleComponent {
|
|
54
|
-
|
|
51
|
+
messageCount = 5;
|
|
52
|
+
hasUnread = true;
|
|
55
53
|
}
|
|
56
54
|
```
|
|
57
55
|
|
|
58
|
-
###
|
|
56
|
+
### Các Mode hiển thị
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
| Mode | Count = 0 | Count = 5 | Count = 15 | Count = 100 | Count > maxCount |
|
|
59
|
+
|------|-----------|-----------|------------|-------------|------------------|
|
|
60
|
+
| `x` | 0 | 5 | 15 | 100 | - |
|
|
61
|
+
| `0x` | 00 | 05 | 15 | 100 | - |
|
|
62
|
+
| `x+` | 00 | 05 | 15 | 100 | 99+ |
|
|
63
|
+
| `+x` | +00 | +05 | +15 | +100 | - |
|
|
64
|
+
| `k` | - | - | - | - | 1K, 1.5M |
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
selector: 'app-tooltip-example',
|
|
66
|
-
standalone: true,
|
|
67
|
-
imports: [LibsUiComponentsBadgeComponent],
|
|
68
|
-
templateUrl: './tooltip-example.component.html',
|
|
69
|
-
})
|
|
70
|
-
export class TooltipExampleComponent {
|
|
71
|
-
newMessages = 12;
|
|
72
|
-
}
|
|
73
|
-
```
|
|
66
|
+
### Ví dụ với mode 'x+'
|
|
74
67
|
|
|
75
68
|
```html
|
|
69
|
+
<!-- Hiển thị "99+" khi count > maxCount -->
|
|
76
70
|
<libs_ui-components-badge
|
|
77
|
-
[count]="
|
|
78
|
-
[
|
|
79
|
-
[
|
|
71
|
+
[count]="150"
|
|
72
|
+
[mode]="'x+'"
|
|
73
|
+
[maxCount]="99"
|
|
74
|
+
/>
|
|
75
|
+
<!-- Output: 99+ -->
|
|
80
76
|
```
|
|
81
77
|
|
|
82
|
-
|
|
78
|
+
### Ví dụ với mode 'k' (rút gọn)
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
```html
|
|
81
|
+
<!-- Hiển thị số rút gọn -->
|
|
82
|
+
<libs_ui-components-badge [count]="1500" [mode]="'k'" />
|
|
83
|
+
<!-- Output: 1,5K -->
|
|
86
84
|
|
|
87
|
-
|
|
85
|
+
<libs_ui-components-badge [count]="1500000" [mode]="'k'" />
|
|
86
|
+
<!-- Output: 1,5M -->
|
|
87
|
+
```
|
|
88
88
|
|
|
89
|
-
###
|
|
89
|
+
### Trạng thái Active
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
| ignoreMarginDefault | `boolean` | `undefined` | Bỏ qua margin mặc định bên trái của badge |
|
|
99
|
-
| classCircle | `string` | `libs-ui-font-h6r` | CSS class cho vòng tròn badge |
|
|
100
|
-
| ignoreStopPropagationEvent | `boolean` | `true` | Bỏ qua việc lan truyền sự kiện khi nhấp vào badge |
|
|
91
|
+
```html
|
|
92
|
+
<!-- Badge bình thường -->
|
|
93
|
+
<libs_ui-components-badge [count]="5" />
|
|
94
|
+
|
|
95
|
+
<!-- Badge active (màu xanh) -->
|
|
96
|
+
<libs_ui-components-badge [count]="5" [active]="true" />
|
|
97
|
+
```
|
|
101
98
|
|
|
102
|
-
|
|
99
|
+
## API Reference
|
|
103
100
|
|
|
104
|
-
|
|
101
|
+
### Inputs
|
|
105
102
|
|
|
106
|
-
|
|
103
|
+
| Tên | Kiểu | Mặc định | Mô tả |
|
|
104
|
+
|-----|------|----------|-------|
|
|
105
|
+
| `count` | `number` | `0` | Số lượng hiển thị trên badge |
|
|
106
|
+
| `mode` | `TYPE_BADGE_MODE` | `undefined` | Chế độ định dạng: 'x', '0x', 'x+', '+x', 'k' |
|
|
107
|
+
| `maxCount` | `number` | `MAX_SAFE_INTEGER` | Giới hạn tối đa, vượt qua sẽ hiển thị "maxCount+" (với mode 'x+') |
|
|
108
|
+
| `active` | `boolean` | `false` | Trạng thái active, thay đổi màu sắc badge |
|
|
109
|
+
| `classCircle` | `string` | `'libs-ui-font-h6r'` | Class CSS tùy chỉnh cho badge |
|
|
110
|
+
| `ignoreMarginDefault` | `boolean` | `false` | Bỏ margin-left mặc định (8px) |
|
|
111
|
+
| `popoverConfig` | `IPopoverOverlay` | `undefined` | Cấu hình cho popover tooltip |
|
|
112
|
+
| `ignoreStopPropagationEvent` | `boolean` | `true` | Bỏ qua stopPropagation khi click |
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
### Types
|
|
109
115
|
|
|
110
116
|
```typescript
|
|
111
|
-
|
|
117
|
+
// Các mode hiển thị số
|
|
118
|
+
type TYPE_BADGE_MODE = 'x' | 'x+' | '+x' | 'k' | '0x';
|
|
119
|
+
|
|
120
|
+
// Interface cho badge (dùng khi cần type cho object)
|
|
121
|
+
interface IBadge {
|
|
112
122
|
mode?: TYPE_BADGE_MODE;
|
|
113
123
|
count?: number;
|
|
114
124
|
maxCount?: number;
|
|
@@ -116,26 +126,82 @@ export interface IBadge {
|
|
|
116
126
|
}
|
|
117
127
|
```
|
|
118
128
|
|
|
119
|
-
|
|
129
|
+
### Giải thích các Mode
|
|
120
130
|
|
|
121
|
-
|
|
131
|
+
| Mode | Mô tả | Ví dụ |
|
|
132
|
+
|------|-------|-------|
|
|
133
|
+
| `x` | Số thường, không có số 0 đằng trước | 0, 5, 15, 100 |
|
|
134
|
+
| `0x` | Có số 0 đằng trước nếu < 10 | 00, 05, 15, 100 |
|
|
135
|
+
| `x+` | Hiển thị "maxCount+" khi vượt giới hạn | 99+, 999+ |
|
|
136
|
+
| `+x` | Thêm dấu + phía trước số | +00, +05, +15 |
|
|
137
|
+
| `k` | Rút gọn hàng nghìn/triệu | 1,5K, 1,0M |
|
|
122
138
|
|
|
123
|
-
|
|
124
|
-
export type TYPE_BADGE_MODE = 'x' | 'x+' | '+x' | 'k' | '0x';
|
|
125
|
-
```
|
|
139
|
+
## Styling
|
|
126
140
|
|
|
127
|
-
|
|
141
|
+
Badge có 2 trạng thái CSS:
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
```scss
|
|
144
|
+
// Normal state
|
|
145
|
+
.libs-ui-badge {
|
|
146
|
+
background: #e6e7ea;
|
|
147
|
+
color: #6a7383;
|
|
148
|
+
}
|
|
130
149
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
150
|
+
// Active state
|
|
151
|
+
.libs-ui-badge-active {
|
|
152
|
+
background: var(--libs-ui-color-light-3, #f4f8ff);
|
|
153
|
+
color: var(--libs-ui-color-default, #226ff5);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Bạn có thể override bằng CSS variables:
|
|
158
|
+
|
|
159
|
+
```css
|
|
160
|
+
:root {
|
|
161
|
+
--libs-ui-color-default: #your-primary-color;
|
|
162
|
+
--libs-ui-color-light-3: #your-light-color;
|
|
138
163
|
}
|
|
139
164
|
```
|
|
140
165
|
|
|
141
|
-
|
|
166
|
+
## Công nghệ sử dụng
|
|
167
|
+
|
|
168
|
+
- **Angular 18+** - Standalone Components
|
|
169
|
+
- **Angular Signals** - Reactive state với `computed()`
|
|
170
|
+
- **TailwindCSS** - Utility classes
|
|
171
|
+
- **OnPush** - Change Detection Strategy
|
|
172
|
+
|
|
173
|
+
## Demo
|
|
174
|
+
|
|
175
|
+
Demo có sẵn trong ứng dụng `core-ui`:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Chạy demo app
|
|
179
|
+
npx nx serve core-ui
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**File demo:** `apps/core-ui/src/app/components/badge/badge.component.ts`
|
|
183
|
+
|
|
184
|
+
### Tính năng Demo
|
|
185
|
+
|
|
186
|
+
- 🎮 **Interactive Demo**: Điều chỉnh count, maxCount bằng slider
|
|
187
|
+
- 📊 **Mode Comparison Table**: So sánh tất cả modes với nhiều giá trị count
|
|
188
|
+
- 🔄 **Active State Toggle**: Bật/tắt trạng thái active
|
|
189
|
+
- 📋 **API Reference**: Bảng tham chiếu đầy đủ các inputs và types
|
|
190
|
+
|
|
191
|
+
## Unit Tests
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Chạy tests
|
|
195
|
+
npx nx test badge
|
|
196
|
+
|
|
197
|
+
# Chạy tests với coverage
|
|
198
|
+
npx nx test badge --coverage
|
|
199
|
+
|
|
200
|
+
# Watch mode
|
|
201
|
+
npx nx test badge --watch
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT
|
|
207
|
+
|
package/badge.component.d.ts
CHANGED
|
@@ -1,16 +1,83 @@
|
|
|
1
1
|
import { IPopoverOverlay } from '@libs-ui/components-popover';
|
|
2
2
|
import { TYPE_BADGE_MODE } from './interfaces/mode.type';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Badge Component - Hiển thị số lượng/đếm với nhiều chế độ định dạng
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* Component dùng để hiển thị số lượng (notifications, messages, cart items...)
|
|
9
|
+
* với nhiều chế độ format khác nhau: số thường, có số 0 đằng trước, rút gọn K/M,...
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```html
|
|
13
|
+
* <!-- Basic -->
|
|
14
|
+
* <libs_ui-components-badge [count]="5" />
|
|
15
|
+
*
|
|
16
|
+
* <!-- Với mode -->
|
|
17
|
+
* <libs_ui-components-badge [count]="5" mode="0x" />
|
|
18
|
+
*
|
|
19
|
+
* <!-- Với maxCount -->
|
|
20
|
+
* <libs_ui-components-badge [count]="150" mode="x+" [maxCount]="99" />
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @publicApi
|
|
24
|
+
*/
|
|
4
25
|
export declare class LibsUiComponentsBadgeComponent {
|
|
26
|
+
/**
|
|
27
|
+
* Giá trị hiển thị đã được format theo mode
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
5
30
|
protected countDisplay: import("@angular/core").Signal<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Cấu hình popover tooltip khi hover
|
|
33
|
+
* @default undefined
|
|
34
|
+
*/
|
|
6
35
|
readonly popoverConfig: import("@angular/core").InputSignal<IPopoverOverlay | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Trạng thái active - thay đổi màu sắc badge
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
7
40
|
readonly active: import("@angular/core").InputSignal<boolean | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Số lượng hiển thị trên badge
|
|
43
|
+
* @default 0
|
|
44
|
+
*/
|
|
8
45
|
readonly count: import("@angular/core").InputSignalWithTransform<number, number>;
|
|
46
|
+
/**
|
|
47
|
+
* Chế độ hiển thị số
|
|
48
|
+
* - `'x'`: Số thường (1, 5, 15, 100)
|
|
49
|
+
* - `'0x'`: Có số 0 đằng trước nếu < 10 (01, 05)
|
|
50
|
+
* - `'x+'`: Hiển thị "maxCount+" khi vượt giới hạn (99+)
|
|
51
|
+
* - `'+x'`: Thêm dấu + phía trước (+01, +05)
|
|
52
|
+
* - `'k'`: Rút gọn hàng nghìn/triệu (1K, 1.5M)
|
|
53
|
+
* @default undefined - Các giá trị < 10 sẽ có số 0 ở đầu
|
|
54
|
+
*/
|
|
9
55
|
readonly mode: import("@angular/core").InputSignal<TYPE_BADGE_MODE | undefined>;
|
|
56
|
+
/**
|
|
57
|
+
* Giới hạn tối đa - Khi count > maxCount sẽ hiển thị "maxCount+" (với mode 'x+')
|
|
58
|
+
* @default Number.MAX_SAFE_INTEGER
|
|
59
|
+
*/
|
|
10
60
|
readonly maxCount: import("@angular/core").InputSignalWithTransform<number, number>;
|
|
61
|
+
/**
|
|
62
|
+
* Bỏ margin-left mặc định của badge
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
11
65
|
readonly ignoreMarginDefault: import("@angular/core").InputSignal<boolean | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Class CSS tùy chỉnh cho badge circle
|
|
68
|
+
* @default 'libs-ui-font-h6r'
|
|
69
|
+
*/
|
|
12
70
|
readonly classCircle: import("@angular/core").InputSignalWithTransform<string, string>;
|
|
71
|
+
/**
|
|
72
|
+
* Bỏ qua stopPropagation khi click vào badge
|
|
73
|
+
* @default true
|
|
74
|
+
*/
|
|
13
75
|
readonly ignoreStopPropagationEvent: import("@angular/core").InputSignalWithTransform<boolean, boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* Tính toán giá trị hiển thị dựa trên count và mode
|
|
78
|
+
* @returns Chuỗi đã format theo mode
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
14
81
|
private countDisplayComputed;
|
|
15
82
|
static ɵfac: i0.ɵɵFactoryDeclaration<LibsUiComponentsBadgeComponent, never>;
|
|
16
83
|
static ɵcmp: i0.ɵɵComponentDeclaration<LibsUiComponentsBadgeComponent, "libs_ui-components-badge", never, { "popoverConfig": { "alias": "popoverConfig"; "required": false; "isSignal": true; }; "active": { "alias": "active"; "required": false; "isSignal": true; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "maxCount": { "alias": "maxCount"; "required": false; "isSignal": true; }; "ignoreMarginDefault": { "alias": "ignoreMarginDefault"; "required": false; "isSignal": true; }; "classCircle": { "alias": "classCircle"; "required": false; "isSignal": true; }; "ignoreStopPropagationEvent": { "alias": "ignoreStopPropagationEvent"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
@@ -2,20 +2,100 @@ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/co
|
|
|
2
2
|
import { LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';
|
|
3
3
|
import { viewDataNumberByLanguage } from '@libs-ui/utils';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Badge Component - Hiển thị số lượng/đếm với nhiều chế độ định dạng
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* Component dùng để hiển thị số lượng (notifications, messages, cart items...)
|
|
10
|
+
* với nhiều chế độ format khác nhau: số thường, có số 0 đằng trước, rút gọn K/M,...
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```html
|
|
14
|
+
* <!-- Basic -->
|
|
15
|
+
* <libs_ui-components-badge [count]="5" />
|
|
16
|
+
*
|
|
17
|
+
* <!-- Với mode -->
|
|
18
|
+
* <libs_ui-components-badge [count]="5" mode="0x" />
|
|
19
|
+
*
|
|
20
|
+
* <!-- Với maxCount -->
|
|
21
|
+
* <libs_ui-components-badge [count]="150" mode="x+" [maxCount]="99" />
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @publicApi
|
|
25
|
+
*/
|
|
5
26
|
export class LibsUiComponentsBadgeComponent {
|
|
6
|
-
//
|
|
27
|
+
// =========================================
|
|
28
|
+
// COMPUTED PROPERTIES
|
|
29
|
+
// =========================================
|
|
30
|
+
/**
|
|
31
|
+
* Giá trị hiển thị đã được format theo mode
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
7
34
|
countDisplay = computed(this.countDisplayComputed.bind(this));
|
|
8
|
-
//
|
|
35
|
+
// =========================================
|
|
36
|
+
// INPUTS
|
|
37
|
+
// =========================================
|
|
38
|
+
/**
|
|
39
|
+
* Cấu hình popover tooltip khi hover
|
|
40
|
+
* @default undefined
|
|
41
|
+
*/
|
|
9
42
|
popoverConfig = input();
|
|
43
|
+
/**
|
|
44
|
+
* Trạng thái active - thay đổi màu sắc badge
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
10
47
|
active = input();
|
|
48
|
+
/**
|
|
49
|
+
* Số lượng hiển thị trên badge
|
|
50
|
+
* @default 0
|
|
51
|
+
*/
|
|
11
52
|
count = input(0, { transform: (value) => value ?? 0 });
|
|
12
|
-
|
|
13
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Chế độ hiển thị số
|
|
55
|
+
* - `'x'`: Số thường (1, 5, 15, 100)
|
|
56
|
+
* - `'0x'`: Có số 0 đằng trước nếu < 10 (01, 05)
|
|
57
|
+
* - `'x+'`: Hiển thị "maxCount+" khi vượt giới hạn (99+)
|
|
58
|
+
* - `'+x'`: Thêm dấu + phía trước (+01, +05)
|
|
59
|
+
* - `'k'`: Rút gọn hàng nghìn/triệu (1K, 1.5M)
|
|
60
|
+
* @default undefined - Các giá trị < 10 sẽ có số 0 ở đầu
|
|
61
|
+
*/
|
|
62
|
+
mode = input();
|
|
63
|
+
/**
|
|
64
|
+
* Giới hạn tối đa - Khi count > maxCount sẽ hiển thị "maxCount+" (với mode 'x+')
|
|
65
|
+
* @default Number.MAX_SAFE_INTEGER
|
|
66
|
+
*/
|
|
67
|
+
maxCount = input(Number.MAX_SAFE_INTEGER, {
|
|
68
|
+
transform: (value) => value ?? Number.MAX_SAFE_INTEGER,
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* Bỏ margin-left mặc định của badge
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
14
74
|
ignoreMarginDefault = input();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Class CSS tùy chỉnh cho badge circle
|
|
77
|
+
* @default 'libs-ui-font-h6r'
|
|
78
|
+
*/
|
|
79
|
+
classCircle = input('libs-ui-font-h6r', {
|
|
80
|
+
transform: (value) => value ?? 'libs-ui-font-h6r',
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* Bỏ qua stopPropagation khi click vào badge
|
|
84
|
+
* @default true
|
|
85
|
+
*/
|
|
86
|
+
ignoreStopPropagationEvent = input(true, {
|
|
87
|
+
transform: (value) => value ?? true,
|
|
88
|
+
});
|
|
89
|
+
// =========================================
|
|
90
|
+
// PRIVATE METHODS
|
|
91
|
+
// =========================================
|
|
92
|
+
/**
|
|
93
|
+
* Tính toán giá trị hiển thị dựa trên count và mode
|
|
94
|
+
* @returns Chuỗi đã format theo mode
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
18
97
|
countDisplayComputed() {
|
|
98
|
+
// Mode 'k': Rút gọn hàng nghìn/triệu
|
|
19
99
|
if (this.mode() === 'k' && this.count() > 999) {
|
|
20
100
|
const count = this.count() / 1000;
|
|
21
101
|
if (count > 1000) {
|
|
@@ -23,10 +103,12 @@ export class LibsUiComponentsBadgeComponent {
|
|
|
23
103
|
}
|
|
24
104
|
return `${viewDataNumberByLanguage(count, true, 1, false, true)}K`;
|
|
25
105
|
}
|
|
106
|
+
// Mode 'x+': Hiển thị maxCount+ khi vượt giới hạn
|
|
26
107
|
if (this.mode() === 'x+' && this.count() > this.maxCount()) {
|
|
27
108
|
const countFormat = viewDataNumberByLanguage(this.maxCount(), true);
|
|
28
109
|
return `${countFormat}+`;
|
|
29
110
|
}
|
|
111
|
+
// Xử lý count = 0
|
|
30
112
|
if (!this.count()) {
|
|
31
113
|
switch (this.mode()) {
|
|
32
114
|
case '+x':
|
|
@@ -39,6 +121,7 @@ export class LibsUiComponentsBadgeComponent {
|
|
|
39
121
|
return '00';
|
|
40
122
|
}
|
|
41
123
|
}
|
|
124
|
+
// Xử lý count < 10
|
|
42
125
|
if (this.count() < 10) {
|
|
43
126
|
switch (this.mode()) {
|
|
44
127
|
case '+x':
|
|
@@ -51,6 +134,7 @@ export class LibsUiComponentsBadgeComponent {
|
|
|
51
134
|
return `0${this.count()}`;
|
|
52
135
|
}
|
|
53
136
|
}
|
|
137
|
+
// Mặc định: Format số và thêm + nếu mode '+x'
|
|
54
138
|
const countFormat = viewDataNumberByLanguage(this.count(), true);
|
|
55
139
|
return this.mode() === '+x' ? `+${countFormat}` : `${countFormat}`;
|
|
56
140
|
}
|
|
@@ -61,4 +145,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
61
145
|
type: Component,
|
|
62
146
|
args: [{ selector: 'libs_ui-components-badge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [LibsUiComponentsPopoverComponent], template: "<span\n class=\"libs-ui-badge {{ classCircle() }}\"\n [class.libs-ui-badge-active]=\"active()\"\n [class.ml-0]=\"ignoreMarginDefault()\"\n LibsUiComponentsPopoverDirective\n [type]=\"popoverConfig() ? 'other' : 'text'\"\n [config]=\"popoverConfig() ?? { content: countDisplay() }\"\n [ignoreStopPropagationEvent]=\"ignoreStopPropagationEvent()\">\n {{ countDisplay() }}\n</span>\n", styles: [".libs-ui-badge{width:fit-content;height:20px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#6a7383;background:#e6e7ea;margin-left:8px;padding:2px 6px}.libs-ui-badge-active{color:var(--libs-ui-color-default, #226ff5);background:var(--libs-ui-color-light-3, #f4f8ff)}\n"] }]
|
|
63
147
|
}] });
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFkZ2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2JhZGdlL3NyYy9iYWRnZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYmFkZ2Uvc3JjL2JhZGdlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRixPQUFPLEVBQW1CLGdDQUFnQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDaEcsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7O0FBWTFELE1BQU0sT0FBTyw4QkFBOEI7SUFDekMsbUJBQW1CO0lBQ1QsWUFBWSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFFeEUsZ0JBQWdCO0lBQ1AsYUFBYSxHQUFHLEtBQUssRUFBbUIsQ0FBQztJQUN6QyxNQUFNLEdBQUcsS0FBSyxFQUFXLENBQUM7SUFDMUIsS0FBSyxHQUFHLEtBQUssQ0FBaUIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2RSxJQUFJLEdBQUcsS0FBSyxFQUFtQixDQUFDLENBQUMsMERBQTBEO0lBQzNGLFFBQVEsR0FBRyxLQUFLLENBQWlCLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxJQUFJLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxvREFBb0Q7SUFDM0ssbUJBQW1CLEdBQUcsS0FBSyxFQUFXLENB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Q0FBZ0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBpbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSVBvcG92ZXJPdmVybGF5LCBMaWJzVWlDb21wb25lbnRzUG9wb3ZlckNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtcG9wb3Zlcic7XG5pbXBvcnQgeyB2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UgfSBmcm9tICdAbGlicy11aS91dGlscyc7XG5pbXBvcnQgeyBUWVBFX0JBREdFX01PREUgfSBmcm9tICcuL2ludGVyZmFjZXMvbW9kZS50eXBlJztcblxuQENvbXBvbmVudCh7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvY29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnbGlic191aS1jb21wb25lbnRzLWJhZGdlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2JhZGdlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vYmFkZ2UuY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGltcG9ydHM6IFtMaWJzVWlDb21wb25lbnRzUG9wb3ZlckNvbXBvbmVudF0sXG59KVxuZXhwb3J0IGNsYXNzIExpYnNVaUNvbXBvbmVudHNCYWRnZUNvbXBvbmVudCB7XG4gIC8vICNyZWdpb24gUFJPUEVSVFlcbiAgcHJvdGVjdGVkIGNvdW50RGlzcGxheSA9IGNvbXB1dGVkKHRoaXMuY291bnREaXNwbGF5Q29tcHV0ZWQuYmluZCh0aGlzKSk7XG5cbiAgLy8gI3JlZ2lvbiBJTlBVVFxuICByZWFkb25seSBwb3BvdmVyQ29uZmlnID0gaW5wdXQ8SVBvcG92ZXJPdmVybGF5PigpO1xuICByZWFkb25seSBhY3RpdmUgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBjb3VudCA9IGlucHV0PG51bWJlciwgbnVtYmVyPigwLCB7IHRyYW5zZm9ybTogKHZhbHVlKSA9PiB2YWx1ZSA/PyAwIH0pO1xuICByZWFkb25seSBtb2RlID0gaW5wdXQ8VFlQRV9CQURHRV9NT0RFPigpOyAvLyBraMO0bmcgdHJ1eeG7gW4gbeG6t2MgxJHhu4tuaCBjw6FjIGdpw6EgdHLhu4sgPCAxMCBz4bq9IGPDsyBz4buRIDAg4bufIMSR4bqndVxuICByZWFkb25seSBtYXhDb3VudCA9IGlucHV0PG51bWJlciwgbnVtYmVyPihOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwgeyB0cmFuc2Zvcm06ICh2YWx1ZSkgPT4gdmFsdWUgPz8gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgfSk7IC8vIG7hur91IGNvdW50ID4gbWF4Q291bnQgc+G6vSB4ZW0geMOpdCBtb2RlIMSR4buDIGhp4buDbiB0aOG7iy5cbiAgcmVhZG9ubHkgaWdub3JlTWFyZ2luRGVmYXVsdCA9IGlucHV0PGJvb2xlYW4+KCk7XG4gIHJlYWRvbmx5IGNsYXNzQ2lyY2xlID0gaW5wdXQ8c3RyaW5nLCBzdHJpbmc+KCdsaWJzLXVpLWZvbnQtaDZyJywgeyB0cmFuc2Zvcm06ICh2YWx1ZSkgPT4gdmFsdWUgPz8gJ2xpYnMtdWktZm9udC1oNnInIH0pO1xuICByZWFkb25seSBpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudCA9IGlucHV0PGJvb2xlYW4sIGJvb2xlYW4+KHRydWUsIHsgdHJhbnNmb3JtOiAodmFsdWUpID0+IHZhbHVlID8/IHRydWUgfSk7XG5cbiAgLyogQ09NUFVURUQgUFJPUEVSVElFUyBGVU5DVElPTiAqL1xuICBwcml2YXRlIGNvdW50RGlzcGxheUNvbXB1dGVkKCkge1xuICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ2snICYmIHRoaXMuY291bnQoKSA+IDk5OSkge1xuICAgICAgY29uc3QgY291bnQgPSB0aGlzLmNvdW50KCkgLyAxMDAwO1xuXG4gICAgICBpZiAoY291bnQgPiAxMDAwKSB7XG4gICAgICAgIHJldHVybiBgJHt2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UoY291bnQgLyAxMDAwLCB0cnVlLCAxLCBmYWxzZSwgdHJ1ZSl9TWA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgJHt2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UoY291bnQsIHRydWUsIDEsIGZhbHNlLCB0cnVlKX1LYDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tb2RlKCkgPT09ICd4KycgJiYgdGhpcy5jb3VudCgpID4gdGhpcy5tYXhDb3VudCgpKSB7XG4gICAgICBjb25zdCBjb3VudEZvcm1hdCA9IHZpZXdEYXRhTnVtYmVyQnlMYW5ndWFnZSh0aGlzLm1heENvdW50KCksIHRydWUpO1xuXG4gICAgICByZXR1cm4gYCR7Y291bnRGb3JtYXR9K2A7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNvdW50KCkpIHtcbiAgICAgIHN3aXRjaCAodGhpcy5tb2RlKCkpIHtcbiAgICAgICAgY2FzZSAnK3gnOlxuICAgICAgICAgIHJldHVybiAnKzAwJztcblxuICAgICAgICBjYXNlICd4Kyc6XG4gICAgICAgICAgcmV0dXJuICcwMCc7XG5cbiAgICAgICAgY2FzZSAneCc6XG4gICAgICAgICAgcmV0dXJuICcwJztcblxuICAgICAgICBjYXNlICcweCc6XG4gICAgICAgICAgcmV0dXJuICcwMCc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY291bnQoKSA8IDEwKSB7XG4gICAgICBzd2l0Y2ggKHRoaXMubW9kZSgpKSB7XG4gICAgICAgIGNhc2UgJyt4JzpcbiAgICAgICAgICByZXR1cm4gYCswJHt0aGlzLmNvdW50KCl9YDtcblxuICAgICAgICBjYXNlICd4Kyc6XG4gICAgICAgICAgcmV0dXJuIGAwJHt0aGlzLmNvdW50KCl9YDtcblxuICAgICAgICBjYXNlICd4JzpcbiAgICAgICAgICByZXR1cm4gYCR7dGhpcy5jb3VudCgpfWA7XG5cbiAgICAgICAgY2FzZSAnMHgnOlxuICAgICAgICAgIHJldHVybiBgMCR7dGhpcy5jb3VudCgpfWA7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGNvdW50Rm9ybWF0ID0gdmlld0RhdGFOdW1iZXJCeUxhbmd1YWdlKHRoaXMuY291bnQoKSwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gdGhpcy5tb2RlKCkgPT09ICcreCcgPyBgKyR7Y291bnRGb3JtYXR9YCA6IGAke2NvdW50Rm9ybWF0fWA7XG4gIH1cbn1cbiIsIjxzcGFuXG4gIGNsYXNzPVwibGlicy11aS1iYWRnZSB7eyBjbGFzc0NpcmNsZSgpIH19XCJcbiAgW2NsYXNzLmxpYnMtdWktYmFkZ2UtYWN0aXZlXT1cImFjdGl2ZSgpXCJcbiAgW2NsYXNzLm1sLTBdPVwiaWdub3JlTWFyZ2luRGVmYXVsdCgpXCJcbiAgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJEaXJlY3RpdmVcbiAgW3R5cGVdPVwicG9wb3ZlckNvbmZpZygpID8gJ290aGVyJyA6ICd0ZXh0J1wiXG4gIFtjb25maWddPVwicG9wb3ZlckNvbmZpZygpID8/IHsgY29udGVudDogY291bnREaXNwbGF5KCkgfVwiXG4gIFtpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudF09XCJpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudCgpXCI+XG4gIHt7IGNvdW50RGlzcGxheSgpIH19XG48L3NwYW4+XG4iXX0=
|
|
148
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFkZ2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2JhZGdlL3NyYy9iYWRnZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvYmFkZ2Uvc3JjL2JhZGdlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRixPQUFPLEVBQW1CLGdDQUFnQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDaEcsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7O0FBRzFEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQVVILE1BQU0sT0FBTyw4QkFBOEI7SUFDekMsNENBQTRDO0lBQzVDLHNCQUFzQjtJQUN0Qiw0Q0FBNEM7SUFFNUM7OztPQUdHO0lBQ08sWUFBWSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFFeEUsNENBQTRDO0lBQzVDLFNBQVM7SUFDVCw0Q0FBNEM7SUFFNUM7OztPQUdHO0lBQ00sYUFBYSxHQUFHLEtBQUssRUFBbUIsQ0FBQztJQUVsRDs7O09BR0c7SUFDTSxNQUFNLEdBQUcsS0FBSyxFQUFXLENBQUM7SUFFbkM7OztPQUdHO0lBQ00sS0FBSyxHQUFHLEtBQUssQ0FBaUIsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUVoRjs7Ozs7Ozs7T0FRRztJQUNNLElBQUksR0FBRyxLQUFLLEVBQW1CLENBQUM7SUFFekM7OztPQUdHO0lBQ00sUUFBUSxHQUFHLEtBQUssQ0FBaUIs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QUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pFLE9BQU8sSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUNyRSxDQUFDO3dHQXBJVSw4QkFBOEI7NEZBQTlCLDhCQUE4Qiw0ckNDbkMzQyxzWUFVQSx1V0R1QlksZ0NBQWdDOzs0RkFFL0IsOEJBQThCO2tCQVQxQyxTQUFTOytCQUVFLDBCQUEwQixjQUd4QixJQUFJLG1CQUNDLHVCQUF1QixDQUFDLE1BQU0sV0FDdEMsQ0FBQyxnQ0FBZ0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBpbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSVBvcG92ZXJPdmVybGF5LCBMaWJzVWlDb21wb25lbnRzUG9wb3ZlckNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtcG9wb3Zlcic7XG5pbXBvcnQgeyB2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UgfSBmcm9tICdAbGlicy11aS91dGlscyc7XG5pbXBvcnQgeyBUWVBFX0JBREdFX01PREUgfSBmcm9tICcuL2ludGVyZmFjZXMvbW9kZS50eXBlJztcblxuLyoqXG4gKiBCYWRnZSBDb21wb25lbnQgLSBIaeG7g24gdGjhu4sgc+G7kSBsxrDhu6NuZy/EkeG6v20gduG7m2kgbmhp4buBdSBjaOG6vyDEkeG7mSDEkeG7i25oIGThuqFuZ1xuICpcbiAqIEBkZXNjcmlwdGlvblxuICogQ29tcG9uZW50IGTDuW5nIMSR4buDIGhp4buDbiB0aOG7iyBz4buRIGzGsOG7o25nIChub3RpZmljYXRpb25zLCBtZXNzYWdlcywgY2FydCBpdGVtcy4uLilcbiAqIHbhu5tpIG5oaeG7gXUgY2jhur8gxJHhu5kgZm9ybWF0IGtow6FjIG5oYXU6IHPhu5EgdGjGsOG7nW5nLCBjw7Mgc+G7kSAwIMSR4bqxbmcgdHLGsOG7m2MsIHLDunQgZ+G7jW4gSy9NLC4uLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8IS0tIEJhc2ljIC0tPlxuICogPGxpYnNfdWktY29tcG9uZW50cy1iYWRnZSBbY291bnRdPVwiNVwiIC8+XG4gKlxuICogPCEtLSBW4bubaSBtb2RlIC0tPlxuICogPGxpYnNfdWktY29tcG9uZW50cy1iYWRnZSBbY291bnRdPVwiNVwiIG1vZGU9XCIweFwiIC8+XG4gKlxuICogPCEtLSBW4bubaSBtYXhDb3VudCAtLT5cbiAqIDxsaWJzX3VpLWNvbXBvbmVudHMtYmFkZ2UgW2NvdW50XT1cIjE1MFwiIG1vZGU9XCJ4K1wiIFttYXhDb3VudF09XCI5OVwiIC8+XG4gKiBgYGBcbiAqXG4gKiBAcHVibGljQXBpXG4gKi9cbkBDb21wb25lbnQoe1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L2NvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ2xpYnNfdWktY29tcG9uZW50cy1iYWRnZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9iYWRnZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2JhZGdlLmNvbXBvbmVudC5zY3NzJ10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c1BvcG92ZXJDb21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzQmFkZ2VDb21wb25lbnQge1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBDT01QVVRFRCBQUk9QRVJUSUVTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEdpw6EgdHLhu4sgaGnhu4NuIHRo4buLIMSRw6MgxJHGsOG7o2MgZm9ybWF0IHRoZW8gbW9kZVxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByb3RlY3RlZCBjb3VudERpc3BsYXkgPSBjb21wdXRlZCh0aGlzLmNvdW50RGlzcGxheUNvbXB1dGVkLmJpbmQodGhpcykpO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIElOUFVUU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBD4bqldSBow6xuaCBwb3BvdmVyIHRvb2x0aXAga2hpIGhvdmVyXG4gICAqIEBkZWZhdWx0IHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcG9wb3ZlckNvbmZpZyA9IGlucHV0PElQb3BvdmVyT3ZlcmxheT4oKTtcblxuICAvKipcbiAgICogVHLhuqFuZyB0aMOhaSBhY3RpdmUgLSB0aGF5IMSR4buVaSBtw6B1IHPhuq9jIGJhZGdlXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBhY3RpdmUgPSBpbnB1dDxib29sZWFuPigpO1xuXG4gIC8qKlxuICAgKiBT4buRIGzGsOG7o25nIGhp4buDbiB0aOG7iyB0csOqbiBiYWRnZVxuICAgKiBAZGVmYXVsdCAwXG4gICAqL1xuICByZWFkb25seSBjb3VudCA9IGlucHV0PG51bWJlciwgbnVtYmVyPigwLCB7IHRyYW5zZm9ybTogKHZhbHVlKSA9PiB2YWx1ZSA/PyAwIH0pO1xuXG4gIC8qKlxuICAgKiBDaOG6vyDEkeG7mSBoaeG7g24gdGjhu4sgc+G7kVxuICAgKiAtIGAneCdgOiBT4buRIHRoxrDhu51uZyAoMSwgNSwgMTUsIDEwMClcbiAgICogLSBgJzB4J2A6IEPDsyBz4buRIDAgxJHhurFuZyB0csaw4bubYyBu4bq/dSA8IDEwICgwMSwgMDUpXG4gICAqIC0gYCd4KydgOiBIaeG7g24gdGjhu4sgXCJtYXhDb3VudCtcIiBraGkgdsaw4bujdCBnaeG7m2kgaOG6oW4gKDk5KylcbiAgICogLSBgJyt4J2A6IFRow6ptIGThuqV1ICsgcGjDrWEgdHLGsOG7m2MgKCswMSwgKzA1KVxuICAgKiAtIGAnaydgOiBSw7p0IGfhu41uIGjDoG5nIG5naMOsbi90cmnhu4d1ICgxSywgMS41TSlcbiAgICogQGRlZmF1bHQgdW5kZWZpbmVkIC0gQ8OhYyBnacOhIHRy4buLIDwgMTAgc+G6vSBjw7Mgc+G7kSAwIOG7nyDEkeG6p3VcbiAgICovXG4gIHJlYWRvbmx5IG1vZGUgPSBpbnB1dDxUWVBFX0JBREdFX01PREU+KCk7XG5cbiAgLyoqXG4gICAqIEdp4bubaSBo4bqhbiB04buRaSDEkWEgLSBLaGkgY291bnQgPiBtYXhDb3VudCBz4bq9IGhp4buDbiB0aOG7iyBcIm1heENvdW50K1wiICh24bubaSBtb2RlICd4KycpXG4gICAqIEBkZWZhdWx0IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSXG4gICAqL1xuICByZWFkb25seSBtYXhDb3VudCA9IGlucHV0PG51bWJlciwgbnVtYmVyPihOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiwge1xuICAgIHRyYW5zZm9ybTogKHZhbHVlKSA9PiB2YWx1ZSA/PyBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUixcbiAgfSk7XG5cbiAgLyoqXG4gICAqIELhu48gbWFyZ2luLWxlZnQgbeG6t2MgxJHhu4tuaCBj4bunYSBiYWRnZVxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaWdub3JlTWFyZ2luRGVmYXVsdCA9IGlucHV0PGJvb2xlYW4+KCk7XG5cbiAgLyoqXG4gICAqIENsYXNzIENTUyB0w7l5IGNo4buJbmggY2hvIGJhZGdlIGNpcmNsZVxuICAgKiBAZGVmYXVsdCAnbGlicy11aS1mb250LWg2cidcbiAgICovXG4gIHJlYWRvbmx5IGNsYXNzQ2lyY2xlID0gaW5wdXQ8c3RyaW5nLCBzdHJpbmc+KCdsaWJzLXVpLWZvbnQtaDZyJywge1xuICAgIHRyYW5zZm9ybTogKHZhbHVlKSA9PiB2YWx1ZSA/PyAnbGlicy11aS1mb250LWg2cicsXG4gIH0pO1xuXG4gIC8qKlxuICAgKiBC4buPIHF1YSBzdG9wUHJvcGFnYXRpb24ga2hpIGNsaWNrIHbDoG8gYmFkZ2VcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgaWdub3JlU3RvcFByb3BhZ2F0aW9uRXZlbnQgPSBpbnB1dDxib29sZWFuLCBib29sZWFuPih0cnVlLCB7XG4gICAgdHJhbnNmb3JtOiAodmFsdWUpID0+IHZhbHVlID8/IHRydWUsXG4gIH0pO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBSSVZBVEUgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBUw61uaCB0b8OhbiBnacOhIHRy4buLIGhp4buDbiB0aOG7iyBk4buxYSB0csOqbiBjb3VudCB2w6AgbW9kZVxuICAgKiBAcmV0dXJucyBDaHXhu5dpIMSRw6MgZm9ybWF0IHRoZW8gbW9kZVxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgY291bnREaXNwbGF5Q29tcHV0ZWQoKTogc3RyaW5nIHtcbiAgICAvLyBNb2RlICdrJzogUsO6dCBn4buNbiBow6BuZyBuZ2jDrG4vdHJp4buHdVxuICAgIGlmICh0aGlzLm1vZGUoKSA9PT0gJ2snICYmIHRoaXMuY291bnQoKSA+IDk5OSkge1xuICAgICAgY29uc3QgY291bnQgPSB0aGlzLmNvdW50KCkgLyAxMDAwO1xuXG4gICAgICBpZiAoY291bnQgPiAxMDAwKSB7XG4gICAgICAgIHJldHVybiBgJHt2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UoY291bnQgLyAxMDAwLCB0cnVlLCAxLCBmYWxzZSwgdHJ1ZSl9TWA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgJHt2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UoY291bnQsIHRydWUsIDEsIGZhbHNlLCB0cnVlKX1LYDtcbiAgICB9XG5cbiAgICAvLyBNb2RlICd4Kyc6IEhp4buDbiB0aOG7iyBtYXhDb3VudCsga2hpIHbGsOG7o3QgZ2nhu5tpIGjhuqFuXG4gICAgaWYgKHRoaXMubW9kZSgpID09PSAneCsnICYmIHRoaXMuY291bnQoKSA+IHRoaXMubWF4Q291bnQoKSkge1xuICAgICAgY29uc3QgY291bnRGb3JtYXQgPSB2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UodGhpcy5tYXhDb3VudCgpLCB0cnVlKTtcbiAgICAgIHJldHVybiBgJHtjb3VudEZvcm1hdH0rYDtcbiAgICB9XG5cbiAgICAvLyBY4butIGzDvSBjb3VudCA9IDBcbiAgICBpZiAoIXRoaXMuY291bnQoKSkge1xuICAgICAgc3dpdGNoICh0aGlzLm1vZGUoKSkge1xuICAgICAgICBjYXNlICcreCc6XG4gICAgICAgICAgcmV0dXJuICcrMDAnO1xuICAgICAgICBjYXNlICd4Kyc6XG4gICAgICAgICAgcmV0dXJuICcwMCc7XG4gICAgICAgIGNhc2UgJ3gnOlxuICAgICAgICAgIHJldHVybiAnMCc7XG4gICAgICAgIGNhc2UgJzB4JzpcbiAgICAgICAgICByZXR1cm4gJzAwJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBY4butIGzDvSBjb3VudCA8IDEwXG4gICAgaWYgKHRoaXMuY291bnQoKSA8IDEwKSB7XG4gICAgICBzd2l0Y2ggKHRoaXMubW9kZSgpKSB7XG4gICAgICAgIGNhc2UgJyt4JzpcbiAgICAgICAgICByZXR1cm4gYCswJHt0aGlzLmNvdW50KCl9YDtcbiAgICAgICAgY2FzZSAneCsnOlxuICAgICAgICAgIHJldHVybiBgMCR7dGhpcy5jb3VudCgpfWA7XG4gICAgICAgIGNhc2UgJ3gnOlxuICAgICAgICAgIHJldHVybiBgJHt0aGlzLmNvdW50KCl9YDtcbiAgICAgICAgY2FzZSAnMHgnOlxuICAgICAgICAgIHJldHVybiBgMCR7dGhpcy5jb3VudCgpfWA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTeG6t2MgxJHhu4tuaDogRm9ybWF0IHPhu5EgdsOgIHRow6ptICsgbuG6v3UgbW9kZSAnK3gnXG4gICAgY29uc3QgY291bnRGb3JtYXQgPSB2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UodGhpcy5jb3VudCgpLCB0cnVlKTtcbiAgICByZXR1cm4gdGhpcy5tb2RlKCkgPT09ICcreCcgPyBgKyR7Y291bnRGb3JtYXR9YCA6IGAke2NvdW50Rm9ybWF0fWA7XG4gIH1cbn1cbiIsIjxzcGFuXG4gIGNsYXNzPVwibGlicy11aS1iYWRnZSB7eyBjbGFzc0NpcmNsZSgpIH19XCJcbiAgW2NsYXNzLmxpYnMtdWktYmFkZ2UtYWN0aXZlXT1cImFjdGl2ZSgpXCJcbiAgW2NsYXNzLm1sLTBdPVwiaWdub3JlTWFyZ2luRGVmYXVsdCgpXCJcbiAgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJEaXJlY3RpdmVcbiAgW3R5cGVdPVwicG9wb3ZlckNvbmZpZygpID8gJ290aGVyJyA6ICd0ZXh0J1wiXG4gIFtjb25maWddPVwicG9wb3ZlckNvbmZpZygpID8/IHsgY29udGVudDogY291bnREaXNwbGF5KCkgfVwiXG4gIFtpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudF09XCJpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudCgpXCI+XG4gIHt7IGNvdW50RGlzcGxheSgpIH19XG48L3NwYW4+XG4iXX0=
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFkZ2UuaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2JhZGdlL3NyYy9pbnRlcmZhY2VzL2JhZGdlLmludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVFlQRV9CQURHRV9NT0RFIH0gZnJvbSAnLi9tb2RlLnR5cGUnO1xuXG4vKipcbiAqIEludGVyZmFjZSBj4bqldSBow6xuaCBjaG8gQmFkZ2UgY29tcG9uZW50XG4gKlxuICogQGRlc2NyaXB0aW9uXG4gKiBEw7luZyBraGkgY+G6p24gdHJ1eeG7gW4gY29uZmlnIGThuqFuZyBvYmplY3QgY2hvIGJhZGdlXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGJhZGdlQ29uZmlnOiBJQmFkZ2UgPSB7XG4gKiAgIG1vZGU6ICcweCcsXG4gKiAgIGNvdW50OiA1LFxuICogICBtYXhDb3VudDogOTlcbiAqIH07XG4gKiBgYGBcbiAqXG4gKiBAaW50ZXJmYWNlIElCYWRnZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIElCYWRnZSB7XG4gIC8qKlxuICAgKiBDaOG6vyDEkeG7mSBoaeG7g24gdGjhu4sgc+G7kVxuICAgKiBAc2VlIFRZUEVfQkFER0VfTU9ERVxuICAgKi9cbiAgbW9kZT86IFRZUEVfQkFER0VfTU9ERTtcblxuICAvKipcbiAgICogU+G7kSBsxrDhu6NuZyBoaeG7g24gdGjhu4tcbiAgICogQGRlZmF1bHQgMFxuICAgKi9cbiAgY291bnQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEdp4bubaSBo4bqhbiB04buRaSDEkWEgKGTDuW5nIHbhu5tpIG1vZGUgJ3grJylcbiAgICogQGRlZmF1bHQgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJcbiAgICovXG4gIG1heENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBDbGFzcyBDU1MgdMO5eSBjaOG7iW5oIGNobyBiYWRnZVxuICAgKiBAZGVmYXVsdCAnbGlicy11aS1mb250LWg2cidcbiAgICovXG4gIGNsYXNzQ2lyY2xlPzogc3RyaW5nO1xufVxuIl19
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZS50eXBlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2JhZGdlL3NyYy9pbnRlcmZhY2VzL21vZGUudHlwZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDw6FjIGNo4bq/IMSR4buZIGhp4buDbiB0aOG7iyBz4buRIHRyw6puIEJhZGdlXG4gKlxuICogQGRlc2NyaXB0aW9uXG4gKiAtIGAneCdgOiBT4buRIHRoxrDhu51uZyAoMSwgNSwgMTUsIDEwMClcbiAqIC0gYCcweCdgOiBDw7Mgc+G7kSAwIMSR4bqxbmcgdHLGsOG7m2MgbuG6v3UgPCAxMCAoMDEsIDA1LCAxNSlcbiAqIC0gYCd4KydgOiBIaeG7g24gdGjhu4sgXCJtYXhDb3VudCtcIiBraGkgdsaw4bujdCBnaeG7m2kgaOG6oW4gKDk5KylcbiAqIC0gYCcreCdgOiBUaMOqbSBk4bqldSArIHBow61hIHRyxrDhu5tjICgrMDEsICswNSwgKzE1KVxuICogLSBgJ2snYDogUsO6dCBn4buNbiBow6BuZyBuZ2jDrG4vdHJp4buHdSAoMUssIDEuNU0pXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG1vZGU6IFRZUEVfQkFER0VfTU9ERSA9ICcweCc7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IHR5cGUgVFlQRV9CQURHRV9NT0RFID0gJ3gnIHwgJ3grJyB8ICcreCcgfCAnaycgfCAnMHgnO1xuIl19
|
|
@@ -3,20 +3,100 @@ import { computed, input, ChangeDetectionStrategy, Component } from '@angular/co
|
|
|
3
3
|
import { LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';
|
|
4
4
|
import { viewDataNumberByLanguage } from '@libs-ui/utils';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Badge Component - Hiển thị số lượng/đếm với nhiều chế độ định dạng
|
|
8
|
+
*
|
|
9
|
+
* @description
|
|
10
|
+
* Component dùng để hiển thị số lượng (notifications, messages, cart items...)
|
|
11
|
+
* với nhiều chế độ format khác nhau: số thường, có số 0 đằng trước, rút gọn K/M,...
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <!-- Basic -->
|
|
16
|
+
* <libs_ui-components-badge [count]="5" />
|
|
17
|
+
*
|
|
18
|
+
* <!-- Với mode -->
|
|
19
|
+
* <libs_ui-components-badge [count]="5" mode="0x" />
|
|
20
|
+
*
|
|
21
|
+
* <!-- Với maxCount -->
|
|
22
|
+
* <libs_ui-components-badge [count]="150" mode="x+" [maxCount]="99" />
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @publicApi
|
|
26
|
+
*/
|
|
6
27
|
class LibsUiComponentsBadgeComponent {
|
|
7
|
-
//
|
|
28
|
+
// =========================================
|
|
29
|
+
// COMPUTED PROPERTIES
|
|
30
|
+
// =========================================
|
|
31
|
+
/**
|
|
32
|
+
* Giá trị hiển thị đã được format theo mode
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
8
35
|
countDisplay = computed(this.countDisplayComputed.bind(this));
|
|
9
|
-
//
|
|
36
|
+
// =========================================
|
|
37
|
+
// INPUTS
|
|
38
|
+
// =========================================
|
|
39
|
+
/**
|
|
40
|
+
* Cấu hình popover tooltip khi hover
|
|
41
|
+
* @default undefined
|
|
42
|
+
*/
|
|
10
43
|
popoverConfig = input();
|
|
44
|
+
/**
|
|
45
|
+
* Trạng thái active - thay đổi màu sắc badge
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
11
48
|
active = input();
|
|
49
|
+
/**
|
|
50
|
+
* Số lượng hiển thị trên badge
|
|
51
|
+
* @default 0
|
|
52
|
+
*/
|
|
12
53
|
count = input(0, { transform: (value) => value ?? 0 });
|
|
13
|
-
|
|
14
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Chế độ hiển thị số
|
|
56
|
+
* - `'x'`: Số thường (1, 5, 15, 100)
|
|
57
|
+
* - `'0x'`: Có số 0 đằng trước nếu < 10 (01, 05)
|
|
58
|
+
* - `'x+'`: Hiển thị "maxCount+" khi vượt giới hạn (99+)
|
|
59
|
+
* - `'+x'`: Thêm dấu + phía trước (+01, +05)
|
|
60
|
+
* - `'k'`: Rút gọn hàng nghìn/triệu (1K, 1.5M)
|
|
61
|
+
* @default undefined - Các giá trị < 10 sẽ có số 0 ở đầu
|
|
62
|
+
*/
|
|
63
|
+
mode = input();
|
|
64
|
+
/**
|
|
65
|
+
* Giới hạn tối đa - Khi count > maxCount sẽ hiển thị "maxCount+" (với mode 'x+')
|
|
66
|
+
* @default Number.MAX_SAFE_INTEGER
|
|
67
|
+
*/
|
|
68
|
+
maxCount = input(Number.MAX_SAFE_INTEGER, {
|
|
69
|
+
transform: (value) => value ?? Number.MAX_SAFE_INTEGER,
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Bỏ margin-left mặc định của badge
|
|
73
|
+
* @default false
|
|
74
|
+
*/
|
|
15
75
|
ignoreMarginDefault = input();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Class CSS tùy chỉnh cho badge circle
|
|
78
|
+
* @default 'libs-ui-font-h6r'
|
|
79
|
+
*/
|
|
80
|
+
classCircle = input('libs-ui-font-h6r', {
|
|
81
|
+
transform: (value) => value ?? 'libs-ui-font-h6r',
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Bỏ qua stopPropagation khi click vào badge
|
|
85
|
+
* @default true
|
|
86
|
+
*/
|
|
87
|
+
ignoreStopPropagationEvent = input(true, {
|
|
88
|
+
transform: (value) => value ?? true,
|
|
89
|
+
});
|
|
90
|
+
// =========================================
|
|
91
|
+
// PRIVATE METHODS
|
|
92
|
+
// =========================================
|
|
93
|
+
/**
|
|
94
|
+
* Tính toán giá trị hiển thị dựa trên count và mode
|
|
95
|
+
* @returns Chuỗi đã format theo mode
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
19
98
|
countDisplayComputed() {
|
|
99
|
+
// Mode 'k': Rút gọn hàng nghìn/triệu
|
|
20
100
|
if (this.mode() === 'k' && this.count() > 999) {
|
|
21
101
|
const count = this.count() / 1000;
|
|
22
102
|
if (count > 1000) {
|
|
@@ -24,10 +104,12 @@ class LibsUiComponentsBadgeComponent {
|
|
|
24
104
|
}
|
|
25
105
|
return `${viewDataNumberByLanguage(count, true, 1, false, true)}K`;
|
|
26
106
|
}
|
|
107
|
+
// Mode 'x+': Hiển thị maxCount+ khi vượt giới hạn
|
|
27
108
|
if (this.mode() === 'x+' && this.count() > this.maxCount()) {
|
|
28
109
|
const countFormat = viewDataNumberByLanguage(this.maxCount(), true);
|
|
29
110
|
return `${countFormat}+`;
|
|
30
111
|
}
|
|
112
|
+
// Xử lý count = 0
|
|
31
113
|
if (!this.count()) {
|
|
32
114
|
switch (this.mode()) {
|
|
33
115
|
case '+x':
|
|
@@ -40,6 +122,7 @@ class LibsUiComponentsBadgeComponent {
|
|
|
40
122
|
return '00';
|
|
41
123
|
}
|
|
42
124
|
}
|
|
125
|
+
// Xử lý count < 10
|
|
43
126
|
if (this.count() < 10) {
|
|
44
127
|
switch (this.mode()) {
|
|
45
128
|
case '+x':
|
|
@@ -52,6 +135,7 @@ class LibsUiComponentsBadgeComponent {
|
|
|
52
135
|
return `0${this.count()}`;
|
|
53
136
|
}
|
|
54
137
|
}
|
|
138
|
+
// Mặc định: Format số và thêm + nếu mode '+x'
|
|
55
139
|
const countFormat = viewDataNumberByLanguage(this.count(), true);
|
|
56
140
|
return this.mode() === '+x' ? `+${countFormat}` : `${countFormat}`;
|
|
57
141
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libs-ui-components-badge.mjs","sources":["../../../../../libs-ui/components/badge/src/badge.component.ts","../../../../../libs-ui/components/badge/src/badge.component.html","../../../../../libs-ui/components/badge/src/libs-ui-components-badge.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { IPopoverOverlay, LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';\nimport { viewDataNumberByLanguage } from '@libs-ui/utils';\nimport { TYPE_BADGE_MODE } from './interfaces/mode.type';\n\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-badge',\n templateUrl: './badge.component.html',\n styleUrls: ['./badge.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LibsUiComponentsPopoverComponent],\n})\nexport class LibsUiComponentsBadgeComponent {\n //
|
|
1
|
+
{"version":3,"file":"libs-ui-components-badge.mjs","sources":["../../../../../libs-ui/components/badge/src/badge.component.ts","../../../../../libs-ui/components/badge/src/badge.component.html","../../../../../libs-ui/components/badge/src/libs-ui-components-badge.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { IPopoverOverlay, LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';\nimport { viewDataNumberByLanguage } from '@libs-ui/utils';\nimport { TYPE_BADGE_MODE } from './interfaces/mode.type';\n\n/**\n * Badge Component - Hiển thị số lượng/đếm với nhiều chế độ định dạng\n *\n * @description\n * Component dùng để hiển thị số lượng (notifications, messages, cart items...)\n * với nhiều chế độ format khác nhau: số thường, có số 0 đằng trước, rút gọn K/M,...\n *\n * @example\n * ```html\n * <!-- Basic -->\n * <libs_ui-components-badge [count]=\"5\" />\n *\n * <!-- Với mode -->\n * <libs_ui-components-badge [count]=\"5\" mode=\"0x\" />\n *\n * <!-- Với maxCount -->\n * <libs_ui-components-badge [count]=\"150\" mode=\"x+\" [maxCount]=\"99\" />\n * ```\n *\n * @publicApi\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-badge',\n templateUrl: './badge.component.html',\n styleUrls: ['./badge.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LibsUiComponentsPopoverComponent],\n})\nexport class LibsUiComponentsBadgeComponent {\n // =========================================\n // COMPUTED PROPERTIES\n // =========================================\n\n /**\n * Giá trị hiển thị đã được format theo mode\n * @internal\n */\n protected countDisplay = computed(this.countDisplayComputed.bind(this));\n\n // =========================================\n // INPUTS\n // =========================================\n\n /**\n * Cấu hình popover tooltip khi hover\n * @default undefined\n */\n readonly popoverConfig = input<IPopoverOverlay>();\n\n /**\n * Trạng thái active - thay đổi màu sắc badge\n * @default false\n */\n readonly active = input<boolean>();\n\n /**\n * Số lượng hiển thị trên badge\n * @default 0\n */\n readonly count = input<number, number>(0, { transform: (value) => value ?? 0 });\n\n /**\n * Chế độ hiển thị số\n * - `'x'`: Số thường (1, 5, 15, 100)\n * - `'0x'`: Có số 0 đằng trước nếu < 10 (01, 05)\n * - `'x+'`: Hiển thị \"maxCount+\" khi vượt giới hạn (99+)\n * - `'+x'`: Thêm dấu + phía trước (+01, +05)\n * - `'k'`: Rút gọn hàng nghìn/triệu (1K, 1.5M)\n * @default undefined - Các giá trị < 10 sẽ có số 0 ở đầu\n */\n readonly mode = input<TYPE_BADGE_MODE>();\n\n /**\n * Giới hạn tối đa - Khi count > maxCount sẽ hiển thị \"maxCount+\" (với mode 'x+')\n * @default Number.MAX_SAFE_INTEGER\n */\n readonly maxCount = input<number, number>(Number.MAX_SAFE_INTEGER, {\n transform: (value) => value ?? Number.MAX_SAFE_INTEGER,\n });\n\n /**\n * Bỏ margin-left mặc định của badge\n * @default false\n */\n readonly ignoreMarginDefault = input<boolean>();\n\n /**\n * Class CSS tùy chỉnh cho badge circle\n * @default 'libs-ui-font-h6r'\n */\n readonly classCircle = input<string, string>('libs-ui-font-h6r', {\n transform: (value) => value ?? 'libs-ui-font-h6r',\n });\n\n /**\n * Bỏ qua stopPropagation khi click vào badge\n * @default true\n */\n readonly ignoreStopPropagationEvent = input<boolean, boolean>(true, {\n transform: (value) => value ?? true,\n });\n\n // =========================================\n // PRIVATE METHODS\n // =========================================\n\n /**\n * Tính toán giá trị hiển thị dựa trên count và mode\n * @returns Chuỗi đã format theo mode\n * @internal\n */\n private countDisplayComputed(): string {\n // Mode 'k': Rút gọn hàng nghìn/triệu\n if (this.mode() === 'k' && this.count() > 999) {\n const count = this.count() / 1000;\n\n if (count > 1000) {\n return `${viewDataNumberByLanguage(count / 1000, true, 1, false, true)}M`;\n }\n\n return `${viewDataNumberByLanguage(count, true, 1, false, true)}K`;\n }\n\n // Mode 'x+': Hiển thị maxCount+ khi vượt giới hạn\n if (this.mode() === 'x+' && this.count() > this.maxCount()) {\n const countFormat = viewDataNumberByLanguage(this.maxCount(), true);\n return `${countFormat}+`;\n }\n\n // Xử lý count = 0\n if (!this.count()) {\n switch (this.mode()) {\n case '+x':\n return '+00';\n case 'x+':\n return '00';\n case 'x':\n return '0';\n case '0x':\n return '00';\n }\n }\n\n // Xử lý count < 10\n if (this.count() < 10) {\n switch (this.mode()) {\n case '+x':\n return `+0${this.count()}`;\n case 'x+':\n return `0${this.count()}`;\n case 'x':\n return `${this.count()}`;\n case '0x':\n return `0${this.count()}`;\n }\n }\n\n // Mặc định: Format số và thêm + nếu mode '+x'\n const countFormat = viewDataNumberByLanguage(this.count(), true);\n return this.mode() === '+x' ? `+${countFormat}` : `${countFormat}`;\n }\n}\n","<span\n class=\"libs-ui-badge {{ classCircle() }}\"\n [class.libs-ui-badge-active]=\"active()\"\n [class.ml-0]=\"ignoreMarginDefault()\"\n LibsUiComponentsPopoverDirective\n [type]=\"popoverConfig() ? 'other' : 'text'\"\n [config]=\"popoverConfig() ?? { content: countDisplay() }\"\n [ignoreStopPropagationEvent]=\"ignoreStopPropagationEvent()\">\n {{ countDisplay() }}\n</span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,40 @@
|
|
|
1
1
|
import { TYPE_BADGE_MODE } from './mode.type';
|
|
2
|
+
/**
|
|
3
|
+
* Interface cấu hình cho Badge component
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Dùng khi cần truyền config dạng object cho badge
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const badgeConfig: IBadge = {
|
|
11
|
+
* mode: '0x',
|
|
12
|
+
* count: 5,
|
|
13
|
+
* maxCount: 99
|
|
14
|
+
* };
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @interface IBadge
|
|
18
|
+
*/
|
|
2
19
|
export interface IBadge {
|
|
20
|
+
/**
|
|
21
|
+
* Chế độ hiển thị số
|
|
22
|
+
* @see TYPE_BADGE_MODE
|
|
23
|
+
*/
|
|
3
24
|
mode?: TYPE_BADGE_MODE;
|
|
25
|
+
/**
|
|
26
|
+
* Số lượng hiển thị
|
|
27
|
+
* @default 0
|
|
28
|
+
*/
|
|
4
29
|
count?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Giới hạn tối đa (dùng với mode 'x+')
|
|
32
|
+
* @default Number.MAX_SAFE_INTEGER
|
|
33
|
+
*/
|
|
5
34
|
maxCount?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Class CSS tùy chỉnh cho badge
|
|
37
|
+
* @default 'libs-ui-font-h6r'
|
|
38
|
+
*/
|
|
6
39
|
classCircle?: string;
|
|
7
40
|
}
|
|
@@ -1 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Các chế độ hiển thị số trên Badge
|
|
3
|
+
*
|
|
4
|
+
* @description
|
|
5
|
+
* - `'x'`: Số thường (1, 5, 15, 100)
|
|
6
|
+
* - `'0x'`: Có số 0 đằng trước nếu < 10 (01, 05, 15)
|
|
7
|
+
* - `'x+'`: Hiển thị "maxCount+" khi vượt giới hạn (99+)
|
|
8
|
+
* - `'+x'`: Thêm dấu + phía trước (+01, +05, +15)
|
|
9
|
+
* - `'k'`: Rút gọn hàng nghìn/triệu (1K, 1.5M)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const mode: TYPE_BADGE_MODE = '0x';
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
1
16
|
export type TYPE_BADGE_MODE = 'x' | 'x+' | '+x' | 'k' | '0x';
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-badge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.356-0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/core": ">=18.0.0",
|
|
6
|
-
"@libs-ui/components-popover": "0.2.
|
|
7
|
-
"@libs-ui/utils": "0.2.
|
|
6
|
+
"@libs-ui/components-popover": "0.2.356-0",
|
|
7
|
+
"@libs-ui/utils": "0.2.356-0",
|
|
8
8
|
"rxjs": "~7.8.0"
|
|
9
9
|
},
|
|
10
10
|
"sideEffects": false,
|