# Halo Widgets - Vue Guide

A complete guide for using Halo Widgets in Vue applications.

---

## 📦 Installation

### Using npm
```bash
npm install halo-widgets
```

### Using yarn
```bash
yarn add halo-widgets
```

### Using pnpm
```bash
pnpm add halo-widgets
```

---

## 🚀 Quick Start

### 1. Import CSS Styles

In your main entry file (`main.ts`), import the widget styles:

```typescript
import 'halo-widgets/dist/base.css';
```

**Complete example (`main.ts`):**
```typescript
import { createApp } from 'vue'
import './style.css'
import 'halo-widgets/dist/base.css'  // ← Import widget styles
import App from './App.vue'

createApp(App).mount('#app')
```

### 2. Import Widgets

Import the widgets you need from `halo-widgets/vue`:

```typescript
import { TextInput, PasswordInput, EmailInput } from "halo-widgets/vue";
```

### 3. Use in Components

```vue
<template>
  <TextInput
    label="Username"
    placeholder="Enter your username"
    v-model="username"
    :required="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput } from 'halo-widgets/vue'

const username = ref('')
</script>
```

---

## 📚 Available Widgets

All widgets are imported from `halo-widgets/vue`:

```typescript
import {
  TextInput,        // Text input with validation & suggestions
  PasswordInput,    // Password with strength meter & generator
  EmailInput,       // Email with domain suggestions
  PhoneInput,       // International phone with country picker
  DateInput,        // Date picker (single, range, month)
  LocationInput,    // Google Places autocomplete
  NumberInput,      // Numeric input with formatting
  SliderInput,      // Range slider
  RadioInput,       // Radio button group
  CheckboxInput,    // Checkbox group (single or multi-select)
  DropdownInput,    // Searchable dropdown
  TextareaInput,    // Multi-line text input
} from "halo-widgets/vue";
```

---

## 💡 Complete Examples

### TextInput - Basic Usage

```vue
<template>
  <TextInput
    label="Username"
    placeholder="Enter your username"
    helperText="3-20 characters, lowercase only"
    v-model="username"
    :required="true"
    :minLength="3"
    :maxLength="20"
    :counter="true"
    :clearable="true"
    :allowSpaces="false"
    caseTransform="lowercase"
    @validate="handleValidation"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput } from 'halo-widgets/vue'

const username = ref('')

const handleValidation = (isValid: boolean, error: string) => {
  console.log('Valid:', isValid, error)
}
</script>
```

### PasswordInput - With Strength Meter

```vue
<template>
  <PasswordInput
    label="Password"
    placeholder="Enter a strong password"
    helperText="At least 8 characters with uppercase, lowercase, number, and symbol"
    v-model="password"
    :required="true"
    :minLength="8"
    :showToggle="true"
    :showStrength="true"
    :showRequirements="true"
    :showGenerator="true"
    :showCopy="false"
    :requireLowercase="true"
    :requireUppercase="true"
    :requireNumber="true"
    :requireSymbol="true"
    @strengthChange="handleStrengthChange"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { PasswordInput } from 'halo-widgets/vue'

const password = ref('')

const handleStrengthChange = (score: number, label: string) => {
  console.log('Password strength:', label, 'Score:', score)
}
</script>
```

### EmailInput - With Domain Suggestions

```vue
<template>
  <EmailInput
    label="Email Address"
    placeholder="you@example.com"
    helperText="We'll never share your email"
    v-model="email"
    :required="true"
    :showDomainSuggestions="true"
    :showGravatar="true"
    :lowercase="true"
    :trim="true"
    :clearable="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { EmailInput } from 'halo-widgets/vue'

const email = ref('')
</script>
```

### PhoneInput - International

```vue
<template>
  <PhoneInput
    label="Phone Number"
    placeholder="Enter phone number"
    helperText="International format"
    v-model="phone"
    :required="true"
    :allowCountrySelect="true"
    country="US"
    format="international"
    :separateDialCode="true"
    :clearable="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { PhoneInput } from 'halo-widgets/vue'

const phone = ref('')
</script>
```

### DateInput - Single & Range

```vue
<template>
  <!-- Single Date -->
  <DateInput
    label="Select Date"
    placeholder="Pick a date"
    v-model="date"
    mode="single"
    format="MM/DD/YYYY"
    :clearable="true"
  />

  <!-- Date Range -->
  <DateInput
    label="Select Date Range"
    placeholder="Pick start and end dates"
    v-model="dateRange"
    mode="range"
    format="MM/DD/YYYY"
    :clearable="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { DateInput } from 'halo-widgets/vue'

const date = ref('')
const dateRange = ref<[string, string]>(['', ''])
</script>
```

