npm package: @relabs_test/relabs-test-uikit-radix
Description: ```tsx import React from 'react';
Latest version: 0.0.4

# ReLabs React UI KIT (test)

### Ui Kit построен на базе [Ant Design](https://ant.design)

### 🙌 Как использовать

#### Изначально есть компонент ` <Provider />` Он оборачивает все остальные компоненты и нужен для смены темы

```tsx
import React from 'react';

import ReactDOM from 'react-dom/client';

import App from './App.tsx';

import { Provider } from '@relabs_test/relabs-test-uikit-radix';

import './index.css';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>,
);
```

#### Для смены темы используется хук `useToggleTheme()` для смены темы

```tsx
import { useToggleTheme } from 'src/lib/theme/utils/ThemeContext';

const App = () => {
  const toggleTheme = useToggleTheme();

  return (
    <>
      <button onClick={toggleTheme}> Change Theme</button>

      {/* остальной код */}
    </>
  );
};

// и все остальные компоненты
```

## 🔨 Разработка

1. Клонируете репозиторий

2. Устанавливаете зависимости

3. Разрабатываете 😁

4. Есть Storybook

## ⚙️ Как собирать

Основная точка входа для пакета - `src/components/index.ts`.

Из этого файла импортируется то, что будет в итоговом npm пакете, точнее что можно будет
использовать.

Если вы написали компонент и не экспортировали его, он будет `недоступен`. Тоже самое
касается хуков и функций.

```tsx
// `src/components/index.ts`

export * from './provider/Provider';

export * from './slider/Slider';

export * from './table/table';

// и все остальные компоненты
```

### Порядок действий для публикации npm-package

1. Обновите версию в package.json (можно увеличить последнюю цифру: было 0.0.1, стало
   0.0.2)

```json
{
  "name": "@relabs_test/test-ui-kit",
  "version": "0.0.1",
  "type": "module",
  "license": "MIT",
  "publishConfig": {
    "access": "public"
  }
}
```

1. Вызовите команду `yarn build` или `npm run build`

2. Вызовите команту `npm login`

3. В терминале в ide будет предложено ввести Username, Password и Email

`терминал`

![терминал](./src/assets/readme/npm_login.png)

Username: `relabs_test`

Password: `relabs123456789`

Email: `test.relabs.library@gmail.com`

1. На указанную почту придет одноразовый пароль, который вас попросят ввести в терминал

2. Заходим на почту test.relabs.library@gmail.com (password: relabs123456789)

3. Вводим одноразовый пароль

4. Запускаем команду npm publish

5. Хваставемся друзьям! 😁

### TypeScript

`ReLabs React UI KIT` написан на typescript и расширяет стандартные типы
компонентов [antd](https://ant.design/docs/react/use-in-typescript).

## Components

### Checkbox

#### Основные пропсы:

- **checked (boolean | indeterminate)** - контролируемое проверенное состояние. Необходимо
  использовать вместе с onCheckedChange

- **onCheckedChange ((checked: CheckedState): void)** - обработчик событий, вызываемый при
  изменении состояния

- **defaultChecked (boolean | indeterminate)** - состояние при первоначальном отображении.
  Используйте, когда вам не нужно контролировать состояние

#### Uncontrolled

```tsx
const App = () => {
  const toggleTheme = useToggleTheme();

  return (
    <>
      <Checkbox defaultChecked={theme === 'dark'} />
    </>
  );
};
```

#### Controlled

```tsx
const App = () => {
  const [checked, setChecked] = useState(false);

  return (
    <>
      <Checkbox
        value='react'
        label='react'
        checked={checked}
        onCheckedChange={() => setChecked((prevState) => !prevState)}
      />
    </>
  );
};
```

#### Group

```tsx
export const GroupOfCheckbox = () => {
  const [value, setValue] = useState<string[]>([]);

  return (
    <>
      {/* Checkbox Group Uncontrolled */}

      <Checkbox.Group defaultValue={['react', 'vue']} gap='lg'>
        <Checkbox value='react' label='react' />

        <Checkbox value='svelte' label='svelte' />

        <Checkbox value='vue' label='vue' />
      </Checkbox.Group>

      {/* Checkbox Group Controlled */}

      <Checkbox.Group value={value} onCheckedChange={setValue} vertical gap='md'>
        <Checkbox value='react' label='react' />

        <Checkbox value='svelte' label='svelte' />

        <Checkbox value='vue' label='vue' />
      </Checkbox.Group>
    </>
  );
};
```

#### Indeterminate

```tsx
export const IndeterminateCheckbox = () => {
  const [values, handlers] = useListState(initialValues);

  const allChecked = values.every((value) => value.checked);

  const indeterminate = values.some((value) => value.checked) && !allChecked && 'indeterminate';

  const handleToggleCheckbox = (index: number) => {
    handlers.setItemProp(index, 'checked', !values[index].checked);
  };

  const items = values.map((value, index) => (
    <Checkbox
      key={value.id}
      label={value.label}
      checked={value.checked}
      defaultChecked={value.checked}
      onCheckedChange={() => handleToggleCheckbox(index)}
      classNameRoot={cls.root}
      classNameIcon={cls.icon}
    />
  ));

  return (
    <div className={cls.container}>
      <Checkbox
        checked={indeterminate || allChecked}
        label='Receive all notifications'
        defaultChecked={false}
        onCheckedChange={() =>
          handlers.setState((current) =>
            current.map((value) => ({ ...value, checked: !allChecked })),
          )
        }
      />

      <div className={cls.container_inner}>{items}</div>
    </div>
  );
};
```

### Input

#### Основные пропсы:

- **value (string)** - входное значение инпута .
- **onChange((event: React.ChangeEvent\<HTMLInputElement\>) => void)** - колбэк функция
  при вводе данных пользователем.

#### Uncontrolled

_Неуправляемые компоненты_ похожи на обычные HTML-формы.
Они запоминают всё, что вы печатали. Затем вы можете получить их значение, используя ref.
Например, в обработчик _onChange_:

```tsx
import React from 'react';

const App = () => {
  const myRef = React.useRef<HTMLInputElement>(null);
  return (
    <Input
      placeholder='uncontrolled input'
      ref={myRef}
      onChange={() => console.log(ref.current.value)}
    />
  );
};
```

#### Controlled

_Управляемый компонент_ принимает свое текущее значение в качестве пропсов, а также
коллбэк для изменения этого значения. Вы можете сказать, что это более “реактивный” способ
управления компонентом, однако это не означает, что вы всегда должны использовать этот
метод. Значение формы ввода должно существовать в неком state. Как правило, компонент,
который рэндерит форму ввода (т.е. форма), сохраняет их в своем state:

```tsx
import React from 'react';

