npm package: @ruc-lib/dual-list
Description: The Dual List Selector is a highly configurable Angular component that allows users to move items between two lists: an "available" list and a "selected" list. It's ideal for scenarios where users need to make multiple selections from a large set of optio
Latest version: 4.0.0

# Dual List Selector

The Dual List Selector is a highly configurable Angular component that allows users to move items between two lists: an "available" list and a "selected" list. It's ideal for scenarios where users need to make multiple selections from a large set of options.

## Features

-   **Two-List Layout**: Clearly separates available and selected items.
-   **Drag and Drop**: Intuitively move items between lists using Angular CDK Drag and Drop.
-   **Button Controls**: Move selected items, or all items, with button clicks.
-   **Search**: Filter items within both lists to quickly find what you're looking for.
-   **Sorting**: Sort items alphabetically in ascending or descending order.
-   **Item Disabling**: Prevent specific items from being moved.
-   **State Persistence**: Optionally persist the selected and available items in `sessionStorage` across page refreshes.
-   **Customizable**: Control dimensions and apply custom themes.



## Dependencies

This library has peer dependencies on `@angular/core`, `@angular/common`, and `@angular/material`.

```bash
npm install @angular/material @angular/cdk

```

## Installation Guide

To use the Dual List Selector component, you can install the entire RUC library or just this specific component.

### Install the Entire Library
```bash
npm install @uxpractice/ruc-lib
```

### Install Individual Component

If you only need the DualList component:

**For Angular 15:**
```bash
npm install @ruc-lib/dual-list@3.2.0 @angular/material@^15.0.0 @angular/cdk@^15.0.0
```

**For Angular 16:**
```bash
npm install @ruc-lib/dual-list@3.2.0 @angular/material@^16.0.0 @angular/cdk@^16.0.0
```

**For Angular 17:**
```bash
npm install @ruc-lib/dual-list@4.0.0 @angular/material@^17.0.0 @angular/cdk@^17.0.0
```

**For Angular 18:**
```bash
npm install @ruc-lib/dual-list@4.0.0 @angular/material@^18.0.0 @angular/cdk@^18.0.0
```

**For Angular 19:**
```bash
npm install @ruc-lib/dual-list@4.0.0 @angular/material@^19.0.0 @angular/cdk@^19.0.0
```

**For Angular 20:**
```bash
npm install @ruc-lib/dual-list@4.0.0
```

> **Note:** When installing in Angular 15-19 apps, you must specify the matching `@angular/material` and `@angular/cdk` versions to avoid peer dependency conflicts. Angular 20 will automatically use the correct versions.


### 📦 Version Compatibility

| Angular Version    | Compatible `@ruc-lib/dual-list` Version     |
|--------------------|------------------------------------------|
| 15.x.x             | `npm install @ruc-lib/dual-list@^3.2.0`     |
| 16.x.x             | `npm install @ruc-lib/dual-list@^3.2.0`     |
| 17.x.x             | `npm install @ruc-lib/dual-list@^4.0.0`     |
| 18.x.x             | `npm install @ruc-lib/dual-list@^4.0.0`     |
| 19.x.x             | `npm install @ruc-lib/dual-list@^4.0.0`     |
| 20.x.x             | `npm install @ruc-lib/dual-list@^4.0.0`     |


## Usage

1. Import the Module In your Angular component file (e.g., `component.ts`), import the `RuclibDualListSelectorModule`:**

    ```typescript
    import { RuclibDualListSelectorModule } from '@ruc-lib/dual-list-selector';
    import { FormsModule } from '@angular/forms';
    import { MatListModule } from '@angular/material/list';
    import { MatChipsModule } from '@angular/material/chips';
    import { DragDropModule } from '@angular/cdk/drag-drop';
    import { MatFormFieldModule } from '@angular/material/form-field';
    import { MatInputModule } from '@angular/material/input';
    import { MatIconModule } from '@angular/material/icon';
    import { MatSortModule } from '@angular/material/sort';
    import { MatTableModule } from '@angular/material/table';

    @NgModule({
      imports: [
        // ... other modules
        RuclibDualListSelectorModule,
        FormsModule,
        MatListModule,
        DragDropModule,
        MatChipsModule,
        MatFormFieldModule,
        MatInputModule,
        MatIconModule,
        MatSortModule,
        MatTableModule
      ]
    })
    export class YourModule { }
    ```

2.  **In your component's template:**

    ```html
    <uxp-ruclib-dual-list-selector
      [dataSource]="items"
      [rucInputData]="config"
      (rucEvent)="onSubmit($event)">
    </uxp-ruclib-dual-list-selector>
    ```

3.  **In your component's TypeScript file:**

    ```typescript
    import { Component } from '@angular/core';

    @Component({
      selector: 'app-your-component',
      templateUrl: './your-component.html',
    })
    export class YourComponent {
      // Configuration for the dual list
      config = {
        height: 450,
        width: 300,
        persistOnRefresh: true,
        enableSearch: true,
        sorting: true,
      };

      // Data for the dual list
      items = [
        { id: 1, name: 'Item 1', disable: true },
        { id: 2, name: 'Item 2', disable: true },
        { id: 3, name: 'Item 3', disable: false }, // This item cannot be moved
        { id: 4, name: 'Item 4', disable: true },
      ];

      onSubmit(selectedItems: any[]) {
        console.log('Submitted Items:', selectedItems);
        // Handle the submitted data
      }
    }
    ```

## API Reference

### Component Selector

`<uxp-ruclib-dual-list-selector>`

### Inputs

| Input          | Type             | Default | Description                                                                              |
| :------------- | :--------------- | :------ | :--------------------------------------------------------------------------------------- |
| `dataSource`   | `Item[]`         | `[]`    | An array of items to populate the lists. Each item should follow the `Item` interface.   |
| `rucInputData` | `DualListConfig` | `{}`    | A configuration object for the component's features. See `DualListConfig` interface below. |
| `customTheme`  | `string`         | `''`    | A custom CSS class name to be applied to the root element for theming purposes.          |

### Outputs

| Output     | Type                  | Description                                                                        |
| :--------- | :-------------------- | :--------------------------------------------------------------------------------- |
| `rucEvent` | `EventEmitter<Item[]>` | Emits an array of the currently selected items when the "Submit" button is clicked. |

### Interfaces

#### `DualListConfig`

```typescript
interface DualListConfig {
  height?: number;
  width?: number;
  persistOnRefresh?: boolean;
  enableSearch?: boolean;
  sorting?: boolean;
}
```

#### `Item`

```typescript
interface Item {
  id: number | string;
  name: string;
  disable: boolean;
}
```

> ⚠️ **IMPORTANT: Custom Theme Usage in Angular Material**

When implementing **custom themes**, such as:

```scss
.custom-theme-1 {
  @include angular-material-theme($custom-theme);
}

// You must also include the typography mixin to ensure text styles are applied correctly as shown below:
.custom-theme-1 {
  @include angular-material-theme($custom-theme);
  @include mat.typography-level($theme-custom-typography-name, body-1);
}
```


## Contribution

Contributions are welcome! Feel free to open issues or pull requests for any enhancements or fixes.

## Acknowledgements

Thank you for choosing the Dual List Selector component. If you have any feedback or suggestions, please let us know!