npm package: @libs-ui/components-buttons-dropdown
Description: > Component Dropdown Button với menu tùy chọn, hỗ trợ chế độ apply ngay hoặc apply sau.
Latest version: 0.2.356-23

# @libs-ui/components-buttons-dropdown

> Component Dropdown Button với menu tùy chọn, hỗ trợ chế độ apply ngay hoặc apply sau.

## Giới thiệu

`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.

### Tính năng

- ✅ 2 chế độ: Apply ngay hoặc Apply sau
- ✅ Tùy chỉnh field hiển thị và key field
- ✅ Two-way binding cho item được chọn
- ✅ Tích hợp popover với nhiều tùy chọn vị trí
- ✅ Hỗ trợ icon cho từng item
- ✅ Hỗ trợ custom template cho item
- ✅ Disable state cho button và từng item
- ✅ Angular Signals cho tính phản hồi cao
- ✅ OnPush Change Detection tối ưu hiệu năng

## Khi nào sử dụng

- Khi cần hiển thị danh sách tùy chọn trong dropdown menu
- Khi cần cho phép user chọn một item từ danh sách
- Khi cần chế độ preview trước khi apply (applyNow = false)
- Phù hợp cho filter buttons, action menus, selection dropdowns

## Cài đặt

```bash
# npm
npm install @libs-ui/components-buttons-dropdown

# yarn
yarn add @libs-ui/components-buttons-dropdown
```

## Import

```typescript
import { LibsUiComponentsButtonsDropdownComponent, IButtonDropdown, IPopupConfigButtonDropdown } from '@libs-ui/components-buttons-dropdown';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsDropdownComponent],
  // ...
})
export class YourComponent {}
```

## Ví dụ

### Basic - Apply Ngay

```html
<libs_ui-components-buttons-dropdown
  label="Select Option"
  [items]="options"
  [applyNow]="true"
  (outSelectItem)="handleSelect($event)" />
```

```typescript
options = [
  { key: '1', label: 'Option 1' },
  { key: '2', label: 'Option 2' },
  { key: '3', label: 'Option 3' }
];

handleSelect(item: any) {
  console.log('Selected:', item);
}
```

### With Apply Button

```html
<libs_ui-components-buttons-dropdown
  label="Select Option"
  [items]="options"
  [applyNow]="false"
  [(keySelected)]="selectedKey"
  (outApply)="handleApply($event)" />
```

```typescript
selectedKey = '1';

handleApply(item: any) {
  console.log('Applied:', item);
}
```

### Custom Field Names

```html
<libs_ui-components-buttons-dropdown
  label="Select User"
  [items]="users"
  fieldDisplay="name"
  keyField="id"
  [applyNow]="true"
  (outSelectItem)="handleSelect($event)" />
```

```typescript
users = [
  { id: 'u1', name: 'John Doe' },
  { id: 'u2', name: 'Jane Smith' },
  { id: 'u3', name: 'Bob Johnson' },
];
```

### With Icons

```html
<libs_ui-components-buttons-dropdown
  label="Actions"
  [items]="actions"
  fieldClassIconLeft="iconClass"
  [applyNow]="true"
  (outSelectItem)="handleAction($event)" />
```

```typescript
actions = [
  { key: 'edit', label: 'Edit', iconClass: 'libs-ui-icon-edit' },
  { key: 'delete', label: 'Delete', iconClass: 'libs-ui-icon-delete' },
  { key: 'share', label: 'Share', iconClass: 'libs-ui-icon-share' },
];
```

### Custom Popup Config

```html
<libs_ui-components-buttons-dropdown
  label="Options"
  [items]="options"
  [popupConfig]="{
    width: 300,
    maxHeight: 200,
    direction: 'bottom',
    zIndex: 1500
  }"
  [applyNow]="true" />
```

### Different Button Types

```html
<!-- Primary -->
<libs_ui-components-buttons-dropdown
  label="Primary"
  [items]="options"
  typeButton="button-primary"
  [applyNow]="true" />

<!-- Secondary -->
<libs_ui-components-buttons-dropdown
  label="Secondary"
  [items]="options"
  typeButton="button-secondary"
  [applyNow]="true" />

<!-- Outline -->
<libs_ui-components-buttons-dropdown
  label="Outline"
  [items]="options"
  typeButton="button-outline"
  [applyNow]="true" />