const App = () => {
  const [inputValue, setInputValue] = React.useState('');
  console.log(inputValue);
  return <Input value={inputValue} onChange={(e) => setInputValue(e.curentTarget.value)} />;
};
```

- **mask (string)** - Маска ввода, replacement используется для замены символов.
- **replacement (string | Replacement)** - Устанавливает заменяемые символы в маске, где
  «ключ» — заменяемый символ, «значение» — регулярное выражение, которому должен
  соответствовать входной символ. Символ замены можно передать в виде строки, тогда
  replacement="_" по умолчанию будет использоваться значение replacement={ _: /./ }.
  Клавиши игнорируются при вводе. См. примеры в InputMasked

- **showMask (boolean)** - Управляет отображением маски, например, +0 ( 123) \_\_\_-\_\_-\_-\_\_ вместо +0 (123)

```tsx
const App = () => {
  return (
    <Input
      showMask
      mask='+375 (__) ___-__-__'
      replacement={{ _: /\d/ }}
      label='mask:+375 (__) ___-__-__, replacement: {{ _: /\d/ }} '
    />
  );
};
```

**_Customization_**
Input элемент представляет собой конструкцию блоков с вложенностью, и предоставляет
возможность кастомизаци каждого элемета путем добавления классов стилизации для
предназначенного пропса:
classNameInput
classNameContainer
classNameLabel
classNameField
classNameBeforeIcon
classNameIcon
classNameMessage
classNameMessageError
classNameMessageSuccess

**_Icons_**

- **icon (JSX.Element)** - изображение в конце инпута.
- **beforeIcon (JSX.Element)** - изображение в начале инпута.
- **onClickBeforeIcon (() => void)** - коллбэк функция обработки клика по _beforeIcon_ .
- **onClickIcon (() => void)** - коллбэк функция обработки клика по _icon_ .

### InputNumber

#### Основные пропсы:

- **value (string)** - входное значение инпута .

- **onChange((event: React.ChangeEvent\<HTMLInputElement\>) => void)** - колбэк функция при вводе данных пользователем.

**_Customization_**

- **arrowColor(string)** - цвет стрелок изменеия значения инпута .

Input элемент представляет собой конструкцию блоков с вложенностью, и предоставляет
возможность кастомизаци каждого элемета путем добавления классов стилизации для предназначенного пропса:

classNameInput

classNameContainer

classNameLabel

classNameField

classNameMessage

classNameMessageError

classNameMessageSuccess

### Text Area

#### Основные пропсы:

- **value (string)** - входное значение поля .

- **onChange((event: React.ChangeEvent\<HTMLTexyAreaElement\>) => void)** - колбэк функция при вводе данных пользователем.

#### Uncontrolled

_Неуправляемые компоненты_ похожи на обычные HTML-формы.

Они запоминают всё, что вы печатали. Затем вы можете получить их значение, используя ref.

Например, в обработчик _onChange_:

```tsx
import React from 'react';

const App = () => {
  const myRef = React.useRef<HTMLTextAreaElement>(null);

  return (
    <TextArea
      placeholder='uncontrolled TextArea'
      ref={myRef}
      onChange={() => console.log(ref.current.value)}
    />
  );
};
```

#### Controlled

_Управляемый компонент_ принимает свое текущее значение в качестве пропсов, а также коллбэк для изменения этого значения. Вы можете сказать, что это более “реактивный” способ управления компонентом, однако это не означает, что вы всегда должны использовать этот метод. Значение формы ввода должно существовать в неком state. Как правило, компонент, который рэндерит форму ввода (т.е. форма), сохраняет их в своем state:

```tsx
import React from 'react';

const App = () => {
  const [TextAreaValue, setTextAreaValue] = React.useState('');

  console.log(TextAreaValue);

  return <TextArea value={inputValue} onChange={(e) => setTextAreaValue(e.curentTarget.value)} />;
};
```

**_Customization_**

Input элемент представляет собой конструкцию блоков с вложенностью, и предоставляет

возможность кастомизаци поля предоставлена возможностью передачи класса:

className

### Datepicker

#### Основные пропсы:

- **value (Date)** - входное значение инпута .

- **onChange((newValue: Date) => void)** - колбэк функция при изменении даты пользователем.

- **showCalendar(boolean),** - указатель отображения календаря _(default : true)_.

- **leftArrowIcon / rightArrowIcon(JSX.Element)** -изображения левой и правой стрелки календаря соответственно.
- **calendarIcon(JSX.Element)** - изображение кнопки отображения календаря.
- **classNameArrowBtn(string)** - класс стрелок календаря.
- **classNameHeaderDatepicker** - класс шапки календаря.
- **classNameDaysOfWeek** - класс дней недели календаря.
- **classNameCell** - класс ячейки календаря.
  _Все пропсы Input также поддерживаютя. Смотрите **Input**_

### Table

#### Основные пропсы:

- **data (TableData)** - используется для автоматической генерации таблицы
- **size (TableSize => sm / md)** - размер ячеек
- **striped (Striped => boolean | 'odd' | 'even')** - выделение четных/нечетных строк
- **withTableBorder (boolean)** - border вокруг таблицы
- **withRowBorders (boolean)** - border у строк
- **withColumnBorders (boolean)** - border у столбцов
- **stickyHeader (boolean)** - прилипание хэдера таблицы к верху страницы при прокрутке
- **stickyHeaderOffset (number)** - значение top для position:sticky. По умолчанию 0
- **onRowClick ((row: unknown) => void;)** - обработчик клика на строку

**Для удобства создадим моковые данные. Они будут использоваться во всех примерах**

```tsx
type Student = {
  Application_No: number;
  Name: string;
  Father_Name: string;
  DOB: string;
};

const data: Student[] = [
  {
    Application_No: 1036,
    Name: 'NABILA TOHEED',
    Father_Name: 'TOHEED AHMED',
    DOB: '15-Dec-1998',
  },
  {
    Application_No: 1072,
    Name: 'PIRHA MASOOD',
    Father_Name: 'MASOOD AHMED SHAIKH',
    DOB: '17-Jan-1997',
  },
  {
    Application_No: 1294,
    Name: 'MUHAMMAD ASHAR NAEEM',
    Father_Name: 'MUHAMMAD NAEEM ANWAR LATE',
    DOB: '20-Feb-1998',
  },
];

const tableData: TableData = {
  head: ['Application_No', 'Name', 'Father Name', 'DOB'],
  body: data.map((item) => Object.values(item)),
};
```

### Есть два способа создания таблицы:

#### Автогенерация таблицы

Для автогенерации таблицы нужно прокинуть в нее объект **data (data: TableData)**:

```tsx
const App = () => {
  return <Table striped='odd' data={tableData} onRowClick={(row) => console.log(row)} />;
};
```

```tsx
export interface TableData {
  head?: ReactNode[];
  body?: ReactNode[][];
  foot?: ReactNode[];
}
```

То есть

```tsx
const tableData: TableData = {
  head: ['Application_No', 'Name', 'Father Name', 'DOB'],
  body: [
    [1036, 'NABILA TOHEED', 'TOHEED AHMED', '15-Dec-1998'],
    [1072, 'PIRHA MASOOD', 'MASOOD AHMED SHAIKH', '17-Jan-1997'],
    [1294, 'MUHAMMAD ASHAR NAEEM', 'MUHAMMAD NAEEM ANWAR LATE', '20-Feb-1998'],
  ],
};
```

будет выглядеть следующим образом:

![пример](./src/assets/readme/example_autogenerate.png)

**onRowClick()** - в данном примере кникнув на первую строку мы получим row:

```

