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

<Meta title='@dxtmisha/functional/en/Composables/useCookieRef'/>

# Composable useCookieRef

Composable for creating a reactive variable synchronized with browser cookies. Automatically manages reading and writing values to cookies with support for cross-tab synchronization via Broadcast Channel API, expiration settings, and singleton pattern for efficient reuse.

## Key Features

- **Two-way synchronization** — automatic sync between ref and cookies
- **Cross-tab synchronization** — changes in one tab instantly reflect in all others via Broadcast Channel
- **Automatic persistence** — ref changes automatically saved to cookies
- **Expiration settings** — supports expires, max-age and other cookie options
- **Singleton pattern** — reuses ref for same cookie names
- **Type safety** — full TypeScript support with generics
- **Default values** — supports initial values and factory functions
- **Cookie integration** — uses Cookie class for cookie management

## Function

### `useCookieRef`

Creates reactive variable synchronized with browser cookies.

**Parameters:**
- `name: string` — cookie name
- `defaultValue?: T | string | (() => (T | string))` — default value or function to generate it (optional)
- `options?: CookieOptions` — additional cookie parameters (optional)

**Returns:** `Ref<T | string | undefined>` — Vue reactive variable linked to cookie

**CookieOptions:**
- `expires?: number | Date` — expiration date
- `path?: string` — path for cookie (default '/')
- `domain?: string` — domain for cookie
- `secure?: boolean` — use HTTPS only
- `sameSite?: 'Strict' | 'Lax' | 'None'` — SameSite policy

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

// Simple usage
const userToken = useCookieRef('token')

// With default value
const theme = useCookieRef('theme', 'light')

// With options (expires in 7 days)
const rememberMe = useCookieRef('remember', true, {
  expires: 7,
  path: '/',
  sameSite: 'Lax'
})
```

## Basic Usage

### Basic Synchronization

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

// Create ref synchronized with cookie
const userTheme = useCookieRef('theme', 'light')

// When ref changes - cookie automatically updates
userTheme.value = 'dark'
// document.cookie contains: 'theme=dark'

// On page reload, value is restored
console.log(userTheme.value) // 'dark'
```

### Singleton Pattern

```javascript
// Repeated calls with same name return existing ref
const token1 = useCookieRef('auth-token', '')
const token2 = useCookieRef('auth-token', '')

console.log(token1 === token2) // true - same ref

token1.value = 'abc123'
console.log(token2.value) // 'abc123' - both point to same ref
```

### Cross-tab Synchronization

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

// In first tab
const userState = useCookieRef('user-online', 'active')
userState.value = 'away'

// In second tab automatically updates instantly
// userState.value === 'away' (thanks to Broadcast Channel)

// In third tab
const sameState = useCookieRef('user-online', 'active')
console.log(sameState.value) // 'away'

// Changes in any tab sync with all others
```

## Usage in Components

### User Settings

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

export default {
  setup() {
    const theme = useCookieRef('user-theme', 'light', {
      expires: 365 // 1 year
    })

    const language = useCookieRef('user-language', 'en', {
      expires: 365
    })

    const fontSize = useCookieRef('font-size', 16, {
      expires: 30 // 30 days
    })

    return {
      theme,
      language,
      fontSize
    }
  }
}

// Template:
// <div>
//   <select v-model="theme">
//     <option value="light">Light</option>
//     <option value="dark">Dark</option>
//   </select>
//   <select v-model="language">
//     <option value="en">English</option>
//     <option value="ru">Русский</option>
//   </select>
// </div>
```

### Authentication with "Remember Me"

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

