import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/en/functional/Classes/ListDataRef - Data List Management'/>

# ListDataRef Class

A reactive class for managing data lists of any complexity. It supports filtering, selection, focus, and nested structures (groups and menus). The class transforms input data into a standardized format and provides an extensive set of methods for navigation, search, and element state management.

## Key Features

- **Reactivity** — automatic update of computed properties when source data (Vue ref) or control parameters change.
- **Standardization** — converts any input format (array of strings, objects) to a unified `ListDataItem` interface.
- **Deep Nesting** — supports tree-like structures with automatic sub-list management via `getSubList`.
- **Smart Navigation** — built-in methods for list movement, considering filtering and element types.
- **Lite Mode** — optimizes rendering for large lists using `liteData`.
- **Selection Management** — controls the number of selected items (min/max) and their states.

## Initialization

Creates a new `ListDataRef` instance for managing list data. The class provides input data standardization, focus management, selection, and search. It supports reactive updates when the source list or control parameters change.

**Parameters:**

- `list: RefOrNormal<ListListInput | undefined>` — reactive or regular data list.
- `focus?: RefType<ListSelectedItem | undefined>` — focused item identifier (Vue ref).
- `highlight?: RefType<string | undefined>` — search text for highlighting (Vue ref).
- `highlightLengthStart?: RefType<number | undefined>` — minimum characters to start searching (Vue ref).
- `filterMode?: RefType<boolean | undefined>` — filter mode (Vue ref).
- `selected?: RefType<ListSelectedList | undefined>` — list of selected identifiers (Vue ref).
- `keyValue?: RefType<string | undefined>` — field name for the value (defaults to `'value'`).
- `keyLabel?: RefType<string | undefined>` — field name for the label (defaults to `'label'`).
- `lite?: RefType<number | undefined>` — number of elements threshold for enabling Lite mode (Vue ref).
- `min: RefOrNormal<number | string | undefined> = 0` — minimum allowed number of selections.
- `max: RefOrNormal<number | string | undefined> = 9_999_999` — maximum allowed number of selections.
- `parent?: string` — parent identifier (used for sub-lists).

```typescript
import { ListDataRef } from '@dxtmisha/functional'
import { ref } from 'vue'

const list = ref([
  { label: 'Item 1', value: 'item-1' },
  { label: 'Group 1', type: 'group', value: [
    { label: 'Sub-item 1.1', value: 'sub-1.1' }
  ]}
])

const focus = ref(undefined)
const selected = ref(['item-1'])

const listData = new ListDataRef(
  list, 
  focus, 
  undefined, // highlight
  undefined, // highlightLengthStart
  undefined, // filterMode
  selected
)
```

## Properties

### Data

- `data: Computed<ListList>` — core standardized data list for the current level.
- `liteData: Computed<ListList>` — simplified list version for fast rendering (Lite mode).
- `fullData: Computed<ListDataFull>` — extended data list with `focus`, `selected`, `disabled`, and `highlight` flags.
- `map: Computed<ListList>` — flat list of all elements in the tree (including containers).
- `mapItems: Computed<ListList>` — flat list of terminal selectable items (`item`).
- `items: Computed<ListList>` — flat list of interactive elements (`item`, `group`, `menu`).

### Selection and State

- `isSelected: Computed<boolean>` — returns `true` if at least one item is selected in the entire tree.
- `isSelectedMin: Computed<boolean>` — `true` if the number of selected items in the group reached `min`.
- `isSelectedMax: Computed<boolean>` — `true` if the number of selected items in the group reached `max`.
- `selectedList: Computed<ListList>` — list of all selected objects across the entire tree.
- `selectedListInGroup: Computed<ListList>` — list of objects selected at the current level.
- `selectedNames: Computed<ListNames>` — array of labels (`label`) for all selected items.
- `selectedValues: Computed<any[]>` — array of values (`value`) for all selected items.

### Search

- `highlightFirstItem: Computed<number>` — index of the first matched element in `map`.

## Methods

### Status and Checks

- `isLite(): boolean` — returns `true` if optimization mode is active.
- `isFocus(): boolean` — checks if focus exists in the current `map`.
- `isHighlight(): boolean` — returns `true` if search found matches.
- `isHighlightActive(): boolean` — checks if search process is active.
- `getLength(): number` — number of elements at the current level.
- `getLengthByMap(): number` — total count of elements in the tree.
- `getLengthByItems(): number` — number of terminal elements in the tree.

### Retrieving Values

- `getFocus(): ListSelectedItem | undefined` — current focused identifier.
- `getHighlight(): string | undefined` — current search string.
- `getHighlightLengthStart(): number` — minimum length for search (defaults to `2`).
- `getSelected(): ListSelectedList | undefined` — list of selected identifiers.

