npm package: @libs-ui/components-modal
Description: > Component Modal mạnh mẽ và linh hoạt hỗ trợ hiển thị nội dung trên một lớp phủ, giúp tập trung sự chú ý của người dùng vào một tác vụ cụ thể.
Latest version: 0.2.356-23

# @libs-ui/components-modal

> Component Modal mạnh mẽ và linh hoạt hỗ trợ hiển thị nội dung trên một lớp phủ, giúp tập trung sự chú ý của người dùng vào một tác vụ cụ thể.

## Giới thiệu

`LibsUiComponentsModalComponent` là một standalone component cung cấp giải pháp hiển thị modal chuyên nghiệp với các tính năng:

- ✅ **Đa dạng Mode**: Hỗ trợ hiển thị ở giữa màn hình (`center`) hoặc trượt từ bên phải (`offset-right`).
- ✅ **Cấu trúc linh hoạt**: Tích hợp sẵn Header, Body, Footer với khả năng tùy biến nội dung cao qua cả `@Input` và content projection.
- ✅ **Quản lý trạng thái**: Hỗ trợ đóng modal qua phím `Escape`, backdrop, hoặc các nút điều khiển.
- ✅ **Signals Ready**: Sử dụng Angular Signals cho việc quản lý hiển thị và cấu hình.
- ✅ **Hiệu ứng mượt mà**: Tích hợp các animation chuyển cảnh hiện đại.

## Khi nào sử dụng

- Khi cần xác nhận một hành động quan trọng từ người dùng (Confirm dialog).
- Khi hiển thị form nhập liệu hoặc chi tiết thông tin mà không muốn rời khỏi trang hiện tại.
- Khi cần thông báo kết quả thao tác (Success/Error/Warning messages).
- Khi hiển thị các tài liệu, hướng dẫn hoặc nội dung phụ trợ.

## Cài đặt

```bash
# npm
npm install @libs-ui/components-modal

# yarn
yarn add @libs-ui/components-modal
```

## Import

```typescript
import { LibsUiComponentsModalComponent } from '@libs-ui/components-modal';

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

## Ví dụ

### Basic Modal (Center)

```html
<libs_ui-components-modal
  [(show)]="isVisible"
  mode="center"
  title="Tiêu đề Modal"
  [bodyConfig]="{
    lines: [{ text: 'Nội dung thông báo đơn giản ở đây.' }]
  }"
  (outEvent)="onModalEvent($event)"></libs_ui-components-modal>
```

### Advanced (Offset Right with Custom Content)

```html
<libs_ui-components-modal
  [(show)]="isDetailOpen"
  mode="offset-right"
  width="600px"
  title="Chi tiết đơn hàng"
  (outEvent)="handlerEvent($event)">
  <div class="libs-ui-modal-body-custom p-4">
    <!-- Nội dung phức tạp của bạn ở đây -->
    <app-order-detail [data]="currentOrder"></app-order-detail>
  </div>

  <div class="libs-ui-modal-footer-custom px-4 py-3 flex justify-end gap-2">
    <button (click)="isDetailOpen = false">Đóng</button>
    <button (click)="save()">Lưu thay đổi</button>
  </div>