{

Application_No: 1036,

Name: 'NABILA TOHEED',

Father_Name: 'TOHEED AHMED',

DOB: '15-Dec-1998',

}

```

#### Составление вручную

```tsx
const App = () => {
  return (
    <Table size='md' withTableBorder withRowBorders withColumnBorders striped>
      <Table.THead>
        <Table.Tr>
          <Table.Th>Application_No</Table.Th>
          <Table.Th>Name</Table.Th>
          <Table.Th>Father_Name</Table.Th>
          <Table.Th>DOB</Table.Th>
        </Table.Tr>
      </Table.THead>
      <Table.TBody>
        {data.map((row, index) => (
          <Table.Tr key={index}>
            <Table.Td>{row.Application_No}</Table.Td>
            <Table.Td>{row.Name}</Table.Td>
            <Table.Td>{row.Father_Name}</Table.Td>
            <Table.Td>{row.DOB}</Table.Td>
          </Table.Tr>
        ))}
      </Table.TBody>
    </Table>
  );
};
```

**Вручную можно прокидывать в компоненты таблицы другие компоненты**

_То есть никто не запрещает прокинуть кнопки, картинки, иконки и так далее_

```tsx
const App = () => {
  return (
    <Table size='md' withTableBorder withRowBorders withColumnBorders striped>
      <Table.THead>
        <Table.Tr>
          <Table.Th>
            <button>Click me</button>
          </Table.Th>

          <Table.Th>
            <AddIcon />
          </Table.Th>

          <Table.Th>
            <Checkbox />
          </Table.Th>

          <Table.Th>DOB</Table.Th>
        </Table.Tr>
      </Table.THead>
      {/* ... */}
    </Table>
  );
};
```

### Button

#### Основные пропсы:

- **size (string)** - по дефолту md.
- **variant (string)** - по дефолту primary.
- **isLoading (boolean)** - кнопка загрузки.
- **selected (boolean)** - выбранная кнопка.
- **children (boolean)** - обязательное присутствие текста.
- **start_icon (JSX.Element)** - вставить иконку в начало.
- **end_icon (JSX.Element)** - вставить икконку в конец.

```tsx
const App = () => {
  return (
    <Button
      size='sm'
      selected={selected}
      isLoading={loading}
      disabled={disabled}
      start_icon={<AddIcon />}
    >
      Button
    </Button>
  );
};
```

### IconButton

#### Основные пропсы:

- **size (string)** - по дефолту md.
- **variant (string)** - по дефолту primary.
- **isLoading (boolean)** - кнопка загрузки.
- **selected (boolean)** - выбранная кнопка.
- **children (boolean)** - обязательное присутствие текста.
- **icon (JSX.Element)** - вставить иконку.

```tsx
const App = () => {
  return (
    <Button
      size='sm'
      selected={selected}
      isLoading={loading}
      disabled={disabled}
      icon={<AddIcon />}
    >
      Button
    </Button>
  );
};
```

### Spinner

#### Основные пропсы:

- **size (string)** - по дефолту md.
- **spinnerColor(string)** - Добавление цвета, можно добавить в любом формате #fff, rgb и другие, в том числе и var() - Пример: `spinnerColor: "--spinner-color"`',

```tsx
const App = () => {
  return <Spinner size='lg' />;
};
```

### Radio

#### Основные пропсы:

- **label (string)** - добавление Lable.
- **labelClassName (string)** - кастомизация Lable.
- **iconClassName (string)** - кастомизация chekbox.
- **inputClassName (string)** - кастомизация input.
- **onChangeValue (void)** - отслеживание изменений значения Radio.

```tsx
const App = () => {
  return (
    <>
      <Radio name='example' label='Radio button' checked />
      <Radio name='example' />
    </>
  );
};
```

### RadioGroup

#### Основные пропсы:

- **name (strin)** - присвоение уникального значение группе кнопок, обязательный параметр.
- **gap (string)** - отсуп меджу кнопками в группе, по умолчанию 'md'.
- **vertical (boolean)** - вертикальное расположение кнопок.
- **defaultValue (string)** - выбор кнопки по дефолту со значением checked.
- **onChangeValue (void)** - отслеживание изменений значения RadioGroup.
- **optionsType ('button' | 'radio')** - radio/radio-button.
- **buttonStyle ('solid' | 'outline')** - вид кнопки для radio-button (по умолчанию outline).
- **size ('sm' | 'md')** - размер для radio-button (по умолчанию 'md').

```tsx
const App = () => {
  const [value, setValue] = useState('two');
  return (
    <RadioGroup name='testRadioGroup' value={value} onChangeValue={setValue} vertical>
      <Radio value='one' label='First' />
      <Radio value='two' label='Second' />
      <Radio value='three' label='Threeth' />
      <Radio value='four' />
    </RadioGroup>
  );
};
```

```tsx
const App = () => {
  return (
    <RadioGroup name='testRadio' defaultValue='one'>
      <Radio value='one' label='First' />
      <Radio value='two' label='Second' />
      <Radio value='three' />
    </RadioGroup>
  );
};
```

### DataGrid

#### Основные пропсы:

- **data (DataGridProps<TData>.data: TData[])** контент таблицы
- **columns (DataGridColumn<T>)** - определения столбцов — **самая важная часть построения таблицы.**
- **rowSelection (rowSelection?: boolean)** - чекбоксы первой колонкой
- **onRowSelect (onRowSelect?: (row: SelectedRow<TData>[]) => void)** - callback, который срабатывает при нажатии на чекбокс
- **sortingFn ((order: Order, columnTitle: keyof TData) => void)** - отключает клиентскую сортировку (нужно, если сортировка происходит на сервере)

#### Остальные пропсы из Table:

- **size (TableSize => sm / md)** - размер ячеек
- **striped (Striped => boolean | 'odd' | 'even')** - выделение четных/нечетных строк
- **withTableBorder (boolean)** - border вокруг таблицы
- **withRowBorders (boolean)** - border у строк
- **withColumnBorders (boolean)** - border у столбцов
- **stickyHeader (boolean)** - прилипание хэдера таблицы к верху страницы при прокрутке
- **stickyHeaderOffset (number)** - значение top для position:sticky. По умолчанию 0
- **onRowClick ((row: unknown) => void;)** - обработчик клика на строку

**Для удобства создадим моковые данные. Они будут использоваться во всех примерах**

```tsx
type Student = {
  Application_No: number;
  Name: string;
  Father_Name: string;
  DOB: string;
};

