@libs-ui/components-buttons-dropdown 0.2.355-13 → 0.2.355-15
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 +329 -0
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# @libs-ui/components-buttons-dropdown
|
|
2
|
+
|
|
3
|
+
> Component Dropdown Button với menu tùy chọn, hỗ trợ chế độ apply ngay hoặc apply sau.
|
|
4
|
+
|
|
5
|
+
## Giới thiệu
|
|
6
|
+
|
|
7
|
+
`LibsUiComponentsButtonsDropdownComponent` là một standalone Angular component được thiết kế để hiển thị button với dropdown menu. Component hỗ trợ 2 chế độ: apply ngay (applyNow) khi chọn item hoặc chọn trước rồi bấm nút Apply.
|
|
8
|
+
|
|
9
|
+
### Tính năng
|
|
10
|
+
|
|
11
|
+
- ✅ 2 chế độ: Apply ngay hoặc Apply sau
|
|
12
|
+
- ✅ Tùy chỉnh field hiển thị và key field
|
|
13
|
+
- ✅ Two-way binding cho item được chọn
|
|
14
|
+
- ✅ Tích hợp popover với nhiều tùy chọn vị trí
|
|
15
|
+
- ✅ Hỗ trợ icon cho từng item
|
|
16
|
+
- ✅ Hỗ trợ custom template cho item
|
|
17
|
+
- ✅ Disable state cho button và từng item
|
|
18
|
+
- ✅ Angular Signals cho tính phản hồi cao
|
|
19
|
+
- ✅ OnPush Change Detection tối ưu hiệu năng
|
|
20
|
+
|
|
21
|
+
## Khi nào sử dụng
|
|
22
|
+
|
|
23
|
+
- Khi cần hiển thị danh sách tùy chọn trong dropdown menu
|
|
24
|
+
- Khi cần cho phép user chọn một item từ danh sách
|
|
25
|
+
- Khi cần chế độ preview trước khi apply (applyNow = false)
|
|
26
|
+
- Phù hợp cho filter buttons, action menus, selection dropdowns
|
|
27
|
+
|
|
28
|
+
## Cài đặt
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# npm
|
|
32
|
+
npm install @libs-ui/components-buttons-dropdown
|
|
33
|
+
|
|
34
|
+
# yarn
|
|
35
|
+
yarn add @libs-ui/components-buttons-dropdown
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Import
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { LibsUiComponentsButtonsDropdownComponent, IButtonDropdown, IPopupConfigButtonDropdown } from '@libs-ui/components-buttons-dropdown';
|
|
42
|
+
|
|
43
|
+
@Component({
|
|
44
|
+
standalone: true,
|
|
45
|
+
imports: [LibsUiComponentsButtonsDropdownComponent],
|
|
46
|
+
// ...
|
|
47
|
+
})
|
|
48
|
+
export class YourComponent {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Ví dụ
|
|
52
|
+
|
|
53
|
+
### Basic - Apply Ngay
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<libs_ui-components-buttons-dropdown
|
|
57
|
+
label="Select Option"
|
|
58
|
+
[items]="options"
|
|
59
|
+
[applyNow]="true"
|
|
60
|
+
(outSelectItem)="handleSelect($event)" />
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
options = [
|
|
65
|
+
{ key: '1', label: 'Option 1' },
|
|
66
|
+
{ key: '2', label: 'Option 2' },
|
|
67
|
+
{ key: '3', label: 'Option 3' }
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
handleSelect(item: any) {
|
|
71
|
+
console.log('Selected:', item);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### With Apply Button
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<libs_ui-components-buttons-dropdown
|
|
79
|
+
label="Select Option"
|
|
80
|
+
[items]="options"
|
|
81
|
+
[applyNow]="false"
|
|
82
|
+
[(keySelected)]="selectedKey"
|
|
83
|
+
(outApply)="handleApply($event)" />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
selectedKey = '1';
|
|
88
|
+
|
|
89
|
+
handleApply(item: any) {
|
|
90
|
+
console.log('Applied:', item);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Custom Field Names
|
|
95
|
+
|
|
96
|
+
```html
|
|
97
|
+
<libs_ui-components-buttons-dropdown
|
|
98
|
+
label="Select User"
|
|
99
|
+
[items]="users"
|
|
100
|
+
fieldDisplay="name"
|
|
101
|
+
keyField="id"
|
|
102
|
+
[applyNow]="true"
|
|
103
|
+
(outSelectItem)="handleSelect($event)" />
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
users = [
|
|
108
|
+
{ id: 'u1', name: 'John Doe' },
|
|
109
|
+
{ id: 'u2', name: 'Jane Smith' },
|
|
110
|
+
{ id: 'u3', name: 'Bob Johnson' },
|
|
111
|
+
];
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### With Icons
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<libs_ui-components-buttons-dropdown
|
|
118
|
+
label="Actions"
|
|
119
|
+
[items]="actions"
|
|
120
|
+
fieldClassIconLeft="iconClass"
|
|
121
|
+
[applyNow]="true"
|
|
122
|
+
(outSelectItem)="handleAction($event)" />
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
actions = [
|
|
127
|
+
{ key: 'edit', label: 'Edit', iconClass: 'libs-ui-icon-edit' },
|
|
128
|
+
{ key: 'delete', label: 'Delete', iconClass: 'libs-ui-icon-delete' },
|
|
129
|
+
{ key: 'share', label: 'Share', iconClass: 'libs-ui-icon-share' },
|
|
130
|
+
];
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Custom Popup Config
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<libs_ui-components-buttons-dropdown
|
|
137
|
+
label="Options"
|
|
138
|
+
[items]="options"
|
|
139
|
+
[popupConfig]="{
|
|
140
|
+
width: 300,
|
|
141
|
+
maxHeight: 200,
|
|
142
|
+
direction: 'bottom',
|
|
143
|
+
zIndex: 1500
|
|
144
|
+
}"
|
|
145
|
+
[applyNow]="true" />
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Different Button Types
|
|
149
|
+
|
|
150
|
+
```html
|
|
151
|
+
<!-- Primary -->
|
|
152
|
+
<libs_ui-components-buttons-dropdown
|
|
153
|
+
label="Primary"
|
|
154
|
+
[items]="options"
|
|
155
|
+
typeButton="button-primary"
|
|
156
|
+
[applyNow]="true" />
|
|
157
|
+
|
|
158
|
+
<!-- Secondary -->
|
|
159
|
+
<libs_ui-components-buttons-dropdown
|
|
160
|
+
label="Secondary"
|
|
161
|
+
[items]="options"
|
|
162
|
+
typeButton="button-secondary"
|
|
163
|
+
[applyNow]="true" />
|
|
164
|
+
|
|
165
|
+
<!-- Outline -->
|
|
166
|
+
<libs_ui-components-buttons-dropdown
|
|
167
|
+
label="Outline"
|
|
168
|
+
[items]="options"
|
|
169
|
+
typeButton="button-outline"
|
|
170
|
+
[applyNow]="true" />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## API
|
|
174
|
+
|
|
175
|
+
### libs_ui-components-buttons-dropdown
|
|
176
|
+
|
|
177
|
+
#### Inputs
|
|
178
|
+
|
|
179
|
+
| Property | Type | Default | Description |
|
|
180
|
+
| -------------------------------------------- | ---------------------------- | ------------------------------------------ | ------------------------------------------------- |
|
|
181
|
+
| `[applyNow]` | `boolean` | `false` | Nếu true: chọn xong tự emit; false: cần bấm Apply |
|
|
182
|
+
| `[classIconLeft]` | `string` | `''` | Class icon bên trái button |
|
|
183
|
+
| `[classIconRight]` | `string` | `'libs-ui-icon-move-right rotate-[90deg]'` | Class icon bên phải button |
|
|
184
|
+
| `[classInclude]` | `string` | `''` | Class CSS bổ sung cho button |
|
|
185
|
+
| `[classIncludeContainer]` | `string` | `undefined` | Class CSS cho container |
|
|
186
|
+
| `[classLabel]` | `string` | `''` | Class CSS cho label |
|
|
187
|
+
| `[disable]` | `boolean` | `false` | Disable button |
|
|
188
|
+
| `[fieldClass]` | `string` | `'class'` | Tên field chứa class của item |
|
|
189
|
+
| `[fieldClassIconLeft]` | `string` | `'classIconLeft'` | Tên field chứa icon class của item |
|
|
190
|
+
| `[fieldDisplay]` | `string` | `'label'` | Tên field hiển thị của item |
|
|
191
|
+
| `[iconOnlyType]` | `boolean` | `false` | Chỉ hiển thị icon, ẩn label |
|
|
192
|
+
| `[ignoreHiddenPopoverContentWhenMouseLeave]` | `boolean` | `true` | Giữ popover mở khi chuột rời |
|
|
193
|
+
| `[items]` | `Array<any>` | required | Danh sách items hiển thị |
|
|
194
|
+
| `[keyField]` | `string` | `'key'` | Tên field làm key của item |
|
|
195
|
+
| `[(keySelected)]` | `string` | `undefined` | Key của item được chọn (two-way binding) |
|
|
196
|
+
| `[label]` | `string` | `undefined` | Label của button |
|
|
197
|
+
| `[modePopover]` | `TYPE_POPOVER_MODE` | `'click-toggle'` | Chế độ hiển thị popover |
|
|
198
|
+
| `[popupConfig]` | `IPopupConfigButtonDropdown` | `{...}` | Cấu hình popup (width, height, direction...) |
|
|
199
|
+
| `[showBorderBottom]` | `boolean` | `false` | Hiển thị border dưới items |
|
|
200
|
+
| `[sizeButton]` | `TYPE_SIZE_BUTTON` | `'medium'` | Kích thước button |
|
|
201
|
+
| `[typeButton]` | `TYPE_BUTTON` | `'button-primary'` | Kiểu button |
|
|
202
|
+
|
|
203
|
+
#### Outputs
|
|
204
|
+
|
|
205
|
+
| Property | Type | Description |
|
|
206
|
+
| ----------------------- | ------------------------------ | ------------------------------------------ |
|
|
207
|
+
| `(outApply)` | `any` | Emit khi bấm Apply (chế độ applyNow=false) |
|
|
208
|
+
| `(outFunctionsControl)` | `IPopoverFunctionControlEvent` | Emit functions điều khiển popover |
|
|
209
|
+
| `(outHover)` | `boolean` | Emit khi hover state thay đổi |
|
|
210
|
+
| `(outIconEvent)` | `MouseEvent` | Emit khi click icon |
|
|
211
|
+
| `(outPopoverEvent)` | `TYPE_POPOVER_EVENT` | Emit events từ popover |
|
|
212
|
+
| `(outSelectItem)` | `any` | Emit khi chọn item |
|
|
213
|
+
|
|
214
|
+
#### Public Methods
|
|
215
|
+
|
|
216
|
+
| Method | Description |
|
|
217
|
+
| ------------------ | --------------------------------------- |
|
|
218
|
+
| `FunctionsControl` | Getter để lấy popover control functions |
|
|
219
|
+
|
|
220
|
+
## Types & Interfaces
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
/**
|
|
224
|
+
* Interface cho Dropdown Button component
|
|
225
|
+
*/
|
|
226
|
+
export interface IButtonDropdown extends IButton {
|
|
227
|
+
/** Danh sách các mục sẽ hiển thị trong menu */
|
|
228
|
+
items: any[];
|
|
229
|
+
/** Tên trường dùng để hiển thị nội dung của mỗi mục */
|
|
230
|
+
fieldDisplay?: string;
|
|
231
|
+
/** Tên trường dùng làm giá trị key của mỗi mục */
|
|
232
|
+
keyField?: string;
|
|
233
|
+
/** Giá trị key đang được chọn (hỗ trợ two-way binding) */
|
|
234
|
+
keySelected?: string;
|
|
235
|
+
/** Nếu true: chọn xong tự emit sự kiện; false: cần bấm nút Áp dụng */
|
|
236
|
+
applyNow?: boolean;
|
|
237
|
+
/** Hiển thị đường kẻ dưới menu khi mở */
|
|
238
|
+
showBorderBottom?: boolean;
|
|
239
|
+
/** Cấu hình chi tiết cho popover (vị trí, kích thước) */
|
|
240
|
+
popupConfig?: IPopupConfigButtonDropdown;
|
|
241
|
+
/** Giữ popover mở khi chuột rời khỏi nội dung */
|
|
242
|
+
ignoreHiddenPopoverContentWhenMouseLeave?: boolean;
|
|
243
|
+
/** Cách hiển thị popover (click, hover,...) */
|
|
244
|
+
modePopover?: TYPE_POPOVER_MODE;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Cấu hình cho Dropdown popover
|
|
249
|
+
*/
|
|
250
|
+
export interface IPopupConfigButtonDropdown {
|
|
251
|
+
width?: number;
|
|
252
|
+
maxWidth?: number;
|
|
253
|
+
maxHeight?: number;
|
|
254
|
+
zIndex?: number;
|
|
255
|
+
direction?: TYPE_POPOVER_DIRECTION;
|
|
256
|
+
timeDestroy?: number;
|
|
257
|
+
widthByParent?: boolean;
|
|
258
|
+
position?: {
|
|
259
|
+
mode: 'start' | 'center' | 'end';
|
|
260
|
+
distance: number;
|
|
261
|
+
};
|
|
262
|
+
classInclude?: string;
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Item Structure
|
|
267
|
+
|
|
268
|
+
Mỗi item trong array `items` có thể có các thuộc tính:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
interface DropdownItem {
|
|
272
|
+
// Required fields (tùy theo fieldDisplay và keyField)
|
|
273
|
+
[fieldDisplay]: string; // Mặc định: 'label'
|
|
274
|
+
[keyField]: string; // Mặc định: 'key'
|
|
275
|
+
|
|
276
|
+
// Optional fields
|
|
277
|
+
class?: string; // Class cho item
|
|
278
|
+
classIconLeft?: string; // Icon class
|
|
279
|
+
classInclude?: string; // Class bổ sung
|
|
280
|
+
classRow?: string; // Class cho row
|
|
281
|
+
disable?: boolean; // Disable item
|
|
282
|
+
ignoreFlex?: boolean; // Không dùng flex layout
|
|
283
|
+
showPopover?: boolean; // Hiển thị popover cho item
|
|
284
|
+
popoverContent?: string; // Nội dung popover
|
|
285
|
+
subTemplate?: TemplateRef; // Custom template
|
|
286
|
+
buttonTemplateConfig?: {
|
|
287
|
+
// Config cho button trong item
|
|
288
|
+
icon?: string;
|
|
289
|
+
iconLeft?: string;
|
|
290
|
+
label?: string;
|
|
291
|
+
type?: TYPE_BUTTON;
|
|
292
|
+
action: (item: any, items: any[]) => void;
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Công nghệ
|
|
298
|
+
|
|
299
|
+
| Technology | Version | Purpose |
|
|
300
|
+
| --------------- | ------- | ---------------- |
|
|
301
|
+
| Angular | 18+ | Framework |
|
|
302
|
+
| Angular Signals | - | State management |
|
|
303
|
+
| TailwindCSS | 3.x | Styling |
|
|
304
|
+
| OnPush | - | Change Detection |
|
|
305
|
+
|
|
306
|
+
## Demo
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
npx nx serve core-ui
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Truy cập: `http://localhost:4500/buttons/dropdown`
|
|
313
|
+
|
|
314
|
+
## Unit Tests
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Chạy tests
|
|
318
|
+
npx nx test components-buttons-dropdown
|
|
319
|
+
|
|
320
|
+
# Coverage
|
|
321
|
+
npx nx test components-buttons-dropdown --coverage
|
|
322
|
+
|
|
323
|
+
# Watch mode
|
|
324
|
+
npx nx test components-buttons-dropdown --watch
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## License
|
|
328
|
+
|
|
329
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-buttons-dropdown",
|
|
3
|
-
"version": "0.2.355-
|
|
3
|
+
"version": "0.2.355-15",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": ">=18.0.0",
|
|
6
6
|
"@angular/core": ">=18.0.0",
|
|
7
|
-
"@libs-ui/components-buttons-button": "0.2.355-
|
|
8
|
-
"@libs-ui/components-popover": "0.2.355-
|
|
9
|
-
"@libs-ui/utils": "0.2.355-
|
|
7
|
+
"@libs-ui/components-buttons-button": "0.2.355-15",
|
|
8
|
+
"@libs-ui/components-popover": "0.2.355-15",
|
|
9
|
+
"@libs-ui/utils": "0.2.355-15",
|
|
10
10
|
"@ngx-translate/core": "^15.0.0",
|
|
11
|
-
"@libs-ui/interfaces-types": "0.2.355-
|
|
11
|
+
"@libs-ui/interfaces-types": "0.2.355-15"
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"module": "fesm2022/libs-ui-components-buttons-dropdown.mjs",
|