export default {
  setup() {
    const authToken = useCookieRef('auth-token', '', {
      expires: 7, // 7 days
      secure: true,
      sameSite: 'Strict'
    })

    const rememberMe = useCookieRef('remember-me', false)

    const login = (token) => {
      const expires = rememberMe.value ? 30 : 1 // 30 days or 1 day
      authToken.value = token

      // Update cookie options
      useCookieRef('auth-token', token, {
        expires,
        secure: true,
        sameSite: 'Strict'
      })
    }

    const logout = () => {
      authToken.value = ''
      rememberMe.value = false
    }

    return {
      authToken,
      rememberMe,
      login,
      logout
    }
  }
}
```

## Cookie Settings

### Expiration

```javascript
// Expires in days
const token = useCookieRef('token', '', {
  expires: 7 // deleted after 7 days
})

// Expires as Date
const session = useCookieRef('session', '', {
  expires: new Date('2025-12-31')
})

// Without expires (session cookie, deleted on browser close)
const tempData = useCookieRef('temp', '')
```

### Security

```javascript
// HTTPS only
const secureToken = useCookieRef('secure-token', '', {
  secure: true,
  sameSite: 'Strict'
})

// Cross-site requests
const apiToken = useCookieRef('api-token', '', {
  secure: true,
  sameSite: 'None' // requires secure: true
})
```

### Path and Domain

```javascript
// For specific path
const adminPrefs = useCookieRef('admin-prefs', {}, {
  path: '/admin'
})

// For subdomain
const sharedData = useCookieRef('shared', '', {
  domain: '.example.com' // accessible for all subdomains
})
```

## Working with Data Types

```javascript
// Strings
const username = useCookieRef<string>('username', '')
username.value = 'John'

// Numbers (automatic serialization)
const count = useCookieRef<number>('count', 0)
count.value = 42

// Booleans
const accepted = useCookieRef<boolean>('accepted', false)
accepted.value = true

// Objects (JSON serialization)
const userPrefs = useCookieRef('prefs', {
  theme: 'dark',
  notifications: true
})
userPrefs.value = { theme: 'light', notifications: false }
```

## Integration with Cookie Class

Composable uses `Cookie` class for cookie management:

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

// Direct class usage
const cookie = new Cookie('theme')
cookie.set('dark', { expires: 30 })
console.log(cookie.get()) // 'dark'

// useCookieRef automatically synchronizes
const themeRef = useCookieRef('theme')
console.log(themeRef.value) // 'dark'

// Changes via Cookie reflect in ref (via Broadcast Channel)
cookie.set('light')
// themeRef.value automatically updates in all tabs
```

## Usage Examples

### Cookie Consent (GDPR)

```javascript
const cookieConsent = useCookieRef('cookie-consent', false, {
  expires: 365,
  sameSite: 'Lax'
})

const acceptCookies = () => {
  cookieConsent.value = true
}

// In template:
// <div v-if="!cookieConsent" class="cookie-banner">
//   <p>We use cookies...</p>
//   <button @click="acceptCookies">Accept</button>
// </div>
```

### Shopping Cart

```javascript
const cart = useCookieRef<CartItem[]>('shopping-cart', [], {
  expires: 7
})

const addToCart = (item) => {
  cart.value = [...cart.value, item]
}

const removeFromCart = (itemId) => {
  cart.value = cart.value.filter(item => item.id !== itemId)
}

// Cart syncs between tabs automatically
```

### Recently Viewed Tracking

```javascript
const recentlyViewed = useCookieRef<number[]>('recently-viewed', [], {
  expires: 30
})

const addToRecent = (productId) => {
  const recent = [productId, ...recentlyViewed.value.filter(id => id !== productId)]
  recentlyViewed.value = recent.slice(0, 10) // Keep last 10
}
```

## Broadcast Channel Synchronization Benefits

**Unlike regular ref with cookie:**
- ✅ Instant cross-tab synchronization (no reload required)
- ✅ Real-time updates (no delays)
- ✅ Efficient data transmission (not via localStorage)
- ✅ Browser session isolation

**How it works:**
1. Change in one tab → saved to cookie
2. Via Broadcast Channel (`__cookie:${name}`) message is sent
3. All other tabs receive update instantly
4. Ref in all tabs updates automatically