const data: Student[] = [
  {
    Application_No: 1036,
    Name: 'NABILA TOHEED',
    Father_Name: 'TOHEED AHMED',
    DOB: '15-Dec-1998',
  },
  {
    Application_No: 1072,
    Name: 'PIRHA MASOOD',
    Father_Name: 'MASOOD AHMED SHAIKH',
    DOB: '17-Jan-1997',
  },
  {
    Application_No: 1294,
    Name: 'MUHAMMAD ASHAR NAEEM',
    Father_Name: 'MUHAMMAD NAEEM ANWAR LATE',
    DOB: '20-Feb-1998',
  },
];
```

#### Генерация таблицы

У нас есть тип Student и data: Student[]. Нужно определить столбцы:

- **id(id?: string)** - id колонки
- **accessorKey((string & NonNullable<unknown>) | keyof T)** - ключ колонки (в данном примере keyof Student)
- **header(string)** - навзание колонки (то, что мы видим в th)
- **sortable(boolean)** - вкл/выкл сортировку колонки
- **sortDescFirst(false)** - начальное направление сортровки `desc`. Для чисел по умолчинаю = true
- **cell** - Используется для форматирования ячеек. Вы можете предоставить собственный форматировщик ячеек, передав функцию свойству ячейки и используя функцию props.getValue() для доступа к значению вашей ячейки (ниже в примере).

Теперь мы можем передать data и columns в DataGrid:

```tsx
interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

const columns: DataGridColumn<Post>[] = [
  {
    accessorKey: 'id',
    header: 'ID',
    sortable: true,
  },
  {
    accessorKey: 'title',
    header: 'Title',
    sortable: true,
    cell: ({ cell }) => <span>{cell.getValue()}</span>,
  },
  {
    accessorKey: 'userId',
    header: () => <div style={{ minWidth: '100px' }}>User Id</div>,
    sortable: true,
  },
  {
    accessorKey: 'body',
    header: 'Body',
    cell: ({ cell }) => <span>{cell.getValue()}</span>,
  },
];

const loadData = async (columnTitle = '', order = '') => {
  const res = await fetch(
    `https://jsonplaceholder.typicode.com/posts?_limit=10&_sort=${columnTitle}&_order=${order}`,
    {
      method: 'Get',
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
      },
    },
  );

  const data = await res.json();
  return data as Post[];
};

export const DataGridExample = () => {
  const [data, setData] = useState<Post[]>([]);

  const loadSortingPosts = async (order: Order, columnTitle: keyof Post) => {
    const posts = await loadData(columnTitle, order);
    setData(posts);
  };

  useEffect(() => {
    const loadInitData = async () => {
      const data = await loadData();

      setData(data);
    };

    loadInitData();
  }, []);

  return <DataGrid data={data} columns={columns} sortingFn={loadSortingPosts} rowSelection />;
};
```

### Skeleton

#### Основные пропсы:

- **animate (boolean)** - добавляет анимацию мерцания. По умолчанию false
- **height (CSSProperties['height'])** - высота, по умолчанию 8px (если задано число - применяется в px, если передать строку '50%' или '10rem' высота будет 50% или 10rem соответственно)
- **width (CSSProperties['width'])** - ширина. По умолчанию 100%. Вычисляется как и с height. Если props circle=true, то значение width игнорируется
- **circle (boolean)** - круг. Ширина круга = высоте. По умолчанию false
- **radius (CSSProperties['borderRadius'])** - border-radius. По умолчанию 0
- **visible (boolean)** - показывать/скрывать skeleton (пример ниже)

```tsx
import { useState } from 'react';

import { Button, Skeleton } from '@/lib';

import cls from './styles.module.css';

export const SkeletonExample = () => {
  const [visible, setVisible] = useState(true);

  return (
    <div className={cls.container}>
      <div className={cls.container}>
        <Button onClick={() => setVisible((prevState) => !prevState)}>
          {visible ? 'hide' : 'show'} skeleton
        </Button>

        <Skeleton visible={visible} radius='5rem'>
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi dolor nihil amet tempore
            magnam optio, numquam nostrum inventore tempora assumenda saepe, aut repellat.
            Temporibus aspernatur aperiam magnam debitis facere odio? Laborum fuga quam voluptas aut
            pariatur delectus repudiandae commodi tempora debitis dolores vero cumque magni cum,
            deserunt, ad tempore consectetur libero molestias similique nemo eum! Dolore maxime
            voluptate inventore atque.
          </p>
        </Skeleton>
      </div>

      <div className={cls.wrapper}>
        <Skeleton height={50} circle animate />

        <div className={cls.right_side}>
          <Skeleton height={15} radius={5} />
          <Skeleton width='50%' height={12} />
          <Skeleton />
        </div>
      </div>
    </div>
  );
};
```

### Avatar

#### Основные пропсы:

- **size (number)** - размер(значение в px)
- **src (string)** - src изображения
- **alt (string)** - альтернативный текст
- **letters (string)** - Перые буквы слов вместо стандартной картинки (Если ввести `Люблю программировать`, будет `ЛП`)
- **tag (HTMLElement)** - стандартный тэг `div`, но можно поменять. Если нужны ссылка, нужно написать `tag={'a'}`
- **isOnline (boolean)** - показать/скрыть онлайн индикатор (по умолчанию false)

#### пропсы для Avatar.Group:

- **max (number)** - максимальное количество аватаров (см пример ниже)
- **size (string)** - ощий размер для всех аватаров

#### пропсы для Avatar.Group:

- **count (number)** - количество заглушек
- **animate (boolean)** - вкл/выкл анимацию
- **size (string)** - ощий размер для всех аватаров

```tsx
import { Avatar } from '@/lib';