### LocationInput - Google Places

```vue
<template>
  <LocationInput
    label="Location"
    placeholder="Search for a location"
    helperText="Start typing to search"
    v-model="location"
    apiKey="YOUR_GOOGLE_MAPS_API_KEY"
    :allowCoordinates="true"
    :countryCodes="['US', 'CA']"
    :clearable="true"
    @change="handleLocationChange"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { LocationInput } from 'halo-widgets/vue'

const location = ref('')

const handleLocationChange = (val: any) => {
  location.value = val.label
  console.log('Full location data:', val)
}
</script>
```

### NumberInput - Currency & Percentage

```vue
<template>
  <!-- Currency -->
  <NumberInput
    label="Price"
    placeholder="0.00"
    v-model="price"
    prefix="$"
    :precision="2"
    :min="0"
    :thousandSeparator="true"
  />

  <!-- Percentage -->
  <NumberInput
    label="Discount"
    v-model="percentage"
    suffix="%"
    :min="0"
    :max="100"
    :precision="0"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { NumberInput } from 'halo-widgets/vue'

const price = ref(0)
const percentage = ref(50)
</script>
```

### SliderInput - Volume & Range

```vue
<template>
  <!-- Single Value -->
  <SliderInput
    label="Volume"
    v-model="volume"
    :min="0"
    :max="100"
    suffix="%"
    :showValueBubble="true"
  />

  <!-- Range -->
  <SliderInput
    label="Price Range"
    v-model="priceRange"
    mode="range"
    :min="0"
    :max="100"
    prefix="$"
    :showValueBubble="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { SliderInput } from 'halo-widgets/vue'

const volume = ref(50)
const priceRange = ref<[number, number]>([20, 80])
</script>
```

### RadioInput - Single Selection

```vue
<template>
  <RadioInput
    label="Choose a Plan"
    helperText="Select your subscription tier"
    :options="planOptions"
    v-model="plan"
    :required="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { RadioInput } from 'halo-widgets/vue'

const plan = ref('basic')

const planOptions = [
  { label: 'Basic - $9/mo', value: 'basic' },
  { label: 'Pro - $29/mo', value: 'pro' },
  { label: 'Enterprise - $99/mo', value: 'enterprise' },
]
</script>
```

### CheckboxInput - Multi-Select

```vue
<template>
  <CheckboxInput
    label="Select Your Interests"
    helperText="Choose at least one"
    :options="interestOptions"
    v-model="interests"
    :required="true"
    :minSelected="1"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { CheckboxInput } from 'halo-widgets/vue'

const interests = ref<string[]>([])

const interestOptions = [
  { label: 'AI & Machine Learning', value: 'ai' },
  { label: 'Web Development', value: 'web' },
  { label: 'Mobile Apps', value: 'mobile' },
  { label: 'Data Science', value: 'data' },
  { label: 'DevOps', value: 'devops' },
]
</script>
```

### DropdownInput - Searchable

```vue
<template>
  <!-- Single Select -->
  <DropdownInput
    label="Select Country"
    placeholder="Choose a country..."
    :options="countryOptions"
    v-model="country"
    :searchable="true"
    :clearable="true"
    :required="true"
  />

  <!-- Multi-Select -->
  <DropdownInput
    label="Select Countries"
    placeholder="Choose multiple countries..."
    :options="countryOptions"
    v-model="countries"
    :multiple="true"
    :searchable="true"
    :maxSelected="3"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { DropdownInput } from 'halo-widgets/vue'

const country = ref('us')
const countries = ref<string[]>([])

const countryOptions = [
  { label: 'United States', value: 'us' },
  { label: 'Canada', value: 'ca' },
  { label: 'United Kingdom', value: 'uk' },
  { label: 'Germany', value: 'de' },
  { label: 'France', value: 'fr' },
]
</script>
```

### TextareaInput - Multi-Line

```vue
<template>
  <TextareaInput
    label="Description"
    placeholder="Tell us about your project..."
    helperText="Minimum 20 characters"
    v-model="description"
    :required="true"
    :minLength="20"
    :maxLength="500"
    :rows="4"
    :autoGrow="true"
    :counter="true"
    :clearable="true"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextareaInput } from 'halo-widgets/vue'

const description = ref('')
</script>
```