</libs_ui-components-modal>
```

### Buttons Footer (3 Zones)

```typescript
// Cấu hình buttons footer theo 3 vùng
modalRef.setInput('buttonsFooter', {
  left: [
    { label: 'Xóa', type: 'button-danger', action: async () => console.log('delete') },
  ],
  center: [
    { label: 'Bỏ qua', type: 'button-third' },
  ],
  right: [
    { label: 'Hủy', type: 'button-third', action: async () => modalRef.instance.outEvent.emit('cancel') },
    { label: 'Lưu', action: async () => console.log('save') },
  ],
});
```

## API

### libs_ui-components-modal

#### Inputs

| Property                                      | Type                         | Default          | Description                                                 |
| --------------------------------------------- | ---------------------------- | ---------------- | ----------------------------------------------------------- |
| `[(show)]`                                    | `boolean`                    | `true`           | Điều khiển trạng thái hiển thị của modal (Two-way binding). |
| `[mode]`                                      | `'center' \| 'offset-right'` | `'offset-right'` | Chế độ hiển thị của modal.                                  |
| `[width]`                                     | `string`                     | `undefined`      | Chiều rộng của modal (Model).                               |
| `[height]`                                    | `string`                     | `undefined`      | Chiều cao của modal (Model).                                |
| `[maxWidth]`                                  | `string`                     | `undefined`      | Chiều rộng tối đa (Model).                                  |
| `[maxHeight]`                                 | `string`                     | `undefined`      | Chiều cao tối đa (Model).                                   |
| `[minWidth]`                                  | `string`                     | `undefined`      | Chiều rộng tối thiểu (Model).                               |
| `[title]`                                     | `string`                     | `''`             | Tiêu đề hiển thị trên header.                               |
| `[zIndex]`                                    | `number`                     | `1200`           | Thứ tự hiển thị lớp phủ.                                    |
| `[isFullScreen]`                              | `boolean`                    | `false`          | Bật chế độ hiển thị toàn màn hình.                          |
| `[disable]`                                   | `boolean`                    | `false`          | Vô hiệu hóa các tương tác trong modal (Model).              |
| `[headerConfig]`                              | `IModalHeaderConfig`         | `{}`             | Cấu hình chi tiết cho phần Header.                          |
| `[bodyConfig]`                                | `IModalBodyConfig`           | `{}`             | Cấu hình nội dung mặc định phần Body.                       |
| `[footerConfig]`                              | `IModalFooterConfig`         | `{}`             | Cấu hình phần Footer.                                       |
| `[buttonsFooter]`                             | `{ left?: IButton[]; center?: IButton[]; right?: IButton[] }` | `{ right: [Cancel, Agree] }` | Cấu hình buttons footer theo 3 vùng (Model).              |
| `[escapeKeyboardCloseModal]`                  | `boolean`                    | `false`          | Cho phép đóng modal khi nhấn phím Escape.                   |
| `[isBackdropTransparent]`                     | `boolean`                    | `undefined`      | Làm trong suốt lớp màn mờ (backdrop).                       |
| `[isBackgroundTransparentModal]`              | `boolean`                    | `undefined`      | Làm trong suốt nền của modal.                               |
| `[isSizeBackdropByWidthHeightInput]`          | `boolean`                    | `undefined`      | Backdrop co giãn theo width/height của modal.               |
| `[hasShadowBoxWhenHiddenBackDropTransparent]` | `boolean`                    | `undefined`      | Hiển thị bóng đổ khi backdrop trong suốt.                   |
| `[classIncludeModalWrapper]`                  | `string`                     | `...`            | Class CSS bổ sung cho container bao ngoài modal.            |
| `[ignoreCommunicateMicroEvent]`               | `boolean`                    | `undefined`      | Bỏ qua việc gửi postMessage tới parent window.              |
| `[titleUseXssFilter]`                         | `boolean`                    | `undefined`      | Bật bộ lọc XSS cho tiêu đề.                                 |
| `[titleUseTooltip]`                           | `boolean`                    | `undefined`      | Hiển thị tooltip cho tiêu đề.                               |
| `[titleUseInnerText]`                         | `boolean`                    | `undefined`      | Render tiêu đề dưới dạng innerText.                         |
| `[isClickOutsideClose]`                       | `boolean`                    | `false`          | Cho phép đóng/huỷ modal khi click ra ngoài backdrop.        |

#### Outputs

| Property               | Type                                   | Description                                                                        |
| ---------------------- | -------------------------------------- | ---------------------------------------------------------------------------------- |
| `(outEvent)`           | `EventEmitter<TYPE_MODAL_EVENT>`       | Phát ra các sự kiện khi người dùng tương tác (`close`, `back`, `agree`, `cancel`). |
| `(outScrollContent)`   | `EventEmitter<Event>`                  | Phát ra khi người dùng cuộn nội dung bên trong modal.                              |
| `(outFunctionControl)` | `EventEmitter<IModalFunctionsControl>` | *(Trừ Modal V2)* Cung cấp bộ hàm điều khiển modal từ bên ngoài. Đối với Modal V2, bạn sử dụng `FunctionsControl` nội bộ. |

### Dành riêng cho Modal V2 (Kiến trúc Event-Driven mới)

Modal V2 loại bỏ hoàn toàn sự phụ thuộc vào HTML Template. Bắt buộc khởi tạo động qua \`LibsUiDynamicComponentService\` và giao tiếp qua \`Subject\`:

```typescript
// Định nghĩa Stream Types
export interface IDynamicBodyEventOut { eventName: 'PROCESS_DONE'; data?: { message: string } }
export type TDynamicBodyEventIn = 'PROCESS_DATA';

// 1. Mở Modal V2 
this.activeModalRef = this.dynamicService.resolveComponentFactory(LibsUiComponentsModalV2Component);

// 2. Chế độ thiết lập input (lưu ý bổ sung show/disable)
setInputs(this.activeModalRef, {
  title: 'Modal V2 Standard Architecture',
  mode: 'center',
  buttonsFooter: {
    right: [
      {
        label: 'Thực thi',
        action: async (fc: IModalV2FunctionsControl<TDynamicBodyEventIn, IDynamicBodyEventOut, unknown>) => {
           // Gửi event xuống Component con (Body)
           fc.getEventToComponentStream().next({ groupEvent: 'custom', eventName: 'PROCESS_DATA' });
        }
      }
    ]
  },
  show: true,
  disable: false,
});
this.dynamicService.addToBody(this.activeModalRef);

// 3. Quản lý tương tác 2 chiều và lắng nghe từ Component con
const fc = this.activeModalRef.instance.FunctionsControl;
fc.getEventToModalStream().subscribe((event) => {
   if (event.eventName === 'PROCESS_DONE') {
      fc.hide();
   }
});
```

#### Methods (via Controls)

| Method                   | Parameters | Description                            |
| ------------------------ | ---------- | -------------------------------------- |
| `show()`                 | `-`        | Mở hiển thị modal.                     |
| `hide()`                 | `-`        | Đóng ẩn modal.                         |
| `setStateDisable(state)` | `boolean`  | Cập nhật trạng thái disable của modal. |

## Types & Interfaces

```typescript
export interface IModalHeaderConfig {
  hasBackButton?: boolean;
  removeButtonClose?: boolean;
  hidden?: boolean;
  classTitle?: string;
  // ...
}

export interface IModalBodyConfig {
  lines?: Array<{ text: string; class?: string }>;
  iconType?: 'warning' | 'success' | 'fail' | 'information';
  // ...
}
```

## Công nghệ

| Technology      | Purpose                                       |
| --------------- | --------------------------------------------- |
| Angular 18+     | Framework chính                               |
| Angular Signals | Quản lý state reactive (model, input, signal) |
| RxJS            | Xử lý sự kiện (timer, scroll, keyup)          |
| Standard CSS    | Hệ thống layout và animation                  |

## License

MIT