export const AvatarExample = () => {
  return (
    <div>
      <Avatar size={150} isOnline tag='a' href='#' target='_blank' />
      <Avatar size={60} isOnline letters='Oleg Pol' />

      <Avatar
        size={60}
        isOnline
        src='https://images.unsplash.com/photo-1580489944761-15a19d654956?q=80&w=1961&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'
      />

      <Avatar.Group max={4} size={100}>
        <Avatar isOnline />
        <Avatar isOnline />
      </Avatar.Group>

      <Avatar.Skeleton size={100} count={3} />
    </div>
  );
};
```

### Dropdown

Dropdown представляет собой конструктор из компонентов:

- **Dropdown** - рутовый компонент, в него вкладываются все остальные

- **Dropdown.Trigger** - кнопка, которая переключает выпадающее меню

- **Dropdown.Content** - компонент, который появляется, когда открыто раскрывающееся меню

- **Dropdown.Item** - компонент, содержащий пункты выпадающего меню

- **Dropdown.Label** - используется для отображения заголовка

- **Dropdown.Sub** - содержит все части подменю

- **Dropdown.SubTrigger** - пункт, открывающий подменю. Должен быть отображен внутри DropdownMenu.Sub

- **Dropdown.SubContent** - компонент, который появляется при открытии подменю. Должен быть отображен внутри DropdownMenu.Sub

- **Dropdown.CheckboxItem** - элемент, которым можно управлять и который отображается как флажок

- **Dropdown.Separator** - используется для визуального разделения элементов в раскрывающемся меню

#### Основные пропсы Dropdown:

- **trigger ('click' | 'hover)** - тригер по клику/наведению (по умолчанию click)

- **open (boolean)** - состояние открыто/зыкрыто

- **modal (boolean)** - если установлено значение true, взаимодействие с внешними элементами будет отключено

- **letters (string)** - открытое состояние раскрывающегося меню при его первоначальном отображении

- **children (ReactNode)**

#### Основные пропсы для Dropdown.Trigger:

- **withArrow (boolean)** - иконка стрелки справа

- **iconLeft (ReactNode)** - иконка слева

- **iconRight (ReactNode)** - иконка справа

- **arrowClassName (boolean)** - className для стрелки

- **className (string)** - className для trigger

- **children (ReactNode)**

#### Основные пропсы для Dropdown.Content:

- **loop (boolean)** - eсли установлено значение true, навигация с помощью клавиатуры будет циклически переходить от последнего элемента к первому и наоборот

- **onEscapeKeyDown ((event: KeyboardEvent) => void)** - обработчик событий вызывается, когда клавиша Escape нажата. Это можно предотвратить, вызвав event.preventDefault

- **side ('top' | 'right' | 'bottom' | 'left')** - предпочтительная сторона триггера для рендеринга при открытии

- **sideOffset (number)** - расстояние в пикселях от триггера

- **portalContainer (HTMLElement)** - элемент контейнера для переноса содержимого (по умолчанию document.body)

- **portalContainer (HTMLElement)** - элемент контейнера для переноса содержимого (по умолчанию document.body)

- **className (string)** - className для Dropdown.Content

- **withArrow (boolean)** - добавляет стрелочку для контейнера

- **arrowWidth (number)** - ширина стрелки

- **arrowHeight (number)** - высота стрелки

#### Основные пропсы для Dropdown.Item:

- **disabled (boolean)** - если установлено значение true, пользователь не может взаимодействовать с элементом

- **onSelect ((event: Event) => void)** - обработчик событий вызывается, когда пользователь выбирает элемент (с помощью мыши или клавиатуры). Вызов event.preventDefault в этом обработчике предотвратит закрытие раскрывающегося меню при выборе этого элемента.

- **className (string)** - className для Dropdown.Item

- **children (ReactNode)**

#### Основные пропсы для Dropdown.Label:

- **className (string)** - className для Dropdown.Label

- **children (ReactNode)**

#### Основные пропсы для Dropdown.Sub:

- **open (boolean)** - состояние открыто/зыкрыто

- **onOpenChange ((open: boolean): void)** - обработчик событий, вызываемый при изменении открытого состояния подменю

- **children (ReactNode)**

#### Основные пропсы для Dropdown.SubTrigger:

- **withArrow (boolean)** - иконка стрелки справа

- **disabled (boolean)** - если установлено значение true, пользователь не может взаимодействовать с элементом

- **arrowClassName (boolean)** - className для стрелки

- **className (string)** - className для trigger

- **children (ReactNode)**

#### Основные пропсы для Dropdown.SubContent:

- **loop (boolean)** - eсли установлено значение true, навигация с помощью клавиатуры будет циклически переходить от последнего элемента к первому и наоборот

- **onEscapeKeyDown ((event: KeyboardEvent) => void)** - обработчик событий вызывается, когда клавиша Escape нажата. Это можно предотвратить, вызвав event.preventDefault

- **sideOffset (number)** - расстояние в пикселях от триггера

- **className (string)** - className для Dropdown.Content

- **withArrow (boolean)** - добавляет стрелочку для контейнера

- **arrowWidth (number)** - ширина стрелки

- **arrowHeight (number)** - высота стрелки

#### Основные пропсы для Dropdown.CheckboxItem:

- **checked (boolean)** - контролируемое состояние элемента. Необходимо использовать вместе с onCheckedChange

- **onCheckedChange ((checked: boolean) => void)** - обработчик событий, вызываемый при изменении проверенного состояния

- **disabled (boolean)** - Если установлено значение true, пользователь не может взаимодействовать с элементом

- **className (string)** - className для Dropdown.CheckboxItem

- **children: (ReactNode)**

#### Основные пропсы для Dropdown.Separator:

- **className (string)** - className для Dropdown.Separator

#### Простое меню:

```tsx
import { Dropdown } from '@/lib';

export const DropdownExample = () => {
  return (
    <Dropdown {...args}>
      <Dropdown.Trigger withArrow className={cls.trigger}>
        <span>Dropdown</span>
      </Dropdown.Trigger>

      <Dropdown.Content>
        <Dropdown.Item>Option1</Dropdown.Item>

        <Dropdown.Item>Option2</Dropdown.Item>

        <Dropdown.Separator />

        <Dropdown.Label>Title</Dropdown.Label>

        <Dropdown.Item>Option 3</Dropdown.Item>

        <Dropdown.Item disabled>Option disabled</Dropdown.Item>
      </Dropdown.Content>
    </Dropdown>
  );
};
```

#### Вложенное меню:

```tsx
import { BarChartIcon, Dropdown, SaveIcon, SettingsIcon, UniverseIcon } from '@/lib';

import cls from './DropdownExample.module.css';

