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

<Meta title='@dxtmisha/functional/ru/Composables/useStorageRef'/>

# Композабл useStorageRef

Композабл для создания реактивной переменной, синхронизированной с localStorage. Автоматически управляет чтением и записью значений в локальное хранилище браузера с поддержкой кеширования, синхронизации между вкладками и singleton паттерна для эффективного переиспользования.

## Основные возможности

- **Двусторонняя синхронизация** — автоматическая синхронизация между ref и localStorage
- **Автоматическое сохранение** — изменения ref автоматически сохраняются в localStorage
- **Кеширование с TTL** — опциональное время жизни кеша в секундах
- **Синхронизация между вкладками** — автоматическое обновление при изменениях в других вкладках
- **Singleton паттерн** — переиспользование ref для одинаковых ключей
- **Типобезопасность** — полная поддержка TypeScript с дженериками
- **Значения по умолчанию** — поддержка начальных значений и функций-фабрик
- **Интеграция с DataStorage** — использует класс DataStorage для управления хранилищем

## Функция

### `useStorageRef`

Создаёт реактивную переменную, синхронизированную с localStorage.

**Параметры:**
- `name: string` — имя ключа в localStorage
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция для его генерации (опционально)
- `cache?: number` — время кеширования в секундах (опционально)

**Возвращает:** `Ref<T | undefined>` — реактивная переменная Vue, связанная с localStorage

```javascript
import { useStorageRef } from '@dxtmisha/functional'

// Простое использование
const theme = useStorageRef('app-theme')

// С значением по умолчанию
const language = useStorageRef('app-language', 'ru')

// С функцией по умолчанию
const userId = useStorageRef('user-id', () => Math.random().toString(36))

// С кешированием (600 секунд = 10 минут)
const cachedData = useStorageRef('cached-data', null, 600)
```

## Основное использование

### Базовая синхронизация

```javascript
import { useStorageRef } from '@dxtmisha/functional'

// Создание ref, синхронизированного с localStorage
const userTheme = useStorageRef('theme', 'light')

// При изменении ref - localStorage автоматически обновляется
userTheme.value = 'dark'
// localStorage: { 'ui-storage__theme': '{"value":"dark","age":1234567890}' }

// При перезагрузке страницы значение восстанавливается
console.log(userTheme.value) // 'dark'
```

### Singleton паттерн

```javascript
// При повторном вызове с тем же именем возвращается существующий ref
const theme1 = useStorageRef('app-theme', 'light')
const theme2 = useStorageRef('app-theme', 'dark')

console.log(theme1 === theme2) // true - тот же ref

theme1.value = 'blue'
console.log(theme2.value) // 'blue' - оба указывают на один ref
```

## Использование в компонентах

### Настройки пользователя

```javascript
import { useStorageRef } from '@dxtmisha/functional'

export default {
  setup() {
    const theme = useStorageRef('user-theme', 'light')
    const fontSize = useStorageRef('font-size', 16)
    const notifications = useStorageRef('notifications', true)

    return {
      theme,
      fontSize,
      notifications
    }
  }
}

// Template:
// <div>
//   <select v-model="theme">
//     <option value="light">Светлая</option>
//     <option value="dark">Тёмная</option>
//   </select>
//   <input v-model.number="fontSize" type="number" />
//   <input v-model="notifications" type="checkbox" />
// </div>
```

### Кеширование данных API

```javascript
import { useStorageRef } from '@dxtmisha/functional'

export default {
  setup() {
    // Кеш на 10 минут (600 секунд)
    const userData = useStorageRef('user-data', null, 600)

    const loadUserData = async () => {
      if (userData.value) {
        console.log('Данные из кеша')
        return userData.value
      }

      console.log('Загрузка с сервера')
      const response = await fetch('/api/user')
      userData.value = await response.json()
      return userData.value
    }

    return { userData, loadUserData }
  }
}
```

## Синхронизация между вкладками

```javascript
import { useStorageRef } from '@dxtmisha/functional'

// В первой вкладке
const counter = useStorageRef('counter', 0)
counter.value = 5

// Во второй вкладке автоматически обновится
// counter.value === 5 (благодаря storage event)

// В третьей вкладке
const sameCounter = useStorageRef('counter', 0)
console.log(sameCounter.value) // 5

// Изменение в любой вкладке обновит все остальные
sameCounter.value = 10
// Все открытые вкладки получат counter.value === 10
```

## Работа с типами данных

```javascript
// Числа
const count = useStorageRef<number>('count', 0)
count.value = 42

// Булевы значения
const isActive = useStorageRef<boolean>('active', false)
isActive.value = true

// Объекты
const settings = useStorageRef('settings', {
  theme: 'dark',
  language: 'ru',
  notifications: true
})
settings.value.theme = 'light'

// Массивы
const items = useStorageRef<string[]>('items', [])
items.value.push('новый элемент')
```

## Примеры использования

### Сохранение состояния формы

```javascript
const formData = useStorageRef('contact-form', {
  name: '',
  email: '',
  message: ''
})

// При заполнении формы данные автоматически сохраняются
formData.value.name = 'Иван'
formData.value.email = 'ivan@example.com'

// При перезагрузке страницы данные восстанавливаются
```

### Избранное пользователя

```javascript
const favorites = useStorageRef<number[]>('favorites', [])

const addToFavorites = (id: number) => {
  if (!favorites.value.includes(id)) {
    favorites.value = [...favorites.value, id]
  }
}

const removeFromFavorites = (id: number) => {
  favorites.value = favorites.value.filter(fav => fav !== id)
}
```

### Кеш с автообновлением

```javascript
// Кеш на 5 минут
const newsData = useStorageRef('news', null, 300)

const fetchNews = async () => {
  // Если кеш валиден - возвращаем сохранённые данные
  if (newsData.value) return newsData.value

  // Иначе загружаем свежие данные
  const response = await fetch('/api/news')
  newsData.value = await response.json()
  return newsData.value
}

// Первый вызов - загружает с сервера
await fetchNews()

// Последующие вызовы в течение 5 минут - используют кеш
await fetchNews() // Из кеша

// Через 5+ минут - снова загрузит с сервера
```