---

## 🎨 Styling & Theming

### Using CSS Variables

Customize widget appearance with CSS variables:

```css
:root {
  --halo-color-primary: #6366f1;
  --halo-color-accent: #8b5cf6;
  --halo-color-surface: #ffffff;
  --halo-color-bg: #f9fafb;
  --halo-color-text: #111827;
  --halo-color-muted: #6b7280;
  --halo-color-border: #e5e7eb;
  --halo-color-error: #ef4444;
  --halo-color-success: #10b981;
  --halo-color-warning: #f59e0b;
  --halo-font-family: system-ui, -apple-system, sans-serif;
  --halo-radius: 8px;
  --halo-border: 1px solid var(--halo-color-border);
}
```

### Using class Prop

Add custom styles to any widget:

```vue
<template>
  <TextInput
    class="my-custom-input"
    label="Username"
    v-model="username"
  />
</template>

<style scoped>
.my-custom-input {
  max-width: 400px;
  margin-bottom: 1rem;
}
</style>
```

### Size Variants

Most widgets support size variants:

```vue
<template>
  <TextInput size="sm" label="Small" />
  <TextInput size="md" label="Medium (default)" />
  <TextInput size="lg" label="Large" />
</template>
```

### Style Variants

Some widgets support style variants:

```vue
<template>
  <TextInput variant="outlined" label="Outlined (default)" />
  <TextInput variant="filled" label="Filled" />
</template>
```

---

## 🎯 TypeScript Support

All widgets are fully typed. Import types for better IDE support:

```typescript
import { 
  TextInput, 
  type TextInputProps 
} from "halo-widgets/vue";

// Use in your component props
interface MyFormProps {
  textInputProps?: Partial<TextInputProps>;
}

// In your component
const props = defineProps<MyFormProps>();
```

### Available Types

```typescript
import type {
  TextInputProps,
  PasswordInputProps,
  EmailInputProps,
  PhoneInputProps,
  DateInputProps,
  LocationInputProps,
  NumberInputProps,
  SliderInputProps,
  RadioInputProps,
  CheckboxInputProps,
  DropdownInputProps,
  TextareaInputProps,
} from "halo-widgets/vue";
```

---

## 🔧 Common Patterns

### Form with Multiple Widgets

```vue
<template>
  <form @submit.prevent="handleSubmit">
    <TextInput
      label="Username"
      v-model="formData.username"
      :required="true"
    />

    <EmailInput
      label="Email"
      v-model="formData.email"
      :required="true"
    />

    <PasswordInput
      label="Password"
      v-model="formData.password"
      :required="true"
      :showStrength="true"
    />

    <CheckboxInput
      label="Interests"
      :options="interestOptions"
      v-model="formData.interests"
    />

    <button type="submit">Submit</button>
  </form>
</template>

<script setup lang="ts">
import { reactive } from 'vue'
import { 
  TextInput, 
  EmailInput, 
  PasswordInput, 
  CheckboxInput 
} from 'halo-widgets/vue'

const formData = reactive({
  username: '',
  email: '',
  password: '',
  interests: [] as string[],
})

const interestOptions = [
  { label: 'Web Dev', value: 'web' },
  { label: 'Mobile', value: 'mobile' },
]

const handleSubmit = () => {
  console.log('Form submitted:', formData)
}
</script>
```

### Validation Handling

```vue
<template>
  <TextInput
    label="Username"
    v-model="value"
    :minLength="3"
    :maxLength="20"
    pattern="^[a-zA-Z0-9_]+$"
    @validate="handleValidation"
    :invalid="!isValid"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput } from 'halo-widgets/vue'

const value = ref('')
const isValid = ref(true)
const error = ref('')

const handleValidation = (valid: boolean, errorMsg: string) => {
  isValid.value = valid
  error.value = errorMsg
}
</script>
```

### Controlled vs Uncontrolled

```vue
<template>
  <!-- Controlled (recommended) -->
  <TextInput
    v-model="value"
    label="Controlled Input"
  />

  <!-- Uncontrolled -->
  <TextInput
    :defaultValue="'initial value'"
    @change="handleChange"
    label="Uncontrolled Input"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput } from 'halo-widgets/vue'

const value = ref('')

const handleChange = (val: string) => {
  console.log('Value:', val)
}
</script>
```

### Debounced API Calls