export const DropdownExample = () => {
  const [checkboxesState, setCheckboxesState] = useState({
    option1: false,

    option2: false,

    option3: false,

    option4: true,
  });

  const handleChangeCheckboxState = (checked: boolean, title: string) => {
    setCheckboxesState((prevState) => ({ ...prevState, [title]: checked }));
  };

  return (
    <Dropdown trigger='click'>
      <Dropdown.Trigger withArrow className={cls.trigger}>
        <span className={cls.trigger_content}>
          {/* <SettingsIcon /> */}
          Dropdown
        </span>
      </Dropdown.Trigger>

      <Dropdown.Content>
        <Dropdown.Item>Option1</Dropdown.Item>

        <Dropdown.Item>Option2</Dropdown.Item>

        <Dropdown.Separator />

        <Dropdown.Label>Title</Dropdown.Label>

        <Dropdown.Item>Option 3</Dropdown.Item>

        <Dropdown.Item disabled>Option disabled</Dropdown.Item>

        <Dropdown.Sub>
          <Dropdown.SubTrigger>
            <span>Sub Dropdown</span>
          </Dropdown.SubTrigger>

          <Dropdown.SubContent>
            <Dropdown.CheckboxItem
              checked={checkboxesState.option1}
              onCheckedChange={(checked) => handleChangeCheckboxState(checked, 'option1')}
            >
              <div className={cls.sub_item_container}>
                <SaveIcon />
                Sub Item 1
              </div>
            </Dropdown.CheckboxItem>

            <Dropdown.CheckboxItem
              checked={checkboxesState.option2}
              onCheckedChange={(checked) => handleChangeCheckboxState(checked, 'option2')}
            >
              <div className={cls.sub_item_container}>
                <UniverseIcon />
                Sub Item 2
              </div>
            </Dropdown.CheckboxItem>

            <Dropdown.CheckboxItem
              checked={checkboxesState.option3}
              onCheckedChange={(checked) => handleChangeCheckboxState(checked, 'option3')}
            >
              <div className={cls.sub_item_container}>
                <SettingsIcon />
                Sub Item 3
              </div>
            </Dropdown.CheckboxItem>

            <Dropdown.CheckboxItem
              disabled
              checked={checkboxesState.option4}
              onCheckedChange={(checked) => handleChangeCheckboxState(checked, 'option4')}
            >
              <div className={cls.sub_item_container}>
                <BarChartIcon />

                <span className={cls.sub_item_with_icon}>Sub Item</span>
              </div>
            </Dropdown.CheckboxItem>
          </Dropdown.SubContent>
        </Dropdown.Sub>
      </Dropdown.Content>
    </Dropdown>
  );
};
```

### Rate

#### Основные пропсы:

- **value (number)** - передача внутрь основного значения рейтинга ( количество активных звезд).
  По умолчанию 0.
- **starSize (number)** - размер самой звезды в пикселях По умолчанию 24.
- **isOnlyRead (boolean)** - возможность либо невозможность изменять количество активных звезд.
- **onFixRating (star:number)** - отслеживание изменений значения рэйтинга и передача значений наружу.

```tsx
export const RateExample = () => {
  const [value, setValue] = useState(0);
  const onFixRating = (star: number) => {
    setValue(star);
  };
  return (
    <div>
      <h4>Uncontrolled</h4>
      <Toggle />
      <h4>Controlled</h4>
      <Toggle isOnlyRead={false} value={value} onFixRating={onFixRating} />
      <h4>Read Only</h4>
      <Toggle value={4.6} isOnlyRead />
    </div>
  );
};
```

### Toggle

#### Основные пропсы:

- **disabled (boolean)**
- **isLoading (boolean)** - Отвечает за отрисовку спиннера.
- **isEmpty (boolean)** - Отвечает за отрисовку статичного элемента внутри тогла, заменяя динамический элемент
- **checked (boolean)** - Передает внутрь компоненты состояние в котором находится динамический элемент. Проще говоря, вкл или выкл.
- **switchToggle (boolean)** - Изменяет состояние тогла.
- **size ('xs' | 'md')** - Изменяет размер тогла.
- **classNameThumb (sting)** - Дополнительные стили для динамического внутреннего элемента.
- **className (sting)** - Дополнительные стили для статического внешнего элемента.

```tsx
export const ToggleExample = () => {
  const [checked, setChecked] = useState(false);

  const onChangeHandler = () => {
    setChecked((prevState) => !prevState);
  };

  return (
    <div>
      <h4>Uncontrolled with focus and hover</h4>
      <Toggle />
      <h4>Disabled</h4>
      <Toggle disabled />
      <h4>Spinner</h4>
      <Toggle isLoading />
      <h4>Empty toggle</h4>
      <Toggle isEmpty />
      <h4>Controlled with focus and hover</h4>
      <Toggle checked={checked} switchToggle={onChangeHandler} />
      <h4>Uncontrolled with focus and hover small size</h4>
      <Toggle size='xs' />
      <h4>Empty toggle with small size</h4>
      <Toggle isEmpty size='xs' />
    </div>
  );
};
```

### Slider

#### Основные пропсы:

- **className (string)** - Дополнительный класс CSS для корневого узла DOM слайдера.

- **value (number | number[])** - Установите текущее значение ползунка.

- **defaultValue (number)** - Значения слайдера по молчанию.

- **min (number)** - Минимальное начения слайдера, 0 по умолчанию.

- **max (number)** - Максимальное значения слайдера, 100 по умолчнию.

- **marks ({number: ReactNode} | {number: { style, label }})** - Метки на слайдере. Ключ определяет позицию, а значение определяет, что будет отображаться. Если вы хотите задать стиль определенной точки отметки, значением должен быть объект, содержащий свойства стиля и метки.

- **step (number | null)** - Значение, которое будет добавляться или вычитаться на каждом шаге, выполняемое ползунком. Должно быть больше нуля, а max - min должно быть равномерно кратно значению шага. Если marks не является пустым объектом, step можно установить равным null, чтобы сделать отметки шагами.

- **disabled (boolean)** - Если значени true, то ползунок нельзя двигать.

- **dots (boolean)** - Если значение шага больше 1, вы можете установить для точек значение true, если хотите отображать ползунок с точками.

- **showLabels (boolean)** - Отображение начального и конечного значений всей шкалы.

- **range (boolean)** - Использовать range slider.

- **pushable (boolean | number)** - pushable может быть установлено как true (в режиме range), чтобы разрешить нажатие окружающих маркеров при перемещении маркера. Если установлено число, оно будет представлять собой минимальное гарантированное расстояние между маркерами.
- **onChange (Function)** - передача внутрь основного значения рейтинга ( количество активных звезд).
- **showTooltip (boolean)** - Отображение tooltip, по умолчанию работает на hover и dragging, при установке значения на true, будет виден постоянно, при установке значения на false отключается отображение.

- **tipProps (object)** - Объект c пропсами компонента Tooltip, документацию можно найти по ссылке https://react-component.github.io/tooltip'.

- **classNamesLabels (string)** - ClassName для label слайдера.

#### Дополнительные пропсы можно наайти по ссылке https://www.npmjs.com/package/rc-slider

```tsx
const App = () => {
  const [value, setValue] = useState('two');

  return (
    <div style={{ width: '300px' }}>
      <Slider defaultValue={50} showLabels />
    </div>
  );
};
```

### Modal

#### Основные пропсы:

- **open (boolean)** - Состояние открыто/закрыто

- **onClose (() => void)** - Колбэк при закрытии модального окна

- **onOk (() => () => void)** - Колбэк при нажатии на "Ok"

- **onCancel (star:number)** - Колбэк при нажатии на "Cancel"

- **title (string)** - Заголовок модальног окна

- **size ('lg' | 'md' | 'sm')** - Размеры модального окна

- **centered (boolean)** - Выравнивание по вертикали

- **withOverlay (boolean)** - Показывать/не показывать затемняющий фон

- **withCloseButton (boolean)** - Показывать/не показывать кнопку закрыть. Лкно закрывается при нажатии на Escape, или при клике вне окна

- **renderHeader (ReactNode)** - Свой header

- **renderBody (ReactNode)** - Свой body

- **renderFooter (ReactNode)** - Свой footer

- **okButtonProps (ButtonProps)** - Пропсы для кнопки "Ok"

- **cancelButtonProps (ButtonProps)** - Пропсы для кнопки "Cancel"

```tsx
import { useState } from 'react';

import { Button, Input, Modal } from '@/lib';

import cls from './ModalExample.module.css';

export const ModalExample = () => {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button variant='outline' onClick={() => setOpen(true)}>
        Trigger modal
      </Button>

      <Modal title='Authentication' open={open} onClose={() => setOpen(false)} size='sm'>
        Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has
        been the industry&apos;s standard dummy text ever since the 1500s, when an unknown printer
        took a galley of type and scrambled it to make a type specimen book. It has survived not
        only five centuries, but also the leap into electronic type
        <Input placeholder='some input' className={cls.input} />
        <Input placeholder='some input' className={cls.input} />
        <Input placeholder='some input' className={cls.input} />
      </Modal>
    </>
  );
};
```

#### Основные пропсы:

```tsx
import { useState } from 'react';

import { Button, Input, Modal } from '@/lib';

import cls from './ModalExample.module.css';

const CustomHeader = <header>My custom header</header>;

