# List

Die List bildet einen strukturierten Rahmen für mehrere ListItems und bietet Funktionen wie Sortierung, Filter und Suche.

## Develop

Die List Component erlaubt das Rendern und Verwalten von Daten in einer
strukturierten Liste. Daten können entweder **statisch** oder **asynchron**, z.
B. über eine API, geladen werden.

# Möglichkeiten zum Laden von Daten

## 1. Statische Daten

Für die Anzeige statischer Daten kann die Component `<StaticData />` verwendet
werden:

```tsx
<List.StaticData data={dataArray} />
```

- `dataArray`: Ein Array mit den Daten, die direkt in der List gerendert werden.
- Diese Variante ist einfach und benötigt keine zusätzliche Logik für das
  Nachladen oder Filtern.

## 2. Dynamische Daten (Asynchrones Laden)

Mit `<LoaderAsync>` können Daten dynamisch aus einer API oder anderen
asynchronen Quellen nachgeladen werden:

```tsx
<List.LoaderAsync>
  {async (options) => {
    const response = await fetchDataFromAPI(options);
    return {
      data: response.items,
      itemTotalCount: response.totalCount,
    };
  }}
</List.LoaderAsync>
```

## 3. Laden über Hooks (z.B. TanStack Query oder SWR)

Mit `<LoaderHooks>` können Daten dynamisch über React Hooks nachgeladen werden.
Der Einsatz von Suspense ist hierbei erforderlich.

```tsx
import { useSuspenseQuery } from "@tanstack/react-query";

<List.LoaderHooks>
  {async (options) => {
    const response = useSuspenseQuery({
      queryKey: ["api", options],
      queryFn: () => fetchDataFromAPI(options),
    });
    return {
      data: response.items,
      itemTotalCount: response.totalCount,
    };
  }}
</List.LoaderHooks>;
```

### Verhalten & Features

- **Ladeanimation:** Während die Daten geladen werden, wird eine Ladeanimation
  angezeigt.
- **Server-seitige Funktionen:**
  - **Pagination** (`manualPagination`): Aktiviert das serverseitige Paging.
  - **Sortierung** (`manualSorting`): Die Sortierung erfolgt auf dem Server.
  - **Filterung** (`manualFiltering`): Filter werden nicht client-seitig
    angewendet, sondern an den Server weitergeleitet.
  - **Suche:** Kann ebenfalls serverseitig erfolgen.

## Optionen für die Async Loader Function

Die `<LoaderAsync>`-Component benötigt eine **Async Loader Function**, die die
Daten anhand von Steuerungsoptionen lädt. Diese Funktion erhält ein
`options`-Objekt mit den folgenden Parametern:

### Struktur des `options`-Objekts

| Property       | Typ                                                                    | Beschreibung                                                                                             |
| -------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `filtering`    | `{ [key: string]: { mode: "all" \| "some" \| "one"; values: any[] } }` | Enthält Filter für die Daten. Jedes Key-Value-Paar repräsentiert eine Filterbedingung für ein Datenfeld. |
| `searchString` | `string`                                                               | Der eingegebene Suchbegriff.                                                                             |
| `pagination`   | `{ offset: number; limit: number }`                                    | Enthält Offset (Startpunkt) und Limit (maximale Anzahl an Datensätzen).                                  |
| `sorting`      | `{ [key: string]: "asc" \| "desc" }`                                   | Gibt an, nach welchen Datenfeldern sortiert werden soll.                                                 |

### Rückgabewert der Async Loader Function

Die Funktion muss ein **Object** mit folgender Struktur zurückgeben:

```tsx
return {
  data: [
    /* Array mit den Datensätzen */
  ],
  itemTotalCount: 100, // Gesamtanzahl der Datensätze (für Pagination)
};
```

| Property         | Typ      | Beschreibung                                                   |
| ---------------- | -------- | -------------------------------------------------------------- |
| `data`           | `any[]`  | Array der geladenen Daten.                                     |
| `itemTotalCount` | `number` | Gesamtanzahl der Datensätze (nur bei Pagination erforderlich). |

---

# Filter

In der Regel werden Filter für ein Property der List gesetzt:

```tsx
<List.Filter mode="some" name="Status" property="status" />
```

Die Anzeige des Filter-Values kann angepasst werden, um z. B. Übersetzungen zu
ermöglichen:

```tsx
<List.Filter mode="some" name="Status" property="status">
  {(value) => translate(value)}
</List.Filter>
```

Es gibt die Möglichkeit, eigene Properties zu verwenden, die nicht in der List
vorkommen . Hierfür muss dem `property` ein "$" vorangestellt werden:

```tsx
<List.Filter
  matcher={(filterValue, item) => filterValue === "disabled" ? !!item.disabled : item.status === filterValue}
  mode="some"
  name="Filter"
  property="$filter"
  values={["active", "inactive", "disabled"]}
>
```

## Filter Properties

| Property          | Typ                               | Beschreibung                                                                |
| ----------------- | --------------------------------- | --------------------------------------------------------------------------- |
| `defaultSelected` | `string[]`                        | Array der als default gesetzten Filter                                      |
| `matcher`         | `FilterMatcher<T, TProp, string>` | Definiert eine eigene Filterlogik für die Listenelemente                    |
| `mode`            | `"all" \| "some" \| "one"`        | Bestimmt, wie mehrere ausgewählte Filterwerte miteinander kombiniert werden |
| `name`            | `string`                          | Der Anzeigename des Filters                                                 |
| `property`        | `string`                          | Das für die Filterung verwendete Property                                   |
| `values`          | `string[]`                        | Die Optionen für den Filter                                                 |

---

# Sorting

Die List unterstützt eine Sortierung nach Properties:

```tsx
<List.Sorting defaultEnabled direction="asc" name="Name" property="name" />
```

Es gibt außerdem die Möglichkeit, eine eigene Sortierung zu benutzen:

```tsx
<List.Sorting
  customSortingFn={(a, b) => sortHostnames(a.hostname, b.hostname)}
  direction="asc"
  name="Domain"
  property="$domain"
  directionName="aufsteigend"
/>
```

## Sorting Properties

| Property          | Typ                   | Beschreibung                                                                                                                                  |
| ----------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `customSortingFn` | `SortingFn<T>`        | Möglichkeit eine eigene Sortierfunktion zu definieren                                                                                         |
| `defaultEnabled`  | `boolean \| "hidden"` | Bestimmt, ob die Sortierung als default gesetzt wird, bei "hidden" ist die Sortier-Option nicht sichtbar, wird aber im Hintergrund angewendet |
| `direction`       | `"asc" \| "desc"`     | Auf- oder absteigende Sortierung                                                                                                              |
| `name`            | `string`              | Der Anzeigename der Sortier-Option                                                                                                            |
| `directionName`   | `string`              | Der Anzeigename der Sortierrichtung                                                                                                           |
| `property`        | `string`              | Das für die Sortierung verwendete Property                                                                                                    |

---

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `batchSize` | `number` | - | The number of items to be displayed on one page. |
| `hidePagination` | `boolean` | - | - |
| `emptySearchResultView` | `ReactNode` | - | - |
| `emptyView` | `ReactNode` | - | - |
| `children` | `ReactNode` | - | - |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |
| `disallowEmptySelection` | `boolean` | - | Whether the collection allows empty selection. |
| `disabledKeys` | `Iterable<Key>` | - | The currently disabled keys in the collection (controlled). |
| `selectionMode` | `SelectionMode` | - | The type of selection that is allowed in the collection. |
| `selectedKeys` | `"all" \| Iterable<Key>` | - | The currently selected keys in the collection (controlled). |
| `defaultSelectedKeys` | `"all" \| Iterable<Key>` | - | The initial selected keys in the collection (uncontrolled). |
| `selectionBehavior` | `SelectionBehavior` | - | - |
| `accordion` | `boolean` | - | - |
| `settingStorageKey` | `string` | - | - |
| `loadingItemsCount` | `number` | - | - |
| `getItemId` | `GetItemId<never>` | - | - |
| `defaultViewMode` | `ListViewMode` | - | - |
| `settingsStorageDefaults` | `ListSettingsStorageDefaults` | - | - |

### Events

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `onChange` | `OnListChanged<never, unknown>` | - | - |
| `onSelectionChange` | `((keys: Selection) => void)` | - | Handler that is called when the selection changes. |
| `onAction` | `ItemActionFn<never>` | - | - |

### Accessibility

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `aria-label` | `string` | - | - |
| `aria-labelledby` | `string` | - | - |

