npm package: @libs-ui/components-buttons-sort
Description: > Version: `0.2.355-14` > > Component nút sort (asc/desc) gọn nhẹ, hỗ trợ disable theo chiều và emit payload `ISort` kèm hàm `reset()`.
Latest version: 0.2.356-23

# Buttons Sort Component

> Version: `0.2.355-14`
>
> Component nút sort (asc/desc) gọn nhẹ, hỗ trợ disable theo chiều và emit payload `ISort` kèm hàm `reset()`.

## Giới thiệu

Package `@libs-ui/components-buttons-sort` cung cấp 2 component:

- `LibsUiComponentsButtonsSortComponent`: 2 nút riêng cho `asc` và `desc`
- `LibsUiComponentsButtonsSortArrowComponent`: 1 nút toggle `asc` ↔ `desc`, có thể bật popover mô tả

## Tính năng

- ✅ Có 2 kiểu UI: **2 nút (Sort)** và **1 nút toggle (Arrow)**
- ✅ Sort 2 chiều: `asc` / `desc`
- ✅ Two-way binding qua `[(mode)]`
- ✅ Emit payload `(outChange)` kiểu `ISort`
- ✅ Hỗ trợ disable toàn bộ hoặc disable từng chiều (`disableAsc`, `disableDesc`)
- ✅ Hỗ trợ `onlyEmit` để luôn emit event theo click
- ✅ Arrow hỗ trợ `defaultMode` và popover content (asc/desc)
- ✅ OnPush Change Detection
- ✅ Angular Signals

## Cài đặt

```bash
npm install @libs-ui/components-buttons-sort
```

## Import

```typescript
import { Component } from '@angular/core';
import { LibsUiComponentsButtonsSortArrowComponent, LibsUiComponentsButtonsSortComponent, ISort, TYPE_SORT_TYPE } from '@libs-ui/components-buttons-sort';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSortArrowComponent, LibsUiComponentsButtonsSortComponent],
  template: '',
})
export class ExampleComponent {}
```

## Cách sử dụng

### 1. Ví dụ inline template

```html
<libs_ui-components-buttons-sort
  [fieldSort]="'name'"
  [(mode)]="mode"
  (outChange)="onChange($event)"
/>
```

```typescript
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSortComponent, ISort, TYPE_SORT_TYPE } from '@libs-ui/components-buttons-sort';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSortComponent],
  template: `
    <libs_ui-components-buttons-sort
      [fieldSort]="'name'"
      [(mode)]="mode()"
      (outChange)="onChange($event)"
    />
  `,
})
export class InlineExampleComponent {
  readonly mode = signal<TYPE_SORT_TYPE>('');

  onChange(sort: ISort): void {
    console.log(sort.mode, sort.fieldSort);
  }
}
```

### 2. Arrow - 1 nút toggle (có thể bật popover)

```html
<libs_ui-components-buttons-sort-arrow
  [fieldSort]="'name'"
  [ignorePopoverContent]="false"
  [popoverContentAsc]="'Sắp xếp tăng dần (A → Z)'"
  [popoverContentDesc]="'Sắp xếp giảm dần (Z → A)'"
  [defaultMode]="'asc'"
  [(mode)]="mode"
  (outChange)="onChange($event)"
/>
```

### 2. Ví dụ với file HTML riêng

`example.component.html`

```html
<libs_ui-components-buttons-sort
  [size]="14"
  [disableAsc]="true"
  [fieldSort]="'createdAt'"
  [(mode)]="mode"
  (outChange)="onChange($event)"
/>
```

`example.component.ts`

```typescript
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSortComponent, ISort, TYPE_SORT_TYPE } from '@libs-ui/components-buttons-sort';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSortComponent],
  templateUrl: './example.component.html',
})
export class HtmlFileExampleComponent {
  readonly mode = signal<TYPE_SORT_TYPE>('');

  onChange(sort: ISort): void {
    // sort.reset() có thể dùng để reset mode về ''
    console.log(sort);
  }
}
```

## Công nghệ

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

## API

### libs_ui-components-buttons-sort

#### Inputs

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `[disable]` | `boolean` | `false` | Disable toàn bộ sort |
| `[disableAsc]` | `boolean` | `false` | Disable chiều asc |
| `[disableDesc]` | `boolean` | `false` | Disable chiều desc |
| `[defaultMode]` | `TYPE_SORT_TYPE` | `''` | Chỉ áp dụng cho Arrow: mode mặc định khi click lần đầu |
| `[fieldSort]` | `string` | `''` | Field đang sort (được trả về trong `ISort`) |
| `[ignorePopoverContent]` | `boolean` | `true` | Chỉ áp dụng cho Arrow: bỏ qua hiển thị popover content |
| `[onlyEmit]` | `boolean` | `false` | Chỉ emit event, không chặn khi mode đang trùng |
| `[popoverContentAsc]` | `string \| undefined` | `undefined` | Chỉ áp dụng cho Arrow: nội dung popover khi asc |
| `[popoverContentDesc]` | `string \| undefined` | `undefined` | Chỉ áp dụng cho Arrow: nội dung popover khi desc |
| `[size]` | `number` | `10` | Kích thước icon sort (px) |
| `[zIndex]` | `number` | `10` | Chỉ áp dụng cho Arrow: zIndex của popover |
| `[(mode)]` | `TYPE_SORT_TYPE` | `''` | Mode sort hiện tại: `asc` / `desc` / `''` |

#### Outputs

| Property | Type | Description |
|----------|------|-------------|
| `(outChange)` | `EventEmitter<ISort>` | Emit khi người dùng click sort, trả về payload `ISort` |

## Types & Interfaces

```typescript
export type TYPE_SORT_TYPE = 'asc' | 'desc' | '';

export interface ISort {
  mode: TYPE_SORT_TYPE;
  modeNumber: 1 | 2; // 1: asc; 2:desc
  fieldSort: string;
  reset: () => void;
}
```

### Mô tả Types

- **TYPE_SORT_TYPE**: Kiểu mode sort: `asc`, `desc`, hoặc rỗng (không sort).
- **ISort**: Payload emit ra khi sort thay đổi, có `reset()` để reset mode.

## Demo

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

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