export const ModalExample = () => {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button variant='outline' onClick={() => setOpen(true)}>
        Trigger modal
      </Button>

      <Modal
        title='Authentication'
        open={open}
        onClose={() => setOpen(false)}
        renderHeader={() => <CustomHeader />}
        okButtonProps={{ children: 'Новый текст для кнопки', disabled: true, isLoading: true }}
      />
    </>
  );
};
```

### Tag

#### Основные пропсы:

- **backgroundColor (string)** - устанавливает цвет фона тэга. По умолчанию 'neutral-3'.

- **textColor (string)** - устанавливает цвет текста тэга.

- **link (boolean)** - определяет, использовать ли тэг как ссылку. По умолчанию false.

- **src (string)** - URL-адрес для использования, если тэг представляет собой ссылку. По умолчанию пустая строка.

- **removable (boolean)** - указывает, является ли тэг удалаемым. По умолчанию false.

- **onRemoveTag (() => void)** - функция, вызванная при удалении тега, если он является удаляемым.

- **startIcon (React.ReactNode)** - иконка в начале тега.

- **children (string)** - текстовое содержимое тэга. По умолчанию 'Tag'.

- **className (string)** - использование для передачи пользовательского класса в компонент тега.

```tsx
export const TagExample = () => {
  const tags = [
    {
      backgroundColor: 'neutral-3',

      title: 'Tag 1',

      textColor: 'red-3',

      link: false,

      src: 'http://example1.com',

      removable: true,

      onRemoveTag: () => console.log('Remove tag1'),

      className: 'class1',
    },

    {
      backgroundColor: 'neutral-3',

      title: 'Tag 2',

      textColor: 'red-3',

      link: true,

      src: 'http://example2.com',

      removable: false,

      startIcon: <Avatar />,

      onRemoveTag: () => console.log('Remove tag2'),

      className: 'class2',
    },

    {
      backgroundColor: 'neutral-3',

      title: 'Tag 3',

      textColor: 'red-3',

      link: false,

      src: 'http://example3.com',

      removable: true,

      startIcon: <Avatar />,

      onRemoveTag: () => console.log('Remove tag3'),

      className: 'class3',
    },

    {
      backgroundColor: 'neutral-3',

      title: 'Tag 4',

      textColor: 'red-3',

      className: 'class4',
    },
  ];

  return (
    <div className={cls.container}>
      <div className={cls.tag}>
        <Tag backgroundColor='neutral-3' textColor='red-3' startIcon={<Avatar />} removable>
          Tag
        </Tag>
      </div>

      <div>
        <span>LINKED TAGS: </span>

        <div className={cls.tag}>
          <Tag backgroundColor='cyan-3' link src={'https://ant.design/components/tag'}>
            Tag
          </Tag>
        </div>
      </div>

      <div>
        <span>TAG GROUP: </span>

        <div className={cls.tagGroup}>
          {tags.map((tag, index) => {
            return (
              <Tag
                key={index}
                backgroundColor={tag.backgroundColor}
                textColor={tag.textColor}
                link={tag.link}
                src={tag.src}
                removable={tag.removable}
                startIcon={tag.startIcon}
                onRemoveTag={tag.onRemoveTag}
                className={tag.className}
              >
                {tag.title}
              </Tag>
            );
          })}
        </div>
      </div>
    </div>
  );
};
```

### Badge

#### Основные пропсы:

Данный компонент служит своего рода оберткой для другого элемента, это может быть как отдельная компонента, так и просто блок, которые принимаются в виде children в компонент badge (см пример ниже)

- **dot (boolean)** Если он тру, то будет отрисовываться просто точка, при этом, если мы обрисовываем точку, а не число, то все статусы применять нельзя, можно только те, которые входят в
  type BaseStatus.
- **value (number)** - Отвечает за отрисовку числового значения .
- **status ("Success""Error""Default""Processing""Warning""Primary""Removed""Added")** - Отвечает за цвет. Статусы, которые можно применить к числовому значению шире, чем те, что можно применить к точке. Для точки type BaseStatus, для числового значения ExtendedStatus (он расширяет BaseStatus).
- **size ("sm""md""lg")** - По умолчанию lg. Отвечает за размер бейджа, если это не точка.
- **badgePosition ("top-left""top-right""bottom-left""bottom-right")** - Изменяет позицию бэйджа относительно чилдрена По умолчанию "top-right".

```tsx
export const BadgeExample = () => {
  return (
    <div>
      <h4>Just dot</h4>
      <div style={{ display: 'flex', gap: '15px' }}>
        <div>
          <Badge dot status='Success' badgePosition='top-left'>
            <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
          </Badge>
        </div>
        <div>
          <Badge dot status='Error' badgePosition='top-right'>
            <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
          </Badge>
        </div>
        <div>
          <Badge dot status='Processing' badgePosition='bottom-left'>
            <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
          </Badge>
        </div>
        <h4>With Numbers Large</h4>
        <div style={{ display: 'flex', gap: '25px' }}>
          <div>
            <Badge value={21} status='Success' badgePosition='top-right'>
              <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
            </Badge>
          </div>
          <div>
            <Badge value={21} status='Error' badgePosition='bottom-left'>
              <div style={{ width: '90px', height: '90px', background: 'yellow' }} />
            </Badge>
          </div>
          <div>
            <Badge value={21} status='Default' badgePosition='bottom-right'>
              <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
            </Badge>
          </div>
          <div>
            <Badge value={21} status='Processing'>
              <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
            </Badge>
          </div>
          <div>
            <Badge value={21} status='Primary'>
              <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
            </Badge>
          </div>
          <div>
            <Badge value={21} status='Added'>
              <div style={{ width: '20px', height: '20px', background: 'yellow' }} />
            </Badge>
          </div>
        </div>
      </div>
    </div>
  );
};
```

### Portal

#### Основные пропсы:

- **container? (HTMLElement | null)** HTML Element, куда будет помещаться сожержимое портала. По умолчанию document.body
- **containerId? (string)** - id элемента, куда будет помещаться содержимое портала
- **children? (ReactNode)** - содержимое портала

### Tooltip

#### Основные пропсы:

- **as (string)** - устанавливает HTML-тег контейнера подсказки. По умолчанию 'div'.
- **distance (number)** - устанавливает расстояние от контейнера подсказки до целевого элемента.
- **behavior (TTooltipBehaviorType)** - определяет поведение подсказки. Возможные значения: 'Наведение', 'Клик'. По умолчанию 'Наведение'.
- **children (ReactNode)** - содержимое подсказки.
- **classes (TClasses)** - устанавливает дополнительные CSS-классы для стилизации.
- **classNames (string)** - позволяет передать пользовательские классы в компонент подсказки.
- **message (string | React.ReactElement)** - содержимое или React-элемент для отображения внутри подсказки.
- **modifiers (TModifiers)** - устанавливает дополнительные модификаторы для подсказки.
- **placement (TPlacement)** - устанавливает расположение подсказки. По умолчанию 'вверх'.
- **timerDelay (number)** - устанавливает задержку по времени для отображения подсказки. По умолчанию 100 мс.
- **arrow (boolean)** - определяет, нужно ли отображать стрелку в подсказке. По умолчанию false.
- **width (number)** - определяет ширину Tooltip. По умолчанию 500.

```tsx
<Tooltip
  message={
    'Use this if you want to insert a text hint. The tooltip appears when hovering over an object. This is the maximum block width that should be used.'
  }
  placement='top'
  distance={10}
  arrow={true}
  behavior='hover'