```vue
<template>
  <TextInput
    label="Search"
    placeholder="Type to search..."
    v-model="query"
    :debounceMs="500"
    @change="handleSearch"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput } from 'halo-widgets/vue'

const query = ref('')

const handleSearch = (value: string) => {
  console.log('Searching for:', value)
}
</script>
```

---

## ⚙️ Advanced Usage

### API-Based Suggestions

```vue
<template>
  <TextInput
    label="Search Words"
    placeholder="Type to get suggestions..."
    suggestionsSource="api"
    suggestionsApi="https://api.datamuse.com/sug?s="
    :minCharsForSuggestions="2"
    :debounceMs="300"
  />
</template>

<script setup lang="ts">
import { TextInput } from 'halo-widgets/vue'
</script>
```

### Custom Validation

```vue
<template>
  <TextInput
    label="Username"
    :validate="validateUsername"
    validateOn="change"
  />
</template>

<script setup lang="ts">
import { TextInput } from 'halo-widgets/vue'

const validateUsername = (value: string): string | null => {
  if (value.includes('admin')) {
    return "Username cannot contain 'admin'"
  }
  if (value.length < 3) {
    return 'Username must be at least 3 characters'
  }
  return null // null means valid
}
</script>
```

### Password with Breach Check

```vue
<template>
  <PasswordInput
    label="Password"
    :checkPwned="true"
    :minLengthForPwned="8"
    :showRequirements="true"
    :requireLowercase="true"
    :requireUppercase="true"
    :requireNumber="true"
    :requireSymbol="true"
  />
</template>

<script setup lang="ts">
import { PasswordInput } from 'halo-widgets/vue'
</script>
```

---

## 🐛 Troubleshooting

### Styles Not Applied

**Problem:** Widgets appear unstyled

**Solution:** Make sure you imported the CSS:
```typescript
import 'halo-widgets/dist/base.css'
```

### TypeScript Errors

**Problem:** Type errors on props

**Solution:** Check the prop names in `PROPS_REFERENCE.md`. Common mistakes:
- ❌ `showCounter` → ✅ `counter`
- ❌ `showCopyButton` → ✅ `showCopy`
- ❌ `showVisibilityToggle` → ✅ `showToggle`

### Widget Losing Focus

**Problem:** Input loses focus after each keystroke

**Solution:** This was a bug in v1.0.5 and earlier. Make sure you're using the latest version or the fixed local package.

### LocationInput Not Working

**Problem:** LocationInput doesn't show suggestions

**Solution:** You need a valid Google Maps API key:
```vue
<LocationInput apiKey="YOUR_ACTUAL_API_KEY" />
```

---

## 📋 Requirements

- Vue 3.0.0 or higher
- TypeScript 5.0+ (optional, but recommended)

---

## 🔗 Additional Resources

- **Props Reference:** See `PROPS_REFERENCE.md` for complete prop documentation
- **Examples:** Check `src/App.vue` for working examples
- **Package Version:** v1.0.9

---

## 💪 Best Practices

1. **Always import CSS** in your main entry file
2. **Use v-model** for two-way data binding
3. **Validate user input** using built-in validation props
4. **Handle null values** for NumberInput onChange
5. **Type check arrays** for EmailInput with multiple emails
6. **Use TypeScript types** for better IDE support
7. **Debounce API calls** to reduce server load
8. **Provide helper text** to guide users
9. **Mark required fields** with `:required="true"`
10. **Test validation** with `@validate` callback

---

## 🎉 Quick Start Template

Copy this template to get started quickly:

```vue
<template>
  <form @submit.prevent="handleSubmit">
    <TextInput
      label="Username"
      placeholder="Enter username"
      v-model="username"
      :required="true"
      :minLength="3"
      :maxLength="20"
      :counter="true"
    />

    <EmailInput
      label="Email"
      placeholder="you@example.com"
      v-model="email"
      :required="true"
      :showDomainSuggestions="true"
    />

    <PasswordInput
      label="Password"
      placeholder="Enter password"
      v-model="password"
      :required="true"
      :minLength="8"
      :showStrength="true"
      :showToggle="true"
    />

    <button type="submit">Submit</button>
  </form>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { TextInput, EmailInput, PasswordInput } from 'halo-widgets/vue'

const username = ref('')
const email = ref('')
const password = ref('')

const handleSubmit = () => {
  console.log({ username: username.value, email: email.value, password: password.value })
}
</script>
```

---

**Happy coding with Halo Widgets! 🚀**