```

## API

### libs_ui-components-buttons-dropdown

#### Inputs

| Property                                     | Type                         | Default                                    | Description                                       |
| -------------------------------------------- | ---------------------------- | ------------------------------------------ | ------------------------------------------------- |
| `[applyNow]`                                 | `boolean`                    | `false`                                    | Nếu true: chọn xong tự emit; false: cần bấm Apply |
| `[classIconLeft]`                            | `string`                     | `''`                                       | Class icon bên trái button                        |
| `[classIconRight]`                           | `string`                     | `'libs-ui-icon-move-right rotate-[90deg]'` | Class icon bên phải button                        |
| `[classInclude]`                             | `string`                     | `''`                                       | Class CSS bổ sung cho button                      |
| `[classIncludeContainer]`                    | `string`                     | `undefined`                                | Class CSS cho container                           |
| `[classLabel]`                               | `string`                     | `''`                                       | Class CSS cho label                               |
| `[disable]`                                  | `boolean`                    | `false`                                    | Disable button                                    |
| `[fieldClass]`                               | `string`                     | `'class'`                                  | Tên field chứa class của item                     |
| `[fieldClassIconLeft]`                       | `string`                     | `'classIconLeft'`                          | Tên field chứa icon class của item                |
| `[fieldDisplay]`                             | `string`                     | `'label'`                                  | Tên field hiển thị của item                       |
| `[iconOnlyType]`                             | `boolean`                    | `false`                                    | Chỉ hiển thị icon, ẩn label                       |
| `[ignoreHiddenPopoverContentWhenMouseLeave]` | `boolean`                    | `true`                                     | Giữ popover mở khi chuột rời                      |
| `[items]`                                    | `Array<any>`                 | required                                   | Danh sách items hiển thị                          |
| `[keyField]`                                 | `string`                     | `'key'`                                    | Tên field làm key của item                        |
| `[(keySelected)]`                            | `string`                     | `undefined`                                | Key của item được chọn (two-way binding)          |
| `[label]`                                    | `string`                     | `undefined`                                | Label của button                                  |
| `[modePopover]`                              | `TYPE_POPOVER_MODE`          | `'click-toggle'`                           | Chế độ hiển thị popover                           |
| `[popupConfig]`                              | `IPopupConfigButtonDropdown` | `{...}`                                    | Cấu hình popup (width, height, direction...)      |
| `[showBorderBottom]`                         | `boolean`                    | `false`                                    | Hiển thị border dưới items                        |
| `[sizeButton]`                               | `TYPE_SIZE_BUTTON`           | `'medium'`                                 | Kích thước button                                 |
| `[typeButton]`                               | `TYPE_BUTTON`                | `'button-primary'`                         | Kiểu button                                       |

#### Outputs

| Property                | Type                           | Description                                |
| ----------------------- | ------------------------------ | ------------------------------------------ |
| `(outApply)`            | `any`                          | Emit khi bấm Apply (chế độ applyNow=false) |
| `(outFunctionsControl)` | `IPopoverFunctionControlEvent` | Emit functions điều khiển popover          |
| `(outHover)`            | `boolean`                      | Emit khi hover state thay đổi              |
| `(outIconEvent)`        | `MouseEvent`                   | Emit khi click icon                        |
| `(outPopoverEvent)`     | `TYPE_POPOVER_EVENT`           | Emit events từ popover                     |
| `(outSelectItem)`       | `any`                          | Emit khi chọn item                         |

#### Public Methods

| Method             | Description                             |
| ------------------ | --------------------------------------- |
| `FunctionsControl` | Getter để lấy popover control functions |

## Types & Interfaces

```typescript
/**
 * Interface cho Dropdown Button component
 */
export interface IButtonDropdown extends IButton {
  /** Danh sách các mục sẽ hiển thị trong menu */
  items: any[];
  /** Tên trường dùng để hiển thị nội dung của mỗi mục */
  fieldDisplay?: string;
  /** Tên trường dùng làm giá trị key của mỗi mục */
  keyField?: string;
  /** Giá trị key đang được chọn (hỗ trợ two-way binding) */
  keySelected?: string;
  /** Nếu true: chọn xong tự emit sự kiện; false: cần bấm nút Áp dụng */
  applyNow?: boolean;
  /** Hiển thị đường kẻ dưới menu khi mở */
  showBorderBottom?: boolean;
  /** Cấu hình chi tiết cho popover (vị trí, kích thước) */
  popupConfig?: IPopupConfigButtonDropdown;
  /** Giữ popover mở khi chuột rời khỏi nội dung */
  ignoreHiddenPopoverContentWhenMouseLeave?: boolean;
  /** Cách hiển thị popover (click, hover,...) */
  modePopover?: TYPE_POPOVER_MODE;
}

/**
 * Cấu hình cho Dropdown popover
 */
export interface IPopupConfigButtonDropdown {
  width?: number;
  maxWidth?: number;
  maxHeight?: number;
  zIndex?: number;
  direction?: TYPE_POPOVER_DIRECTION;
  timeDestroy?: number;
  widthByParent?: boolean;
  position?: {
    mode: 'start' | 'center' | 'end';
    distance: number;
  };
  classInclude?: string;
}
```

## Item Structure

Mỗi item trong array `items` có thể có các thuộc tính:

```typescript
interface DropdownItem {
  // Required fields (tùy theo fieldDisplay và keyField)
  [fieldDisplay]: string; // Mặc định: 'label'
  [keyField]: string; // Mặc định: 'key'

  // Optional fields
  class?: string; // Class cho item
  classIconLeft?: string; // Icon class
  classInclude?: string; // Class bổ sung
  classRow?: string; // Class cho row
  disable?: boolean; // Disable item
  ignoreFlex?: boolean; // Không dùng flex layout
  showPopover?: boolean; // Hiển thị popover cho item
  popoverContent?: string; // Nội dung popover
  subTemplate?: TemplateRef; // Custom template
  buttonTemplateConfig?: {
    // Config cho button trong item
    icon?: string;
    iconLeft?: string;
    label?: string;
    type?: TYPE_BUTTON;
    action: (item: any, items: any[]) => void;
  };
}
```

## Công nghệ

| Technology      | Version | Purpose          |
| --------------- | ------- | ---------------- |
| Angular         | 18+     | Framework        |
| Angular Signals | -       | State management |
| TailwindCSS     | 3.x     | Styling          |
| OnPush          | -       | Change Detection |

## Demo

```bash
npx nx serve core-ui
```

Truy cập: `http://localhost:4500/buttons/dropdown`

## Unit Tests

```bash
# Chạy tests
npx nx test components-buttons-dropdown

# Coverage
npx nx test components-buttons-dropdown --coverage

# Watch mode
npx nx test components-buttons-dropdown --watch
```

## License

MIT