>
  Hello
</Tooltip>
```

### Breadcrumbs

#### Основные пропсы:

- **breadcrumbItems({href: string, title?: string, icon?: ReactNode})** - Массив объетов {href: string , title?: string , icon?: ReactNode} где передаются значения Breadcrumbs.
- **variantLink(string)** - Выбор стиля отображения значений Breadcrumbs, может быть "background" | "underline", по умолчанию "background".
- **separator(ReactNode)** - Рзделитель, по молчанию "/", можно вставить картинку.
- **collapsed(boolean | number)** - Можно сжать Breadcrumb до последнего значения, принимает как boolean так и number, при передачи числа, отслеживает сколько предыдущих ссылок будет видно перед активной.
- **tooltipProps(object)** - объект пропсов компонента <Tooltip>, основные пропсы компонента смотреть в описании Tooltip.

```tsx
const items = [
  {
    href: '/1',
    title: 'Item1',
  },
  {
    href: '/2',
    title: 'Item2',
  },
  {
    href: '/3',
    title: 'Item3',
  },
];

<div>
  <Breadcrumbs breadcrumbItems={items} collapsed />
</div>;
```

### LinearProgress

#### Основные пропсы:

- **progress(number)** - Значение прогресса загрузки от 0 до 100,
- **size('sm' | 'md' | 'lg')** - Размер полоски,
- **width(number)** - Длинна полоски загрузки, по умолчанию 100%,
- **className(string)** - Передача стилей основвной обертки,
- **isError(boolean)** - Передача присутствия ошибки,
- **isSuccessful(boolean)** - Передача успеха загрузки, по умолчаанию срабатывает при 100%,
- **linearColor(string)** - Изменение цвета полоски загрузки, передача цета в различных форматах (Keyword, Hexadecimal, RGB, HSL и т.д),
- **backgroundLinearColor(string)** - Изменение цвета заднего фона полоски загрузки, передача цета в различных форматах (Keyword, Hexadecimal, RGB, HSL и т.д),

```tsx
const [progress, setProgress] = useState(0);

useEffect(() => {
  const timer = setInterval(() => {
    setProgress((oldProgress) => {
      if (oldProgress === 100) {
        return 0;
      }
      const diff = Math.random() * 10;
      return Math.floor(Math.min(oldProgress + diff, 100));
    });
  }, 500);

  return () => {
    clearInterval(timer);
  };
}, []);

return (
  <>
    <LinearProgress size='lg' width={500} progress={100} />
    <LinearProgress width={450} progress={progress} />
    <div className={cls.progressWrapper}>
      <LinearProgress isError size='sm' progress={60} />
    </div>
    <LinearProgress size='sm' progress={progress} />
  </>
);
```

### Pagination

#### Основные пропсы:

- **disabledAll(boolean)** - Устанавливает кнопки в неактивное состояниее.

##### все остальные props можно найти перейдя поссылке https://www.npmjs.com/package/react-responsive-pagination

```tsx
const [currentPage, setCurrentPage] = useState<number>(1);

return (
  <>
    <Pagination
      total={20}
      maxWidth={500}
      current={currentPage}
      onPageChange={(page) => setCurrentPage(page)}
    />
  </>
);
```

### TimePicker

#### Основные пропсы:

- **value?:{string)** - Значение в формате `__:__:__`, в противном случае будет установлено `00:00:00`.
- **onChange? ((timeString: string) => void)** - Обработчик для изменения значения.
- **size? ('sm' | 'md')** - Размер контейнера. По умолчанию `'md'`.
- **invalid? (boolean)** - Индикатор невалидности значения (автоматически становится true, если `0 > h > 23`, `0 > m > 59`, `0 > s > 59`).
- **disabled? (boolean)** - Заблокировать timepicker
- **className? (string)** - ClassName для основного контейнера
- **inputClassName? (string)** - ClassName для input
- **iconClassName? (string)** - ClassName для иконки
- **closeIconClassName? (string)** - ClassName для кнопки "remove"
- **popupClassName? (string)** - ClassName для контейнера со временем
- **nowButtonClassName? (string)** - ClassName для кнопки 'Now'
- **okButtonClassName? (string)** - ClassName для кнопки 'Ok'
- **nowButtonTitle? (string)** - Текст для кнопки 'Now'
- **okButtonTitle? (string)** - Текст для кнопки 'Ok'
- **disabledTime? (DisabledTime)** - Заблокированное время

```tsx
type DisabledTime = (now: string) => {
  disabledHours?: () => number[];
  disabledMinutes?: (selectedHour: number) => number[];
  disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[];
};

const disabledTime: DisabledTime = (now) => {
  return {
    disabledHours: () => [1, 2, 3, 5, 10, 14],
    disabledMinutes: () => [20, 21, 22, 30, 46, 59],
    disabledSeconds: () => [],
  };
};
```

```tsx
import { useState } from 'react';

import { TimePicker } from '@/lib';

export const TimePickerExample = () => {
  const [time, setTime] = useState('10:27:00');
  const [invalid, setInvalid] = useState(false);

  const handleChange = (time: string) => {
    setTime(time);
  };

  return (
    <div style={{ margin: '50px' }}>
      <TimePicker size='md' value={time} onChange={handleChange} />
      <TimePicker size='sm' invalid={invalid} />

      <button onClick={() => setInvalid((prevState) => !prevState)}>Toggle Invalid</button>
    </div>
  );
};
```

### TimePickerRange

#### Основные пропсы:

- **основне пропсы от TimePicker**
- **startValue? (string)** - Начальное значение
- **endValue? (string)** - Конечное значение
- **onChange?: (startValue: string, endValue: string) => void** - Обработчик для изменения значения

```tsx
import { useState } from 'react';

import { TimePicker } from '@/lib';

export const TimePickerExample = () => {
  const [time, setTime] = useState('10:27:00');
  const [invalid, setInvalid] = useState(false);

  const handleChange = (time: string) => {
    setTime(time);
  };

  const handleDisabledTime: DisabledTime = (now) => {
    return {
      disabledHours: () => [1, 2, 3, 5, 10, 14],
      disabledMinutes: () => [20, 21, 33, 59],
      disabledSeconds: () => [],
    };
  };

  const handleDisabledEndTime: DisabledTime = (now) => {
    return {
      disabledHours: () => [10, 11, 12, 13, 14, 15, 16],
      disabledMinutes: () => [],
      disabledSeconds: () => [
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
      ],
    };
  };

  return (
    <div>
      <TimePicker.RangePicker
        disabledStartTime={handleDisabledTime}
        disabledEndTime={handleDisabledEndTime}
      />

      <button onClick={() => setInvalid((prevState) => !prevState)}>Toggle Invalid</button>
    </div>
  );
};
```