### Navigation and Search

- `getSelectedByStep(step): ListSelectedItem | undefined` — finds neighbor relative to selection.
- `getSelectedNext(): ListSelectedItem | undefined` — next element from selection.
- `getSelectedPrev(): ListSelectedItem | undefined` — previous element from selection.
- `getItemByStep(item, step): ListDataItem | undefined` — finds neighbor relative to item.
- `getItemNext(item): ListDataItem | undefined` — next from item.
- `getItemPrev(item): ListDataItem | undefined` — previous from item.
- `getIndexByStep(index, step): ListDataItem | undefined` — finds neighbor relative to index.
- `getIndexNext(index): ListDataItem | undefined` — next from index.
- `getIndexPrev(index): ListDataItem | undefined` — previous from index.
- `getItemByIndex(index): { key, item } | undefined` — finds item by index.
- `getItemByKey(key): ListDataItem | undefined` — returns item by map key.
- `getFirstItemByParent(parent): ListDataItem | undefined` — first interactive element of parent.
- `getLastItemByParent(parent): ListDataItem | undefined` — last interactive element of parent.
- `getSubList(item): ListDataRef` — creates/returns sub-list instance.

## Data Types

The class uses standardized structures to ensure predictable behavior with any input data format.

### `ListType`

Defines the functional role of an item in the list:
- `item` — the primary interactive element available for selection and focus.
- `group` / `menu` — containers holding nested lists (`value`).
- `subtitle` — a text header within the list.
- `html` — an element for inserting arbitrary HTML code.
- `line` / `space` — visual dividers and spacers.

### `ListDataItem`

The object that all input data is converted to after standardization:
- `index: string` — a unique identifier (automatically generated if not provided).
- `type: ListType` — the item type (defaults to `item`).
- `label?: string | number` — the text displayed in the interface.
- `value?: any` — an arbitrary value associated with the item.
- `parent?: string` — the identifier of the parent item (for nested structures).

### `ListDataFullItem`

An extended version of `ListDataItem` used in the `fullData` property. Includes calculated state flags:
- `focus: boolean` — `true` if the item is currently focused.
- `selected: boolean` — `true` if the item is selected.
- `disabled: boolean` — `true` if the item is disabled (e.g., when the `max` selection limit is reached).
- `highlight?: string` — the current search string if it matches the item's text.

### `ListListInput`

Supported data formats for the constructor and nested groups:
- `string[]` — a simple array of strings (used as labels).
- `Record<string, string>` — an object where the key is the technical value and the property is the text label.
- `ListDataBasic[]` — an array of objects with fields like `label`, `value`, `type`, etc.

## Selection Management

The class provides powerful tools for controlling the selection state in the list, supporting single and multiple selections with constraints.

### Core Selection Parameters

- `selected` — a reactive variable (Vue `ref`) storing an array of identifiers for the selected items.
- `min` / `max` — constraints on the number of selected items **at the current nesting level** (within a group).

### Global vs Group-Level Selection

- **selectedList** (Global) — returns all selected items of type `item` from the entire data tree.
- **selectedListInGroup** (Group-level) — returns selected items only from the current level (`data`). The `min` and `max` constraints are calculated based on this list.

### Automatic disabled state

When the `max` limit is reached (the `isSelectedMax` property becomes `true`), the class automatically marks the remaining unselected items in `fullData` as `disabled: true`. This allows UI components to visually block further selections.

### Retrieving Data

For convenience, the properties `selectedNames` (array of `label` strings) and `selectedValues` (array of `value` values) aggregate data across all selected items in the tree.

## Focus Management

Focus state in `ListDataRef` is implemented via an external reactive variable (typically a Vue `ref`) passed to the constructor.

### Key Focus Features

- **Shared Global State** — when sub-lists are created via `getSubList`, the same focus `ref` is passed to all child instances. This ensures that in a complex data tree, only one element can be focused at any given time.
- **Reactivity via fullData** — the `fullData` property automatically recalculates the `focus: true` flag for the specific item whose `index` matches the current focus value.
- **Manual Control** — the `ListDataRef` class **does not modify** the focus state itself. Navigation methods (like `getItemNext`) only return the target object. The developer must manually assign the new index to the focus ref.

```javascript
// Example: setting focus to the next item
const next = listData.getItemNext(currentItem)
if (next) {
    focus.value = next.index // Reactive focus update
}
```

### Checking Focus Presence

The `isFocus()` method allows you to quickly determine if any element within the current instance (including all nested levels in `map`) is focused. This is useful for visual indicators of list activity (e.g., adding a border or shadow to the entire component).

## Search and Highlighting

The search mechanism allows for filtering or visually highlighting items based on text input.

### Core Search Parameters

- `highlight` — a reactive string containing the search query.
- `highlightLengthStart` — activation threshold (defaults to `2`). Searching does not begin until the string length reaches this value.

### How Search Works

1. **Regex Generation** — when the search string changes, the class automatically generates a case-insensitive regular expression.
2. **Search Fields** — the search is performed across three item fields: `label`, `index`, and the special `search` field (if defined in the source data).
3. **Integration in fullData** — during an active search, every item in the `fullData` property receives the current `highlight` value. This allows UI components to highlight matched substrings.
4. **First Match** — the `highlightFirstItem` property always returns the sequence index of the first found item in the `map` array. This is useful for auto-scrolling to the first result.

### Status Checks

- `isHighlight()` — returns `true` if at least one item matches the query.
- `isHighlightActive()` — returns `true` if the search string has reached the required length, **regardless** of whether results were found. This helps distinguish between "no input" and "no results found" states.

### Filtering Mode (filterMode)

The `filterMode` parameter is a state flag that instructs UI components whether to physically hide items that do not match the search query.

- **Propagation** — the `filterMode` value is automatically injected into every `ListDataItem` object within `fullData`.
- **Inheritance** — when sub-lists are created via `getSubList`, the filtering flag is inherited by child instances.
- **Logical Impact** — the `ListDataRef` class itself does not remove items from the `data` or `map` arrays when `filterMode` is active. This allows the UI layer to decide exactly how to animate or hide the filtered rows.

## Lite Mode

Lite Mode is designed to optimize performance when working with very large data lists. It avoids deep calculation of all properties for every item when it's not required for initial rendering.

### How It Works

1. **Activation Threshold** — the `lite` parameter in the constructor defines the maximum number of elements for normal mode. If the element count in `data` exceeds this threshold, Lite Mode is automatically activated.
2. **liteData Property** — in this mode, the `liteData` property contains a simplified structure of elements, minimizing memory and CPU load during rendering.
3. **isLite() Method** — allows you to programmatically check if the optimization mode is currently active.

This is extremely useful for dropdowns or tables with thousands of rows, where full reactivity for every off-screen item could slow down the interface.

## Working with Navigation

Navigation in `ListDataRef` is built on a deep understanding of the data structure. The class distinguishes between containers (`group`, `menu`) and terminal selection elements (`item`).

### Flat Cyclic Navigation

The `getItemNext`, `getItemPrev`, `getIndexNext`, and `getIndexPrev` methods operate via the `mapItems` property. This means:
1. **Structure Agnostic**: Movement occurs only through elements of type `item`, skipping group headers and menus.
2. **Global Search**: Navigation traverses the entire data tree (Flat Map), even if items are located in different groups.
3. **Cyclic Behavior**: If you are on the last item and call `Next`, the method will return the **first** item in the list. Similarly, `Prev` from the first item will return the **last** one.

### Selection-Based Navigation

The `getSelectedNext` and `getSelectedPrev` methods automatically find the first selected item in the list and return its neighbor. If nothing is selected, navigation starts from the first item in the list.

### Contextual Navigation (Parent)

To restrict movement within a single group, use the `getFirstItemByParent` and `getLastItemByParent` methods. These allow you to quickly find the boundaries of the current nesting level using the parent identifier.

### Example: Implementing Focus Movement

```javascript
import { ListDataRef } from '@dxtmisha/functional'
import { ref } from 'vue'

const list = ref([
    { label: 'Group 1', type: 'group', value: [ { label: 'Item 1.1' } ] },
    { label: 'Item 2' }
])
const focus = ref(undefined)
const listData = new ListDataRef(list, focus)

/**
 * Method to handle ArrowDown key press
 */
const onArrowDown = () => {
    // Get the current item from focus
    const current = listData.getItemByIndex(focus.value)?.item
    
    // Get the next terminal item across the entire map (mapItems)
    // If focus is empty or the item is the last one — it returns the first item (cyclic)
    const next = current ? listData.getItemNext(current) : listData.mapItems.value[0]
    
    if (next) {
        focus.value = next.index
    }
}
```

## Usage Examples

### Rendering a Group Tree

```vue
<template>
  <ul>
    <li v-for="item in listData.data.value" :key="item.index">
      {{ item.label }}
      
      <!-- If it's a group, recursively render the sub-list -->
      <ul v-if="item.type === 'group'">
        <li v-for="sub in listData.getSubList(item).data.value" :key="sub.index">
           {{ sub.label }}
        </li>
      </ul>
    </li>
  </ul>
</template>

<script setup>
const listData = new ListDataRef(props.list)
</script>
```
