Maz-UI v4 - Vue & Nuxt Component Library Maz-UI is a comprehensive, standalone component library for Vue 3 and Nuxt 3 applications, offering 50+ production-ready components, powerful theming, internationalization, and exceptional developer experience. Latest Version : 4.3.3 (as of 2025-12-29) Package : | | | | Quick Start Vue 3 Installation Setup in : Use Components : Nuxt 3 Installation Setup in : Use Components (no imports needed): Core Capabilities 🎨 Components (50+) Forms & Inputs : - - Text input with validation states - - Dropdown select - - Multi-line text input - - Checkbox with labe…

) | `''` |\n\n### Auto-Color Behavior\n\nWhen `autoColor` is enabled:\n- **0-49%** → `destructive` (red)\n- **50-99%** → `warning` (orange)\n- **100%** → `success` (green)\n\n### Examples\n\n**Different Sizes**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"flex gap-4\">\n \u003cMazCircularProgressBar :percentage=\"75\" size=\"3em\" />\n \u003cMazCircularProgressBar :percentage=\"75\" size=\"100px\" />\n \u003cMazCircularProgressBar :percentage=\"75\" size=\"10rem\" />\n \u003cMazCircularProgressBar :percentage=\"75\" size=\"15rem\" />\n \u003c/div>\n\u003c/template>\n```\n\n**Custom Duration**:\n```vue\n\u003ctemplate>\n \u003c!-- Slow animation over 5 seconds -->\n \u003cMazCircularProgressBar\n :percentage=\"100\"\n :duration=\"5000\"\n />\n\u003c/template>\n```\n\n**Different Colors**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"flex gap-4\">\n \u003cMazCircularProgressBar :percentage=\"75\" color=\"primary\" />\n \u003cMazCircularProgressBar :percentage=\"75\" color=\"secondary\" />\n \u003cMazCircularProgressBar :percentage=\"75\" color=\"success\" />\n \u003cMazCircularProgressBar :percentage=\"75\" color=\"warning\" />\n \u003cMazCircularProgressBar :percentage=\"75\" color=\"destructive\" />\n \u003c/div>\n\u003c/template>\n```\n\n**Auto-Color Mode**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"flex gap-4\">\n \u003cMazCircularProgressBar :percentage=\"0\" auto-color /> \u003c!-- Red -->\n \u003cMazCircularProgressBar :percentage=\"25\" auto-color /> \u003c!-- Red -->\n \u003cMazCircularProgressBar :percentage=\"50\" auto-color /> \u003c!-- Orange -->\n \u003cMazCircularProgressBar :percentage=\"100\" auto-color /> \u003c!-- Green -->\n \u003c/div>\n\u003c/template>\n```\n\n**Custom Slot Content**:\n```vue\n\u003ctemplate>\n \u003cMazCircularProgressBar :percentage=\"50\">\n 2/4\n \u003c/MazCircularProgressBar>\n\n \u003cMazCircularProgressBar :percentage=\"75\">\n \u003cMazIcon name=\"check\" />\n \u003c/MazCircularProgressBar>\n\u003c/template>\n```\n\n---\n\n## MazReadingProgressBar\n\nReading progress indicator for articles and long-form content.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazReadingProgressBar from 'maz-ui/components/MazReadingProgressBar'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazReadingProgressBar color=\"primary\" position=\"top\" />\n\n \u003carticle>\n \u003c!-- Long article content -->\n \u003c/article>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive'` | Bar color | `'primary'` |\n| `height` | `string` | Bar height | `'4px'` |\n| `position` | `'top' \\| 'bottom'` | Bar position | `'top'` |\n| `target` | `string` | Target element selector | `'body'` |\n\n### Examples\n\n**Article Progress**:\n```vue\n\u003ctemplate>\n \u003cdiv>\n \u003cMazReadingProgressBar\n color=\"success\"\n position=\"top\"\n height=\"6px\"\n target=\"#article-content\"\n />\n\n \u003cdiv id=\"article-content\">\n \u003ch1>Article Title\u003c/h1>\n \u003cp>Long article content...\u003c/p>\n \u003c!-- More content -->\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**Custom Target Element**:\n```vue\n\u003ctemplate>\n \u003cdiv>\n \u003cMazReadingProgressBar target=\".content-wrapper\" />\n\n \u003cdiv class=\"content-wrapper\">\n \u003c!-- Target content -->\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## MazAnimatedText\n\nAnimated text effects with various animation styles.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazAnimatedText from 'maz-ui/components/MazAnimatedText'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"fade-in\">\n Welcome to Maz-UI\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `animation` | `'fade-in' \\| 'slide-up' \\| 'slide-down' \\| 'zoom-in' \\| 'type'` | Animation type | `'fade-in'` |\n| `duration` | `number` | Animation duration (ms) | `600` |\n| `delay` | `number` | Animation delay (ms) | `0` |\n| `once` | `boolean` | Animate only once | `true` |\n\n### Animation Types\n\n**fade-in**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"fade-in\">\n Fade in animation\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n**slide-up**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"slide-up\">\n Slide up from bottom\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n**zoom-in**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"zoom-in\" :duration=\"1000\">\n Zoom in effect\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n**type** (typewriter effect):\n```vue\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"type\" :duration=\"2000\">\n Typewriter effect...\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n### Examples\n\n**Delayed Animation**:\n```vue\n\u003ctemplate>\n \u003cdiv>\n \u003cMazAnimatedText animation=\"slide-up\" :delay=\"0\">\n First line\n \u003c/MazAnimatedText>\n \u003cMazAnimatedText animation=\"slide-up\" :delay=\"200\">\n Second line (200ms delay)\n \u003c/MazAnimatedText>\n \u003cMazAnimatedText animation=\"slide-up\" :delay=\"400\">\n Third line (400ms delay)\n \u003c/MazAnimatedText>\n \u003c/div>\n\u003c/template>\n```\n\n**Repeating Animation**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedText animation=\"fade-in\" :once=\"false\">\n This animates every time it enters viewport\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n---\n\n## MazAnimatedElement\n\nGeneric element animation wrapper with scroll-triggered animations.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazAnimatedElement from 'maz-ui/components/MazAnimatedElement'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAnimatedElement animation=\"fade-up\">\n \u003cMazCard>\n \u003ch2>Animated Card\u003c/h2>\n \u003cp>This card animates when scrolled into view\u003c/p>\n \u003c/MazCard>\n \u003c/MazAnimatedElement>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `animation` | `string` | Animation name (AOS-compatible) | `'fade-up'` |\n| `duration` | `number` | Animation duration (ms) | `600` |\n| `delay` | `number` | Animation delay (ms) | `0` |\n| `once` | `boolean` | Animate only once | `true` |\n| `offset` | `number` | Trigger offset (px) | `120` |\n\n### Animation Names\n\nAll AOS animations are supported:\n- **Fade**: `fade-up`, `fade-down`, `fade-left`, `fade-right`\n- **Zoom**: `zoom-in`, `zoom-out`, `zoom-in-up`, `zoom-in-down`\n- **Slide**: `slide-up`, `slide-down`, `slide-left`, `slide-right`\n- **Flip**: `flip-left`, `flip-right`, `flip-up`, `flip-down`\n\n### Examples\n\n**Card Grid Animation**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"grid grid-cols-3 gap-4\">\n \u003cMazAnimatedElement\n v-for=\"(item, i) in items\"\n :key=\"item.id\"\n animation=\"fade-up\"\n :delay=\"i * 100\"\n >\n \u003cMazCard>\n {{ item.title }}\n \u003c/MazCard>\n \u003c/MazAnimatedElement>\n \u003c/div>\n\u003c/template>\n```\n\n**Different Animations**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedElement animation=\"zoom-in\">\n \u003cdiv>Zooms in\u003c/div>\n \u003c/MazAnimatedElement>\n\n \u003cMazAnimatedElement animation=\"slide-left\">\n \u003cdiv>Slides from right\u003c/div>\n \u003c/MazAnimatedElement>\n\n \u003cMazAnimatedElement animation=\"flip-up\">\n \u003cdiv>Flips up\u003c/div>\n \u003c/MazAnimatedElement>\n\u003c/template>\n```\n\n---\n\n## MazAnimatedCounter\n\nAnimated number counter with prefix/suffix support.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazAnimatedCounter from 'maz-ui/components/MazAnimatedCounter'\n\nconst count = ref(1000)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAnimatedCounter :count=\"count\" />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `count` | `number` | Target number to count to | `0` |\n| `duration` | `number` | Animation duration (ms) | `1000` |\n| `prefix` | `string` | Prefix text (e.g., '

Maz-UI v4 - Vue & Nuxt Component Library Maz-UI is a comprehensive, standalone component library for Vue 3 and Nuxt 3 applications, offering 50+ production-ready components, powerful theming, internationalization, and exceptional developer experience. Latest Version : 4.3.3 (as of 2025-12-29) Package : | | | | Quick Start Vue 3 Installation Setup in : Use Components : Nuxt 3 Installation Setup in : Use Components (no imports needed): Core Capabilities 🎨 Components (50+) Forms & Inputs : - - Text input with validation states - - Dropdown select - - Multi-line text input - - Checkbox with labe…

) | `''` |\n| `suffix` | `string` | Suffix text (e.g., '%') | `''` |\n| `decimals` | `number` | Decimal places | `0` |\n\n### Slots\n\n| Slot | Description |\n|------|-------------|\n| `prefix` | Custom prefix content |\n| `suffix` | Custom suffix content |\n\n### Examples\n\n**Currency Counter**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedCounter :count=\"2999.99\" prefix=\"$\" :decimals=\"2\" />\n \u003c!-- Output: $2,999.99 -->\n\u003c/template>\n```\n\n**Percentage Counter**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedCounter :count=\"75\" suffix=\"%\" />\n \u003c!-- Output: 75% -->\n\u003c/template>\n```\n\n**Custom Duration**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedCounter\n :count=\"10000\"\n :duration=\"5000\"\n prefix=\"$\"\n />\n \u003c!-- Counts to $10,000 over 5 seconds -->\n\u003c/template>\n```\n\n**Prefix/Suffix Slots**:\n```vue\n\u003ctemplate>\n \u003cMazAnimatedCounter :count=\"20\">\n \u003ctemplate #prefix>\n \u003cMazIcon name=\"dollar\" class=\"mr-1\" />\n \u003c/template>\n \u003ctemplate #suffix>\n \u003cspan class=\"ml-1 text-sm\">USD\u003c/span>\n \u003c/template>\n \u003c/MazAnimatedCounter>\n\u003c/template>\n```\n\n**Reactive Counter**:\n```vue\n\u003cscript setup>\nimport { ref, onMounted } from 'vue'\n\nconst count = ref(0)\n\nonMounted(() => {\n // Update counter every 3 seconds\n setInterval(() => {\n count.value = Math.floor(Math.random() * 10000)\n }, 3000)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAnimatedCounter :count=\"count\" prefix=\"$\" />\n\u003c/template>\n```\n\n---\n\n## MazCardSpotlight\n\nInteractive card with animated spotlight effect that follows cursor.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazCardSpotlight from 'maz-ui/components/MazCardSpotlight'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCardSpotlight>\n \u003ch3>Spotlight Card\u003c/h3>\n \u003cp>Hover to see the spotlight effect\u003c/p>\n \u003c/MazCardSpotlight>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `color` | `string` | Spotlight color (CSS color) | `'rgba(255,255,255,0.1)'` |\n| `intensity` | `number` | Spotlight intensity (0-1) | `0.3` |\n| `size` | `number` | Spotlight size (px) | `300` |\n| `disabled` | `boolean` | Disable spotlight effect | `false` |\n\n### Examples\n\n**Custom Spotlight Color**:\n```vue\n\u003ctemplate>\n \u003cMazCardSpotlight color=\"rgba(59, 130, 246, 0.2)\">\n \u003ch3>Blue Spotlight\u003c/h3>\n \u003cp>Custom blue spotlight effect\u003c/p>\n \u003c/MazCardSpotlight>\n\u003c/template>\n```\n\n**Intense Spotlight**:\n```vue\n\u003ctemplate>\n \u003cMazCardSpotlight :intensity=\"0.8\" :size=\"500\">\n \u003ch3>Intense Effect\u003c/h3>\n \u003cp>Larger, more intense spotlight\u003c/p>\n \u003c/MazCardSpotlight>\n\u003c/template>\n```\n\n**Conditional Spotlight**:\n```vue\n\u003cscript setup>\nconst isPremium = ref(true)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCardSpotlight :disabled=\"!isPremium\">\n \u003ch3>{{ isPremium ? 'Premium' : 'Basic' }} Card\u003c/h3>\n \u003cp>Spotlight only for premium users\u003c/p>\n \u003c/MazCardSpotlight>\n\u003c/template>\n```\n\n**Card Grid with Spotlights**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"grid grid-cols-3 gap-4\">\n \u003cMazCardSpotlight\n v-for=\"product in products\"\n :key=\"product.id\"\n color=\"rgba(16, 185, 129, 0.15)\"\n >\n \u003ch4>{{ product.name }}\u003c/h4>\n \u003cp>{{ product.price }}\u003c/p>\n \u003cMazBtn color=\"success\">Buy Now\u003c/MazBtn>\n \u003c/MazCardSpotlight>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Best Practices\n\n### Loading States\n\n**DO**:\n- Use `MazFullscreenLoader` for critical operations that block user interaction\n- Use `MazLoadingBar` for page/route transitions\n- Use `MazCircularProgressBar` to show determinate progress\n- Provide meaningful loading messages\n\n**DON'T**:\n- Use fullscreen loader for minor operations\n- Show multiple loading indicators simultaneously\n- Leave users without feedback during long operations\n\n```vue\n\u003c!-- ✅ Good: Clear loading state with message -->\n\u003cMazFullscreenLoader v-if=\"isProcessing\">\n \u003cMazCircularProgressBar :percentage=\"progress\" />\n \u003cp class=\"mt-2\">Processing {{ currentFile }} ({{ progress }}%)\u003c/p>\n\u003c/MazFullscreenLoader>\n\n\u003c!-- ❌ Bad: No context or progress indication -->\n\u003cMazFullscreenLoader v-if=\"isProcessing\" />\n```\n\n### Progress Indicators\n\n**DO**:\n- Use `auto-color` for intuitive progress feedback\n- Show percentage when possible\n- Animate progress smoothly\n- Update progress in real-time\n\n**DON'T**:\n- Show fake progress without actual data\n- Use indeterminate progress for long operations\n- Forget to handle 100% completion state\n\n```vue\n\u003c!-- ✅ Good: Real progress with auto-color -->\n\u003cMazCircularProgressBar\n :percentage=\"uploadProgress\"\n auto-color\n suffix=\"%\"\n/>\n\n\u003c!-- ❌ Bad: Static fake progress -->\n\u003cMazCircularProgressBar :percentage=\"50\" />\n```\n\n### Animations\n\n**DO**:\n- Use subtle animations for better UX\n- Set appropriate animation durations (300-600ms)\n- Use `once: true` for performance\n- Match animation style to content\n\n**DON'T**:\n- Over-animate every element\n- Use very long animations (>2s)\n- Animate critical content on every scroll\n\n```vue\n\u003c!-- ✅ Good: Subtle, performant animations -->\n\u003cMazAnimatedElement\n v-for=\"item in items\"\n :key=\"item.id\"\n animation=\"fade-up\"\n :duration=\"400\"\n once\n>\n \u003cMazCard>{{ item.title }}\u003c/MazCard>\n\u003c/MazAnimatedElement>\n\n\u003c!-- ❌ Bad: Excessive animation -->\n\u003cMazAnimatedElement\n animation=\"flip-left\"\n :duration=\"3000\"\n :once=\"false\"\n>\n \u003cp>Critical navigation content\u003c/p>\n\u003c/MazAnimatedElement>\n```\n\n---\n\n## Accessibility\n\n### Screen Readers\n\nAll feedback components include proper ARIA attributes:\n\n```vue\n\u003c!-- Fullscreen loader with ARIA -->\n\u003cMazFullscreenLoader\n v-if=\"isLoading\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Loading content\"\n>\n \u003cp>Loading...\u003c/p>\n\u003c/MazFullscreenLoader>\n\n\u003c!-- Progress bar with ARIA -->\n\u003cMazCircularProgressBar\n :percentage=\"75\"\n role=\"progressbar\"\n :aria-valuenow=\"75\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-label=\"Upload progress\"\n/>\n```\n\n### Reduced Motion\n\nRespect user's motion preferences:\n\n```vue\n\u003cscript setup>\nimport { ref, computed, onMounted } from 'vue'\n\nconst prefersReducedMotion = ref(false)\n\n// ✅ Client-only: Access window after mount\nonMounted(() => {\n prefersReducedMotion.value = window.matchMedia('(prefers-reduced-motion: reduce)').matches\n})\n\nconst animationDuration = computed(() =>\n prefersReducedMotion.value ? 0 : 600\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAnimatedText :duration=\"animationDuration\">\n Respects motion preferences\n \u003c/MazAnimatedText>\n\u003c/template>\n```\n\n---\n\n## SSR Compatibility\n\nAll feedback components are SSR-safe:\n\n```vue\n\u003c!-- Nuxt 3 - Works automatically -->\n\u003ctemplate>\n \u003cdiv>\n \u003cMazFullscreenLoader v-if=\"isLoading\" />\n \u003cMazAnimatedElement animation=\"fade-up\">\n \u003cMazCard>SSR-safe content\u003c/MazCard>\n \u003c/MazAnimatedElement>\n \u003c/div>\n\u003c/template>\n```\n\n**Hydration Notes**:\n- Animations trigger after hydration completes\n- Progress states sync correctly server → client\n- No layout shift issues with loaders\n\n---\n\n## Related Documentation\n\n- **[Components Forms](./components-forms.md)** - Form input components\n- **[Components Navigation](./components-navigation.md)** - Navigation components\n- **[Components Layout](./components-layout.md)** - Layout and container components\n- **[Composables Reference](./composables.md)** - useWait, useAos composables\n- **[Plugins Reference](./plugins.md)** - AOS plugin for scroll animations\n\n---\n\n**Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-14\n**Component Count**: 8 feedback & animation components\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":19565,"content_sha256":"0096e0299579ba91434ad8e9c069b54e250f35a5308e6850d457f172ba7da9a5"},{"filename":"references/components-forms.md","content":"# Maz-UI Form Components\n\nComprehensive guide to all form-related components in Maz-UI.\n\n## MazInput\n\nVersatile text input component with validation states and icons.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst name = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"name\"\n label=\"Full Name\"\n placeholder=\"Enter your name\"\n required\n />\n\u003c/template>\n```\n\n**With Validation States**:\n```vue\n\u003ctemplate>\n \u003c!-- Success state -->\n \u003cMazInput v-model=\"email\" label=\"Email\" success />\n\n \u003c!-- Warning state -->\n \u003cMazInput v-model=\"username\" label=\"Username\" warning />\n\n \u003c!-- Error state -->\n \u003cMazInput v-model=\"password\" label=\"Password\" error hint=\"Password too weak\" />\n\u003c/template>\n```\n\n**With Icons**:\n```vue\n\u003ctemplate>\n \u003cMazInput\n v-model=\"email\"\n label=\"Email\"\n left-icon=\"envelope\"\n right-icon=\"check\"\n />\n\u003c/template>\n```\n\n**Props**: label, placeholder, type, disabled, required, error, warning, success, hint, assistive-text, top-label, left-icon, right-icon, debounce, size, color, rounded-size\n\n## MazInputPhoneNumber\n\nInternational phone number input with country detection and validation.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\n\nconst phoneNumber = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInputPhoneNumber\n v-model=\"phoneNumber\"\n default-country-code=\"US\"\n :preferred-countries=\"['US', 'CA', 'GB']\"\n @update=\"handlePhoneUpdate\"\n />\n\u003c/template>\n```\n\n**With Full Validation**:\n```vue\n\u003cscript setup>\nconst phone = ref('')\nconst isValid = ref(false)\n\nfunction handleUpdate(payload) {\n isValid.value = payload.isValid\n console.log('Country:', payload.countryCode)\n console.log('E164:', payload.e164)\n console.log('National:', payload.nationalNumber)\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInputPhoneNumber\n v-model=\"phone\"\n default-country-code=\"US\"\n show-code-on-list\n :success=\"isValid\"\n @update=\"handleUpdate\"\n />\n\u003c/template>\n```\n\n**Required Dependency**:\n```bash\npnpm add libphonenumber-js\n```\n\n## MazSelect\n\nDropdown select component with search and multiple selection.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst selected = ref(null)\nconst options = [\n { label: 'Option 1', value: 1 },\n { label: 'Option 2', value: 2 },\n { label: 'Option 3', value: 3 }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSelect\n v-model=\"selected\"\n :options=\"options\"\n label=\"Choose option\"\n placeholder=\"Select one\"\n />\n\u003c/template>\n```\n\n**With Search**:\n```vue\n\u003ctemplate>\n \u003cMazSelect\n v-model=\"selected\"\n :options=\"options\"\n label=\"Country\"\n search\n searchPlaceholder=\"Search countries...\"\n />\n\u003c/template>\n```\n\n**Multiple Selection**:\n```vue\n\u003cscript setup>\nconst selectedItems = ref([])\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSelect\n v-model=\"selectedItems\"\n :options=\"options\"\n label=\"Select multiple\"\n multiple\n />\n\u003c/template>\n```\n\n## MazCheckbox\n\nCheckbox component with label and indeterminate state.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst agree = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCheckbox v-model=\"agree\" label=\"I agree to terms\" />\n\u003c/template>\n```\n\n**Indeterminate State**:\n```vue\n\u003cscript setup>\nconst allSelected = ref(false)\nconst indeterminate = ref(true)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCheckbox\n v-model=\"allSelected\"\n :indeterminate=\"indeterminate\"\n label=\"Select All\"\n />\n\u003c/template>\n```\n\n## MazRadio / MazRadioButtons\n\nRadio button components for single selection.\n\n**Individual Radios**:\n```vue\n\u003cscript setup>\nconst plan = ref('basic')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazRadio v-model=\"plan\" value=\"basic\" label=\"Basic Plan\" />\n \u003cMazRadio v-model=\"plan\" value=\"pro\" label=\"Pro Plan\" />\n \u003cMazRadio v-model=\"plan\" value=\"enterprise\" label=\"Enterprise\" />\n\u003c/template>\n```\n\n**Radio Button Group**:\n```vue\n\u003cscript setup>\nconst plan = ref('basic')\nconst options = [\n { label: 'Basic', value: 'basic' },\n { label: 'Pro', value: 'pro' },\n { label: 'Enterprise', value: 'enterprise' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazRadioButtons\n v-model=\"plan\"\n :options=\"options\"\n orientation=\"horizontal\"\n />\n\u003c/template>\n```\n\n## MazSwitch\n\nToggle switch component.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst enabled = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSwitch v-model=\"enabled\" label=\"Enable feature\" />\n\u003c/template>\n```\n\n**With Colors**:\n```vue\n\u003ctemplate>\n \u003cMazSwitch v-model=\"enabled\" label=\"Notifications\" color=\"success\" />\n\u003c/template>\n```\n\n## MazTextarea\n\nMulti-line text input.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst message = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTextarea\n v-model=\"message\"\n label=\"Message\"\n placeholder=\"Enter your message\"\n :rows=\"4\"\n />\n\u003c/template>\n```\n\n**Auto-Resize**:\n```vue\n\u003ctemplate>\n \u003cMazTextarea\n v-model=\"message\"\n label=\"Message\"\n auto-grow\n :min-height=\"100\"\n :max-height=\"400\"\n />\n\u003c/template>\n```\n\n## MazSlider\n\nRange slider component.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst value = ref(50)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSlider\n v-model=\"value\"\n label=\"Volume\"\n :min=\"0\"\n :max=\"100\"\n :step=\"5\"\n />\n\u003c/template>\n```\n\n**Range Slider**:\n```vue\n\u003cscript setup>\nconst range = ref([20, 80])\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSlider\n v-model=\"range\"\n label=\"Price Range\"\n :min=\"0\"\n :max=\"1000\"\n :step=\"10\"\n />\n\u003c/template>\n```\n\n## MazInputCode\n\nPIN/code input component.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst code = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInputCode\n v-model=\"code\"\n :code-length=\"6\"\n type=\"number\"\n @completed=\"handleCodeComplete\"\n />\n\u003c/template>\n```\n\n## MazInputTags\n\nTag/chip input component.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst tags = ref(['vue', 'nuxt'])\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInputTags\n v-model=\"tags\"\n label=\"Tags\"\n placeholder=\"Add tag\"\n />\n\u003c/template>\n```\n\n## MazInputPrice\n\nCurrency input with formatting.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst price = ref(null)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInputPrice\n v-model=\"price\"\n label=\"Price\"\n currency=\"USD\"\n locale=\"en-US\"\n />\n\u003c/template>\n```\n\n## MazDatePicker\n\nDate picker component.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst date = ref(null)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazDatePicker\n v-model=\"date\"\n label=\"Select Date\"\n format=\"YYYY-MM-DD\"\n />\n\u003c/template>\n```\n\n**Date Range**:\n```vue\n\u003cscript setup>\nconst dateRange = ref({ start: null, end: null })\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazDatePicker\n v-model=\"dateRange\"\n label=\"Date Range\"\n range\n />\n\u003c/template>\n```\n\n## MazChecklist\n\nSearchable checklist with multiple selection.\n\n**Basic Usage**:\n```vue\n\u003cscript setup>\nconst selectedItems = ref([])\nconst items = [\n { label: 'Item 1', value: 1 },\n { label: 'Item 2', value: 2 },\n { label: 'Item 3', value: 3 }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazChecklist\n v-model=\"selectedItems\"\n :options=\"items\"\n search\n searchPlaceholder=\"Search items...\"\n />\n\u003c/template>\n```\n\n## Form Validation with useFormValidator\n\n**Setup** (Valibot required):\n```bash\npnpm add valibot\n```\n\n**Usage**:\n```vue\n\u003cscript setup>\nimport { string, email, minLength } from 'valibot'\nimport { useFormValidator } from 'maz-ui/composables'\n\nconst formData = ref({\n email: '',\n password: '',\n name: ''\n})\n\nconst { errors, validate, isValid } = useFormValidator({\n schema: {\n email: [string(), email()],\n password: [string(), minLength(8)],\n name: [string(), minLength(2)]\n },\n data: formData\n})\n\nasync function handleSubmit() {\n if (await validate()) {\n console.log('Form is valid!', formData.value)\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit.prevent=\"handleSubmit\">\n \u003cMazInput\n v-model=\"formData.email\"\n label=\"Email\"\n type=\"email\"\n :error=\"!!errors.email\"\n :hint=\"errors.email\"\n />\n\n \u003cMazInput\n v-model=\"formData.password\"\n label=\"Password\"\n type=\"password\"\n :error=\"!!errors.password\"\n :hint=\"errors.password\"\n />\n\n \u003cMazInput\n v-model=\"formData.name\"\n label=\"Name\"\n :error=\"!!errors.name\"\n :hint=\"errors.name\"\n />\n\n \u003cMazBtn\n type=\"submit\"\n color=\"primary\"\n :disabled=\"!isValid\"\n >\n Submit\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n## Common Props (Most Components)\n\n- **size**: 'mini' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n- **color**: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'destructive' | 'accent' | 'contrast'\n- **rounded-size**: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\n- **disabled**: boolean\n- **required**: boolean\n- **error**: boolean\n- **warning**: boolean\n- **success**: boolean\n- **hint**: string (error message)\n- **label**: string\n- **placeholder**: string\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8556,"content_sha256":"cab731c47a1c580199e8e1fbea2b32cb9041062129130e0190fa8adb21fa9f48"},{"filename":"references/components-layout.md","content":"# Maz-UI Layout & Display Components Reference\n\nComprehensive guide to all Maz-UI layout and display components for structuring content and creating interactive interfaces.\n\n## Overview\n\nMaz-UI provides **12 powerful layout and display components** for organizing content, creating overlays, and enhancing visual presentation:\n\n**Containers & Cards**:\n- `MazCard` - Versatile container with header/footer\n- `MazAccordion` - Collapsible content panels\n\n**Overlays & Modals**:\n- `MazDrawer` - Slide-out side panel\n- `MazBottomSheet` - Mobile bottom drawer\n- `MazBackdrop` - Overlay backdrop\n- `MazPopover` - Floating tooltip/menu\n- `MazDropdown` - Dropdown menu\n\n**Media & Display**:\n- `MazCarousel` - Image/content carousel\n- `MazGallery` - Image gallery with lightbox\n- `MazLazyImg` - Lazy-loaded images\n\n**Animations & Interactions**:\n- `MazExpandAnimation` - Smooth expand/collapse\n- `MazPullToRefresh` - Mobile pull-to-refresh\n\n**Key Features**:\n- ✅ **Responsive** - Adapts to all screen sizes\n- ✅ **Customizable** - Colors, sizes, positions\n- ✅ **Accessible** - ARIA attributes and keyboard support\n- ✅ **Touch-Friendly** - Mobile gestures and interactions\n- ✅ **SSR Compatible** - Works with Nuxt 3\n\n---\n\n## MazCard\n\nVersatile container component with optional header and footer sections.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazCard from 'maz-ui/components/MazCard'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCard>\n \u003ctemplate #header>\n \u003ch3>Card Title\u003c/h3>\n \u003c/template>\n\n \u003cp>Card content goes here...\u003c/p>\n\n \u003ctemplate #footer>\n \u003cMazBtn>Action\u003c/MazBtn>\n \u003c/template>\n \u003c/MazCard>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive' \\| 'contrast'` | Border/header color | `'contrast'` |\n| `elevation` | `boolean \\| number` | Box shadow elevation (0-5) | `1` |\n| `bordered` | `boolean` | Show border | `false` |\n| `overflowHidden` | `boolean` | Hide overflow content | `false` |\n| `padding` | `'none' \\| 'sm' \\| 'md' \\| 'lg'` | Card padding | `'md'` |\n| `radius` | `'none' \\| 'sm' \\| 'md' \\| 'lg'` | Border radius | `'md'` |\n\n### Slots\n\n| Slot | Description |\n|------|-------------|\n| `header` | Card header content |\n| `default` | Main card content |\n| `footer` | Card footer content |\n\n### Examples\n\n**Elevated Card**:\n```vue\n\u003ctemplate>\n \u003cMazCard :elevation=\"3\" bordered>\n \u003ctemplate #header>\n \u003ch3>Product Card\u003c/h3>\n \u003c/template>\n \u003cp>Product description...\u003c/p>\n \u003ctemplate #footer>\n \u003cMazBtn color=\"primary\">Buy Now\u003c/MazBtn>\n \u003c/template>\n \u003c/MazCard>\n\u003c/template>\n```\n\n**Card Grid**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"grid grid-cols-3 gap-4\">\n \u003cMazCard\n v-for=\"item in items\"\n :key=\"item.id\"\n :elevation=\"2\"\n >\n \u003cimg :src=\"item.image\" alt=\"\" class=\"w-full\" />\n \u003ch4 class=\"mt-2\">{{ item.title }}\u003c/h4>\n \u003cp>{{ item.description }}\u003c/p>\n \u003c/MazCard>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## MazAccordion\n\nCollapsible content panels for organizing information.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazAccordion from 'maz-ui/components/MazAccordion'\n\nconst openPanels = ref(['panel-1'])\n\nconst panels = [\n { id: 'panel-1', title: 'Panel 1', content: 'Content 1' },\n { id: 'panel-2', title: 'Panel 2', content: 'Content 2' },\n { id: 'panel-3', title: 'Panel 3', content: 'Content 3' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAccordion v-model=\"openPanels\" :panels=\"panels\">\n \u003ctemplate #panel-1>\n \u003cp>Detailed content for panel 1...\u003c/p>\n \u003c/template>\n \u003ctemplate #panel-2>\n \u003cp>Detailed content for panel 2...\u003c/p>\n \u003c/template>\n \u003ctemplate #panel-3>\n \u003cp>Detailed content for panel 3...\u003c/p>\n \u003c/template>\n \u003c/MazAccordion>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `modelValue` | `string[]` | Open panel IDs (v-model) | `[]` |\n| `panels` | `Panel[]` | Array of panel objects | `[]` |\n| `multiple` | `boolean` | Allow multiple panels open | `false` |\n| `bordered` | `boolean` | Show borders | `false` |\n| `color` | `string` | Header color | `'primary'` |\n\n### Panel Object\n\n```typescript\ninterface Panel {\n id: string\n title: string\n disabled?: boolean\n icon?: string\n}\n```\n\n### Examples\n\n**Single Panel Open**:\n```vue\n\u003ctemplate>\n \u003cMazAccordion\n v-model=\"openPanels\"\n :panels=\"panels\"\n :multiple=\"false\"\n >\n \u003c!-- Only one panel can be open at a time -->\n \u003c/MazAccordion>\n\u003c/template>\n```\n\n**FAQ Example**:\n```vue\n\u003cscript setup>\nconst faqs = [\n {\n id: 'faq-1',\n title: 'What is Maz-UI?',\n icon: 'question'\n },\n {\n id: 'faq-2',\n title: 'How do I install it?',\n icon: 'download'\n }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAccordion v-model=\"openFaqs\" :panels=\"faqs\" bordered>\n \u003ctemplate #faq-1>\n \u003cp>Maz-UI is a comprehensive Vue component library...\u003c/p>\n \u003c/template>\n \u003ctemplate #faq-2>\n \u003cpre>\u003ccode>npm install maz-ui\u003c/code>\u003c/pre>\n \u003c/template>\n \u003c/MazAccordion>\n\u003c/template>\n```\n\n---\n\n## MazDrawer\n\nSlide-out panel from screen edge for navigation or content.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazDrawer from 'maz-ui/components/MazDrawer'\n\nconst isOpen = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"isOpen = true\">Open Drawer\u003c/MazBtn>\n\n \u003cMazDrawer\n v-model=\"isOpen\"\n position=\"right\"\n width=\"400px\"\n >\n \u003ctemplate #header>\n \u003ch3>Drawer Title\u003c/h3>\n \u003c/template>\n\n \u003cdiv class=\"p-4\">\n \u003cp>Drawer content...\u003c/p>\n \u003c/div>\n\n \u003ctemplate #footer>\n \u003cMazBtn @click=\"isOpen = false\">Close\u003c/MazBtn>\n \u003c/template>\n \u003c/MazDrawer>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `modelValue` | `boolean` | Open/close state (v-model) | `false` |\n| `position` | `'left' \\| 'right' \\| 'top' \\| 'bottom'` | Drawer position | `'right'` |\n| `width` | `string` | Drawer width (left/right) | `'400px'` |\n| `height` | `string` | Drawer height (top/bottom) | `'50vh'` |\n| `backdrop` | `boolean` | Show backdrop overlay | `true` |\n| `closeOnBackdropClick` | `boolean` | Close when backdrop clicked | `true` |\n| `persistent` | `boolean` | Prevent closing | `false` |\n\n### Examples\n\n**Navigation Drawer**:\n```vue\n\u003ctemplate>\n \u003cMazDrawer\n v-model=\"isNavOpen\"\n position=\"left\"\n width=\"280px\"\n >\n \u003ctemplate #header>\n \u003ch2>Menu\u003c/h2>\n \u003c/template>\n\n \u003cnav>\n \u003ca href=\"/dashboard\">Dashboard\u003c/a>\n \u003ca href=\"/profile\">Profile\u003c/a>\n \u003ca href=\"/settings\">Settings\u003c/a>\n \u003c/nav>\n \u003c/MazDrawer>\n\u003c/template>\n```\n\n**Settings Panel**:\n```vue\n\u003ctemplate>\n \u003cMazDrawer\n v-model=\"showSettings\"\n position=\"right\"\n width=\"500px\"\n >\n \u003ctemplate #header>\n \u003ch3>Settings\u003c/h3>\n \u003c/template>\n\n \u003cdiv class=\"p-4\">\n \u003cMazInput label=\"Username\" />\n \u003cMazSwitch label=\"Dark Mode\" />\n \u003c/div>\n\n \u003ctemplate #footer>\n \u003cMazBtn @click=\"saveSettings\" color=\"primary\">Save\u003c/MazBtn>\n \u003cMazBtn @click=\"showSettings = false\">Cancel\u003c/MazBtn>\n \u003c/template>\n \u003c/MazDrawer>\n\u003c/template>\n```\n\n---\n\n## MazBottomSheet\n\nMobile-first bottom drawer with drag-to-close gesture.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazBottomSheet from 'maz-ui/components/MazBottomSheet'\n\nconst isOpen = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"isOpen = true\">Open Bottom Sheet\u003c/MazBtn>\n\n \u003cMazBottomSheet v-model=\"isOpen\">\n \u003ctemplate #header>\n \u003ch3>Bottom Sheet Title\u003c/h3>\n \u003c/template>\n\n \u003cdiv class=\"p-4\">\n \u003cp>Content goes here...\u003c/p>\n \u003c/div>\n \u003c/MazBottomSheet>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `modelValue` | `boolean` | Open/close state (v-model) | `false` |\n| `height` | `string` | Sheet height | `'auto'` |\n| `maxHeight` | `string` | Maximum height | `'90vh'` |\n| `draggable` | `boolean` | Enable drag-to-close | `true` |\n| `backdrop` | `boolean` | Show backdrop | `true` |\n| `snapPoints` | `number[]` | Snap positions (0-1) | `[0.5, 1]` |\n\n### Examples\n\n**Action Sheet**:\n```vue\n\u003ctemplate>\n \u003cMazBottomSheet v-model=\"showActions\" height=\"auto\">\n \u003cdiv class=\"p-4\">\n \u003cMazBtn block @click=\"handleEdit\">Edit\u003c/MazBtn>\n \u003cMazBtn block @click=\"handleShare\">Share\u003c/MazBtn>\n \u003cMazBtn block color=\"destructive\" @click=\"handleDelete\">\n Delete\n \u003c/MazBtn>\n \u003c/div>\n \u003c/MazBottomSheet>\n\u003c/template>\n```\n\n**Filter Panel**:\n```vue\n\u003ctemplate>\n \u003cMazBottomSheet\n v-model=\"showFilters\"\n height=\"60vh\"\n :snap-points=\"[0.3, 0.6, 1]\"\n >\n \u003ctemplate #header>\n \u003ch3>Filters\u003c/h3>\n \u003c/template>\n\n \u003cdiv class=\"p-4\">\n \u003cMazSelect label=\"Category\" :options=\"categories\" />\n \u003cMazSlider label=\"Price Range\" />\n \u003c/div>\n\n \u003ctemplate #footer>\n \u003cMazBtn @click=\"applyFilters\" color=\"primary\">Apply\u003c/MazBtn>\n \u003c/template>\n \u003c/MazBottomSheet>\n\u003c/template>\n```\n\n---\n\n## MazBackdrop\n\nOverlay backdrop for modals and drawers.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazBackdrop from 'maz-ui/components/MazBackdrop'\n\nconst showBackdrop = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBackdrop\n v-if=\"showBackdrop\"\n @click=\"showBackdrop = false\"\n />\n\n \u003cdiv v-if=\"showBackdrop\" class=\"modal\">\n \u003c!-- Modal content -->\n \u003c/div>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `color` | `string` | Backdrop color (CSS color) | `'rgba(0,0,0,0.5)'` |\n| `blur` | `boolean` | Enable backdrop blur | `false` |\n| `zIndex` | `number` | Z-index value | `9998` |\n| `persistent` | `boolean` | Prevent click events | `false` |\n\n---\n\n## MazPopover\n\nFloating tooltip or menu positioned relative to trigger element.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazPopover from 'maz-ui/components/MazPopover'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazPopover>\n \u003ctemplate #trigger>\n \u003cMazBtn>Show Popover\u003c/MazBtn>\n \u003c/template>\n\n \u003ctemplate #content>\n \u003cdiv class=\"p-4\">\n \u003ch4>Popover Title\u003c/h4>\n \u003cp>Popover content...\u003c/p>\n \u003c/div>\n \u003c/template>\n \u003c/MazPopover>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `position` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | Popover position | `'bottom'` |\n| `trigger` | `'click' \\| 'hover' \\| 'focus'` | Trigger event | `'click'` |\n| `offset` | `number` | Distance from trigger (px) | `8` |\n| `arrow` | `boolean` | Show arrow pointer | `true` |\n| `closeOnClickOutside` | `boolean` | Close on outside click | `true` |\n\n### Examples\n\n**User Menu**:\n```vue\n\u003ctemplate>\n \u003cMazPopover position=\"bottom-end\" trigger=\"click\">\n \u003ctemplate #trigger>\n \u003cMazAvatar :src=\"user.avatar\" />\n \u003c/template>\n\n \u003ctemplate #content>\n \u003cdiv class=\"w-64 p-2\">\n \u003ca href=\"/profile\" class=\"block px-4 py-2\">Profile\u003c/a>\n \u003ca href=\"/settings\" class=\"block px-4 py-2\">Settings\u003c/a>\n \u003chr />\n \u003ca href=\"/logout\" class=\"block px-4 py-2 text-destructive\">\n Logout\n \u003c/a>\n \u003c/div>\n \u003c/template>\n \u003c/MazPopover>\n\u003c/template>\n```\n\n**Info Popover**:\n```vue\n\u003ctemplate>\n \u003cMazPopover trigger=\"hover\" position=\"top\">\n \u003ctemplate #trigger>\n \u003cMazIcon name=\"info-circle\" />\n \u003c/template>\n\n \u003ctemplate #content>\n \u003cdiv class=\"p-3 max-w-xs\">\n \u003cp class=\"text-sm\">Additional information about this feature...\u003c/p>\n \u003c/div>\n \u003c/template>\n \u003c/MazPopover>\n\u003c/template>\n```\n\n---\n\n## MazDropdown\n\nDropdown menu with keyboard navigation.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazDropdown from 'maz-ui/components/MazDropdown'\n\nconst items = [\n { id: '1', label: 'Item 1', icon: 'check' },\n { id: '2', label: 'Item 2', icon: 'star' },\n { id: '3', label: 'Item 3', icon: 'heart', divider: true },\n { id: '4', label: 'Delete', icon: 'trash', color: 'destructive' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazDropdown :items=\"items\" @select=\"handleSelect\">\n \u003ctemplate #trigger>\n \u003cMazBtn>Actions\u003c/MazBtn>\n \u003c/template>\n \u003c/MazDropdown>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `items` | `DropdownItem[]` | Menu items | `[]` |\n| `position` | `'bottom-start' \\| 'bottom-end' \\| 'top-start' \\| 'top-end'` | Menu position | `'bottom-start'` |\n| `width` | `string` | Menu width | `'auto'` |\n\n### DropdownItem\n\n```typescript\ninterface DropdownItem {\n id: string\n label: string\n icon?: string\n disabled?: boolean\n divider?: boolean // Show divider after this item\n color?: string\n onClick?: () => void\n}\n```\n\n---\n\n## MazCarousel\n\nImage and content carousel with navigation controls.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazCarousel from 'maz-ui/components/MazCarousel'\n\nconst slides = [\n { id: 1, src: '/images/slide-1.jpg', alt: 'Slide 1' },\n { id: 2, src: '/images/slide-2.jpg', alt: 'Slide 2' },\n { id: 3, src: '/images/slide-3.jpg', alt: 'Slide 3' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCarousel :slides=\"slides\" />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `slides` | `Slide[]` | Array of slide objects | `[]` |\n| `autoplay` | `boolean` | Enable autoplay | `false` |\n| `interval` | `number` | Autoplay interval (ms) | `5000` |\n| `showArrows` | `boolean` | Show navigation arrows | `true` |\n| `showDots` | `boolean` | Show pagination dots | `true` |\n| `loop` | `boolean` | Enable infinite loop | `true` |\n\n### Examples\n\n**Hero Carousel**:\n```vue\n\u003ctemplate>\n \u003cMazCarousel\n :slides=\"heroSlides\"\n autoplay\n :interval=\"4000\"\n loop\n class=\"h-96\"\n >\n \u003ctemplate #slide=\"{ slide }\">\n \u003cdiv class=\"relative h-full\">\n \u003cimg :src=\"slide.src\" class=\"w-full h-full object-cover\" />\n \u003cdiv class=\"absolute inset-0 flex items-center justify-center\">\n \u003ch2 class=\"text-white text-4xl\">{{ slide.title }}\u003c/h2>\n \u003c/div>\n \u003c/div>\n \u003c/template>\n \u003c/MazCarousel>\n\u003c/template>\n```\n\n---\n\n## MazGallery\n\nImage gallery with lightbox viewer.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazGallery from 'maz-ui/components/MazGallery'\n\nconst images = [\n { id: 1, src: '/gallery/photo-1.jpg', thumbnail: '/gallery/thumb-1.jpg' },\n { id: 2, src: '/gallery/photo-2.jpg', thumbnail: '/gallery/thumb-2.jpg' },\n { id: 3, src: '/gallery/photo-3.jpg', thumbnail: '/gallery/thumb-3.jpg' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazGallery :images=\"images\" />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `images` | `GalleryImage[]` | Array of image objects | `[]` |\n| `columns` | `number` | Grid columns | `3` |\n| `gap` | `string` | Gap between images | `'1rem'` |\n| `lightbox` | `boolean` | Enable lightbox viewer | `true` |\n\n---\n\n## MazLazyImg\n\nLazy-loaded images with IntersectionObserver.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazLazyImg from 'maz-ui/components/MazLazyImg'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazLazyImg\n src=\"/images/large-photo.jpg\"\n placeholder=\"/images/placeholder.jpg\"\n alt=\"Photo description\"\n />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `src` | `string` | Image source URL | `''` |\n| `placeholder` | `string` | Placeholder image URL | `''` |\n| `alt` | `string` | Image alt text | `''` |\n| `threshold` | `number` | Intersection threshold (0-1) | `0.1` |\n| `fadeIn` | `boolean` | Fade in on load | `true` |\n\n---\n\n## MazExpandAnimation\n\nSmooth expand/collapse animation wrapper.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazExpandAnimation from 'maz-ui/components/MazExpandAnimation'\n\nconst isExpanded = ref(false)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"isExpanded = !isExpanded\">\n Toggle Content\n \u003c/MazBtn>\n\n \u003cMazExpandAnimation :expanded=\"isExpanded\">\n \u003cdiv class=\"p-4\">\n \u003cp>This content smoothly expands and collapses...\u003c/p>\n \u003c/div>\n \u003c/MazExpandAnimation>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `expanded` | `boolean` | Expanded state | `false` |\n| `duration` | `number` | Animation duration (ms) | `300` |\n\n---\n\n## MazPullToRefresh\n\nMobile pull-to-refresh gesture handler.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport MazPullToRefresh from 'maz-ui/components/MazPullToRefresh'\n\nasync function handleRefresh() {\n await fetchNewData()\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazPullToRefresh @refresh=\"handleRefresh\">\n \u003cdiv class=\"content\">\n \u003cdiv v-for=\"item in items\" :key=\"item.id\">\n {{ item.title }}\n \u003c/div>\n \u003c/div>\n \u003c/MazPullToRefresh>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `threshold` | `number` | Pull distance to trigger (px) | `60` |\n| `color` | `string` | Spinner color | `'primary'` |\n\n### Events\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `refresh` | - | Emitted when refresh triggered |\n\n---\n\n## Best Practices\n\n### Cards & Containers\n\n**DO**:\n- Use cards to group related content\n- Provide visual hierarchy with elevation\n- Use header/footer for actions and titles\n\n**DON'T**:\n- Nest cards deeply (max 2 levels)\n- Use cards for every small piece of content\n\n### Overlays & Modals\n\n**DO**:\n- Use drawers for navigation and settings\n- Use bottom sheets for mobile action menus\n- Provide clear close mechanisms\n\n**DON'T**:\n- Show multiple modals simultaneously\n- Use persistent modals without escape route\n\n### Media Components\n\n**DO**:\n- Use lazy loading for images below fold\n- Provide alt text for all images\n- Optimize image sizes for web\n\n**DON'T**:\n- Load all gallery images at once\n- Skip placeholder images for lazy loading\n\n---\n\n## Related Documentation\n\n- **[Components Forms](./components-forms.md)** - Form input components\n- **[Components Feedback](./components-feedback.md)** - Loading and feedback components\n- **[Components Navigation](./components-navigation.md)** - Navigation components\n- **[Directives Reference](./directives.md)** - v-lazy-img, v-zoom-img, v-fullscreen-img\n\n---\n\n**Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-14\n**Component Count**: 12 layout & display components\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":18209,"content_sha256":"9bf01ff06b8d4c278965d5665e36e30ba1e33658cbd5cd76ac587b514407c276"},{"filename":"references/components-navigation.md","content":"# Maz-UI Navigation Components Reference\n\nComprehensive guide to all Maz-UI navigation components for organizing content and improving user flow.\n\n## Overview\n\nMaz-UI provides **3 powerful navigation components** for structuring content and guiding users through multi-step flows:\n\n**Components**:\n- `MazTabs` - Tab-based navigation for content sections\n- `MazStepper` - Step-by-step progress indicator\n- `MazPagination` - Pagination controls for data tables and lists\n\n**Key Features**:\n- ✅ **Keyboard Accessible** - Full arrow key navigation support\n- ✅ **Responsive** - Adapts to mobile and desktop layouts\n- ✅ **Customizable** - Colors, sizes, orientations\n- ✅ **Router Integration** - Optional Vue Router integration\n- ✅ **TypeScript Support** - Full type safety with TypeScript\n\n---\n\n## MazTabs\n\nTab navigation component for organizing content into separate views.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazTabs from 'maz-ui/components/MazTabs'\n\nconst activeTab = ref('overview')\n\nconst tabs = [\n { id: 'overview', label: 'Overview' },\n { id: 'features', label: 'Features' },\n { id: 'pricing', label: 'Pricing' },\n { id: 'faq', label: 'FAQ' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #overview>\n \u003ch2>Overview Content\u003c/h2>\n \u003cp>Product overview details...\u003c/p>\n \u003c/template>\n\n \u003ctemplate #features>\n \u003ch2>Features Content\u003c/h2>\n \u003cp>Feature list...\u003c/p>\n \u003c/template>\n\n \u003ctemplate #pricing>\n \u003ch2>Pricing Content\u003c/h2>\n \u003cp>Pricing plans...\u003c/p>\n \u003c/template>\n\n \u003ctemplate #faq>\n \u003ch2>FAQ Content\u003c/h2>\n \u003cp>Frequently asked questions...\u003c/p>\n \u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `modelValue` | `string \\| number` | Active tab ID (v-model) | `null` |\n| `tabs` | `Tab[]` | Array of tab objects | `[]` |\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive'` | Active tab color | `'primary'` |\n| `orientation` | `'horizontal' \\| 'vertical'` | Tab layout orientation | `'horizontal'` |\n| `size` | `'sm' \\| 'md' \\| 'lg'` | Tab button size | `'md'` |\n| `alignTabs` | `'start' \\| 'center' \\| 'end'` | Tab alignment | `'start'` |\n| `fullWidth` | `boolean` | Tabs stretch to full width | `false` |\n| `underline` | `boolean` | Underline active tab | `true` |\n| `disabled` | `boolean` | Disable all tabs | `false` |\n\n### Tab Object\n\n```typescript\ninterface Tab {\n id: string | number\n label: string\n icon?: string // Icon name (from @maz-ui/icons)\n disabled?: boolean // Disable this tab\n badge?: string // Badge text (e.g., \"New\", \"3\")\n badgeColor?: string // Badge color\n}\n```\n\n### Events\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `update:modelValue` | `string \\| number` | Emitted when active tab changes |\n| `change` | `{ id: string \\| number, tab: Tab }` | Emitted when tab is clicked |\n\n### Slots\n\n| Slot | Props | Description |\n|------|-------|-------------|\n| `[tab-id]` | - | Content for each tab (dynamic slot) |\n| `tab-label` | `{ tab: Tab, active: boolean }` | Custom tab button content |\n\n### Examples\n\n**With Icons and Badges**:\n```vue\n\u003cscript setup>\nconst tabs = [\n {\n id: 'inbox',\n label: 'Inbox',\n icon: 'inbox',\n badge: '5',\n badgeColor: 'destructive'\n },\n {\n id: 'sent',\n label: 'Sent',\n icon: 'send'\n },\n {\n id: 'drafts',\n label: 'Drafts',\n icon: 'file',\n badge: '2',\n badgeColor: 'warning'\n }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #inbox>\n \u003cdiv>Inbox messages...\u003c/div>\n \u003c/template>\n \u003ctemplate #sent>\n \u003cdiv>Sent messages...\u003c/div>\n \u003c/template>\n \u003ctemplate #drafts>\n \u003cdiv>Draft messages...\u003c/div>\n \u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n**Vertical Orientation**:\n```vue\n\u003ctemplate>\n \u003cMazTabs\n v-model=\"activeTab\"\n :tabs=\"tabs\"\n orientation=\"vertical\"\n class=\"h-screen\"\n >\n \u003ctemplate #tab1>Content 1\u003c/template>\n \u003ctemplate #tab2>Content 2\u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n**Full Width Tabs**:\n```vue\n\u003ctemplate>\n \u003cMazTabs\n v-model=\"activeTab\"\n :tabs=\"tabs\"\n full-width\n align-tabs=\"center\"\n >\n \u003ctemplate #tab1>Content 1\u003c/template>\n \u003ctemplate #tab2>Content 2\u003c/template>\n \u003ctemplate #tab3>Content 3\u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n**Custom Tab Labels**:\n```vue\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #tab-label=\"{ tab, active }\">\n \u003cdiv class=\"flex items-center gap-2\">\n \u003cMazIcon :name=\"tab.icon\" />\n \u003cspan :class=\"{ 'font-bold': active }\">\n {{ tab.label }}\n \u003c/span>\n \u003cMazBadge v-if=\"tab.badge\" size=\"sm\">\n {{ tab.badge }}\n \u003c/MazBadge>\n \u003c/div>\n \u003c/template>\n\n \u003ctemplate #tab1>Content 1\u003c/template>\n \u003ctemplate #tab2>Content 2\u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n**Disabled Tabs**:\n```vue\n\u003cscript setup>\nconst tabs = [\n { id: 'tab1', label: 'Available' },\n { id: 'tab2', label: 'Coming Soon', disabled: true },\n { id: 'tab3', label: 'Premium Only', disabled: true }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #tab1>\n \u003cp>This content is available\u003c/p>\n \u003c/template>\n \u003ctemplate #tab2>\n \u003cp>Coming soon...\u003c/p>\n \u003c/template>\n \u003ctemplate #tab3>\n \u003cp>Upgrade to premium\u003c/p>\n \u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n**Router Integration**:\n```vue\n\u003cscript setup>\nimport { useRouter, useRoute } from 'vue-router'\nimport { computed } from 'vue'\n\nconst router = useRouter()\nconst route = useRoute()\n\nconst activeTab = computed({\n get: () => route.query.tab || 'overview',\n set: (tab) => router.push({ query: { tab } })\n})\n\nconst tabs = [\n { id: 'overview', label: 'Overview' },\n { id: 'details', label: 'Details' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #overview>Overview\u003c/template>\n \u003ctemplate #details>Details\u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n---\n\n## MazStepper\n\nStep-by-step progress indicator for multi-step workflows.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref } from 'vue'\nimport MazStepper from 'maz-ui/components/MazStepper'\n\nconst currentStep = ref(1)\n\nconst steps = [\n { id: 1, label: 'Account Details', icon: 'user' },\n { id: 2, label: 'Payment Info', icon: 'credit-card' },\n { id: 3, label: 'Confirmation', icon: 'check-circle' }\n]\n\nfunction nextStep() {\n if (currentStep.value \u003c steps.length) {\n currentStep.value++\n }\n}\n\nfunction previousStep() {\n if (currentStep.value > 1) {\n currentStep.value--\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n />\n\n \u003c!-- Step content -->\n \u003cdiv v-if=\"currentStep === 1\">\n \u003ch2>Step 1: Account Details\u003c/h2>\n \u003cMazInput label=\"Name\" />\n \u003cMazInput label=\"Email\" type=\"email\" />\n \u003c/div>\n\n \u003cdiv v-if=\"currentStep === 2\">\n \u003ch2>Step 2: Payment Info\u003c/h2>\n \u003cMazInput label=\"Card Number\" />\n \u003c/div>\n\n \u003cdiv v-if=\"currentStep === 3\">\n \u003ch2>Step 3: Confirmation\u003c/h2>\n \u003cp>Review your information\u003c/p>\n \u003c/div>\n\n \u003c!-- Navigation -->\n \u003cdiv class=\"flex gap-2\">\n \u003cMazBtn\n @click=\"previousStep\"\n :disabled=\"currentStep === 1\"\n >\n Previous\n \u003c/MazBtn>\n \u003cMazBtn\n @click=\"nextStep\"\n color=\"primary\"\n :disabled=\"currentStep === steps.length\"\n >\n Next\n \u003c/MazBtn>\n \u003c/div>\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `modelValue` | `number` | Current step index (v-model) | `1` |\n| `steps` | `Step[]` | Array of step objects | `[]` |\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive'` | Active/completed step color | `'primary'` |\n| `orientation` | `'horizontal' \\| 'vertical'` | Stepper layout | `'horizontal'` |\n| `size` | `'sm' \\| 'md' \\| 'lg'` | Step indicator size | `'md'` |\n| `clickable` | `boolean` | Allow clicking to navigate steps | `false` |\n| `showLabels` | `boolean` | Show step labels | `true` |\n| `showNumbers` | `boolean` | Show step numbers | `true` |\n| `linear` | `boolean` | Only allow sequential navigation | `true` |\n\n### Step Object\n\n```typescript\ninterface Step {\n id: number\n label: string\n description?: string // Optional step description\n icon?: string // Icon name\n disabled?: boolean // Disable this step\n completed?: boolean // Mark as completed (auto-calculated if not provided)\n error?: boolean // Mark step as having error\n}\n```\n\n### Events\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `update:modelValue` | `number` | Emitted when current step changes |\n| `change` | `{ step: number, stepData: Step }` | Emitted when step changes |\n| `click-step` | `{ step: number, stepData: Step }` | Emitted when step is clicked (if clickable) |\n\n### Examples\n\n**Vertical Stepper**:\n```vue\n\u003ctemplate>\n \u003cdiv class=\"flex\">\n \u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n orientation=\"vertical\"\n class=\"w-64\"\n />\n\n \u003cdiv class=\"flex-1 ml-8\">\n \u003c!-- Step content -->\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**Clickable Steps (Non-Linear)**:\n```vue\n\u003cscript setup>\nconst steps = [\n { id: 1, label: 'Personal Info' },\n { id: 2, label: 'Address' },\n { id: 3, label: 'Review' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n clickable\n :linear=\"false\"\n @click-step=\"handleStepClick\"\n />\n\u003c/template>\n```\n\n**With Descriptions**:\n```vue\n\u003cscript setup>\nconst steps = [\n {\n id: 1,\n label: 'Account',\n description: 'Enter your basic information'\n },\n {\n id: 2,\n label: 'Verification',\n description: 'Verify your email address'\n },\n {\n id: 3,\n label: 'Complete',\n description: 'Finalize your account'\n }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper v-model=\"currentStep\" :steps=\"steps\" />\n\u003c/template>\n```\n\n**Error States**:\n```vue\n\u003cscript setup>\nconst steps = ref([\n { id: 1, label: 'Info', completed: true },\n { id: 2, label: 'Payment', error: true }, // Show error\n { id: 3, label: 'Done' }\n])\n\nconst currentStep = ref(2)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper v-model=\"currentStep\" :steps=\"steps\" />\n\n \u003cdiv v-if=\"currentStep === 2\">\n \u003cMazAlert color=\"destructive\">\n Payment failed. Please update your payment method.\n \u003c/MazAlert>\n \u003c/div>\n\u003c/template>\n```\n\n**Form Wizard Example**:\n```vue\n\u003cscript setup>\nimport { ref, computed } from 'vue'\n\nconst currentStep = ref(1)\nconst formData = ref({\n name: '',\n email: '',\n cardNumber: ''\n})\n\nconst steps = computed(() => [\n {\n id: 1,\n label: 'Personal Info',\n completed: currentStep.value > 1\n },\n {\n id: 2,\n label: 'Payment',\n completed: currentStep.value > 2\n },\n {\n id: 3,\n label: 'Confirmation',\n completed: currentStep.value > 3\n }\n])\n\nasync function nextStep() {\n if (await validateStep(currentStep.value)) {\n currentStep.value++\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper v-model=\"currentStep\" :steps=\"steps\" />\n\n \u003c!-- Step content with validation -->\n \u003cform @submit.prevent=\"nextStep\">\n \u003cdiv v-show=\"currentStep === 1\">\n \u003cMazInput v-model=\"formData.name\" label=\"Name\" required />\n \u003cMazInput v-model=\"formData.email\" label=\"Email\" type=\"email\" required />\n \u003c/div>\n\n \u003cdiv v-show=\"currentStep === 2\">\n \u003cMazInput v-model=\"formData.cardNumber\" label=\"Card Number\" required />\n \u003c/div>\n\n \u003cdiv v-show=\"currentStep === 3\">\n \u003ch3>Review Your Information\u003c/h3>\n \u003cp>Name: {{ formData.name }}\u003c/p>\n \u003cp>Email: {{ formData.email }}\u003c/p>\n \u003c/div>\n\n \u003cMazBtn type=\"submit\" color=\"primary\">\n {{ currentStep \u003c steps.length ? 'Next' : 'Submit' }}\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n---\n\n## MazPagination\n\nPagination controls for data tables and lists.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { ref, computed } from 'vue'\nimport MazPagination from 'maz-ui/components/MazPagination'\n\nconst currentPage = ref(1)\nconst perPage = ref(10)\nconst totalItems = ref(250)\n\nconst paginatedData = computed(() => {\n const start = (currentPage.value - 1) * perPage.value\n const end = start + perPage.value\n return allData.value.slice(start, end)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTable :data=\"paginatedData\" />\n\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `currentPage` | `number` | Current page number (v-model:current-page) | `1` |\n| `total` | `number` | Total number of items | `0` |\n| `perPage` | `number` | Items per page | `10` |\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive'` | Active page color | `'primary'` |\n| `size` | `'sm' \\| 'md' \\| 'lg'` | Button size | `'md'` |\n| `maxVisiblePages` | `number` | Max page buttons to show | `7` |\n| `showFirstLast` | `boolean` | Show first/last page buttons | `true` |\n| `showPrevNext` | `boolean` | Show previous/next buttons | `true` |\n| `disabled` | `boolean` | Disable all buttons | `false` |\n\n### Computed Properties\n\n```typescript\nconst totalPages = computed(() =>\n Math.ceil(props.total / props.perPage)\n)\n\nconst isFirstPage = computed(() =>\n props.currentPage === 1\n)\n\nconst isLastPage = computed(() =>\n props.currentPage === totalPages.value\n)\n```\n\n### Events\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `update:currentPage` | `number` | Emitted when page changes |\n| `change` | `{ page: number, perPage: number }` | Emitted when page changes |\n\n### Examples\n\n**With Per-Page Selector**:\n```vue\n\u003cscript setup>\nimport { ref, watch } from 'vue'\n\nconst currentPage = ref(1)\nconst perPage = ref(10)\nconst totalItems = ref(500)\n\nconst perPageOptions = [10, 25, 50, 100]\n\nwatch(perPage, () => {\n currentPage.value = 1 // Reset to first page\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cMazTable :data=\"paginatedData\" />\n\n \u003cdiv class=\"flex items-center justify-between mt-4\">\n \u003cMazSelect\n v-model=\"perPage\"\n :options=\"perPageOptions\"\n label=\"Per page\"\n class=\"w-32\"\n />\n\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n />\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**Compact Pagination**:\n```vue\n\u003ctemplate>\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n :max-visible-pages=\"5\"\n :show-first-last=\"false\"\n size=\"sm\"\n />\n\u003c/template>\n```\n\n**Server-Side Pagination**:\n```vue\n\u003cscript setup>\nimport { ref, watch, onMounted } from 'vue'\n\nconst currentPage = ref(1)\nconst perPage = ref(20)\nconst totalItems = ref(0)\nconst data = ref([])\nconst isLoading = ref(false)\n\nasync function fetchData() {\n isLoading.value = true\n try {\n const response = await api.getData({\n page: currentPage.value,\n limit: perPage.value\n })\n data.value = response.data\n totalItems.value = response.total\n } finally {\n isLoading.value = false\n }\n}\n\nwatch([currentPage, perPage], fetchData)\nonMounted(fetchData)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTable :data=\"data\" :loading=\"isLoading\" />\n\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n @change=\"fetchData\"\n />\n\u003c/template>\n```\n\n**With Page Info**:\n```vue\n\u003cscript setup>\nconst startItem = computed(() =>\n (currentPage.value - 1) * perPage.value + 1\n)\n\nconst endItem = computed(() =>\n Math.min(currentPage.value * perPage.value, totalItems.value)\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cMazTable :data=\"paginatedData\" />\n\n \u003cdiv class=\"flex items-center justify-between mt-4\">\n \u003cp class=\"text-sm text-muted\">\n Showing {{ startItem }} to {{ endItem }} of {{ totalItems }} results\n \u003c/p>\n\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n />\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Best Practices\n\n### Tabs\n\n**DO**:\n- Use tabs for related content that users might switch between frequently\n- Limit tab count to 5-7 for horizontal tabs\n- Use icons with labels for better recognition\n- Provide visual feedback for active tab\n\n**DON'T**:\n- Use tabs for sequential workflows (use stepper instead)\n- Create tabs that are too similar in name\n- Hide important content in rarely-accessed tabs\n\n```vue\n\u003c!-- ✅ Good: Clear, distinct tabs -->\n\u003cMazTabs v-model=\"activeTab\" :tabs=\"[\n { id: 'overview', label: 'Overview', icon: 'info' },\n { id: 'features', label: 'Features', icon: 'star' },\n { id: 'pricing', label: 'Pricing', icon: 'dollar' }\n]\" />\n\n\u003c!-- ❌ Bad: Too many similar tabs -->\n\u003cMazTabs v-model=\"activeTab\" :tabs=\"[\n { id: 'info1', label: 'Information' },\n { id: 'info2', label: 'Details' },\n { id: 'info3', label: 'Data' },\n { id: 'info4', label: 'Content' }\n]\" />\n```\n\n### Stepper\n\n**DO**:\n- Use steppers for sequential workflows (checkout, onboarding, forms)\n- Show progress visually\n- Allow users to go back and review previous steps\n- Validate each step before allowing progression\n\n**DON'T**:\n- Use steppers for non-sequential content\n- Skip validation between steps\n- Make all steps clickable if order matters\n\n```vue\n\u003c!-- ✅ Good: Linear stepper with validation -->\n\u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n linear\n @change=\"validateStep\"\n/>\n\n\u003c!-- ❌ Bad: Non-linear stepper for sequential process -->\n\u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n :linear=\"false\"\n clickable\n/>\n```\n\n### Pagination\n\n**DO**:\n- Show total item count\n- Provide per-page options for user control\n- Use server-side pagination for large datasets\n- Reset to page 1 when filters/search changes\n\n**DON'T**:\n- Load all data client-side for large datasets\n- Use pagination for very small datasets (\u003c20 items)\n- Forget to show current page range\n\n```vue\n\u003c!-- ✅ Good: Server-side pagination with info -->\n\u003cdiv>\n \u003cp>Showing {{ startItem }}-{{ endItem }} of {{ totalItems }}\u003c/p>\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalItems\"\n :per-page=\"perPage\"\n @change=\"fetchData\"\n />\n\u003c/div>\n\n\u003c!-- ❌ Bad: Client-side pagination for 10,000 items -->\n\u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"10000\"\n :per-page=\"10\"\n/>\n\u003c!-- (All 10,000 items loaded in memory) -->\n```\n\n---\n\n## Accessibility\n\n### Keyboard Navigation\n\nAll navigation components support keyboard navigation:\n\n**Tabs**:\n- `Arrow Left/Right` - Navigate between tabs\n- `Home` - Go to first tab\n- `End` - Go to last tab\n- `Enter/Space` - Activate focused tab\n\n**Stepper**:\n- `Tab` - Focus next step (if clickable)\n- `Enter/Space` - Navigate to step (if clickable)\n\n**Pagination**:\n- `Tab` - Focus next/previous page buttons\n- `Enter/Space` - Navigate to page\n\n### ARIA Attributes\n\n```vue\n\u003c!-- Tabs with ARIA -->\n\u003cMazTabs\n v-model=\"activeTab\"\n :tabs=\"tabs\"\n role=\"tablist\"\n aria-label=\"Product information tabs\"\n>\n \u003ctemplate #overview>\n \u003cdiv role=\"tabpanel\" aria-labelledby=\"tab-overview\">\n Content\n \u003c/div>\n \u003c/template>\n\u003c/MazTabs>\n\n\u003c!-- Stepper with ARIA -->\n\u003cMazStepper\n v-model=\"currentStep\"\n :steps=\"steps\"\n role=\"navigation\"\n aria-label=\"Checkout steps\"\n/>\n\n\u003c!-- Pagination with ARIA -->\n\u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"total\"\n :per-page=\"perPage\"\n aria-label=\"Pagination navigation\"\n/>\n```\n\n---\n\n## Related Documentation\n\n- **[Components Forms](./components-forms.md)** - Form input components\n- **[Components Feedback](./components-feedback.md)** - Loading and feedback components\n- **[Components Layout](./components-layout.md)** - Layout and container components\n- **[Router Integration](./setup-vue.md#router-integration)** - Vue Router integration patterns\n\n---\n\n**Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-14\n**Component Count**: 3 navigation components\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":19923,"content_sha256":"dd1ff229a94bf8a5356917608c75b20260f9cdf2f2765239a2334bbf2dd7ea62"},{"filename":"references/composables.md","content":"# Maz-UI Composables Guide\n\nMaz-UI provides 14+ Vue composables for theming, UI interactions, utilities, and form validation. All composables use Vue 3 Composition API and are fully typed with TypeScript.\n\n**Last Verified**: 2025-12-29 | **Maz-UI Version**: 4.3.3\n\n## Overview\n\nComposables are Vue 3 composition functions that encapsulate and reuse stateful logic. Maz-UI's composables cover:\n\n- **Theming**: Dark mode, theme switching (`useTheme`)\n- **Translations**: i18n management (`useTranslations`)\n- **UI Interactions**: Toasts, dialogs, loading states (`useToast`, `useDialog`, `useWait`)\n- **Utilities**: Responsive design, timers, gestures, idle detection\n- **Forms**: Comprehensive validation with Valibot integration (`useFormValidator`, `useFormField`)\n\n---\n\n## Theming\n\n### useTheme()\n\nManages theme and dark mode for Maz-UI applications.\n\n**Installation Required**: MazUi plugin must be installed with theme option enabled.\n\n```typescript\n// Vue 3\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes'\n\napp.use(MazUi, {\n theme: { preset: mazUi }\n})\n\n// Nuxt 3\nexport default defineNuxtConfig({\n mazUi: {\n composables: { useTheme: true },\n theme: { preset: 'maz-ui' }\n }\n})\n```\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `theme` | `Ref\u003cstring>` | Current theme name (`'light'` or `'dark'`) |\n| `toggleTheme()` | `() => void` | Toggle between light and dark mode |\n| `setTheme(theme)` | `(theme: 'light' \\| 'dark') => void` | Set specific theme |\n| `isDark` | `ComputedRef\u003cboolean>` | True if dark mode is active |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useTheme } from 'maz-ui/composables'\n\nconst { theme, toggleTheme, isDark } = useTheme()\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cp>Current theme: {{ theme }}\u003c/p>\n \u003cp>Dark mode: {{ isDark }}\u003c/p>\n \u003cMazBtn @click=\"toggleTheme\">\n Toggle Theme\n \u003c/MazBtn>\n \u003c/div>\n\u003c/template>\n```\n\n**SSR Compatibility**: ✅ Full support with automatic theme persistence\n\n**Common Use Cases**:\n- Theme toggle buttons in app headers\n- Automatic dark mode based on system preferences\n- Per-user theme preferences stored in localStorage\n\n---\n\n## Translations\n\n### useTranslations()\n\nManages i18n (internationalization) for Maz-UI components.\n\n**Installation Required**: MazUi plugin with translations configuration.\n\n```typescript\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { fr, es } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true,\n messages: { fr, es }\n }\n})\n```\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `locale` | `Ref\u003cstring>` | Current locale (e.g., 'en', 'fr') |\n| `setLocale(locale)` | `(locale: string) => Promise\u003cvoid>` | Switch to different locale (async for lazy loading) |\n| `t(key, variables?)` | `(key: string, vars?: Record\u003cstring, any>) => string` | Translate a key with optional variable substitution |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useTranslations, useToast } from 'maz-ui/composables'\n\nconst { locale, setLocale } = useTranslations()\nconst toast = useToast()\n\nasync function switchLanguage(newLocale: string) {\n try {\n await setLocale(newLocale)\n toast.success(`Language changed to ${newLocale}`)\n } catch (error) {\n toast.error('Failed to load translations')\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazSelect\n v-model=\"locale\"\n :options=\"[\n { label: 'English', value: 'en' },\n { label: 'Français', value: 'fr' }\n ]\"\n @update:model-value=\"switchLanguage\"\n />\n\u003c/template>\n```\n\n**SSR Compatibility**: ✅ Requires immediate loading for initial locale to prevent hydration mismatch\n\n**Important Notes**:\n- Always `await` `setLocale()` when lazy loading translations\n- Use `preloadFallback: true` to prevent raw translation keys from showing\n- For SSR (Nuxt), provide initial locale immediately (not as lazy function)\n\n---\n\n## UI Interactions\n\n### useToast()\n\nDisplay toast notifications (success, error, warning, info, custom).\n\n**Installation Required**: Toast plugin must be installed.\n\n```typescript\n// Vue 3\nimport { MazToast } from 'maz-ui/plugins/toast'\napp.use(MazToast)\n\n// Nuxt 3 - auto-enabled with @maz-ui/nuxt module\n```\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `success(message, options?)` | `(msg: string, opts?: ToastOptions) => void` | Show success toast (green) |\n| `error(message, options?)` | `(msg: string, opts?: ToastOptions) => void` | Show error toast (red) |\n| `warning(message, options?)` | `(msg: string, opts?: ToastOptions) => void` | Show warning toast (orange) |\n| `info(message, options?)` | `(msg: string, opts?: ToastOptions) => void` | Show info toast (blue) |\n| `message(message, options?)` | `(msg: string, opts?: ToastOptions) => void` | Show neutral toast (gray) |\n\n**ToastOptions**:\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `position` | `'top' \\| 'top-right' \\| 'top-left' \\| 'bottom' \\| 'bottom-right' \\| 'bottom-left'` | `'top-right'` | Toast position |\n| `timeout` | `number` | `10000` | Auto-close timeout (ms), `false` for persistent |\n| `button` | `{ text: string, onClick?: () => void, href?: string, closeToast?: boolean }` | - | Action button |\n| `persistent` | `boolean` | `false` | Prevent auto-close |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useToast } from 'maz-ui/composables'\n\nconst toast = useToast()\n\nasync function handleSubmit() {\n try {\n await submitForm()\n toast.success('Form submitted successfully!', {\n position: 'bottom',\n button: {\n text: 'View',\n href: '/submissions',\n closeToast: true\n }\n })\n } catch (error) {\n toast.error('Submission failed. Please try again.', {\n timeout: 5000\n })\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"handleSubmit\">Submit\u003c/MazBtn>\n\u003c/template>\n```\n\n**Best Practices**:\n- Use appropriate toast type for context (success for confirmations, error for failures)\n- Keep messages concise (1-2 sentences)\n- Use action buttons for navigation or undo actions\n- Set shorter `timeout` for less critical messages\n\n---\n\n### useDialog()\n\nProgrammatically open confirmation dialogs without template code.\n\n**Installation Required**: Dialog plugin must be installed.\n\n```typescript\n// Vue 3\nimport { MazDialog } from 'maz-ui/plugins/dialog'\napp.use(MazDialog)\n\n// Nuxt 3 - auto-enabled with @maz-ui/nuxt module\n```\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `open(options)` | `(opts: DialogOptions) => void` | Open dialog with configuration |\n\n**DialogOptions**:\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `title` | `string` | Dialog title |\n| `message` | `string` | Dialog message/content |\n| `onAccept` | `(response: DialogResponse) => void` | Callback when user confirms |\n| `onReject` | `(response: DialogResponse) => void` | Callback when user cancels |\n| `acceptText` | `string` | Custom accept button text (default: \"Accept\") |\n| `rejectText` | `string` | Custom reject button text (default: \"Cancel\") |\n| `persistent` | `boolean` | Prevent closing on backdrop click |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useDialog, useToast } from 'maz-ui/composables'\n\nconst dialog = useDialog()\nconst toast = useToast()\n\nfunction confirmDelete() {\n dialog.open({\n title: 'Delete Account',\n message: 'Are you sure you want to delete your account? This action cannot be undone.',\n acceptText: 'Delete',\n rejectText: 'Cancel',\n onAccept: async () => {\n await deleteAccount()\n toast.success('Account deleted', { position: 'bottom' })\n },\n onReject: () => {\n toast.info('Deletion cancelled', { position: 'bottom' })\n }\n })\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn color=\"danger\" @click=\"confirmDelete\">\n Delete Account\n \u003c/MazBtn>\n\u003c/template>\n```\n\n**Best Practices**:\n- Always provide clear `title` and `message`\n- Use for destructive actions (delete, logout, etc.)\n- Provide custom button text that describes the action\n- Handle both `onAccept` and `onReject` callbacks\n\n---\n\n### useWait()\n\nManage global loading states with named waiters.\n\n**Installation Required**: Wait plugin must be installed.\n\n```typescript\n// Vue 3\nimport { MazWait } from 'maz-ui/plugins/wait'\napp.use(MazWait)\n\n// Nuxt 3 - auto-enabled with @maz-ui/nuxt module\n```\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `start(name)` | `(name: string) => void` | Start named loader |\n| `stop(name)` | `(name: string) => void` | Stop named loader |\n| `isLoading(name)` | `(name: string) => boolean` | Check if specific loader is active |\n| `isLoading()` | `() => boolean` | Check if any loader is active |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useWait } from 'maz-ui/composables'\nimport { onMounted } from 'vue'\n\nconst wait = useWait()\n\nasync function loadData() {\n wait.start('FETCH_DATA')\n try {\n const data = await fetchData()\n // Process data\n } finally {\n wait.stop('FETCH_DATA')\n }\n}\n\nonMounted(loadData)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazFullscreenLoader v-if=\"wait.isLoading('FETCH_DATA')\">\n Loading data...\n \u003c/MazFullscreenLoader>\n \u003cdiv v-else>\n \u003c!-- Content -->\n \u003c/div>\n\u003c/template>\n```\n\n**Best Practices**:\n- Use descriptive waiter names (e.g., 'FETCH_USERS', 'SUBMIT_FORM')\n- Always use try/finally to ensure `stop()` is called\n- Use different waiter names for independent loading states\n- Use `isLoading()` without argument to check global loading state\n\n---\n\n## Utilities\n\n### useBreakpoints()\n\nManage responsive breakpoints for adaptive layouts.\n\n**Installation**: No plugin required (works standalone)\n\n**API**:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `isSmallScreen` | `ComputedRef\u003cboolean>` | True if width \u003c medium breakpoint |\n| `isMediumScreen` | `ComputedRef\u003cboolean>` | True if width >= medium and \u003c large |\n| `isLargeScreen` | `ComputedRef\u003cboolean>` | True if width >= large breakpoint |\n| `width` | `Ref\u003cnumber>` | Current window width |\n| `height` | `Ref\u003cnumber>` | Current window height |\n\n**Configuration**:\n\n```typescript\nconst breakpoints = {\n 'sm': '640px',\n 'md': '768px',\n 'lg': '1024px',\n 'xl': '1280px',\n '2xl': '1536px',\n}\n\nconst {\n isLargeScreen,\n isMediumScreen,\n isSmallScreen,\n} = useBreakpoints({\n breakpoints,\n initialWidth: 0,\n mediumBreakPoint: 'md',\n largeBreakPoint: 'lg',\n})\n```\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useBreakpoints } from 'maz-ui/composables'\n\nconst { isSmallScreen, isMediumScreen, isLargeScreen } = useBreakpoints({\n breakpoints: {\n sm: '640px',\n md: '768px',\n lg: '1024px'\n },\n mediumBreakPoint: 'md',\n largeBreakPoint: 'lg'\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv v-if=\"isSmallScreen\">Mobile view\u003c/div>\n \u003cdiv v-else-if=\"isMediumScreen\">Tablet view\u003c/div>\n \u003cdiv v-else-if=\"isLargeScreen\">Desktop view\u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**SSR Compatibility**: ⚠️ Use `initialWidth` prop for server-side rendering\n\n---\n\n### useWindowSize()\n\nTrack window dimensions reactively.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `width` | `Ref\u003cnumber>` | Current window width in pixels |\n| `height` | `Ref\u003cnumber>` | Current window height in pixels |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useWindowSize } from 'maz-ui/composables'\n\nconst { width, height } = useWindowSize()\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n Window size: {{ width }}x{{ height }}\n \u003c/div>\n\u003c/template>\n```\n\n**Performance**: Uses debounced resize listener to avoid excessive updates\n\n---\n\n### useTimer()\n\nCreate countdown/countup timers with pause/resume/reset.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `time` | `Ref\u003cnumber>` | Current time value |\n| `isRunning` | `Ref\u003cboolean>` | True if timer is active |\n| `start()` | `() => void` | Start/resume timer |\n| `pause()` | `() => void` | Pause timer |\n| `reset()` | `() => void` | Reset to initial value |\n\n**Usage Example - OTP Timer**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useTimer } from 'maz-ui/composables'\n\nconst { time, isRunning, start, reset } = useTimer({\n initialTime: 60,\n countdown: true,\n onComplete: () => {\n console.log('OTP expired')\n }\n})\n\nfunction resendOTP() {\n reset()\n start()\n // Send new OTP\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cp v-if=\"isRunning\">Resend OTP in {{ time }}s\u003c/p>\n \u003cMazBtn v-else @click=\"resendOTP\">Resend OTP\u003c/MazBtn>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n### useSwipe()\n\nDetect swipe gestures for touch interactions.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `direction` | `Ref\u003c'left' \\| 'right' \\| 'up' \\| 'down' \\| null>` | Detected swipe direction |\n| `onSwipe(callback)` | `(cb: (dir: SwipeDirection) => void) => void` | Register swipe callback |\n\n**Usage Example - Mobile Carousel**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useSwipe } from 'maz-ui/composables'\nimport { ref } from 'vue'\n\nconst currentSlide = ref(0)\nconst { onSwipe } = useSwipe()\n\nonSwipe((direction) => {\n if (direction === 'left') {\n currentSlide.value = Math.min(currentSlide.value + 1, totalSlides - 1)\n } else if (direction === 'right') {\n currentSlide.value = Math.max(currentSlide.value - 1, 0)\n }\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"carousel\">\n \u003cimg :src=\"slides[currentSlide]\" />\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n### useIdleTimeout()\n\nDetect user inactivity for auto-logout or session warnings.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `isIdle` | `Ref\u003cboolean>` | True if user is idle |\n| `idleTime` | `Ref\u003cnumber>` | Time elapsed since last activity (ms) |\n| `reset()` | `() => void` | Reset idle timer |\n\n**Usage Example - Session Timeout Warning**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useIdleTimeout, useDialog } from 'maz-ui/composables'\nimport { watch } from 'vue'\n\nconst { isIdle, reset } = useIdleTimeout({\n timeout: 5 * 60 * 1000, // 5 minutes\n events: ['mousemove', 'keydown', 'click']\n})\n\nconst dialog = useDialog()\n\nwatch(isIdle, (idle) => {\n if (idle) {\n dialog.open({\n title: 'Session Timeout Warning',\n message: 'You will be logged out in 1 minute due to inactivity.',\n acceptText: 'Stay Logged In',\n onAccept: () => {\n reset()\n },\n onReject: () => {\n logout()\n }\n })\n }\n})\n\u003c/script>\n```\n\n---\n\n### useUserVisibility()\n\nDetect page visibility changes (tab switch, minimize).\n\n**Installation**: No plugin required\n\n**API**:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `isVisible` | `Ref\u003cboolean>` | True if page is visible |\n| `onVisibilityChange(callback)` | `(cb: (visible: boolean) => void) => void` | Register visibility callback |\n\n**Usage Example - Video Player Pause**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useUserVisibility } from 'maz-ui/composables'\nimport { ref, watch } from 'vue'\n\nconst { isVisible } = useUserVisibility()\nconst videoRef = ref\u003cHTMLVideoElement>()\n\nwatch(isVisible, (visible) => {\n if (!visible && videoRef.value) {\n videoRef.value.pause()\n }\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cvideo ref=\"videoRef\" src=\"/video.mp4\" />\n\u003c/template>\n```\n\n---\n\n### useReadingTime()\n\nCalculate estimated reading time for text content.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `calculateReadingTime(text)` | `(text: string, wpm?: number) => number` | Returns reading time in minutes |\n\n**Usage Example - Blog Post Reading Time**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useReadingTime } from 'maz-ui/composables'\nimport { computed } from 'vue'\n\nconst props = defineProps\u003c{ content: string }>()\n\nconst readingTime = computed(() => {\n const { calculateReadingTime } = useReadingTime()\n return calculateReadingTime(props.content, 200) // 200 words per minute\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cp>{{ readingTime }} min read\u003c/p>\n\u003c/template>\n```\n\n---\n\n### useStringMatching()\n\nFuzzy search and highlighting utilities.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `fuzzyMatch(query, text)` | `(query: string, text: string) => boolean` | Test if query matches text (fuzzy) |\n| `highlight(query, text)` | `(query: string, text: string) => string` | Return text with `\u003cmark>` tags around matches |\n\n**Usage Example - Search Autocomplete**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useStringMatching } from 'maz-ui/composables'\nimport { ref, computed } from 'vue'\n\nconst { fuzzyMatch, highlight } = useStringMatching()\n\nconst searchQuery = ref('')\nconst items = ref(['Apple', 'Banana', 'Cherry', 'Date'])\n\nconst filteredItems = computed(() => {\n return items.value\n .filter(item => fuzzyMatch(searchQuery.value, item))\n .map(item => ({\n text: item,\n highlighted: highlight(searchQuery.value, item)\n }))\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput v-model=\"searchQuery\" placeholder=\"Search...\" />\n \u003cdiv v-for=\"item in filteredItems\" :key=\"item.text\">\n \u003cspan v-html=\"item.highlighted\" />\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n### useDisplayNames()\n\nGet localized display names for countries, languages, currencies.\n\n**Installation**: No plugin required\n\n**API**:\n\n| Method | Signature | Description |\n|--------|-----------|-------------|\n| `getCountryName(code, locale)` | `(code: string, locale: string) => string` | Get country name in specific locale |\n| `getLanguageName(code, locale)` | `(code: string, locale: string) => string` | Get language name in specific locale |\n\n**Usage Example**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useDisplayNames } from 'maz-ui/composables'\n\nconst { getCountryName, getLanguageName } = useDisplayNames()\n\nconst countryName = getCountryName('US', 'en') // \"United States\"\nconst languageName = getLanguageName('fr', 'en') // \"French\"\n\u003c/script>\n```\n\n---\n\n## Forms\n\n### useFormValidator()\n\nComprehensive form validation using Valibot schemas with multiple validation modes.\n\n**Installation**: Valibot peer dependency required\n\n```bash\npnpm add valibot\n```\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `model` | `Ref\u003cModel>` | Form data model (reactive) |\n| `isValid` | `ComputedRef\u003cboolean>` | True if entire form is valid |\n| `isDirty` | `ComputedRef\u003cboolean>` | True if form has been modified |\n| `isSubmitting` | `Ref\u003cboolean>` | True during form submission |\n| `isSubmitted` | `Ref\u003cboolean>` | True after form submission |\n| `errors` | `ComputedRef\u003cRecord\u003cstring, ValidationIssues>>` | Validation errors per field |\n| `errorMessages` | `ComputedRef\u003cRecord\u003cstring, string>>` | First error message per field |\n| `fieldsStates` | `FieldsStates` | Validation state per field |\n| `validateForm()` | `(setErrors?: boolean) => Promise\u003cboolean>` | Manually validate entire form |\n| `handleSubmit(callback)` | `(callback: (data: Model) => void) => (e: Event) => void` | Form submission handler |\n\n**Validation Modes**:\n\n| Mode | Behavior | Use Case |\n|------|----------|----------|\n| `lazy` | Validate on value change | Simple forms (default) |\n| `aggressive` | Validate all fields immediately | Real-time validation |\n| `eager` | Validate on blur (if not empty), then on change | Recommended for UX |\n| `blur` | Validate only on focus loss | Minimal interruption |\n| `progressive` | Field becomes valid after first success, shows error on blur | Best UX for complex forms |\n\n**Basic Usage (Lazy Mode)**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useFormValidator, useToast } from 'maz-ui/composables'\nimport { pipe, string, nonEmpty, number, minValue, maxValue } from 'valibot'\n\nconst schema = {\n name: pipe(\n string('Name is required'),\n nonEmpty('Name is required')\n ),\n age: pipe(\n number('Age is required'),\n minValue(18, 'Must be 18 or older'),\n maxValue(100, 'Must be under 100')\n )\n}\n\nconst { model, isSubmitting, errorMessages, fieldsStates, handleSubmit } =\n useFormValidator({ schema })\n\nconst toast = useToast()\n\nconst onSubmit = handleSubmit(async (formData) => {\n await submitToAPI(formData)\n toast.success('Form submitted!')\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit=\"onSubmit\">\n \u003cMazInput\n v-model=\"model.name\"\n label=\"Name\"\n :hint=\"errorMessages.name\"\n :error=\"!!errorMessages.name\"\n :success=\"fieldsStates.name.valid\"\n />\n \u003cMazInput\n v-model=\"model.age\"\n type=\"number\"\n label=\"Age\"\n :hint=\"errorMessages.age\"\n :error=\"!!errorMessages.age\"\n :success=\"fieldsStates.age.valid\"\n />\n \u003cMazBtn type=\"submit\" :loading=\"isSubmitting\">\n Submit\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n**Advanced: Throttling & Debouncing**:\n\n```typescript\nconst { model, errorMessages } = useFormValidator({\n schema,\n options: {\n debouncedFields: { name: 500 }, // Wait 500ms after typing\n throttledFields: { age: true } // Throttle validation (1000ms default)\n }\n})\n```\n\n**Advanced: Async Validation**:\n\n```typescript\nimport { pipeAsync, checkAsync } from 'valibot'\n\nconst schema = {\n username: pipeAsync(\n string('Username is required'),\n nonEmpty('Username is required'),\n checkAsync(\n async (username) => {\n const available = await checkUsername(username)\n return available\n },\n 'Username is already taken'\n )\n )\n}\n```\n\n**TypeScript Type Safety**:\n\n```typescript\n// Automatic type inference from schema\nconst schema = {\n name: pipe(string(), nonEmpty()),\n age: pipe(number(), minValue(18))\n}\n\nconst { model } = useFormValidator({ schema })\n// model.name is string\n// model.age is number\n```\n\n**See Also**: `references/form-validation.md` for comprehensive examples and patterns\n\n---\n\n### useFormField()\n\nFine-grained control over individual form fields with per-field validation modes.\n\n**Prerequisites**: Must be used with `useFormValidator` initialized first\n\n**API**:\n\n| Property/Method | Type | Description |\n|----------------|------|-------------|\n| `value` | `WritableComputedRef\u003cT>` | Field value (reactive, typed) |\n| `errors` | `ComputedRef\u003cValidationIssues>` | Field validation errors |\n| `errorMessage` | `ComputedRef\u003cstring>` | First error message |\n| `isValid` | `ComputedRef\u003cboolean>` | True if field is valid |\n| `isDirty` | `ComputedRef\u003cboolean>` | True if field modified |\n| `hasError` | `ComputedRef\u003cboolean>` | True if field has errors |\n| `isValidating` | `ComputedRef\u003cboolean>` | True during async validation |\n| `validationEvents` | `ComputedRef\u003c{ onBlur?: () => void }>` | Events to bind with `v-bind` |\n\n**Usage with Eager Mode** (recommended):\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useFormValidator, useFormField } from 'maz-ui/composables'\nimport { useTemplateRef } from 'vue'\n\nconst schema = {\n email: pipe(string(), nonEmpty(), email())\n}\n\nuseFormValidator({\n schema,\n options: { mode: 'eager', identifier: 'signup-form' }\n})\n\n// Method 1: Using ref for automatic event binding\nconst { value: email, hasError, errorMessage } = useFormField\u003cstring>('email', {\n ref: useTemplateRef('emailRef'),\n formIdentifier: 'signup-form'\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n ref=\"emailRef\"\n v-model=\"email\"\n label=\"Email\"\n :hint=\"errorMessage\"\n :error=\"hasError\"\n />\n\u003c/template>\n```\n\n**Usage with Progressive Mode**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst { value, hasError, errorMessage, validationEvents } = useFormField\u003cstring>('name', {\n mode: 'progressive',\n formIdentifier: 'contact-form'\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"value\"\n v-bind=\"validationEvents\"\n label=\"Name\"\n :hint=\"errorMessage\"\n :error=\"hasError\"\n />\n\u003c/template>\n```\n\n**Multiple Forms on Same Page**:\n\n```typescript\n// Form 1\nconst form1 = useFormValidator({\n schema: schema1,\n options: { identifier: 'login-form' }\n})\n\n// Form 2\nconst form2 = useFormValidator({\n schema: schema2,\n options: { identifier: 'signup-form' }\n})\n\n// Use matching identifiers in useFormField\nconst { value } = useFormField\u003cstring>('email', {\n formIdentifier: 'login-form'\n})\n```\n\n**See Also**: `references/form-validation.md` for complete form validation guide\n\n---\n\n## Best Practices\n\n### Performance Tips\n\n1. **Use debouncing/throttling** for expensive validations:\n ```typescript\n useFormValidator({\n schema,\n options: {\n debouncedFields: { username: 500 }, // Check username availability\n throttledFields: { search: true } // Throttle search queries\n }\n })\n ```\n\n2. **Prefer eager/progressive modes** over aggressive for better UX\n3. **Use lazy mode** for simple forms with minimal validation\n4. **Leverage TypeScript** for automatic type inference from schemas\n\n### SSR Compatibility\n\n| Composable | SSR Support | Notes |\n|-----------|-------------|-------|\n| `useTheme` | ✅ Full | Auto theme persistence |\n| `useTranslations` | ✅ Full | Provide initial locale immediately |\n| `useToast` | ✅ Full | Works in SSR mode |\n| `useDialog` | ✅ Full | Works in SSR mode |\n| `useWait` | ✅ Full | Works in SSR mode |\n| `useBreakpoints` | ⚠️ Partial | Use `initialWidth` prop |\n| `useWindowSize` | ⚠️ Partial | Returns 0 on server |\n| `useFormValidator` | ✅ Full | Full SSR support |\n| `useTimer` | ❌ Client-only | Browser API required |\n| `useSwipe` | ❌ Client-only | Touch events required |\n| `useIdleTimeout` | ❌ Client-only | Browser events required |\n| `useUserVisibility` | ❌ Client-only | Page Visibility API required |\n\n### Common Patterns\n\n**Form Submission with Loading & Toasts**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst { handleSubmit, isSubmitting } = useFormValidator({ schema })\nconst toast = useToast()\n\nconst onSubmit = handleSubmit(async (data) => {\n try {\n await api.submit(data)\n toast.success('Submitted successfully!')\n router.push('/success')\n } catch (error) {\n toast.error('Submission failed. Please try again.')\n }\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit=\"onSubmit\">\n \u003c!-- fields -->\n \u003cMazBtn type=\"submit\" :loading=\"isSubmitting\">Submit\u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n**Dark Mode Toggle with Persistence**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst { theme, toggleTheme, isDark } = useTheme()\n\n// Theme is automatically persisted to localStorage\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"toggleTheme\">\n \u003cMazIcon :name=\"isDark ? 'moon' : 'sun'\" />\n {{ isDark ? 'Light' : 'Dark' }} Mode\n \u003c/MazBtn>\n\u003c/template>\n```\n\n---\n\n## Troubleshooting\n\n### useFormValidator Type Errors\n\n**Problem**: `WritableComputedRef\u003cstring | number | boolean | undefined>`\n\n```typescript\n// ❌ Wrong - loses type precision\nconst { value } = useFormField('name')\n\n// ✅ Correct - precise typing\nconst { value } = useFormField\u003cstring>('name')\n```\n\n### Validation Not Triggering (Eager/Progressive modes)\n\n**Problem**: Field validation doesn't work with `eager`/`progressive` modes\n\n```vue\n\u003c!-- ❌ Missing ref or validation events -->\n\u003cMazInput v-model=\"value\" />\n\n\u003c!-- ✅ Use ref for automatic detection -->\n\u003cscript setup>\nconst { value } = useFormField\u003cstring>('name', {\n ref: useTemplateRef('inputRef')\n})\n\u003c/script>\n\u003cMazInput ref=\"inputRef\" v-model=\"value\" />\n\n\u003c!-- ✅ Or use validation events manually -->\n\u003cscript setup>\nconst { value, validationEvents } = useFormField\u003cstring>('name')\n\u003c/script>\n\u003cMazInput v-model=\"value\" v-bind=\"validationEvents\" />\n```\n\n### useTheme Error: \"must be used within MazUi plugin\"\n\n**Problem**: MazUi plugin not installed or theme disabled\n\n```typescript\n// ✅ Vue 3 Fix\napp.use(MazUi, {\n theme: { preset: mazUi }\n})\n\n// ✅ Nuxt 3 Fix\nexport default defineNuxtConfig({\n mazUi: {\n composables: { useTheme: true },\n theme: { preset: 'maz-ui' }\n }\n})\n```\n\n### Translations Showing Raw Keys\n\n**Problem**: Translation keys like `inputPhoneNumber.phoneInput.example` shown instead of translated text\n\n**Causes**:\n- Missing locale import\n- Lazy loading not awaited\n- Missing `preloadFallback` configuration\n\n```typescript\n// ✅ Fix: Immediate loading\nimport { fr } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n preloadFallback: true,\n messages: { fr } // Import immediately\n }\n})\n\n// ✅ Fix: Lazy loading with await\nconst { setLocale } = useTranslations()\nawait setLocale('fr') // Don't forget await!\n```\n\n---\n\n## Related Documentation\n\n- **Form Validation Deep Dive**: `references/form-validation.md`\n- **Translations & i18n**: `references/translations.md`\n- **Plugins (Toast, Dialog, Wait)**: `references/plugins.md`\n- **Theming**: `references/theming.md`\n- **SSR/SSG Considerations**: `references/ssr-ssg.md`\n\n---\n\n**Last Updated**: 2025-12-29 | **Maz-UI Version**: 4.3.3\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":28942,"content_sha256":"7d22c1d95f388ad3cd042d7aee673cb6a6097f21c03ec45b05516aa2745537d4"},{"filename":"references/directives.md","content":"# Maz-UI Directives Guide\n\nMaz-UI provides 5 Vue directives for common UI patterns like tooltips, click detection, and image handling. Directives are special attributes that apply reactive behavior to DOM elements.\n\n**Last Verified**: 2025-12-29 | **Maz-UI Version**: 4.3.3\n\n## Overview\n\nDirectives in Maz-UI:\n\n- **v-tooltip** - Display tooltips on hover/focus\n- **v-click-outside** - Detect clicks outside an element\n- **v-lazy-img** - Lazy-load images with Intersection Observer\n- **v-zoom-img** - Add zoom functionality to images\n- **v-fullscreen-img** - Open images in fullscreen viewer\n\nAll directives are auto-imported in Nuxt 3 with `@maz-ui/nuxt` module. In Vue 3, directives must be registered globally or imported per component.\n\n---\n\n## Installation\n\n### Vue 3\n\n```typescript\n// Import specific directive\nimport { vTooltip } from 'maz-ui/directives/vTooltip'\nimport { vClickOutside } from 'maz-ui/directives/vClickOutside'\n\n// Register globally\napp.directive('tooltip', vTooltip)\napp.directive('click-outside', vClickOutside)\n```\n\n### Nuxt 3\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt']\n // All directives auto-imported!\n})\n```\n\n**Usage in Components**:\n\n```vue\n\u003ctemplate>\n \u003c!-- No imports needed in Nuxt 3 -->\n \u003cdiv v-tooltip=\"'Hello World'\">Hover me\u003c/div>\n\u003c/template>\n```\n\n---\n\n## v-tooltip\n\nDisplay tooltips on hover or focus with customizable positioning and styling.\n\n### Basic Usage\n\n```vue\n\u003ctemplate>\n \u003c!-- String value -->\n \u003cMazBtn v-tooltip=\"'Click to submit'\">Submit\u003c/MazBtn>\n\n \u003c!-- Object with options -->\n \u003cMazBtn v-tooltip=\"{ text: 'Delete item', position: 'left' }\">\n Delete\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### API\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `text` | `string` | - | Tooltip content (required) |\n| `position` | `'top' \\| 'bottom' \\| 'left' \\| 'right'` | `'top'` | Tooltip position |\n| `delay` | `number` | `0` | Show delay in milliseconds |\n| `color` | `'primary' \\| 'secondary' \\| 'success' \\| 'danger' \\| 'warning' \\| 'info'` | `'primary'` | Tooltip color theme |\n| `arrow` | `boolean` | `true` | Show arrow pointing to element |\n\n### Syntax\n\n**String (Simple)**:\n\n```vue\n\u003cbutton v-tooltip=\"'Tooltip text'\">Hover\u003c/button>\n```\n\n**Object (Advanced)**:\n\n```vue\n\u003cbutton v-tooltip=\"{\n text: 'Save changes',\n position: 'bottom',\n color: 'success',\n delay: 300\n}\">\n Save\n\u003c/button>\n```\n\n**Reactive Value**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst tooltipText = ref('Initial tooltip')\n\nfunction updateTooltip() {\n tooltipText.value = 'Updated tooltip!'\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cbutton v-tooltip=\"tooltipText\" @click=\"updateTooltip\">\n Dynamic Tooltip\n \u003c/button>\n\u003c/template>\n```\n\n### Positioning\n\n```vue\n\u003ctemplate>\n \u003cdiv class=\"demo\">\n \u003cbutton v-tooltip=\"{ text: 'Top tooltip', position: 'top' }\">Top\u003c/button>\n \u003cbutton v-tooltip=\"{ text: 'Right tooltip', position: 'right' }\">Right\u003c/button>\n \u003cbutton v-tooltip=\"{ text: 'Bottom tooltip', position: 'bottom' }\">Bottom\u003c/button>\n \u003cbutton v-tooltip=\"{ text: 'Left tooltip', position: 'left' }\">Left\u003c/button>\n \u003c/div>\n\u003c/template>\n```\n\n### Color Themes\n\n```vue\n\u003ctemplate>\n \u003cMazBtn v-tooltip=\"{ text: 'Primary action', color: 'primary' }\">Primary\u003c/MazBtn>\n \u003cMazBtn v-tooltip=\"{ text: 'Danger zone!', color: 'danger' }\">Delete\u003c/MazBtn>\n \u003cMazBtn v-tooltip=\"{ text: 'Success!', color: 'success' }\">Save\u003c/MazBtn>\n \u003cMazBtn v-tooltip=\"{ text: 'Warning!', color: 'warning' }\">Caution\u003c/MazBtn>\n\u003c/template>\n```\n\n### Accessibility\n\n- **ARIA**: Automatically adds `aria-label` attribute\n- **Focus**: Tooltip shows on keyboard focus\n- **Screen Readers**: Content announced to assistive technology\n\n### Best Practices\n\n1. **Keep text concise** - 1-2 sentences maximum\n2. **Don't rely on tooltips alone** - Important info should be visible\n3. **Use appropriate delays** - Immediate for icons, delayed for text buttons\n4. **Avoid HTML content** - Use plain text for accessibility\n5. **Position wisely** - Ensure tooltip doesn't overflow viewport\n\n---\n\n## v-click-outside\n\nDetect clicks outside an element to close dropdowns, modals, or menus.\n\n### Basic Usage\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst isOpen = ref(false)\n\nfunction closeDropdown() {\n isOpen.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-click-outside=\"closeDropdown\" class=\"dropdown\">\n \u003cbutton @click=\"isOpen = !isOpen\">Toggle Menu\u003c/button>\n \u003cdiv v-if=\"isOpen\" class=\"menu\">\n \u003ca href=\"#\">Option 1\u003c/a>\n \u003ca href=\"#\">Option 2\u003c/a>\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n### API\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `handler` | `(event: Event) => void` | - | Function to call on outside click |\n| `exclude` | `string[] \\| HTMLElement[]` | `[]` | Elements to exclude from outside click detection |\n| `events` | `string[]` | `['click']` | Events to listen for (e.g., `['click', 'touchstart']`) |\n| `enabled` | `boolean` | `true` | Enable/disable directive |\n\n### Syntax\n\n**Function Handler (Simple)**:\n\n```vue\n\u003cdiv v-click-outside=\"closeMenu\">\n \u003c!-- Content -->\n\u003c/div>\n```\n\n**Object with Options**:\n\n```vue\n\u003cdiv v-click-outside=\"{\n handler: closeMenu,\n exclude: ['.modal-backdrop'],\n events: ['click', 'touchstart']\n}\">\n \u003c!-- Content -->\n\u003c/div>\n```\n\n### Excluding Elements\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst isOpen = ref(false)\nconst triggerRef = ref\u003cHTMLElement>()\n\nfunction close() {\n isOpen.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cbutton ref=\"triggerRef\" @click=\"isOpen = !isOpen\">\n Open Menu\n \u003c/button>\n\n \u003cdiv v-click-outside=\"{\n handler: close,\n exclude: [triggerRef]\n }\"\n v-if=\"isOpen\">\n \u003c!-- Clicking trigger button won't close menu -->\n Menu content\n \u003c/div>\n\u003c/template>\n```\n\n### Conditional Activation\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst isEditing = ref(false)\n\nfunction saveChanges() {\n isEditing.value = false\n // Save logic\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-click-outside=\"{\n handler: saveChanges,\n enabled: isEditing\n }\">\n \u003c!-- Only detect outside clicks when editing -->\n \u003c/div>\n\u003c/template>\n```\n\n### Common Use Cases\n\n**Dropdown Menu**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst showDropdown = ref(false)\n\nfunction closeDropdown() {\n showDropdown.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-click-outside=\"closeDropdown\" class=\"dropdown\">\n \u003cMazBtn @click=\"showDropdown = !showDropdown\">\n Menu\n \u003c/MazBtn>\n \u003cdiv v-if=\"showDropdown\" class=\"dropdown-menu\">\n \u003ca href=\"/profile\">Profile\u003c/a>\n \u003ca href=\"/settings\">Settings\u003c/a>\n \u003ca href=\"/logout\">Logout\u003c/a>\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**Modal Close**:\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst isModalOpen = ref(false)\n\nfunction closeModal() {\n isModalOpen.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-if=\"isModalOpen\" class=\"modal-backdrop\">\n \u003cdiv v-click-outside=\"closeModal\" class=\"modal-content\">\n \u003c!-- Modal content -->\n \u003c!-- Clicking backdrop closes modal -->\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n### Performance Considerations\n\n- Event listeners are **added/removed automatically** with directive lifecycle\n- Use `exclude` option to prevent unnecessary checks\n- Consider disabling during animations for better performance\n\n---\n\n## v-lazy-img\n\nLazy-load images using Intersection Observer API for better performance.\n\n### Basic Usage\n\n```vue\n\u003ctemplate>\n \u003c!-- Image loads when scrolled into view -->\n \u003cimg v-lazy-img=\"'/images/photo.jpg'\" alt=\"Photo\" />\n\u003c/template>\n```\n\n### API\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `src` | `string` | - | Image URL to lazy load |\n| `placeholder` | `string` | - | Placeholder image URL while loading |\n| `error` | `string` | - | Image to show if loading fails |\n| `loading` | `string` | - | Loading spinner/image |\n| `threshold` | `number` | `0.01` | Intersection Observer threshold (0-1) |\n| `rootMargin` | `string` | `'0px'` | Margin around root (e.g., '50px' loads 50px before visible) |\n\n### Syntax\n\n**Simple (String)**:\n\n```vue\n\u003cimg v-lazy-img=\"imageUrl\" alt=\"Description\" />\n```\n\n**With Options (Object)**:\n\n```vue\n\u003cimg v-lazy-img=\"{\n src: '/images/photo.jpg',\n placeholder: '/images/placeholder.jpg',\n error: '/images/error.jpg',\n threshold: 0.5\n}\"\nalt=\"Photo\" />\n```\n\n### Placeholder & Error Handling\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst imageUrl = '/images/large-photo.jpg'\nconst placeholderUrl = '/images/blur-placeholder.jpg'\nconst errorUrl = '/images/image-not-found.jpg'\n\u003c/script>\n\n\u003ctemplate>\n \u003cimg\n v-lazy-img=\"{\n src: imageUrl,\n placeholder: placeholderUrl,\n error: errorUrl\n }\"\n alt=\"Product photo\"\n />\n\u003c/template>\n```\n\n### Preload Before Visible\n\n```vue\n\u003ctemplate>\n \u003c!-- Load images 100px before they enter viewport -->\n \u003cimg\n v-lazy-img=\"{\n src: '/images/photo.jpg',\n rootMargin: '100px'\n }\"\n alt=\"Photo\"\n />\n\u003c/template>\n```\n\n### Loading State\n\n```vue\n\u003ctemplate>\n \u003cimg\n v-lazy-img=\"{\n src: '/images/photo.jpg',\n loading: '/images/spinner.gif'\n }\"\n alt=\"Photo\"\n class=\"lazy-image\"\n />\n\u003c/template>\n\n\u003cstyle scoped>\n.lazy-image {\n min-height: 200px;\n background: #f0f0f0;\n}\n\u003c/style>\n```\n\n### Intersection Observer Threshold\n\n```vue\n\u003ctemplate>\n \u003c!-- Load when 50% of image is visible -->\n \u003cimg\n v-lazy-img=\"{\n src: '/images/photo.jpg',\n threshold: 0.5\n }\"\n alt=\"Photo\"\n />\n\n \u003c!-- Load when fully visible -->\n \u003cimg\n v-lazy-img=\"{\n src: '/images/photo.jpg',\n threshold: 1.0\n }\"\n alt=\"Photo\"\n />\n\u003c/template>\n```\n\n### Best Practices\n\n1. **Always provide alt text** - Required for accessibility\n2. **Use placeholders** - Improve perceived performance\n3. **Set dimensions** - Prevent layout shift\n4. **Optimize placeholder images** - Use small, blurred versions\n5. **Use appropriate threshold** - Balance between early loading and performance\n\n### SSR Compatibility\n\n- ✅ Works in SSR (Nuxt)\n- Placeholder shown on server, lazy loading on client\n- No hydration mismatches\n\n---\n\n## v-zoom-img\n\nAdd zoom functionality to images on hover or click.\n\n### Basic Usage\n\n```vue\n\u003ctemplate>\n \u003c!-- Hover to zoom -->\n \u003cimg v-zoom-img=\"'/images/product.jpg'\" alt=\"Product\" />\n\u003c/template>\n```\n\n### API\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `scale` | `number` | `2` | Zoom scale multiplier |\n| `trigger` | `'hover' \\| 'click'` | `'hover'` | Zoom trigger event |\n| `duration` | `number` | `300` | Transition duration (ms) |\n| `origin` | `'center' \\| 'cursor'` | `'cursor'` | Zoom origin point |\n\n### Syntax\n\n**Simple**:\n\n```vue\n\u003cimg v-zoom-img=\"imageUrl\" alt=\"Photo\" />\n```\n\n**With Options**:\n\n```vue\n\u003cimg v-zoom-img=\"{\n src: '/images/photo.jpg',\n scale: 3,\n trigger: 'click',\n duration: 500\n}\"\nalt=\"Photo\" />\n```\n\n### Zoom on Hover\n\n```vue\n\u003ctemplate>\n \u003cimg\n v-zoom-img=\"{\n src: '/images/product.jpg',\n scale: 2,\n trigger: 'hover'\n }\"\n alt=\"Product\"\n class=\"product-image\"\n />\n\u003c/template>\n\n\u003cstyle scoped>\n.product-image {\n cursor: zoom-in;\n transition: transform 0.3s ease;\n}\n\u003c/style>\n```\n\n### Zoom on Click\n\n```vue\n\u003ctemplate>\n \u003cimg\n v-zoom-img=\"{\n src: '/images/artwork.jpg',\n scale: 4,\n trigger: 'click',\n origin: 'center'\n }\"\n alt=\"Artwork\"\n />\n\u003c/template>\n```\n\n### Use Cases\n\n- **Product Images**: Allow customers to inspect details\n- **Gallery**: Preview images before fullscreen\n- **Documentation**: Zoom into diagrams or screenshots\n- **Portfolio**: Showcase artwork details\n\n---\n\n## v-fullscreen-img\n\nOpen images in fullscreen viewer with zoom and navigation.\n\n### Basic Usage\n\n```vue\n\u003ctemplate>\n \u003c!-- Click to open fullscreen -->\n \u003cimg v-fullscreen-img=\"'/images/photo.jpg'\" alt=\"Photo\" />\n\u003c/template>\n```\n\n### API\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `images` | `string[]` | - | Array of image URLs for gallery mode |\n| `index` | `number` | `0` | Starting index in gallery |\n| `closeOnBackdrop` | `boolean` | `true` | Close on backdrop click |\n| `showNavigation` | `boolean` | `true` | Show prev/next buttons |\n| `showZoom` | `boolean` | `true` | Show zoom controls |\n\n### Syntax\n\n**Single Image**:\n\n```vue\n\u003cimg v-fullscreen-img=\"'/images/photo.jpg'\" alt=\"Photo\" />\n```\n\n**Gallery Mode**:\n\n```vue\n\u003ctemplate>\n \u003cdiv class=\"gallery\">\n \u003cimg\n v-for=\"(image, index) in images\"\n :key=\"image\"\n v-fullscreen-img=\"{\n images: images,\n index: index\n }\"\n :src=\"image\"\n alt=\"Gallery photo\"\n />\n \u003c/div>\n\u003c/template>\n\n\u003cscript setup lang=\"ts\">\nconst images = [\n '/images/photo1.jpg',\n '/images/photo2.jpg',\n '/images/photo3.jpg'\n]\n\u003c/script>\n```\n\n### Fullscreen Options\n\n```vue\n\u003ctemplate>\n \u003cimg\n v-fullscreen-img=\"{\n src: '/images/photo.jpg',\n closeOnBackdrop: false,\n showZoom: true,\n showNavigation: false\n }\"\n alt=\"Photo\"\n />\n\u003c/template>\n```\n\n### Gallery with Thumbnails\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst galleryImages = [\n { thumb: '/thumbs/1.jpg', full: '/full/1.jpg' },\n { thumb: '/thumbs/2.jpg', full: '/full/2.jpg' },\n { thumb: '/thumbs/3.jpg', full: '/full/3.jpg' }\n]\n\nconst fullImages = galleryImages.map(img => img.full)\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"gallery-grid\">\n \u003cimg\n v-for=\"(item, i) in galleryImages\"\n :key=\"i\"\n v-fullscreen-img=\"{\n images: fullImages,\n index: i\n }\"\n :src=\"item.thumb\"\n alt=\"Gallery thumbnail\"\n class=\"thumbnail\"\n />\n \u003c/div>\n\u003c/template>\n```\n\n### Keyboard Navigation\n\nFullscreen viewer supports:\n- **Esc**: Close viewer\n- **Arrow Left/Right**: Navigate gallery\n- **+/-**: Zoom in/out\n- **Space**: Toggle zoom\n\n### Accessibility\n\n- **Focus trap**: Keyboard navigation contained within viewer\n- **ARIA labels**: Screen reader announcements\n- **Keyboard support**: All functions accessible via keyboard\n\n---\n\n## Directive Registration (Vue 3)\n\n### Global Registration\n\n```typescript\n// main.ts\nimport { createApp } from 'vue'\nimport {\n vTooltip,\n vClickOutside,\n vLazyImg,\n vZoomImg,\n vFullscreenImg\n} from 'maz-ui/directives'\n\nconst app = createApp(App)\n\napp.directive('tooltip', vTooltip)\napp.directive('click-outside', vClickOutside)\napp.directive('lazy-img', vLazyImg)\napp.directive('zoom-img', vZoomImg)\napp.directive('fullscreen-img', vFullscreenImg)\n\napp.mount('#app')\n```\n\n### Component-Level Registration\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { vTooltip, vClickOutside } from 'maz-ui/directives'\n\n// Directives available in this component only\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-tooltip=\"'Tooltip text'\">\n \u003cbutton v-click-outside=\"closeMenu\">Menu\u003c/button>\n \u003c/div>\n\u003c/template>\n```\n\n### Custom Directive Names\n\n```typescript\n// Use custom names to avoid conflicts\napp.directive('maz-tooltip', vTooltip)\napp.directive('maz-click-outside', vClickOutside)\n```\n\n---\n\n## Best Practices\n\n### Performance\n\n1. **v-lazy-img**: Use for images below the fold\n2. **v-tooltip**: Tooltips are lightweight, safe for many elements\n3. **v-click-outside**: Automatically cleans up event listeners\n4. **v-zoom-img**: Use `transform` for GPU acceleration\n5. **v-fullscreen-img**: Only load fullscreen viewer when triggered\n\n### Accessibility\n\n1. **Tooltips**: Provide `aria-label` for screen readers\n2. **Click-outside**: Ensure alternative close methods (Esc key, close button)\n3. **Images**: Always include `alt` attributes\n4. **Keyboard**: Test all directives with keyboard navigation\n5. **Focus**: Ensure logical focus order\n\n### SSR Considerations\n\n| Directive | SSR Support | Notes |\n|-----------|-------------|-------|\n| `v-tooltip` | ✅ Full | Works in SSR |\n| `v-click-outside` | ✅ Full | Event listeners added on client |\n| `v-lazy-img` | ✅ Full | Shows placeholder on server |\n| `v-zoom-img` | ⚠️ Partial | Initialize on client only |\n| `v-fullscreen-img` | ⚠️ Partial | Viewer opens on client only |\n\n---\n\n## Troubleshooting\n\n### Directive Not Working\n\n**Problem**: Directive has no effect\n\n```vue\n\u003c!-- ❌ Wrong: directive not registered -->\n\u003cdiv v-tooltip=\"'Text'\">Hover\u003c/div>\n\n\u003c!-- ✅ Correct: register directive first -->\n\u003cscript setup>\nimport { vTooltip } from 'maz-ui/directives'\n\u003c/script>\n\u003cdiv v-tooltip=\"'Text'\">Hover\u003c/div>\n```\n\n### Click-Outside Triggers Immediately\n\n**Problem**: Click-outside fires on mount\n\n**Solution**: Add small delay or exclude trigger element\n\n```vue\n\u003cscript setup>\nconst triggerRef = ref\u003cHTMLElement>()\n\nfunction close() {\n // Handler\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cbutton ref=\"triggerRef\" @click=\"open\">Open\u003c/button>\n \u003cdiv v-click-outside=\"{\n handler: close,\n exclude: [triggerRef]\n }\">\n Content\n \u003c/div>\n\u003c/template>\n```\n\n### Lazy Images Not Loading\n\n**Problem**: Images never load\n\n**Causes**:\n- Intersection Observer not supported (IE11)\n- Image dimensions not set (0x0 size)\n- Threshold too high\n\n**Solution**:\n\n```vue\n\u003ctemplate>\n \u003c!-- Set explicit dimensions -->\n \u003cimg\n v-lazy-img=\"{\n src: '/photo.jpg',\n threshold: 0.01\n }\"\n alt=\"Photo\"\n width=\"300\"\n height=\"200\"\n />\n\u003c/template>\n```\n\n---\n\n## Related Documentation\n\n- **Composables**: `references/composables.md`\n- **Components**: `references/components-*.md`\n- **Accessibility**: `references/accessibility.md`\n- **Performance**: `references/performance.md`\n\n---\n\n**Last Updated**: 2025-12-29 | **Maz-UI Version**: 4.3.3\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":17365,"content_sha256":"6025653b1d3e717cfff98e6d2ad736b6dc5bbc4211fa0c175a20f35937de9c8d"},{"filename":"references/form-validation.md","content":"---\nname: \"Maz-UI Form Validation Reference\"\ndescription: \"Complete guide to form validation in Maz-UI using useFormValidator composable with Valibot integration\"\nversion: \"4.3.3\"\nframework: \"Vue 3 / Nuxt 3\"\n---\n\n# Maz-UI Form Validation Guide\n\nComplete guide to form validation in Maz-UI using the `useFormValidator` composable with Valibot integration.\n\n## Overview\n\nMaz-UI provides a powerful form validation system through the `useFormValidator` composable, offering:\n\n- 🔒 TypeScript type safety (automatic type inference from schemas)\n- 📝 5 validation modes (lazy, aggressive, eager, blur, progressive)\n- ✅ Valibot integration (60+ built-in validators)\n- 🎯 Field-level validation states\n- 🚀 Async validation support\n- ♿ Accessibility built-in (ARIA attributes)\n\n---\n\n## Basic Setup\n\n### Installation\n\n```bash\nnpm install valibot\n```\n\n### Framework Differences: Vue vs Nuxt\n\nThis guide shows examples for both **Vue 3** and **Nuxt 3**. The key differences:\n\n**Vue 3 + Vite**:\n- ✅ Explicit imports required: `import { ref } from 'vue'`\n- ✅ Import Maz-UI: `import { useFormValidator } from 'maz-ui/composables'`\n- ✅ Import Valibot: `import { string, email, pipe } from 'valibot'`\n\n**Nuxt 3**:\n- ✅ Auto-imports enabled (no import statements needed)\n- ✅ `ref`, `computed`, `watch` - auto-imported from Vue\n- ✅ `useFormValidator`, `useToast` - auto-imported from Maz-UI\n- ✅ `string`, `email`, `pipe` - auto-imported from Valibot\n\nThroughout this guide, examples will show both versions where they differ.\n\n---\n\n### Simple Form Validation\n\n#### Vue 3 + Vite\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useFormValidator } from 'maz-ui/composables'\nimport { string, email, pipe, minLength, nonEmpty } from 'valibot'\n\n// Define validation schema\nconst schema = {\n email: pipe(\n string('Email is required'),\n nonEmpty('Email is required'),\n email('Invalid email format')\n ),\n password: pipe(\n string('Password is required'),\n minLength(8, 'Password must be at least 8 characters')\n )\n}\n\n// Initialize form validator\nconst {\n model,\n isSubmitting,\n errorMessages,\n fieldsStates,\n handleSubmit\n} = useFormValidator({ schema })\n\n// Submit handler\nconst onSubmit = handleSubmit(async (formData) => {\n console.log('Valid form data:', formData)\n // formData is fully typed from schema\n await api.login(formData.email, formData.password)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit.prevent=\"onSubmit\">\n \u003cMazInput\n v-model=\"model.email\"\n label=\"Email\"\n type=\"email\"\n :error=\"errorMessages.email\"\n :success=\"fieldsStates.email.valid\"\n />\n\n \u003cMazInput\n v-model=\"model.password\"\n label=\"Password\"\n type=\"password\"\n :error=\"errorMessages.password\"\n :success=\"fieldsStates.password.valid\"\n />\n\n \u003cMazBtn type=\"submit\" :loading=\"isSubmitting\">\n Login\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n#### Nuxt 3\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✅ No imports needed - auto-imported!\n// useFormValidator, string, email, pipe, minLength, nonEmpty all available\n\n// Define validation schema\nconst schema = {\n email: pipe(\n string('Email is required'),\n nonEmpty('Email is required'),\n email('Invalid email format')\n ),\n password: pipe(\n string('Password is required'),\n minLength(8, 'Password must be at least 8 characters')\n )\n}\n\n// Initialize form validator\nconst {\n model,\n isSubmitting,\n errorMessages,\n fieldsStates,\n handleSubmit\n} = useFormValidator({ schema })\n\n// Submit handler\nconst onSubmit = handleSubmit(async (formData) => {\n console.log('Valid form data:', formData)\n // formData is fully typed from schema\n\n // ✅ Nuxt: Use $fetch\n await $fetch('/api/login', {\n method: 'POST',\n body: { email: formData.email, password: formData.password }\n })\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit.prevent=\"onSubmit\">\n \u003cMazInput\n v-model=\"model.email\"\n label=\"Email\"\n type=\"email\"\n :error=\"errorMessages.email\"\n :success=\"fieldsStates.email.valid\"\n />\n\n \u003cMazInput\n v-model=\"model.password\"\n label=\"Password\"\n type=\"password\"\n :error=\"errorMessages.password\"\n :success=\"fieldsStates.password.valid\"\n />\n\n \u003cMazBtn type=\"submit\" :loading=\"isSubmitting\">\n Login\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n---\n\n## Validation Modes\n\n### Lazy Mode (Default)\n\n**Validates**: On submit only\n\n```typescript\nconst { model, handleSubmit } = useFormValidator({\n schema,\n mode: 'lazy' // Default\n})\n```\n\n**Best for**:\n- Simple forms\n- One-time submission\n- Minimal validation UX\n\n**User experience**:\n- No validation on input\n- Errors appear after submit attempt\n- Fast initial interaction\n\n---\n\n### Aggressive Mode\n\n**Validates**: On every keystroke\n\n```typescript\nconst { model } = useFormValidator({\n schema,\n mode: 'aggressive'\n})\n```\n\n**Best for**:\n- Complex validation rules\n- Real-time feedback needed\n- Password strength meters\n\n**User experience**:\n- Immediate validation feedback\n- Can be overwhelming for users\n- Best for technical users\n\n**Example**: Password strength indicator\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✅ Vue 3: Explicit imports\nimport { useFormValidator } from 'maz-ui/composables'\nimport { pipe, string, minLength, custom } from 'valibot'\n\nconst schema = {\n password: pipe(\n string(),\n minLength(8),\n custom((value) => {\n const hasUppercase = /[A-Z]/.test(value)\n const hasLowercase = /[a-z]/.test(value)\n const hasNumber = /[0-9]/.test(value)\n const hasSpecial = /[!@#$%^&*]/.test(value)\n\n return hasUppercase && hasLowercase && hasNumber && hasSpecial\n }, 'Password must include uppercase, lowercase, number, and special character')\n )\n}\n\nconst { model, errorMessages } = useFormValidator({\n schema,\n mode: 'aggressive' // Instant feedback\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"model.password\"\n label=\"Password\"\n type=\"password\"\n :error=\"errorMessages.password\"\n hint=\"Must include uppercase, lowercase, number, and special character\"\n />\n\u003c/template>\n```\n\n---\n\n### Eager Mode\n\n**Validates**: On input change after first blur\n\n```typescript\nconst { model } = useFormValidator({\n schema,\n mode: 'eager'\n})\n```\n\n**Best for**:\n- Most forms (recommended)\n- Balance between UX and validation\n- Standard web applications\n\n**User experience**:\n- No validation until user leaves field\n- Then validates on every change\n- Good balance of feedback\n\n---\n\n### Blur Mode\n\n**Validates**: Only when field loses focus\n\n```typescript\nconst { model } = useFormValidator({\n schema,\n mode: 'blur'\n})\n```\n\n**Best for**:\n- Long forms\n- Reduced visual noise\n- Mobile forms (less intrusive)\n\n**User experience**:\n- Validation appears after leaving field\n- Less intrusive than aggressive\n- Cleaner form appearance\n\n---\n\n### Progressive Mode\n\n**Validates**: Progressively as form is filled\n\n```typescript\nconst { model } = useFormValidator({\n schema,\n mode: 'progressive'\n})\n```\n\n**Best for**:\n- Multi-step forms\n- Wizard-style interfaces\n- Sequential input patterns\n\n**User experience**:\n- Validates completed fields first\n- Guides user through form\n- Reduces cognitive load\n\n---\n\n## Valibot Schema Patterns\n\n### Basic Validators\n\n```typescript\nimport {\n string,\n number,\n boolean,\n array,\n object,\n pipe,\n nonEmpty,\n email,\n url,\n minLength,\n maxLength,\n minValue,\n maxValue,\n regex\n} from 'valibot'\n\nconst schema = {\n // String validation\n name: pipe(\n string('Name is required'),\n nonEmpty('Name cannot be empty'),\n minLength(2, 'Name must be at least 2 characters')\n ),\n\n // Email validation\n email: pipe(\n string(),\n email('Invalid email format')\n ),\n\n // Number validation\n age: pipe(\n number('Age must be a number'),\n minValue(18, 'Must be 18 or older'),\n maxValue(120, 'Invalid age')\n ),\n\n // Boolean validation\n terms: pipe(\n boolean(),\n custom((value) => value === true, 'You must accept the terms')\n ),\n\n // URL validation\n website: pipe(\n string(),\n url('Invalid URL format')\n ),\n\n // Pattern validation\n phone: pipe(\n string(),\n regex(/^\\+?[1-9]\\d{1,14}$/, 'Invalid phone number')\n )\n}\n```\n\n---\n\n### Custom Validators\n\n```typescript\nimport { custom, string, pipe } from 'valibot'\n\nconst schema = {\n username: pipe(\n string(),\n minLength(3),\n custom((value) => {\n // No spaces allowed\n return !value.includes(' ')\n }, 'Username cannot contain spaces'),\n custom((value) => {\n // Only alphanumeric and underscore\n return /^[a-zA-Z0-9_]+$/.test(value)\n }, 'Username can only contain letters, numbers, and underscores')\n ),\n\n // Password strength\n password: pipe(\n string(),\n minLength(8),\n custom((value) => {\n const strength = calculatePasswordStrength(value)\n return strength >= 3 // Strong password\n }, 'Password is too weak')\n )\n}\n\nfunction calculatePasswordStrength(password: string): number {\n let strength = 0\n if (password.length >= 8) strength++\n if (/[A-Z]/.test(password)) strength++\n if (/[0-9]/.test(password)) strength++\n if (/[!@#$%^&*]/.test(password)) strength++\n return strength\n}\n```\n\n---\n\n### Async Validation\n\n```typescript\nimport { customAsync } from 'valibot'\n\nconst schema = {\n username: pipe(\n string(),\n minLength(3),\n customAsync(async (value) => {\n // Check if username is available\n const response = await fetch(`/api/check-username?username=${value}`)\n const { available } = await response.json()\n return available\n }, 'Username is already taken')\n ),\n\n email: pipe(\n string(),\n email(),\n customAsync(async (value) => {\n // Check if email is registered\n const response = await fetch(`/api/check-email?email=${value}`)\n const { exists } = await response.json()\n return !exists\n }, 'Email is already registered')\n )\n}\n```\n\n---\n\n### Conditional Validation\n\n```typescript\nimport { object, string, pipe, optional, custom } from 'valibot'\n\nconst schema = object({\n shippingMethod: string(),\n\n // Only validate if shipping method is 'express'\n expressDate: pipe(\n string(),\n custom((value, context) => {\n const shippingMethod = context.dataset.shippingMethod\n if (shippingMethod === 'express' && !value) {\n return false\n }\n return true\n }, 'Express shipping requires a delivery date')\n ),\n\n // Optional field with validation when provided\n promoCode: optional(pipe(\n string(),\n regex(/^PROMO[0-9]{4}$/, 'Invalid promo code format')\n ))\n})\n```\n\n---\n\n## Real-World Form Examples\n\n### Multi-Step Registration Form\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✅ Vue 3: Explicit imports\nimport { ref } from 'vue'\nimport { useFormValidator } from 'maz-ui/composables'\nimport { string, email, pipe, minLength, boolean } from 'valibot'\n\nconst currentStep = ref(1)\n\n// Step 1: Personal Info\nconst step1Schema = {\n firstName: pipe(string(), minLength(2)),\n lastName: pipe(string(), minLength(2)),\n email: pipe(string(), email())\n}\n\nconst step1 = useFormValidator({\n schema: step1Schema,\n mode: 'eager'\n})\n\n// Step 2: Account\nconst step2Schema = {\n username: pipe(string(), minLength(3)),\n password: pipe(string(), minLength(8))\n}\n\nconst step2 = useFormValidator({\n schema: step2Schema,\n mode: 'eager'\n})\n\n// Step 3: Preferences\nconst step3Schema = {\n newsletter: boolean(),\n notifications: boolean()\n}\n\nconst step3 = useFormValidator({\n schema: step3Schema\n})\n\nconst nextStep = step1.handleSubmit(() => {\n currentStep.value = 2\n})\n\nconst nextStep2 = step2.handleSubmit(() => {\n currentStep.value = 3\n})\n\nconst finalSubmit = step3.handleSubmit(async () => {\n const allData = {\n ...step1.model,\n ...step2.model,\n ...step3.model\n }\n\n await api.register(allData)\n toast.success('Registration complete!')\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazStepper v-model=\"currentStep\" :steps=\"3\" />\n\n \u003c!-- Step 1: Personal Info -->\n \u003cform v-if=\"currentStep === 1\" @submit.prevent=\"nextStep\">\n \u003cMazInput\n v-model=\"step1.model.firstName\"\n label=\"First Name\"\n :error=\"step1.errorMessages.firstName\"\n />\n \u003cMazInput\n v-model=\"step1.model.lastName\"\n label=\"Last Name\"\n :error=\"step1.errorMessages.lastName\"\n />\n \u003cMazInput\n v-model=\"step1.model.email\"\n label=\"Email\"\n type=\"email\"\n :error=\"step1.errorMessages.email\"\n />\n \u003cMazBtn type=\"submit\">Next\u003c/MazBtn>\n \u003c/form>\n\n \u003c!-- Step 2: Account -->\n \u003cform v-if=\"currentStep === 2\" @submit.prevent=\"nextStep2\">\n \u003cMazInput\n v-model=\"step2.model.username\"\n label=\"Username\"\n :error=\"step2.errorMessages.username\"\n />\n \u003cMazInput\n v-model=\"step2.model.password\"\n label=\"Password\"\n type=\"password\"\n :error=\"step2.errorMessages.password\"\n />\n \u003cMazBtn @click=\"currentStep = 1\">Back\u003c/MazBtn>\n \u003cMazBtn type=\"submit\">Next\u003c/MazBtn>\n \u003c/form>\n\n \u003c!-- Step 3: Preferences -->\n \u003cform v-if=\"currentStep === 3\" @submit.prevent=\"finalSubmit\">\n \u003cMazCheckbox\n v-model=\"step3.model.newsletter\"\n label=\"Subscribe to newsletter\"\n />\n \u003cMazCheckbox\n v-model=\"step3.model.notifications\"\n label=\"Enable notifications\"\n />\n \u003cMazBtn @click=\"currentStep = 2\">Back\u003c/MazBtn>\n \u003cMazBtn type=\"submit\" :loading=\"step3.isSubmitting\">\n Complete Registration\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n---\n\n### Dynamic Form with Conditional Fields\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✅ Vue 3: Explicit imports\nimport { ref, computed, watch } from 'vue'\nimport { useFormValidator } from 'maz-ui/composables'\nimport { string, email, pipe, minLength, regex } from 'valibot'\n\nconst accountType = ref('personal')\n\nconst schema = computed(() => ({\n accountType: string(),\n\n // Personal account fields\n ...(accountType.value === 'personal' && {\n firstName: pipe(string(), minLength(2)),\n lastName: pipe(string(), minLength(2))\n }),\n\n // Business account fields\n ...(accountType.value === 'business' && {\n companyName: pipe(string(), minLength(2)),\n taxId: pipe(string(), regex(/^\\d{2}-\\d{7}$/))\n }),\n\n email: pipe(string(), email())\n}))\n\nconst { model, errorMessages, handleSubmit } = useFormValidator({\n schema,\n mode: 'eager'\n})\n\nwatch(accountType, (newType) => {\n model.accountType = newType\n})\n\nconst onSubmit = handleSubmit(async (data) => {\n await api.createAccount(data)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit.prevent=\"onSubmit\">\n \u003cMazSelect\n v-model=\"accountType\"\n label=\"Account Type\"\n :options=\"[\n { value: 'personal', label: 'Personal' },\n { value: 'business', label: 'Business' }\n ]\"\n />\n\n \u003c!-- Personal fields -->\n \u003ctemplate v-if=\"accountType === 'personal'\">\n \u003cMazInput\n v-model=\"model.firstName\"\n label=\"First Name\"\n :error=\"errorMessages.firstName\"\n />\n \u003cMazInput\n v-model=\"model.lastName\"\n label=\"Last Name\"\n :error=\"errorMessages.lastName\"\n />\n \u003c/template>\n\n \u003c!-- Business fields -->\n \u003ctemplate v-if=\"accountType === 'business'\">\n \u003cMazInput\n v-model=\"model.companyName\"\n label=\"Company Name\"\n :error=\"errorMessages.companyName\"\n />\n \u003cMazInput\n v-model=\"model.taxId\"\n label=\"Tax ID\"\n placeholder=\"XX-XXXXXXX\"\n :error=\"errorMessages.taxId\"\n />\n \u003c/template>\n\n \u003cMazInput\n v-model=\"model.email\"\n label=\"Email\"\n type=\"email\"\n :error=\"errorMessages.email\"\n />\n\n \u003cMazBtn type=\"submit\">Create Account\u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\n---\n\n## Error Handling Patterns\n\n### Field-Level Errors\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst { model, errorMessages, fieldsStates } = useFormValidator({ schema })\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"model.email\"\n label=\"Email\"\n :error=\"errorMessages.email\"\n :success=\"fieldsStates.email.valid\"\n :warning=\"fieldsStates.email.validating\"\n />\n\u003c/template>\n```\n\n---\n\n### Global Error Messages\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst { errorMessages, hasErrors } = useFormValidator({ schema })\n\nconst globalErrors = computed(() => {\n return Object.values(errorMessages).filter(Boolean)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazAlert v-if=\"hasErrors\" color=\"destructive\">\n \u003cul>\n \u003cli v-for=\"error in globalErrors\" :key=\"error\">\n {{ error }}\n \u003c/li>\n \u003c/ul>\n \u003c/MazAlert>\n\u003c/template>\n```\n\n---\n\n### Custom Error Messages\n\n```typescript\nconst schema = {\n password: pipe(\n string(),\n minLength(8, 'Too short!'), // Custom message\n custom((value) => {\n return /[A-Z]/.test(value)\n }, 'Needs uppercase letter') // Custom message\n )\n}\n```\n\n---\n\n## TypeScript Type Inference\n\n### Automatic Type Safety\n\n```typescript\nconst schema = {\n name: string(),\n age: number(),\n email: pipe(string(), email()),\n newsletter: boolean()\n}\n\nconst { model, handleSubmit } = useFormValidator({ schema })\n\n// model is fully typed:\n// {\n// name: string\n// age: number\n// email: string\n// newsletter: boolean\n// }\n\nconst onSubmit = handleSubmit((data) => {\n // data is fully typed (same as model)\n console.log(data.name) // ✅ string\n console.log(data.age) // ✅ number\n // console.log(data.unknown) // ❌ TypeScript error\n})\n```\n\n---\n\n### Complex Type Inference\n\n```typescript\nimport { object, array, string, number } from 'valibot'\n\nconst schema = object({\n user: object({\n name: string(),\n age: number()\n }),\n tags: array(string()),\n settings: object({\n notifications: boolean()\n })\n})\n\nconst { model } = useFormValidator({ schema })\n\n// model is typed as:\n// {\n// user: {\n// name: string\n// age: number\n// }\n// tags: string[]\n// settings: {\n// notifications: boolean\n// }\n// }\n```\n\n---\n\n## Performance Optimization\n\n### Debouncing Validation\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useDebounceFn } from '@vueuse/core'\n\nconst schema = {\n username: pipe(\n string(),\n customAsync(async (value) => {\n const { available } = await api.checkUsername(value)\n return available\n }, 'Username taken')\n )\n}\n\nconst { model, errorMessages } = useFormValidator({\n schema,\n mode: 'eager'\n})\n\n// Debounce username validation to avoid excessive API calls\nconst debouncedValidation = useDebounceFn(() => {\n // Validation happens automatically via useFormValidator\n}, 500)\n\nwatch(() => model.username, debouncedValidation)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"model.username\"\n label=\"Username\"\n :error=\"errorMessages.username\"\n hint=\"Checking availability...\"\n />\n\u003c/template>\n```\n\n---\n\n### Conditional Validation\n\nOnly validate when necessary:\n\n```typescript\nconst schema = computed(() => {\n const base = {\n email: pipe(string(), email())\n }\n\n // Only add password validation for new users\n if (!props.isEditing) {\n base.password = pipe(string(), minLength(8))\n }\n\n return base\n})\n\nconst { model } = useFormValidator({ schema })\n```\n\n---\n\n## Testing Form Validation\n\n### Unit Testing\n\n```typescript\n// forms/login.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { mount } from '@vue/test-utils'\nimport LoginForm from './LoginForm.vue'\n\ndescribe('LoginForm', () => {\n it('should show error for invalid email', async () => {\n const wrapper = mount(LoginForm)\n\n const emailInput = wrapper.find('input[type=\"email\"]')\n await emailInput.setValue('invalid-email')\n await emailInput.trigger('blur')\n\n await wrapper.vm.$nextTick()\n\n expect(wrapper.text()).toContain('Invalid email format')\n })\n\n it('should submit with valid data', async () => {\n const wrapper = mount(LoginForm)\n\n await wrapper.find('input[type=\"email\"]').setValue('[email protected]')\n await wrapper.find('input[type=\"password\"]').setValue('password123')\n\n await wrapper.find('form').trigger('submit')\n\n // Assert API was called with correct data\n expect(mockApi.login).toHaveBeenCalledWith({\n email: '[email protected]',\n password: 'password123'\n })\n })\n})\n```\n\n---\n\n### E2E Testing\n\n```typescript\n// e2e/registration.spec.ts\nimport { test, expect } from '@playwright/test'\n\ntest('registration form validation', async ({ page }) => {\n await page.goto('/register')\n\n // Submit without filling form\n await page.click('button[type=\"submit\"]')\n\n // Check error messages appear\n await expect(page.locator('text=Email is required')).toBeVisible()\n await expect(page.locator('text=Password is required')).toBeVisible()\n\n // Fill valid data\n await page.fill('input[name=\"email\"]', '[email protected]')\n await page.fill('input[name=\"password\"]', 'SecurePass123!')\n\n // Submit\n await page.click('button[type=\"submit\"]')\n\n // Check success\n await expect(page.locator('text=Registration successful')).toBeVisible()\n})\n```\n\n---\n\n## Accessibility Considerations\n\n### ARIA Attributes\n\n```vue\n\u003ctemplate>\n \u003cMazInput\n v-model=\"model.email\"\n label=\"Email\"\n :error=\"errorMessages.email\"\n :aria-invalid=\"!!errorMessages.email\"\n :aria-describedby=\"errorMessages.email ? 'email-error' : undefined\"\n />\n\n \u003cspan\n v-if=\"errorMessages.email\"\n id=\"email-error\"\n role=\"alert\"\n class=\"error-message\"\n >\n {{ errorMessages.email }}\n \u003c/span>\n\u003c/template>\n```\n\n**Generated HTML**:\n```html\n\u003cinput\n type=\"email\"\n aria-invalid=\"true\"\n aria-describedby=\"email-error\"\n/>\n\u003cspan id=\"email-error\" role=\"alert\">\n Invalid email format\n\u003c/span>\n```\n\n---\n\n### Live Regions\n\n```vue\n\u003ctemplate>\n \u003cdiv aria-live=\"polite\" aria-atomic=\"true\">\n \u003cspan v-if=\"fieldsStates.email.validating\">\n Checking email availability...\n \u003c/span>\n \u003cspan v-else-if=\"fieldsStates.email.valid\">\n Email is available\n \u003c/span>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Validation Checklist\n\n### Form-Level\n\n- [ ] **Validation mode** chosen based on UX requirements\n- [ ] **Error messages** clear and actionable\n- [ ] **Success states** shown for valid fields\n- [ ] **Submit button** disabled during submission\n- [ ] **Loading states** shown during async validation\n- [ ] **ARIA attributes** properly set (`aria-invalid`, `aria-describedby`)\n\n### Field-Level\n\n- [ ] **Required fields** marked with `*` or \"(required)\"\n- [ ] **Password fields** use `type=\"password\"`\n- [ ] **Email fields** use `type=\"email\"` + email validator\n- [ ] **Number fields** use appropriate min/max validators\n- [ ] **Custom validators** have clear error messages\n- [ ] **Async validators** debounced to avoid excessive API calls\n\n---\n\n## Related Documentation\n\n- **[Composables](./composables.md)** - useFormValidator API reference\n- **[Components Forms](./components-forms.md)** - Form components\n- **[Accessibility](./accessibility.md)** - Form accessibility\n- **[Troubleshooting](./troubleshooting.md)** - Common validation errors\n\n---\n\n## External Resources\n\n- **[Valibot Documentation](https://valibot.dev/)** - Complete Valibot guide\n- **[Valibot Validators](https://valibot.dev/api/)** - All built-in validators\n- **[ARIA Forms](https://www.w3.org/WAI/ARIA/apg/patterns/forms/)** - ARIA form patterns\n\n---\n\n**Form Validation Version**: Maz-UI v4.3.3 + Valibot\n**Last Updated**: 2025-12-29\n\n::: tip Validation Mode Recommendation\nFor most forms, use `mode: 'eager'` for the best balance between user experience and validation feedback. It validates after the first blur, then on every change.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":23210,"content_sha256":"9c5cbd4a96fa8283a0d5511a19c4cfc6298007bd2d41e892ec28c6eb1dd1d484"},{"filename":"references/icons.md","content":"# Maz-UI Icons Reference\n\nComprehensive guide to the @maz-ui/icons package - 840+ optimized SVG icons for Vue and Nuxt applications.\n\n## Overview\n\nMaz-UI provides a comprehensive icon library through the `@maz-ui/icons` package and `MazIcon` component:\n\n**Features**:\n- ✅ **840+ Icons** - Comprehensive icon set covering all common use cases\n- ✅ **Optimized SVGs** - Lightweight, crisp at any size\n- ✅ **Tree-Shakable** - Only bundle icons you use\n- ✅ **Customizable** - Size, color, rotation controls\n- ✅ **TypeScript Support** - Full type safety with icon name autocomplete\n- ✅ **Accessibility** - Semantic HTML with ARIA attributes\n- ✅ **SSR Compatible** - Works with Nuxt 3 server-side rendering\n\n**Package**: `@maz-ui/icons`\n**Version**: v4.3.3\n**Icon Count**: 840+\n\n---\n\n## Installation\n\n### Vue 3 Installation\n\n```bash\n# Install icons package\npnpm add @maz-ui/icons\n\n# Or with npm\nnpm install @maz-ui/icons\n```\n\n### Nuxt 3 Installation\n\nIcons are automatically included with the `@maz-ui/nuxt` module:\n\n```bash\npnpm add @maz-ui/nuxt\n```\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt']\n // MazIcon component auto-imported!\n})\n```\n\n---\n\n## Basic Usage\n\n### MazIcon Component\n\n```vue\n\u003cscript setup>\nimport MazIcon from 'maz-ui/components/MazIcon'\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Basic icon -->\n \u003cMazIcon name=\"home\" />\n\n \u003c!-- With color -->\n \u003cMazIcon name=\"heart\" color=\"destructive\" />\n\n \u003c!-- With size -->\n \u003cMazIcon name=\"user\" size=\"2rem\" />\n\n \u003c!-- Custom color (CSS color) -->\n \u003cMazIcon name=\"star\" color=\"#FFD700\" />\n\u003c/template>\n```\n\n### Props\n\n| Prop | Type | Description | Default |\n|------|------|-------------|---------|\n| `name` | `string` | Icon name (required) | - |\n| `size` | `string \\| number` | Icon size (px, em, rem) | `'1.5rem'` |\n| `color` | `'primary' \\| 'secondary' \\| 'info' \\| 'success' \\| 'warning' \\| 'destructive' \\| string` | Icon color | `'current'` |\n| `rotate` | `number` | Rotation angle (degrees) | `0` |\n| `spin` | `boolean` | Enable spin animation | `false` |\n| `pulse` | `boolean` | Enable pulse animation | `false` |\n\n### Direct SVG Import\n\nFor custom usage or tree-shaking optimization:\n\n```vue\n\u003cscript setup>\nimport HomeIcon from '@maz-ui/icons/home'\nimport UserIcon from '@maz-ui/icons/user'\n\u003c/script>\n\n\u003ctemplate>\n \u003cHomeIcon class=\"w-6 h-6 text-primary\" />\n \u003cUserIcon class=\"w-8 h-8 text-success\" />\n\u003c/template>\n```\n\n---\n\n## Icon Categories\n\n### Common Icons\n\n**UI & Navigation** (~120 icons):\n- `home`, `menu`, `search`, `settings`, `close`, `chevron-left`, `chevron-right`, `chevron-up`, `chevron-down`\n- `arrow-left`, `arrow-right`, `arrow-up`, `arrow-down`\n- `more-vertical`, `more-horizontal`, `external-link`, `link`\n\n**Actions** (~100 icons):\n- `edit`, `delete`, `trash`, `save`, `download`, `upload`, `copy`, `paste`\n- `plus`, `minus`, `check`, `x`, `refresh`, `undo`, `redo`\n- `play`, `pause`, `stop`, `skip-forward`, `skip-back`\n\n**Communication** (~80 icons):\n- `mail`, `send`, `inbox`, `message`, `chat`, `comment`, `bell`, `notification`\n- `phone`, `video`, `mic`, `mic-off`, `volume-up`, `volume-down`, `volume-mute`\n\n**Files & Documents** (~70 icons):\n- `file`, `file-text`, `file-image`, `file-video`, `file-audio`, `file-code`\n- `folder`, `folder-open`, `download-cloud`, `upload-cloud`\n- `archive`, `clipboard`, `document`, `page`\n\n**Media** (~60 icons):\n- `image`, `camera`, `video`, `film`, `music`, `headphones`\n- `play-circle`, `pause-circle`, `stop-circle`\n- `volume`, `mic`, `tv`, `monitor`\n\n**Social** (~50 icons):\n- `share`, `heart`, `star`, `thumbs-up`, `thumbs-down`\n- `facebook`, `twitter`, `instagram`, `linkedin`, `github`\n- `youtube`, `twitch`, `discord`, `slack`\n\n**Business** (~80 icons):\n- `briefcase`, `calendar`, `clock`, `dollar`, `credit-card`, `shopping-cart`\n- `tag`, `gift`, `trending-up`, `trending-down`, `bar-chart`, `pie-chart`\n- `users`, `user-plus`, `user-minus`, `user-check`\n\n**System** (~90 icons):\n- `alert-circle`, `alert-triangle`, `info`, `help-circle`, `question`\n- `check-circle`, `x-circle`, `shield`, `lock`, `unlock`, `key`\n- `eye`, `eye-off`, `filter`, `sliders`, `grid`, `list`\n\n**Devices** (~40 icons):\n- `smartphone`, `tablet`, `laptop`, `monitor`, `desktop`, `watch`\n- `printer`, `hard-drive`, `server`, `cpu`, `battery`, `wifi`\n\n**Weather** (~30 icons):\n- `sun`, `moon`, `cloud`, `cloud-rain`, `cloud-snow`, `wind`\n- `umbrella`, `droplet`, `thermometer`\n\n**Other** (~120 icons):\n- `map`, `map-pin`, `navigation`, `compass`, `globe`\n- `bookmark`, `flag`, `award`, `trophy`, `target`\n- `tool`, `wrench`, `hammer`, `scissors`, `paperclip`\n\n---\n\n## Common Icon Names\n\n### Most Used Icons\n\n```vue\n\u003ctemplate>\n \u003c!-- Navigation -->\n \u003cMazIcon name=\"home\" />\n \u003cMazIcon name=\"menu\" />\n \u003cMazIcon name=\"search\" />\n \u003cMazIcon name=\"settings\" />\n \u003cMazIcon name=\"user\" />\n\n \u003c!-- Actions -->\n \u003cMazIcon name=\"edit\" />\n \u003cMazIcon name=\"delete\" />\n \u003cMazIcon name=\"save\" />\n \u003cMazIcon name=\"plus\" />\n \u003cMazIcon name=\"check\" />\n\n \u003c!-- Status -->\n \u003cMazIcon name=\"check-circle\" />\n \u003cMazIcon name=\"x-circle\" />\n \u003cMazIcon name=\"alert-circle\" />\n \u003cMazIcon name=\"info\" />\n\n \u003c!-- UI -->\n \u003cMazIcon name=\"chevron-down\" />\n \u003cMazIcon name=\"chevron-right\" />\n \u003cMazIcon name=\"x\" />\n \u003cMazIcon name=\"more-vertical\" />\n\n \u003c!-- Social -->\n \u003cMazIcon name=\"heart\" />\n \u003cMazIcon name=\"star\" />\n \u003cMazIcon name=\"share\" />\n \u003cMazIcon name=\"mail\" />\n\u003c/template>\n```\n\n---\n\n## Icon Sizing\n\n### Predefined Sizes\n\n```vue\n\u003ctemplate>\n \u003cMazIcon name=\"star\" size=\"sm\" /> \u003c!-- 1rem -->\n \u003cMazIcon name=\"star\" size=\"md\" /> \u003c!-- 1.5rem (default) -->\n \u003cMazIcon name=\"star\" size=\"lg\" /> \u003c!-- 2rem -->\n \u003cMazIcon name=\"star\" size=\"xl\" /> \u003c!-- 3rem -->\n\u003c/template>\n```\n\n### Custom Sizes\n\n```vue\n\u003ctemplate>\n \u003c!-- Pixel values -->\n \u003cMazIcon name=\"heart\" size=\"24px\" />\n \u003cMazIcon name=\"heart\" :size=\"24\" /> \u003c!-- Number = px -->\n\n \u003c!-- Em/Rem values -->\n \u003cMazIcon name=\"heart\" size=\"1.5em\" />\n \u003cMazIcon name=\"heart\" size=\"2rem\" />\n\n \u003c!-- Responsive -->\n \u003cMazIcon name=\"heart\" size=\"clamp(1rem, 2vw, 2rem)\" />\n\u003c/template>\n```\n\n---\n\n## Icon Colors\n\n### Theme Colors\n\n```vue\n\u003ctemplate>\n \u003cMazIcon name=\"check\" color=\"primary\" />\n \u003cMazIcon name=\"check\" color=\"secondary\" />\n \u003cMazIcon name=\"check\" color=\"info\" />\n \u003cMazIcon name=\"check\" color=\"success\" />\n \u003cMazIcon name=\"check\" color=\"warning\" />\n \u003cMazIcon name=\"check\" color=\"destructive\" />\n\u003c/template>\n```\n\n### Custom Colors\n\n```vue\n\u003ctemplate>\n \u003c!-- Hex -->\n \u003cMazIcon name=\"star\" color=\"#FFD700\" />\n\n \u003c!-- RGB/RGBA -->\n \u003cMazIcon name=\"heart\" color=\"rgb(239, 68, 68)\" />\n \u003cMazIcon name=\"heart\" color=\"rgba(239, 68, 68, 0.5)\" />\n\n \u003c!-- CSS Variables -->\n \u003cMazIcon name=\"user\" color=\"var(--custom-color)\" />\n\n \u003c!-- Current color (inherits from parent) -->\n \u003cMazIcon name=\"info\" color=\"current\" />\n\u003c/template>\n```\n\n---\n\n## Icon Animations\n\n### Spin Animation\n\nPerfect for loading indicators:\n\n```vue\n\u003ctemplate>\n \u003c!-- Continuous spin -->\n \u003cMazIcon name=\"loader\" spin />\n \u003cMazIcon name=\"refresh\" spin />\n\n \u003c!-- With button -->\n \u003cMazBtn :loading=\"isLoading\">\n \u003cMazIcon v-if=\"isLoading\" name=\"loader\" spin class=\"mr-2\" />\n {{ isLoading ? 'Loading...' : 'Load Data' }}\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Pulse Animation\n\nFor notification badges:\n\n```vue\n\u003ctemplate>\n \u003cdiv class=\"relative\">\n \u003cMazIcon name=\"bell\" />\n \u003cMazIcon\n name=\"circle\"\n color=\"destructive\"\n pulse\n size=\"8px\"\n class=\"absolute top-0 right-0\"\n />\n \u003c/div>\n\u003c/template>\n```\n\n### Rotation\n\n```vue\n\u003ctemplate>\n \u003c!-- Static rotation -->\n \u003cMazIcon name=\"arrow-up\" :rotate=\"90\" /> \u003c!-- Points right -->\n \u003cMazIcon name=\"arrow-up\" :rotate=\"180\" /> \u003c!-- Points down -->\n \u003cMazIcon name=\"arrow-up\" :rotate=\"270\" /> \u003c!-- Points left -->\n\n \u003c!-- Dynamic rotation -->\n \u003cMazIcon\n name=\"chevron-down\"\n :rotate=\"isOpen ? 180 : 0\"\n class=\"transition-transform\"\n />\n\u003c/template>\n```\n\n---\n\n## Icon in Components\n\n### Buttons with Icons\n\n```vue\n\u003ctemplate>\n \u003c!-- Icon only -->\n \u003cMazBtn icon>\n \u003cMazIcon name=\"heart\" />\n \u003c/MazBtn>\n\n \u003c!-- Icon + Text -->\n \u003cMazBtn>\n \u003cMazIcon name=\"download\" class=\"mr-2\" />\n Download\n \u003c/MazBtn>\n\n \u003c!-- Icon on right -->\n \u003cMazBtn>\n Next\n \u003cMazIcon name=\"chevron-right\" class=\"ml-2\" />\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Input Icons\n\n```vue\n\u003ctemplate>\n \u003cMazInput\n v-model=\"email\"\n type=\"email\"\n placeholder=\"Email\"\n >\n \u003ctemplate #prefix>\n \u003cMazIcon name=\"mail\" />\n \u003c/template>\n \u003c/MazInput>\n\n \u003cMazInput\n v-model=\"password\"\n type=\"password\"\n >\n \u003ctemplate #suffix>\n \u003cMazBtn\n icon\n @click=\"showPassword = !showPassword\"\n >\n \u003cMazIcon :name=\"showPassword ? 'eye-off' : 'eye'\" />\n \u003c/MazBtn>\n \u003c/template>\n \u003c/MazInput>\n\u003c/template>\n```\n\n### Cards with Icons\n\n```vue\n\u003ctemplate>\n \u003cMazCard>\n \u003ctemplate #header>\n \u003cdiv class=\"flex items-center gap-2\">\n \u003cMazIcon name=\"inbox\" color=\"primary\" />\n \u003ch3>Inbox\u003c/h3>\n \u003c/div>\n \u003c/template>\n\n \u003cp>5 new messages\u003c/p>\n \u003c/MazCard>\n\u003c/template>\n```\n\n### Tabs with Icons\n\n```vue\n\u003cscript setup>\nconst tabs = [\n { id: 'home', label: 'Home', icon: 'home' },\n { id: 'settings', label: 'Settings', icon: 'settings' },\n { id: 'profile', label: 'Profile', icon: 'user' }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTabs v-model=\"activeTab\" :tabs=\"tabs\">\n \u003ctemplate #tab-label=\"{ tab }\">\n \u003cMazIcon :name=\"tab.icon\" class=\"mr-2\" />\n {{ tab.label }}\n \u003c/template>\n \u003c/MazTabs>\n\u003c/template>\n```\n\n---\n\n## Icon Discovery\n\n### Icon Browser\n\nVisit the official Maz-UI documentation to browse all 840+ icons:\n\n**https://maz-ui.com/components/maz-icon**\n\nThe icon browser provides:\n- Visual grid of all icons\n- Search by name or category\n- Click to copy icon name\n- Preview with different sizes/colors\n\n### Search Icons Programmatically\n\n```vue\n\u003cscript setup>\nimport { ref, computed } from 'vue'\n\nconst searchQuery = ref('')\n\n// Common icon names for autocomplete\nconst iconNames = [\n 'home', 'user', 'settings', 'heart', 'star',\n 'mail', 'phone', 'search', 'menu', 'close',\n // ... 830+ more\n]\n\nconst filteredIcons = computed(() =>\n iconNames.filter(name =>\n name.includes(searchQuery.value.toLowerCase())\n )\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"searchQuery\"\n placeholder=\"Search icons...\"\n />\n\n \u003cdiv class=\"grid grid-cols-8 gap-4 mt-4\">\n \u003cdiv\n v-for=\"icon in filteredIcons\"\n :key=\"icon\"\n class=\"flex flex-col items-center gap-1\"\n >\n \u003cMazIcon :name=\"icon\" size=\"2rem\" />\n \u003cspan class=\"text-xs\">{{ icon }}\u003c/span>\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Best Practices\n\n### Icon Sizing\n\n**DO**:\n- Use consistent icon sizes throughout your app\n- Scale icons relative to text (1em, 1.5em)\n- Use larger icons for touch targets on mobile (min 44px)\n\n**DON'T**:\n- Mix wildly different icon sizes in the same context\n- Use icons smaller than 16px (hard to see)\n- Use icons larger than 64px without purpose\n\n```vue\n\u003c!-- ✅ Good: Consistent sizing -->\n\u003cdiv class=\"flex items-center gap-2\">\n \u003cMazIcon name=\"user\" size=\"1.25em\" />\n \u003cspan class=\"text-base\">John Doe\u003c/span>\n\u003c/div>\n\n\u003c!-- ❌ Bad: Inconsistent sizing -->\n\u003cdiv class=\"flex items-center gap-2\">\n \u003cMazIcon name=\"user\" size=\"3rem\" />\n \u003cspan class=\"text-sm\">John Doe\u003c/span>\n\u003c/div>\n```\n\n### Icon Colors\n\n**DO**:\n- Use semantic colors (success, warning, destructive)\n- Maintain sufficient contrast for accessibility\n- Use `color=\"current\"` to inherit parent color\n\n**DON'T**:\n- Use too many different colors\n- Use colors that don't convey meaning\n- Forget about dark mode color contrast\n\n```vue\n\u003c!-- ✅ Good: Semantic colors -->\n\u003cMazIcon name=\"check-circle\" color=\"success\" />\n\u003cMazIcon name=\"alert-triangle\" color=\"warning\" />\n\u003cMazIcon name=\"x-circle\" color=\"destructive\" />\n\n\u003c!-- ❌ Bad: Random colors -->\n\u003cMazIcon name=\"check\" color=\"#FF00FF\" />\n\u003cMazIcon name=\"info\" color=\"#12AB34\" />\n```\n\n### Accessibility\n\n**DO**:\n- Provide meaningful aria-label for icon-only buttons\n- Use semantic HTML alongside icons\n- Ensure icons are not the only indicator\n\n**DON'T**:\n- Rely solely on icons for critical information\n- Use decorative icons without hiding from screen readers\n\n```vue\n\u003c!-- ✅ Good: Accessible icon button -->\n\u003cMazBtn icon aria-label=\"Delete item\">\n \u003cMazIcon name=\"trash\" />\n\u003c/MazBtn>\n\n\u003c!-- ✅ Good: Icon with text -->\n\u003cMazBtn>\n \u003cMazIcon name=\"save\" class=\"mr-2\" />\n Save\n\u003c/MazBtn>\n\n\u003c!-- ❌ Bad: No accessible label -->\n\u003cMazBtn icon>\n \u003cMazIcon name=\"delete\" />\n\u003c/MazBtn>\n```\n\n### Performance\n\n**DO**:\n- Use direct imports for better tree-shaking\n- Preload commonly used icons\n- Use SVG sprites for repeated icons\n\n**DON'T**:\n- Import entire icon library at once\n- Use raster images when SVG is available\n- Inline large icon sets\n\n```vue\n\u003c!-- ✅ Good: Direct import (tree-shaken) -->\n\u003cscript setup>\nimport HomeIcon from '@maz-ui/icons/home'\nimport UserIcon from '@maz-ui/icons/user'\n\u003c/script>\n\n\u003c!-- ❌ Bad: Import all icons -->\n\u003cscript setup>\nimport * as MazIcons from '@maz-ui/icons'\n\u003c/script>\n```\n\n---\n\n## TypeScript Support\n\n### Icon Name Autocomplete\n\n```typescript\n// types/maz-ui.d.ts\nimport type { IconName } from '@maz-ui/icons'\n\ninterface IconProps {\n name: IconName // Autocomplete for 840+ icon names!\n size?: string | number\n color?: string\n}\n```\n\n### Typed Icon Component\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport type { IconName } from '@maz-ui/icons'\n\nconst icons: IconName[] = [\n 'home',\n 'user',\n 'settings',\n // TypeScript validates these names\n]\n\u003c/script>\n```\n\n---\n\n## SSR Compatibility\n\nIcons work seamlessly with Nuxt 3 server-side rendering:\n\n```vue\n\u003c!-- Nuxt 3 - Auto-imported, SSR-safe -->\n\u003ctemplate>\n \u003cdiv>\n \u003cMazIcon name=\"home\" />\n \u003cMazIcon name=\"user\" />\n \u003c/div>\n\u003c/template>\n```\n\n**No hydration mismatches** - Icons render identically on server and client.\n\n---\n\n## Custom Icon Sets\n\n### Adding Custom Icons\n\nWhile Maz-UI provides 840+ icons, you can add your own:\n\n```vue\n\u003cscript setup>\n// Import custom SVG as component\nimport CustomIcon from '@/assets/icons/custom.svg'\n\u003c/script>\n\n\u003ctemplate>\n \u003cCustomIcon class=\"w-6 h-6 text-primary\" />\n\u003c/template>\n```\n\n### Mixing Icon Libraries\n\nUse Maz-UI icons alongside other libraries:\n\n```vue\n\u003cscript setup>\nimport MazIcon from 'maz-ui/components/MazIcon'\nimport { Icon } from '@iconify/vue' // Alternative library\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazIcon name=\"home\" />\n \u003cIcon icon=\"mdi:home\" />\n\u003c/template>\n```\n\n---\n\n## Related Documentation\n\n- **[MazIcon Component](https://maz-ui.com/components/maz-icon)** - Official component docs\n- **[Icon Browser](https://maz-ui.com/components/maz-icon#icon-browser)** - Browse all 840+ icons\n- **[Components Reference](./components-layout.md)** - Using icons in other components\n- **[Theming Guide](./theming.md)** - Icon colors and theme integration\n\n---\n\n## External Resources\n\n- **[@maz-ui/icons Package](https://www.npmjs.com/package/@maz-ui/icons)** - NPM package\n- **[Icon Source Repository](https://github.com/LouisMazel/maz-ui/tree/master/packages/lib/icons)** - GitHub source code\n- **[Lucide Icons](https://lucide.dev/)** - Original icon set (Maz-UI uses optimized versions)\n\n---\n\n**Version**: @maz-ui/icons v4.3.3\n**Last Updated**: 2025-12-14\n**Icon Count**: 840+ optimized SVG icons\n**Package Size**: ~200KB (tree-shakable to only icons used)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":15279,"content_sha256":"976eeb19fa9da7f151cc84a37f62e67b67b04b3993e7c3be3b338931aea50d56"},{"filename":"references/mcp.md","content":"# Maz-UI MCP Server Reference\n\nGuide to integrating Maz-UI with AI assistants using Model Context Protocol (MCP).\n\n## Overview\n\n### What is Model Context Protocol (MCP)?\n\n**Model Context Protocol (MCP)** is a standardized way to connect AI assistants with external knowledge sources. Think of it as a **smart bridge** between your AI assistant and Maz-UI's documentation.\n\n**Package**: `@maz-ui/mcp`\n**NPM**: [![@maz-ui/mcp](https://badgen.net/npm/v/@maz-ui/mcp/latest)](https://www.npmjs.com/package/@maz-ui/mcp)\n\n### Benefits\n\nInstead of asking _\"How do I use MazBtn?\"_ and getting generic or outdated answers, your AI can now:\n\n- 🔍 **Search** through all 50+ Maz-UI components\n- 📖 **Read** exact documentation for components, composables, directives, plugins\n- 💡 **Suggest** best implementation approaches\n- 🛠️ **Help** with code examples and best practices\n\n### What's Included\n\nThe MCP server provides **read-only access** to:\n\n| Resource Type | Count | Description |\n|--------------|-------|-------------|\n| **Components** | 50+ | All Vue components with props, events, examples |\n| **Guides** | 11 | Installation, theming, migration, best practices |\n| **Composables** | 14+ | Reusable Vue composition functions |\n| **Directives** | 5 | Vue directives for enhanced functionality |\n| **Plugins** | 4 | Toast, dialog, AOS, wait overlay systems |\n| **Helpers** | 20+ | Utility functions for common tasks |\n\n::: tip Security Note\nThe MCP server provides **read-only access** to documentation. No sensitive data is transmitted or stored.\n:::\n\n---\n\n## Supported AI Assistants\n\nMaz-UI MCP server works with:\n\n- **Claude Code** - Anthropic's CLI tool\n- **Claude Desktop** - Desktop application\n- **Cursor IDE** - AI-powered code editor\n- **Windsurf** - Development environment\n- **VS Code Copilot** - GitHub Copilot in VS Code\n- **Cline** - VS Code extension\n\n---\n\n## Installation & Configuration\n\n### Claude Code\n\n**1. Add MCP Server**:\n```bash\n# Install at project scope (recommended)\nclaude mcp add maz-ui npx @maz-ui/mcp --scope project\n\n# Or user scope (global)\nclaude mcp add maz-ui npx @maz-ui/mcp --scope user\n\n# Or local scope (current directory only)\nclaude mcp add maz-ui npx @maz-ui/mcp --scope local\n```\n\n**2. Configuration File**:\n\nThe command creates/updates `~/.mcp.json` (or project-specific `.mcp.json`):\n\n```json\n{\n \"mcpServers\": {\n \"maz-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**3. Restart**:\n```bash\n# Restart Claude Code to apply configuration\n```\n\n**4. Verify**:\n\nAsk Claude Code: _\"What Maz-UI components are available for forms?\"_\n\nThe AI will now search the MCP server and provide accurate, up-to-date information.\n\n---\n\n### Claude Desktop\n\n**1. Open Settings**:\n- Launch Claude Desktop\n- Navigate to **Settings**\n\n**2. Edit Config**:\n- Under **Developer** tab\n- Tap **Edit Config** to open configuration file\n\n**3. Add Configuration**:\n\n```json\n{\n \"mcpServers\": {\n \"maz-ui\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**4. Restart**:\n- Save configuration file\n- Restart Claude Desktop\n\n**5. Verify**:\n- Start a new chat\n- Look for hammer (MCP) icon\n- Maz-UI server should be listed as available\n\n---\n\n### Cursor IDE\n\n**1. Create Config Directory**:\n```bash\n# In your project root\nmkdir -p .cursor\n```\n\n**2. Create MCP Config**:\n\nCreate `.cursor/mcp.json`:\n\n```json\n{\n \"mcpServers\": {\n \"maz-ui\": {\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**3. Verify Connection**:\n- Open Cursor Settings\n- Navigate to **Settings** → **MCP**\n- Green active status = successfully connected\n\n**4. Usage**:\n\nAsk Cursor: _\"Show me how to implement a multi-step form with MazStepper\"_\n\n---\n\n### Windsurf\n\n**1. Open MCP Settings**:\n- Launch Windsurf\n- Navigate to **Cascade assistant**\n- Tap hammer (MCP) icon\n- Tap **Configure**\n\n**2. Add Configuration**:\n\n```json\n{\n \"mcpServers\": {\n \"maz-ui\": {\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**3. Reload**:\n- Save configuration file\n- Tap **Refresh** in Cascade assistant\n\n**4. Verify**:\n- Green active status = successfully connected\n\n---\n\n### Visual Studio Code (Copilot)\n\n**1. Create Config Directory**:\n```bash\n# In your project root\nmkdir -p .vscode\n```\n\n**2. Create MCP Config**:\n\nCreate `.vscode/mcp.json`:\n\n```json\n{\n \"servers\": {\n \"maz-ui\": {\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**3. Setup Copilot**:\n- Open Copilot chat\n- Switch to **Agent** mode\n- Tap tool icon to confirm MCP tools are available\n- Enter personal access token when prompted\n\n**4. Usage**:\n\nAsk Copilot: _\"What's the best way to handle form validation with Maz-UI?\"_\n\n---\n\n### Cline (VS Code Extension)\n\n**1. Open MCP Settings**:\n- Open Cline extension in VS Code\n- Tap **MCP Servers** icon\n- Tap **Configure MCP Servers**\n\n**2. Add Configuration**:\n\n```json\n{\n \"mcpServers\": {\n \"maz-ui\": {\n \"command\": \"npx\",\n \"args\": [\"@maz-ui/mcp\"]\n }\n }\n}\n```\n\n**3. Auto-Reload**:\n- Save configuration file\n- Cline automatically reloads configuration\n\n**4. Verify**:\n- Green active status = successfully connected\n\n---\n\n## Usage Examples\n\n### Component Discovery\n\n**Before MCP**:\n```\nUser: \"How do I create a button in Maz-UI?\"\nAI: *Generic answer or outdated information*\n```\n\n**With MCP**:\n```\nUser: \"How do I create a button in Maz-UI?\"\nAI: *Searches MCP server, returns current MazBtn documentation with props, events, and examples*\n```\n\n---\n\n### Implementation Help\n\n**Query**: _\"I need a form with email validation, a loading state, and toast notifications on submit\"_\n\n**AI Response** (with MCP):\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { useToast } from 'maz-ui'\nimport { string, email, pipe } from 'valibot'\n\nconst toast = useToast()\nconst isLoading = ref(false)\nconst emailValue = ref('')\n\nconst schema = {\n email: pipe(\n string('Email is required'),\n email('Invalid email format')\n )\n}\n\nconst handleSubmit = async () => {\n isLoading.value = true\n try {\n await submitToAPI({ email: emailValue.value })\n toast.success('Email submitted successfully!')\n } catch (error) {\n toast.error('Submission failed. Please try again.')\n } finally {\n isLoading.value = false\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cform @submit.prevent=\"handleSubmit\">\n \u003cMazInput\n v-model=\"emailValue\"\n type=\"email\"\n label=\"Email Address\"\n placeholder=\"Enter your email\"\n required\n />\n \u003cMazBtn type=\"submit\" :loading=\"isLoading\">\n Submit\n \u003c/MazBtn>\n \u003c/form>\n\u003c/template>\n```\n\nThe AI knows:\n- MazInput component with validation props\n- MazBtn with loading state\n- useToast composable for notifications\n- Valibot integration for schema validation\n\n---\n\n### Best Practices Discovery\n\n**Query**: _\"What's the recommended way to handle theming in Maz-UI v4?\"_\n\n**AI Response** (with MCP):\n- Fetches theming guide from MCP server\n- Suggests @maz-ui/themes package (not legacy CLI)\n- Provides runtime theme switching example\n- Recommends built-in presets (maz-ui, ocean, pristine, obsidian)\n\n---\n\n## Available Resources Details\n\n### 50+ Components\n\n**Forms**:\n- MazInput, MazSelect, MazTextarea, MazCheckbox, MazRadio\n- MazPhoneNumberInput, MazInputPrice, MazInputCode, MazInputTags\n- MazPicker (date/time), MazSlider, MazSwitch\n\n**Navigation**:\n- MazTabs, MazStepper, MazPagination, MazBreadcrumbs\n\n**Feedback**:\n- MazFullscreenLoader, MazLoadingBar, MazCircularProgressBar\n- MazDialog, MazToast, MazAlert, MazBadge, MazAvatar\n\n**Layout**:\n- MazCard, MazAccordion, MazDrawer, MazBottomSheet\n- MazCarousel, MazGallery, MazDropdown, MazPopover\n\n**Display**:\n- MazBtn, MazIcon, MazLazyImg, MazAnimatedText, MazAnimatedCounter\n\n### 14+ Composables\n\n- **Theme**: useTheme (runtime theme switching)\n- **i18n**: useTranslations (8 languages)\n- **UI**: useToast, useDialog, useWait\n- **Layout**: useBreakpoints, useWindowSize\n- **Forms**: useFormValidator (Valibot integration)\n- **Interaction**: useSwipe, useIdleTimeout, useUserVisibility\n- **Utilities**: useTimer, useReadingTime, useStringMatching, useDisplayNames, useFormField\n\n### 5 Directives\n\n- **v-tooltip**: Customizable tooltips with positioning\n- **v-click-outside**: Detect clicks outside element\n- **v-lazy-img**: Lazy load images with blur-up effect\n- **v-zoom-img**: Image zoom on hover/click\n- **v-fullscreen-img**: Open images in fullscreen viewer\n\n### 4 Plugins\n\n- **Toast**: Notification system with actions, persistence, stacking\n- **Dialog**: Promise-based modals with custom buttons\n- **AOS**: Animate On Scroll with 60+ animations\n- **Wait**: Global loading state management\n\n### 11 Guides\n\n1. Getting Started\n2. Installation (Vue, Nuxt)\n3. Theming (v4 themes package)\n4. Migration (v3 → v4)\n5. Auto-Import Resolvers\n6. CLI (legacy v3)\n7. MCP Server\n8. SSR/SSG Support\n9. Accessibility\n10. Performance Optimization\n11. Best Practices\n\n### 20+ Helpers\n\n**String**: capitalize, kebabCase, camelCase, snakeCase, slugify\n**Number**: formatNumber, formatCurrency, clamp, randomInt\n**Date**: formatDate, formatRelative, isValidDate\n**Array**: chunk, unique, shuffle, groupBy\n**Object**: deepClone, mergeDeep, pick, omit\n**Color**: hexToRgb, rgbToHex, lighten, darken, getContrast\n**Validation**: isEmail, isURL, isPhoneNumber, isCreditCard\n\n---\n\n## Troubleshooting\n\n### MCP Server Not Appearing\n\n**Issue**: AI assistant doesn't show Maz-UI in available MCP servers\n\n**Solutions**:\n1. **Check configuration file syntax**:\n ```bash\n # Validate JSON\n cat ~/.mcp.json | jq .\n ```\n2. **Verify npx is installed**:\n ```bash\n npx --version\n ```\n3. **Check network connectivity** (npx needs to download @maz-ui/mcp)\n4. **Restart AI assistant** after configuration changes\n\n---\n\n### Connection Failed\n\n**Issue**: MCP server shows as \"inactive\" or \"connection failed\"\n\n**Solutions**:\n1. **Test npx command directly**:\n ```bash\n npx @maz-ui/mcp\n ```\n2. **Check Node.js version**:\n ```bash\n node --version # Should be 18+\n ```\n3. **Clear npx cache**:\n ```bash\n npx clear-npx-cache\n npx @maz-ui/mcp\n ```\n4. **Check firewall settings** (if using corporate network)\n\n---\n\n### Outdated Documentation Returned\n\n**Issue**: AI returns old information despite MCP server\n\n**Solutions**:\n1. **Verify MCP server is active** (green status)\n2. **Check @maz-ui/mcp version**:\n ```bash\n npm view @maz-ui/mcp version\n ```\n3. **Update package**:\n ```bash\n npx @maz-ui/mcp@latest\n ```\n4. **Restart AI assistant**\n\n---\n\n### AI Not Using MCP Server\n\n**Issue**: AI gives generic answers instead of using MCP\n\n**Solutions**:\n1. **Explicitly request MCP usage**:\n - \"Search Maz-UI documentation for...\"\n - \"Using the Maz-UI MCP server, show me...\"\n2. **Check MCP server is enabled** in AI settings\n3. **Verify hammer (MCP) icon** appears in UI\n\n---\n\n## Advanced Configuration\n\n### Custom Installation Path\n\n**Problem**: Don't want to use npx (prefer global installation)\n\n**Solution**:\n\n1. **Install globally**:\n ```bash\n npm install -g @maz-ui/mcp\n ```\n\n2. **Update configuration**:\n ```json\n {\n \"mcpServers\": {\n \"maz-ui\": {\n \"command\": \"maz-ui-mcp\",\n \"args\": []\n }\n }\n }\n ```\n\n---\n\n### Multiple Projects\n\n**Problem**: Different Maz-UI versions across projects\n\n**Solution**: Use **project-scoped configuration**\n\n**Claude Code**:\n```bash\n# In project directory\nclaude mcp add maz-ui npx @maz-ui/mcp --scope project\n```\n\nCreates `.mcp.json` in project root, not global `~/.mcp.json`.\n\n**Cursor IDE**:\n```bash\n# Each project has .cursor/mcp.json\n```\n\n**VS Code**:\n```bash\n# Each project has .vscode/mcp.json\n```\n\n---\n\n### Offline Usage\n\n**Problem**: Need MCP server without internet\n\n**Solution**:\n\n1. **Cache @maz-ui/mcp**:\n ```bash\n npx @maz-ui/mcp # Downloads and caches\n ```\n\n2. **Verify cache**:\n ```bash\n ls ~/.npm/_npx\n ```\n\n3. **Offline mode**: npx uses cached version when offline\n\n---\n\n## Benefits Summary\n\n### Before MCP\n- ❌ Generic answers from AI training data\n- ❌ Outdated documentation (AI cutoff date)\n- ❌ No context about current Maz-UI version\n- ❌ Manual documentation searching\n\n### After MCP\n- ✅ Accurate, up-to-date documentation\n- ✅ Current Maz-UI v4 best practices\n- ✅ Component-specific examples\n- ✅ AI searches documentation for you\n- ✅ Integration examples with your stack\n\n### Example Impact\n\n**Without MCP**:\n```\nUser: \"How do I validate a form in Maz-UI?\"\nAI: *Generic Vue form validation answer*\n```\n\n**With MCP**:\n```\nUser: \"How do I validate a form in Maz-UI?\"\nAI: *Returns useFormValidator documentation with Valibot schemas,\n validation modes (lazy, aggressive, eager, blur, progressive),\n error handling, TypeScript type inference, real-world examples*\n```\n\n---\n\n## Related Documentation\n\n- **[Setup Vue](./setup-vue.md)** - Vue 3 installation with auto-import resolvers\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt 3 module configuration\n- **[Composables](./composables.md)** - All 14+ composables reference\n- **[Components Forms](./components-forms.md)** - Form components catalog\n- **[Theming](./theming.md)** - v4 theme customization\n- **[Troubleshooting](./troubleshooting.md)** - Common issues and fixes\n\n---\n\n## External Resources\n\n- **[@maz-ui/mcp on NPM](https://www.npmjs.com/package/@maz-ui/mcp)** - MCP server package\n- **[Official MCP Docs](https://maz-ui.com/guide/mcp)** - Official guide\n- **[Model Context Protocol](https://modelcontextprotocol.io/)** - MCP specification\n- **[Claude Code MCP Guide](https://docs.anthropic.com/claude/docs/mcp)** - Anthropic's MCP documentation\n\n---\n\n**MCP Server Version**: @maz-ui/mcp (latest)\n**Supported Maz-UI Version**: v4.3.3+\n**Last Updated**: 2025-12-14\n\n::: tip Recommendation\nEnable MCP for all Maz-UI projects to get intelligent, context-aware AI assistance with components, composables, and best practices.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13904,"content_sha256":"ea889d69fb0d0fa15fefda4c1dee1b21a4eb65e10125abc0eec02bd33a50c106"},{"filename":"references/migration-v4.md","content":"# Maz-UI v4 Migration Guide\n\nComplete guide to migrate from Maz-UI v3.x to v4.0.0 with breaking changes, new features, and step-by-step instructions.\n\n## Overview\n\nMaz-UI v4.0.0 is a **complete rebuild** designed for flexibility, performance, and modern development workflows. The library is now split into independent packages with optimal tree-shaking, redesigned theme system, and comprehensive i18n support.\n\n**Key Improvements**:\n- 60-90% bundle size reduction\n- Modular package architecture\n- Runtime theme switching\n- 8 languages with custom translation support\n- Better TypeScript support\n- No external dependencies (dropzone removed)\n\n---\n\n## Why Migrate to v4?\n\n### Performance Gains\n\n| Metric | v3.x | v4.0.0 | Improvement |\n|--------|------|--------|-------------|\n| **Bundle Size** | ~500KB | ~50-200KB | 60-90% reduction |\n| **Tree-shaking** | Limited | Optimal | Perfect |\n| **Lazy Loading** | Basic | Advanced | Intelligent |\n| **TypeScript** | Good | Excellent | Strict types |\n\n### Architectural Revolution\n\n**Optimized Tree-Shaking**:\n- Every component, composable, plugin, directive, and utility is individually importable\n- Perfect compatibility with Vite, Webpack 5, Rollup\n- Dramatic bundle reduction\n\n**Modular Architecture**:\n- Restructured monorepo with specialized packages\n- Choose exactly what you need\n- Better maintainability\n\n**Advanced Theme System**:\n- Predefined presets: `mazUi`, `obsidian`, `ocean`, `pristine`\n- Dynamic CSS variable generation\n- Runtime theme switching with dark mode strategies\n\n**Complete Internationalization**:\n- 8 supported languages (EN, FR, DE, ES, IT, PT, JA, ZH-CN)\n- Easy custom translation integration\n- Automatic fallback handling\n\n**New & Refactored Components**:\n- MazLink (replaces `MazBtn variant=\"link\"`)\n- MazExpandAnimation (replaces MazTransitionExpand)\n- MazDropzone (rewritten without dropzone dependency)\n- MazPopover (versatile overlay with smart positioning)\n- MazSelectCountry (country/language selector with i18n)\n\n---\n\n## New Package Architecture\n\nv4.0.0 separates functionality into specialized packages:\n\n| Package | Description | Status |\n|---------|-------------|--------|\n| **maz-ui** | Vue components, composables, plugins | Refactored |\n| **@maz-ui/themes** | Theme system and presets | New |\n| **@maz-ui/translations** | i18n translations | New |\n| **@maz-ui/utils** | JavaScript/TypeScript utilities | New |\n| **@maz-ui/icons** | SVG icons and flags (840+ icons) | New |\n| **@maz-ui/cli** | CLI for legacy v3 theme generation | Renamed |\n| **@maz-ui/nuxt** | Nuxt module | New |\n| **@maz-ui/mcp** | MCP server for AI agents | New |\n\n---\n\n## Migration Checklist\n\n### Step 1: Update Dependencies\n\n```bash\n# Uninstall old version\nnpm uninstall maz-ui\n\n# Install new version\nnpm install [email protected]\n\n# Optional: Install specialized packages\nnpm install @maz-ui/themes @maz-ui/translations @maz-ui/utils @maz-ui/icons\n\n# Remove external dependency no longer needed\nnpm uninstall dropzone\n```\n\n**Updated peer dependencies**:\n- **Vue**: `^3.5.0` (was `^3.0.0`)\n- **unplugin-vue-components**: `>=28.0.0`\n- **unplugin-auto-import**: `>=19.0.0`\n\n---\n\n### Step 2: Plugin Configuration\n\n#### Vue Users\n\n**MANDATORY**: v4.0.0 requires Vue plugin for configuration.\n\n**Before (v3.x)**:\n```typescript\n// main.ts\nimport { createApp } from 'vue'\nimport 'maz-ui/css/main.css'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n```\n\n**After (v4.0.0)**:\n```typescript\n// main.ts\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes/presets'\nimport { fr } from '@maz-ui/translations'\n\n// Import styles before your CSS\nimport 'maz-ui/styles'\nimport './style.css'\n\nimport App from './App.vue'\n\nconst app = createApp(App)\n\n// NEW: MazUi plugin required\napp.use(MazUi, {\n // Theme configuration (optional)\n theme: {\n preset: mazUi, // or 'ocean' | 'pristine' | 'obsidian'\n },\n // Translation configuration (optional)\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: {\n fr,\n },\n },\n})\n\napp.mount('#app')\n```\n\n---\n\n#### Nuxt Users\n\n**NEW**: Dedicated Nuxt module with simplified API.\n\n**Before (v3.x)**:\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['maz-ui/nuxt'],\n mazUi: {\n // v3 configuration\n }\n})\n```\n\n**After (v4.0.0)**:\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'], // New package\n\n mazUi: {\n // New configuration API\n theme: {\n preset: 'maz-ui',\n strategy: 'hybrid',\n darkModeStrategy: 'class',\n },\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n },\n plugins: {\n aos: true,\n dialog: true,\n toast: true,\n wait: true,\n },\n directives: {\n vTooltip: true,\n vLazyImg: true,\n vClickOutside: true,\n },\n }\n})\n```\n\n---\n\n### Step 3: Import Migration\n\n#### Components\n\n**Component imports haven't changed** - they work the same as v3.x:\n\n```typescript\n// ✅ SAME AS v3.x - Still works\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\n\n// ✅ NEW - Batch imports for convenience\nimport { MazBtn, MazInput } from 'maz-ui/components'\n```\n\n---\n\n#### Plugins\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { installToaster, ToastHandler } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport { ToastPlugin, ToastHandler } from 'maz-ui/plugins'\n// or for maximum tree-shaking\nimport { ToastPlugin, ToastHandler } from 'maz-ui/plugins/toast'\n```\n\n---\n\n#### Directives\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { vClickOutside, vTooltip } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport { vClickOutside, vTooltip } from 'maz-ui/directives'\n// or for maximum tree-shaking\nimport { vClickOutside } from 'maz-ui/directives/vClickOutside'\nimport { vTooltip } from 'maz-ui/directives/vTooltip'\n```\n\n---\n\n#### Composables\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { useTimer, useToast } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport { useTimer, useToast } from 'maz-ui/composables'\n// or for maximum tree-shaking\nimport { useTimer } from 'maz-ui/composables/useTimer'\nimport { useToast } from 'maz-ui/composables/useToast'\n```\n\n---\n\n#### Utilities\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { currency, date } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport { formatCurrency, formatDate } from 'maz-ui'\n// or for better performance\nimport { formatCurrency, formatDate } from '@maz-ui/utils'\n```\n\n---\n\n## Component Breaking Changes\n\n### MazBtn\n\n#### Removed `variant=\"link\"`\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazBtn variant=\"link\" href=\"/path\">\n Link\n\u003c/MazBtn>\n\n\u003c!-- ✅ AFTER (v4.0.0) - Use MazLink -->\n\u003cMazLink href=\"/path\">\n Link\n\u003c/MazLink>\n\n\u003c!-- Action with click -->\n\u003cMazLink @click=\"handleClick\">\n Action\n\u003c/MazLink>\n```\n\n#### Prop Changes\n\n```vue\n\u003c!-- CHANGED PROPS -->\n\u003cMazBtn\n outlined \u003c!-- ✅ NEW: was 'outline' -->\n justify=\"space-between\" \u003c!-- 🆕 NEW: Content alignment -->\n :padding=\"false\" \u003c!-- 🆕 NEW: Padding control -->\n rounded-size=\"full\" \u003c!-- 🆕 NEW: Border radius size -->\n>\n Button\n\u003c/MazBtn>\n```\n\n---\n\n### MazLink - New Component\n\nReplaces `MazBtn variant=\"link\"` with a richer API:\n\n```vue\n\u003c!-- ✅ NEW COMPONENT -->\n\u003cMazLink\n href=\"/path\"\n :auto-external=\"true\" \u003c!-- 🆕 Automatic external icon -->\n :underline-hover=\"true\" \u003c!-- 🆕 Underline on hover -->\n left-icon=\"home\" \u003c!-- 🆕 Left icon -->\n right-icon=\"arrow-right\" \u003c!-- 🆕 Right icon -->\n color=\"primary\" \u003c!-- 🆕 Custom color -->\n as=\"router-link\" \u003c!-- 🆕 Custom component -->\n>\n Link with icons\n\u003c/MazLink>\n```\n\n---\n\n### MazPicker → MazDatePicker\n\n**Renamed** with updated props:\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazPicker\n v-model=\"date\"\n :no-header=\"true\"\n input-date-style=\"DD/MM/YYYY\"\n/>\n\n\u003c!-- ✅ AFTER (v4.0.0) -->\n\u003cMazDatePicker\n v-model=\"date\"\n :hide-header=\"true\" \u003c!-- 🔄 CHANGED -->\n input-date-format=\"DD/MM/YYYY\" \u003c!-- 🔄 CHANGED -->\n :min-max-auto=\"true\" \u003c!-- 🆕 NEW -->\n/>\n```\n\n---\n\n### MazInputPhoneNumber - Renamed\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazPhoneNumberInput\n v-model=\"phone\"\n v-model:country-code=\"country\"\n :preferred-countries=\"['FR', 'US']\"\n @update=\"handleUpdate\"\n/>\n\n\u003c!-- ✅ AFTER (v4.0.0) -->\n\u003cMazInputPhoneNumber\n v-model=\"phone\"\n v-model:country-code=\"country\"\n :preferred-countries=\"['FR', 'US']\"\n @data=\"handleData\" \u003c!-- 🔄 CHANGED: @update → @data -->\n/>\n```\n\n---\n\n### MazTransitionExpand → MazExpandAnimation\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazTransitionExpand animation-duration=\"500ms\">\n \u003cdiv v-show=\"isOpen\">Content\u003c/div>\n\u003c/MazTransitionExpand>\n\n\u003c!-- ✅ AFTER (v4.0.0) -->\n\u003cMazExpandAnimation\n v-model=\"isOpen\" \u003c!-- 🆕 v-model for state control -->\n duration=\"500ms\" \u003c!-- 🔄 CHANGED -->\n timing-function=\"ease-in-out\" \u003c!-- 🆕 Timing function -->\n>\n \u003cdiv>Content\u003c/div>\n\u003c/MazExpandAnimation>\n```\n\n---\n\n### MazDropzone - Complete Rewrite\n\n**External dependency removed**:\n\n```bash\n# ❌ BEFORE (v3.x) - External dependency required\nnpm install dropzone\n\n# ✅ AFTER (v4.0.0) - No external dependency\nnpm uninstall dropzone\n```\n\n**New Features**:\n\n```vue\n\u003c!-- ✅ NEW FEATURES -->\n\u003cMazDropzone\n v-model=\"files\"\n :auto-upload=\"'single'\" \u003c!-- 🆕 Automatic upload -->\n url=\"/api/upload\" \u003c!-- 🆕 Upload URL -->\n :request-options=\"{ ... }\" \u003c!-- 🆕 Request options -->\n :transform-body=\"transformFn\" \u003c!-- 🆕 Body transformation -->\n :min-file-size=\"0.1\" \u003c!-- 🆕 Min size in MB -->\n @upload-success=\"onSuccess\" \u003c!-- 🆕 Success event -->\n @upload-error=\"onError\" \u003c!-- 🆕 Error event -->\n/>\n```\n\n---\n\n### MazDropdown & MazSelect - Position API\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazDropdown position=\"bottom right\" />\n\u003cMazSelect position=\"bottom right\" />\n\n\u003c!-- ✅ AFTER (v4.0.0) -->\n\u003cMazDropdown position=\"bottom-end\" />\n\u003cMazSelect position=\"bottom-end\" />\n```\n\n**New position type**:\n```typescript\ntype MazPopoverPosition = 'auto' | 'top' | 'bottom' | 'left' | 'right' |\n 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' |\n 'left-start' | 'left-end' | 'right-start' | 'right-end'\n```\n\n---\n\n### MazPopover - New Component\n\nVersatile overlay component with smart positioning:\n\n```vue\n\u003c!-- 🆕 NEW COMPONENT -->\n\u003cMazPopover\n trigger=\"click\" \u003c!-- 🆕 Trigger mode -->\n position=\"bottom-start\" \u003c!-- 🆕 Smart positioning -->\n :persistent=\"true\" \u003c!-- 🆕 Keep open for interactions -->\n role=\"dialog\" \u003c!-- 🆕 Accessibility role -->\n>\n \u003ctemplate #trigger>\n \u003cMazBtn>Open Popover\u003c/MazBtn>\n \u003c/template>\n\n \u003ctemplate #default>\n \u003cdiv class=\"p-4\">\n Popover content\n \u003c/div>\n \u003c/template>\n\u003c/MazPopover>\n```\n\n---\n\n### MazSelectCountry - New Component\n\nCountry/language selector with i18n support:\n\n```vue\n\u003c!-- 🆕 NEW COMPONENT -->\n\u003cMazSelectCountry\n v-model=\"selectedCountry\"\n :preferred-codes=\"['US', 'FR']\" \u003c!-- 🆕 Preferred countries -->\n :locale=\"'fr'\" \u003c!-- 🆕 Localization -->\n :hide-flags=\"false\" \u003c!-- 🆕 Flag display -->\n :display-code=\"false\" \u003c!-- 🆕 Show codes -->\n/>\n```\n\n---\n\n### MazDialogPromise → MazDialogConfirm\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { MazDialogPromise } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport { MazDialogConfirm } from 'maz-ui'\n```\n\n---\n\n## Composable Breaking Changes\n\n### useDialog - No Longer Promise-Based\n\nTo avoid JavaScript console errors, useDialog is now callback-based:\n\n**Before (v3.x)**:\n```typescript\nconst dialog = useDialog()\n\ntry {\n const result = await dialog.confirm({\n title: 'Confirm',\n message: 'Are you sure?',\n confirmText: 'Yes',\n cancelText: 'No'\n })\n // Handle confirm\n} catch (error) {\n // Handle cancel\n}\n```\n\n**After (v4.0.0)**:\n```typescript\nconst dialog = useDialog()\n\ndialog.confirm({\n title: 'Confirm',\n message: 'Are you sure?',\n buttons: { // 🔄 CHANGED\n confirm: 'Yes',\n cancel: 'No'\n },\n onAccept: () => { // 🆕 NEW: Accept callback\n // Handle confirm\n },\n onReject: () => { // 🆕 NEW: Reject callback\n // Handle cancel\n },\n onClose: () => { // 🆕 NEW: Close callback (finally)\n // Handle close\n }\n})\n```\n\n---\n\n### useDisplayNames - Renamed\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { useLanguageDisplayNames } from 'maz-ui'\n\nconst { getDisplayName } = useLanguageDisplayNames()\n\n// ✅ AFTER (v4.0.0)\nimport { useDisplayNames } from 'maz-ui/composables'\n\nconst { getDisplayName } = useDisplayNames()\n```\n\n---\n\n### Helpers → Composables\n\n**MAJOR CHANGE**: Several helpers are now Vue composables and must be used within Vue context.\n\n#### useIdleTimeout\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport { idleTimeout } from 'maz-ui'\n\nconst controller = idleTimeout({\n timeout: 5000,\n onTimeout: () => console.log('timeout'),\n onActivity: () => console.log('activity')\n})\n\n// ✅ AFTER (v4.0.0)\nimport { useIdleTimeout } from 'maz-ui/composables'\n\n// In a Vue component\nconst { isIdle } = useIdleTimeout({\n timeout: 5000,\n onTimeout: () => console.log('timeout'),\n onActivity: () => console.log('activity')\n})\n```\n\n**Other migrated helpers**:\n- `userVisibility` → `useUserVisibility`\n- `mountComponent` → `useMountComponent`\n- `injectStrict` → `useInjectStrict`\n- `freezeValue` → `useFreezeValue`\n\n---\n\n## Color System Changes\n\n### Color Removals and Replacements\n\n```typescript\n// ❌ REMOVED COLORS\ncolor=\"theme\" // ✅ REPLACED BY: color=\"contrast\"\ncolor=\"white\" // ❌ REMOVED\ncolor=\"black\" // ❌ REMOVED\ncolor=\"danger\" // ✅ REPLACED BY: color=\"destructive\"\n```\n\n### New Color System\n\n**Available colors in v4.0.0**:\n\n```typescript\ntype MazColor = 'primary' | 'secondary' | 'accent' | 'info' | 'success' |\n 'warning' | 'destructive' | 'contrast' | 'transparent'\n```\n\n**Migration examples**:\n\n```vue\n\u003c!-- ❌ BEFORE (v3.x) -->\n\u003cMazBtn color=\"theme\">Theme Button\u003c/MazBtn>\n\u003cMazBtn color=\"danger\">Danger Button\u003c/MazBtn>\n\n\u003c!-- ✅ AFTER (v4.0.0) -->\n\u003cMazBtn color=\"contrast\">Contrast Button\u003c/MazBtn>\n\u003cMazBtn color=\"destructive\">Destructive Button\u003c/MazBtn>\n```\n\n---\n\n## TypeScript Changes\n\n### Type Prefixing\n\nAll component types are now prefixed with `Maz`:\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport type { Props } from 'maz-ui/components/MazBtn'\nimport type { ButtonsRadioOption, Row, Color, Size } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport type { MazBtnProps } from 'maz-ui/components/MazBtn'\nimport type { MazRadioButtonsOption, MazTableRow, MazColor, MazSize } from 'maz-ui'\n```\n\n### Type Import Changes\n\n```typescript\n// ❌ BEFORE (v3.x)\nimport type { Color, Size } from 'maz-ui'\n\n// ✅ AFTER (v4.0.0)\nimport type { MazColor, MazSize } from 'maz-ui'\n```\n\n---\n\n## Theme System Migration\n\n### Basic Configuration\n\n```typescript\n// main.ts\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes/presets'\n\napp.use(MazUi, {\n theme: {\n preset: mazUi, // or 'ocean' | 'pristine' | 'obsidian'\n },\n})\n```\n\n---\n\n### Custom Theme\n\n```typescript\nimport { definePreset } from '@maz-ui/themes'\nimport { mazUi } from '@maz-ui/themes/presets'\n\nconst customTheme = definePreset({\n base: mazUi,\n name: 'custom-theme',\n colors: {\n light: {\n primary: '220 100% 50%',\n secondary: '220 14% 96%',\n },\n dark: {\n primary: '220 100% 70%',\n secondary: '220 14% 4%',\n }\n }\n})\n\napp.use(MazUi, {\n theme: {\n preset: customTheme,\n },\n})\n```\n\n---\n\n### useTheme Composable\n\n```vue\n\u003cscript setup>\nimport { useTheme } from 'maz-ui/composables'\n\nconst { isDark, toggleDarkMode, setTheme } = useTheme()\n\n// Change theme\nsetTheme('ocean')\n\n// Toggle dark mode\ntoggleDarkMode()\n\u003c/script>\n\n\u003ctemplate>\n \u003cbutton @click=\"toggleDarkMode\">\n {{ isDark ? '☀️' : '🌙' }}\n \u003c/button>\n\u003c/template>\n```\n\n---\n\n## Translation System Migration\n\n### Configuration\n\n```typescript\n// main.ts\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { fr, en } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: {\n fr,\n en,\n },\n },\n})\n```\n\n---\n\n### useTranslations Composable\n\n```vue\n\u003cscript setup>\nimport { useTranslations } from 'maz-ui/composables'\n\nconst { t, locale, setLocale } = useTranslations()\n\n// Change language\nsetLocale('fr')\n\u003c/script>\n\n\u003ctemplate>\n \u003cp>{{ t('button.cancel') }}\u003c/p>\n\u003c/template>\n```\n\n---\n\n## Removed Features\n\n### v-closable Directive\n\n```vue\n\u003c!-- ❌ REMOVED - v-closable directive -->\n\u003cdiv v-closable=\"handler\">Content\u003c/div>\n\n\u003c!-- ✅ ALTERNATIVE - Use v-click-outside -->\n\u003cdiv v-click-outside=\"handler\">Content\u003c/div>\n```\n\n---\n\n## Common Errors & Solutions\n\n### Error: \"idleTimeout is not a function\"\n\n```typescript\n// ❌ Old way\nimport { idleTimeout } from 'maz-ui'\n\n// ✅ New way\nimport { useIdleTimeout } from 'maz-ui/composables'\n\n// In a Vue component\nconst { isIdle } = useIdleTimeout({ timeout: 5000 })\n```\n\n---\n\n### Error: \"MazTransitionExpand is not exported\"\n\n```vue\n\u003c!-- ❌ Removed component -->\n\u003cMazTransitionExpand>\n \u003cdiv v-show=\"isOpen\">Content\u003c/div>\n\u003c/MazTransitionExpand>\n\n\u003c!-- ✅ New component -->\n\u003cMazExpandAnimation v-model=\"isOpen\">\n \u003cdiv>Content\u003c/div>\n\u003c/MazExpandAnimation>\n```\n\n---\n\n### Error: \"Module not found: Can't resolve 'dropzone'\"\n\n```bash\n# ❌ Remove old dependency\nnpm uninstall dropzone\n\n# ✅ MazDropzone has no external dependency\n```\n\n---\n\n### Error: \"useTheme must be used within MazUi plugin\"\n\n```typescript\n// ❌ Missing plugin\nimport { createApp } from 'vue'\n\n// ✅ Add MazUi plugin\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\n\napp.use(MazUi)\n```\n\n---\n\n### Error: \"Property 'outline' does not exist\"\n\n```vue\n\u003c!-- ❌ Old prop name -->\n\u003cMazBtn outline>Button\u003c/MazBtn>\n\n\u003c!-- ✅ New prop name -->\n\u003cMazBtn outlined>Button\u003c/MazBtn>\n```\n\n---\n\n## Complete Migration Checklist\n\n### Dependencies\n- [ ] Update maz-ui to v4.0.0+\n- [ ] Remove `dropzone` dependency\n- [ ] Update Vue to v3.5+\n- [ ] Update unplugin-auto-import to v19+\n- [ ] Update unplugin-vue-components to v28+\n\n### Configuration\n- [ ] Add MazUi plugin in main.ts\n- [ ] Configure theme with new system\n- [ ] Configure translations with new system\n- [ ] Migrate Nuxt configuration to @maz-ui/nuxt (if using Nuxt)\n\n### Imports\n- [ ] Migrate plugin imports to `maz-ui/plugins/*`\n- [ ] Migrate directive imports to `maz-ui/directives/*`\n- [ ] Migrate composable imports to `maz-ui/composables/*`\n- [ ] Update utility imports (currency → formatCurrency, etc.)\n\n### Components\n- [ ] Replace `MazBtn variant=\"link\"` with `MazLink`\n- [ ] Update `MazBtn outline` to `outlined`\n- [ ] Rename `MazPhoneNumberInput` to `MazInputPhoneNumber`\n- [ ] Rename `MazPicker` to `MazDatePicker`\n- [ ] Replace `MazTransitionExpand` with `MazExpandAnimation`\n- [ ] Update `MazDropdown`/`MazSelect` position props\n- [ ] Rename `MazDialogPromise` to `MazDialogConfirm`\n- [ ] Check new `MazDropzone` props\n\n### API Changes\n- [ ] Migrate `useDialog` from Promise to callback API\n- [ ] Rename `useLanguageDisplayNames` to `useDisplayNames`\n- [ ] Update `@update` to `@data` in `MazInputPhoneNumber`\n- [ ] Replace removed colors (theme → contrast, danger → destructive)\n- [ ] Remove `v-closable` directive usage\n\n### Helpers → Composables\n- [ ] Migrate `idleTimeout` to `useIdleTimeout`\n- [ ] Migrate `userVisibility` to `useUserVisibility`\n- [ ] Migrate `mountComponent` to `useMountComponent`\n- [ ] Migrate `injectStrict` to `useInjectStrict`\n- [ ] Migrate `freezeValue` to `useFreezeValue`\n\n### TypeScript\n- [ ] Update all type imports to use `Maz` prefix\n- [ ] Update prop type imports (Props → MazBtnProps)\n- [ ] Update generic types (Color → MazColor, Size → MazSize)\n\n### Testing & Validation\n- [ ] Test TypeScript compilation\n- [ ] Test production build\n- [ ] Check bundle size\n- [ ] Run unit tests\n- [ ] Test in development and production\n- [ ] Test SSR/Nuxt if applicable\n- [ ] Validate critical functionality\n\n---\n\n## Migration Benefits\n\n### Performance\n- 60-90% bundle size reduction\n- Perfect tree-shaking\n- Intelligent lazy loading\n- Strict TypeScript support\n\n### Developer Experience\n- Auto-imports with resolvers\n- Perfect TypeScript auto-completion\n- Nuxt DevTools integration\n- Interactive documentation\n\n### Maintainability\n- Separate packages for better maintenance\n- Semantic versioning per package\n- Mature, tested architecture\n\n---\n\n## Additional Resources\n\n- **[Official v4 Documentation](https://maz-ui.com/)** - Complete documentation\n- **[Theme Guide](./theming.md)** - Advanced theme system\n- **[Translation Guide](./translations.md)** - Internationalization\n- **[Setup Vue](./setup-vue.md)** - Vue installation guide\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt module setup\n- **[Resolvers Guide](./resolvers.md)** - Smart auto-imports\n- **[Complete Changelog](https://github.com/LouisMazel/maz-ui/blob/master/CHANGELOG.md)** - All changes\n\n---\n\n## Need Help?\n\n- **[Create Issue](https://github.com/LouisMazel/maz-ui/issues)** - Report bugs\n- **[Discussions](https://github.com/LouisMazel/maz-ui/discussions)** - Ask questions\n- **[MCP Server](./mcp.md)** - AI-powered migration assistance\n\n---\n\n**Migration Version**: v3.x → v4.0.0\n**Last Updated**: 2025-12-14\n\n::: tip Connect to MCP\nFollow the [MCP guide](./mcp.md) to connect your AI assistant to Maz-UI's documentation for smooth migration assistance.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":21542,"content_sha256":"9c8e0b4b6f7036ebb2d1bcd3da378e0bcbf090600c45e2268c946d7280518fa2"},{"filename":"references/performance.md","content":"# Maz-UI Performance Optimization\n\nComplete guide to optimizing Maz-UI applications for maximum performance, minimal bundle size, and fast loading times.\n\n## Overview\n\nMaz-UI v4 achieves **60-90% bundle size reduction** compared to v3 through optimal tree-shaking, modular architecture, and smart lazy loading. This guide covers all performance optimization techniques.\n\n**Key Metrics**:\n- Bundle Size: ~50-200KB (was ~500KB in v3)\n- Tree-shaking: Perfect (every export is individually importable)\n- Lazy Loading: Intelligent (on-demand component loading)\n- TypeScript: Zero runtime overhead\n\n---\n\n## Bundle Optimization\n\n### Auto-Import Resolvers (Recommended)\n\nThe **most efficient** way to use Maz-UI is with auto-import resolvers:\n\n#### Vite Configuration\n\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport Components from 'unplugin-vue-components/vite'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} from 'maz-ui/resolvers'\n\nexport default defineConfig({\n plugins: [\n vue(),\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n dts: true, // TypeScript definitions\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: true,\n }),\n ],\n})\n```\n\n**Benefits**:\n- ✅ Automatic tree-shaking (only imports what you use)\n- ✅ No manual imports needed\n- ✅ Perfect TypeScript auto-completion\n- ✅ Minimal bundle size\n\n**Bundle Impact**:\n```typescript\n// Without auto-import\nimport 'maz-ui/styles' // ~300KB\n\n// With auto-import + only using MazBtn and MazInput\n// Bundle size: ~15KB (components + styles)\n```\n\n---\n\n#### Webpack Configuration\n\n```typescript\n// webpack.config.js\nconst Components = require('unplugin-vue-components/webpack')\nconst AutoImport = require('unplugin-auto-import/webpack')\nconst {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} = require('maz-ui/resolvers')\n\nmodule.exports = {\n plugins: [\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n }),\n ],\n}\n```\n\n---\n\n### Manual Tree-Shaking\n\nIf not using auto-import resolvers, import components individually:\n\n#### Optimal Import Pattern\n\n```typescript\n// ✅ BEST: Individual imports for maximum tree-shaking\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\nimport { useToast } from 'maz-ui/composables/useToast'\nimport { vTooltip } from 'maz-ui/directives/vTooltip'\n```\n\n#### Batch Imports (Acceptable)\n\n```typescript\n// ✅ GOOD: Batch imports still tree-shake well\nimport { MazBtn, MazInput } from 'maz-ui/components'\nimport { useToast, useDialog } from 'maz-ui/composables'\nimport { vTooltip, vClickOutside } from 'maz-ui/directives'\n```\n\n#### Avoid Full Imports\n\n```typescript\n// ❌ AVOID: Imports everything (large bundle)\nimport * as MazUI from 'maz-ui'\n```\n\n---\n\n### Style Optimization\n\n#### On-Demand Styles (Auto-Import)\n\nWith auto-import resolvers, styles are automatically imported per component:\n\n```vue\n\u003ctemplate>\n \u003c!-- Auto-imports MazBtn component + its styles -->\n \u003cMazBtn>Click Me\u003c/MazBtn>\n\u003c/template>\n```\n\n**Bundle**: Only MazBtn styles (~2KB)\n\n---\n\n#### Manual Style Imports\n\nWithout auto-import, import global styles once:\n\n```typescript\n// main.ts\nimport 'maz-ui/styles' // ~300KB (all component styles)\n```\n\n**Optimization**: Load only specific component styles:\n\n```typescript\n// ❌ NOT RECOMMENDED: Manual per-component style imports\nimport 'maz-ui/components/MazBtn/styles'\nimport 'maz-ui/components/MazInput/styles'\n\n// ✅ RECOMMENDED: Use auto-import resolvers instead\n```\n\n---\n\n## Lazy Loading Strategies\n\n### Component Lazy Loading\n\n#### Basic Lazy Loading\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { defineAsyncComponent } from 'vue'\n\n// Lazy load heavy components\nconst MazCarousel = defineAsyncComponent(() =>\n import('maz-ui/components/MazCarousel')\n)\n\nconst MazGallery = defineAsyncComponent(() =>\n import('maz-ui/components/MazGallery')\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cSuspense>\n \u003ctemplate #default>\n \u003cMazCarousel :images=\"images\" />\n \u003c/template>\n \u003ctemplate #fallback>\n \u003cdiv>Loading carousel...\u003c/div>\n \u003c/template>\n \u003c/Suspense>\n\u003c/template>\n```\n\n---\n\n#### Route-Level Code Splitting\n\n```typescript\n// router/index.ts\nimport { createRouter } from 'vue-router'\n\nconst routes = [\n {\n path: '/dashboard',\n name: 'Dashboard',\n // Lazy load entire dashboard component\n component: () => import('../views/Dashboard.vue')\n },\n {\n path: '/profile',\n name: 'Profile',\n component: () => import('../views/Profile.vue')\n }\n]\n```\n\n**Dashboard.vue** (lazy loads Maz-UI components):\n```vue\n\u003cscript setup lang=\"ts\">\nimport { defineAsyncComponent } from 'vue'\n\nconst MazTable = defineAsyncComponent(() =>\n import('maz-ui/components/MazTable')\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cSuspense>\n \u003cMazTable :rows=\"data\" />\n \u003c/Suspense>\n\u003c/template>\n```\n\n---\n\n### Plugin Lazy Loading\n\n#### Conditional Plugin Loading\n\n```typescript\n// main.ts\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\n// Load MazUi plugin\napp.use(MazUi, {\n theme: { preset: 'maz-ui' },\n translations: { locale: 'en' }\n})\n\n// Conditionally load optional plugins\nif (import.meta.env.VITE_ENABLE_AOS === 'true') {\n import('maz-ui/plugins/aos').then(({ AosPlugin }) => {\n app.use(AosPlugin)\n })\n}\n\napp.mount('#app')\n```\n\n---\n\n#### On-Demand Toast/Dialog\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst showToast = async () => {\n // Lazy load Toast plugin when needed\n const { useToast } = await import('maz-ui/composables/useToast')\n const toast = useToast()\n toast.success('Success!')\n}\n\nconst showDialog = async () => {\n // Lazy load Dialog composable when needed\n const { useDialog } = await import('maz-ui/composables/useDialog')\n const dialog = useDialog()\n dialog.confirm({\n title: 'Confirm',\n message: 'Are you sure?',\n onAccept: () => console.log('Confirmed')\n })\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cbutton @click=\"showToast\">Show Toast\u003c/button>\n \u003cbutton @click=\"showDialog\">Show Dialog\u003c/button>\n\u003c/template>\n```\n\n---\n\n## Image Optimization\n\n### Lazy Image Loading\n\n```vue\n\u003ctemplate>\n \u003c!-- v-lazy-img directive for lazy loading -->\n \u003cimg\n v-lazy-img=\"imageUrl\"\n alt=\"Product\"\n class=\"product-image\"\n />\n\n \u003c!-- Or use MazLazyImg component -->\n \u003cMazLazyImg\n :src=\"imageUrl\"\n :blur-up=\"true\"\n alt=\"Product\"\n />\n\u003c/template>\n```\n\n**Benefits**:\n- ✅ Only loads images in viewport\n- ✅ Blur-up effect during load\n- ✅ Reduces initial page weight\n\n---\n\n### Image Format Optimization\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst imageUrl = computed(() => {\n // Serve WebP for browsers that support it\n if (supportsWebP.value) {\n return '/images/product.webp'\n }\n return '/images/product.jpg'\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazLazyImg :src=\"imageUrl\" />\n\u003c/template>\n```\n\n---\n\n## Icon Optimization\n\n### @maz-ui/icons Package\n\nUse the **@maz-ui/icons** package for optimal icon tree-shaking:\n\n```typescript\n// ✅ OPTIMAL: Import specific icons\nimport { IconHome, IconUser, IconSettings } from '@maz-ui/icons'\n```\n\n**Bundle**: ~1KB per icon (SVG optimized)\n\n```vue\n\u003ctemplate>\n \u003cMazIcon :src=\"IconHome\" />\n \u003cMazIcon :src=\"IconUser\" />\n\u003c/template>\n```\n\n---\n\n### Icon Lazy Loading\n\nFor large icon sets:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { defineAsyncComponent, shallowRef } from 'vue'\n\nconst IconLarge = shallowRef(null)\n\nconst loadIcon = async () => {\n const module = await import('@maz-ui/icons')\n IconLarge.value = module.IconLargeFile\n}\n\n// Load on mount or on-demand\nonMounted(loadIcon)\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazIcon v-if=\"IconLarge\" :src=\"IconLarge\" />\n\u003c/template>\n```\n\n---\n\n## Vue 3 Performance Patterns\n\n### Composition API Optimizations\n\n#### Computed vs Reactive\n\n```typescript\nimport { ref, computed, reactive } from 'vue'\n\n// ✅ OPTIMAL: Use ref for primitives\nconst count = ref(0)\nconst doubled = computed(() => count.value * 2)\n\n// ✅ OPTIMAL: Use reactive for objects\nconst state = reactive({\n user: { name: 'John', age: 30 },\n settings: { theme: 'dark' }\n})\n\n// ❌ AVOID: Reactive for primitives (unnecessary overhead)\nconst count = reactive({ value: 0 })\n```\n\n---\n\n#### Shallow Refs for Large Objects\n\n```typescript\nimport { shallowRef, triggerRef } from 'vue'\n\n// ✅ OPTIMAL: shallowRef for large objects that change rarely\nconst largeDataset = shallowRef([/* 10,000 items */])\n\n// Update entire object (triggers reactivity)\nlargeDataset.value = newDataset\n\n// Or manually trigger after mutation\nlargeDataset.value.push(newItem)\ntriggerRef(largeDataset)\n```\n\n---\n\n### Component Optimizations\n\n#### Virtual Scrolling for Large Lists\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst items = ref(Array.from({ length: 10000 }, (_, i) => ({\n id: i,\n name: `Item ${i}`\n})))\n\nconst visibleItems = computed(() => {\n // Only render items in viewport\n const start = scrollTop.value / itemHeight\n const end = start + visibleCount\n return items.value.slice(start, end)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"virtual-scroll\">\n \u003cMazCard\n v-for=\"item in visibleItems\"\n :key=\"item.id\"\n >\n {{ item.name }}\n \u003c/MazCard>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n#### Memoization with Computed\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { computed } from 'vue'\n\nconst users = ref([/* large array */])\n\n// ✅ OPTIMAL: Memoize expensive operations\nconst sortedUsers = computed(() => {\n return users.value.slice().sort((a, b) => a.name.localeCompare(b.name))\n})\n\n// ❌ AVOID: Re-computing on every render\nconst getSortedUsers = () => {\n return users.value.slice().sort((a, b) => a.name.localeCompare(b.name))\n}\n\u003c/script>\n```\n\n---\n\n### Event Handler Optimizations\n\n#### Debouncing Search\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { debounce } from '@maz-ui/utils'\n\nconst searchQuery = ref('')\nconst searchResults = ref([])\n\n// ✅ OPTIMAL: Debounce expensive operations\nconst handleSearch = debounce(async (query: string) => {\n searchResults.value = await fetchResults(query)\n}, 300)\n\nwatch(searchQuery, (newQuery) => {\n handleSearch(newQuery)\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput\n v-model=\"searchQuery\"\n placeholder=\"Search...\"\n />\n\u003c/template>\n```\n\n---\n\n## Theme Optimization\n\n### Runtime vs Build-time Themes\n\n#### Hybrid Strategy (Recommended)\n\n```typescript\n// nuxt.config.ts (Nuxt)\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'hybrid', // ✅ OPTIMAL: Critical CSS + runtime\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n**Benefits**:\n- ✅ Critical CSS in `\u003chead>` (instant theme)\n- ✅ Runtime switching (no page reload)\n- ✅ Dark mode toggle without flash\n\n---\n\n#### Build-time Only (Fastest)\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'buildtime' // ✅ SMALLEST: All CSS pre-generated\n }\n }\n})\n```\n\n**Benefits**:\n- ✅ Smallest bundle (no runtime theme logic)\n- ✅ Fastest initial load\n- ❌ No runtime theme switching\n\n---\n\n#### Runtime Only (Most Flexible)\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'runtime' // ⚠️ LARGER: All themes loaded\n }\n }\n})\n```\n\n**Benefits**:\n- ✅ Full runtime theme switching\n- ✅ User preference persistence\n- ❌ Larger initial bundle\n\n---\n\n## Translation Optimization\n\n### Lazy Translation Loading\n\n```typescript\n// main.ts\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { en } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'en',\n fallbackLocale: 'en',\n messages: {\n en, // Load English immediately\n // Lazy load other languages\n },\n },\n})\n\n// Lazy load French when needed\nconst loadFrench = async () => {\n const { fr } = await import('@maz-ui/translations')\n const { setLocale, addMessages } = useTranslations()\n addMessages('fr', fr)\n setLocale('fr')\n}\n```\n\n---\n\n## Build Configuration\n\n### Vite Optimizations\n\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n build: {\n // ✅ Rollup optimizations\n rollupOptions: {\n output: {\n manualChunks: {\n 'maz-ui-core': ['maz-ui/components/MazBtn', 'maz-ui/components/MazInput'],\n 'maz-ui-forms': ['maz-ui/components/MazSelect', 'maz-ui/components/MazTextarea'],\n }\n }\n },\n // ✅ CSS code splitting\n cssCodeSplit: true,\n // ✅ Minification\n minify: 'terser',\n terserOptions: {\n compress: {\n drop_console: true, // Remove console.log in production\n }\n }\n },\n // ✅ Dependency pre-bundling\n optimizeDeps: {\n include: ['maz-ui', '@maz-ui/themes', '@maz-ui/translations']\n }\n})\n```\n\n---\n\n### Webpack Optimizations\n\n```javascript\n// webpack.config.js\nmodule.exports = {\n optimization: {\n splitChunks: {\n chunks: 'all',\n cacheGroups: {\n mazui: {\n test: /[\\\\/]node_modules[\\\\/]maz-ui/,\n name: 'maz-ui',\n priority: 10\n }\n }\n },\n minimize: true,\n },\n performance: {\n maxEntrypointSize: 250000,\n maxAssetSize: 250000\n }\n}\n```\n\n---\n\n## Performance Monitoring\n\n### Bundle Size Analysis\n\n```bash\n# Vite\nnpm run build\nnpm run preview\n\n# Analyze bundle\nnpx vite-bundle-visualizer\n```\n\n---\n\n### Lighthouse Audit\n\n```bash\n# Install Lighthouse CLI\nnpm install -g lighthouse\n\n# Run audit\nlighthouse https://your-app.com --view\n```\n\n**Target Metrics**:\n- Performance: >90\n- First Contentful Paint: \u003c1.8s\n- Time to Interactive: \u003c3.8s\n- Total Blocking Time: \u003c300ms\n\n---\n\n## Production Checklist\n\n### Pre-Deployment Optimizations\n\n- [ ] **Auto-import resolvers** configured (Vite/Webpack)\n- [ ] **Tree-shaking** verified (bundle analyzer)\n- [ ] **Lazy loading** for heavy components (MazCarousel, MazGallery, MazTable)\n- [ ] **Image optimization** (v-lazy-img, WebP format)\n- [ ] **Icon tree-shaking** (@maz-ui/icons individual imports)\n- [ ] **Theme strategy** optimized (hybrid/buildtime)\n- [ ] **Translation lazy loading** for non-default locales\n- [ ] **Code splitting** configured (route-level)\n- [ ] **Minification** enabled (production build)\n- [ ] **Console.log removal** in production\n- [ ] **Bundle size** \u003c250KB initial load\n- [ ] **Lighthouse score** >90\n\n---\n\n## Performance Anti-Patterns\n\n### Avoid These Mistakes\n\n#### ❌ Importing Everything\n\n```typescript\n// ❌ BAD: Imports entire library\nimport * as MazUI from 'maz-ui'\n\n// ✅ GOOD: Import only what you need\nimport { MazBtn, MazInput } from 'maz-ui/components'\n```\n\n---\n\n#### ❌ Not Using Auto-Import\n\n```vue\n\u003cscript setup>\n// ❌ BAD: Manual imports for every component\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\nimport MazSelect from 'maz-ui/components/MazSelect'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn>Click\u003c/MazBtn>\n \u003cMazInput />\n \u003cMazSelect />\n\u003c/template>\n```\n\n```vue\n\u003cscript setup>\n// ✅ GOOD: Auto-import with resolvers\n// No imports needed!\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn>Click\u003c/MazBtn>\n \u003cMazInput />\n \u003cMazSelect />\n\u003c/template>\n```\n\n---\n\n#### ❌ Loading All Translations\n\n```typescript\n// ❌ BAD: Load all 9 languages upfront\nimport { en, fr, de, es, it, pt, ja, zhCN } from '@maz-ui/translations'\n\n// ✅ GOOD: Load default + lazy load others\nimport { en } from '@maz-ui/translations'\n// Lazy load other languages on demand\n```\n\n---\n\n#### ❌ Not Lazy Loading Heavy Components\n\n```vue\n\u003cscript setup>\n// ❌ BAD: Load MazCarousel even if not visible\nimport MazCarousel from 'maz-ui/components/MazCarousel'\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-if=\"showCarousel\">\n \u003cMazCarousel :images=\"images\" />\n \u003c/div>\n\u003c/template>\n```\n\n```vue\n\u003cscript setup>\n// ✅ GOOD: Lazy load when needed\nimport { defineAsyncComponent } from 'vue'\n\nconst MazCarousel = defineAsyncComponent(() =>\n import('maz-ui/components/MazCarousel')\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cSuspense>\n \u003cdiv v-if=\"showCarousel\">\n \u003cMazCarousel :images=\"images\" />\n \u003c/div>\n \u003c/Suspense>\n\u003c/template>\n```\n\n---\n\n## Benchmarks\n\n### v3 vs v4 Performance\n\n| Metric | v3.x | v4.0.0 | Improvement |\n|--------|------|--------|-------------|\n| **Bundle Size (all components)** | ~500KB | ~300KB | 40% |\n| **Bundle Size (5 components)** | ~500KB | ~50KB | 90% |\n| **Bundle Size (with auto-import)** | ~500KB | ~30KB | 94% |\n| **First Load** | 3.2s | 1.1s | 66% |\n| **Time to Interactive** | 4.5s | 1.8s | 60% |\n\n---\n\n## Related Documentation\n\n- **[Resolvers](./resolvers.md)** - Auto-import configuration\n- **[Setup Vue](./setup-vue.md)** - Vite configuration\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt module with theme strategies\n- **[Theming](./theming.md)** - Theme strategy comparison\n- **[SSR & SSG](./ssr-ssg.md)** - Server-side rendering optimization\n- **[Icons](./icons.md)** - Icon tree-shaking\n\n---\n\n**Performance Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-14\n\n::: tip Bundle Size Tip\nUse auto-import resolvers for automatic tree-shaking and minimal bundle size. With resolvers, you only pay for what you use.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":17366,"content_sha256":"cce6d86ab3639790dda12daf4080a904f0d50c0e94c50685635a220acbddbf23"},{"filename":"references/plugins.md","content":"# Maz-UI Plugins Reference\n\nComprehensive guide to all Maz-UI plugins for Vue 3 and Nuxt 3 applications.\n\n## Overview\n\nMaz-UI provides **4 powerful plugins** that extend your Vue/Nuxt application with essential functionality:\n\n1. **MazUi** (Main Plugin) - Core plugin installation with theme and translations\n2. **Toast** - User-friendly toast notifications\n3. **Dialog** - Promise-based confirmation dialogs\n4. **AOS** (Animations on Scroll) - Scroll-triggered animations\n5. **Wait** - Global loading state management\n\n**Key Features**:\n- ✅ **Composable APIs** - Each plugin has a dedicated composable for easier usage\n- ✅ **Auto-Imports** - Nuxt 3 automatically imports plugins and composables\n- ✅ **TypeScript Support** - Full type safety with TypeScript\n- ✅ **SSR Compatible** - Works with server-side rendering\n- ✅ **Promise-Based** - Dialog plugin returns promises for async workflows\n- ✅ **Global State** - Centralized state management for toasts, dialogs, and loading states\n\n---\n\n## 1. MazUi Plugin (Main Plugin)\n\nThe core plugin that initializes Maz-UI with theme, translations, and composable configuration.\n\n### Vue 3 Installation\n\n```typescript\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes'\nimport { en } from '@maz-ui/translations'\nimport 'maz-ui/styles'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\napp.use(MazUi, {\n theme: {\n preset: mazUi, // or 'ocean', 'pristine', 'obsidian'\n dark: false // Enable dark mode by default\n },\n translations: {\n locale: 'en',\n fallbackLocale: 'en',\n messages: { en }\n }\n})\n\napp.mount('#app')\n```\n\n### Nuxt 3 Installation\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n theme: {\n preset: 'maz-ui' // or 'ocean', 'pristine', 'obsidian'\n },\n translations: {\n locale: 'en',\n messages: {\n en: () => import('@maz-ui/translations/locales/en')\n }\n },\n composables: {\n useTheme: true,\n useTranslations: true,\n useToast: true,\n useDialog: true,\n useWait: true\n }\n }\n})\n```\n\n### Plugin Options\n\n| Option | Type | Description | Default |\n|--------|------|-------------|---------|\n| `theme.preset` | `Theme \\| string` | Theme preset or custom theme object | `mazUi` |\n| `theme.dark` | `boolean` | Enable dark mode by default | `false` |\n| `translations.locale` | `string` | Default locale | `'en'` |\n| `translations.fallbackLocale` | `string` | Fallback locale if translation missing | `'en'` |\n| `translations.messages` | `object` | Translation messages object | `{}` |\n| `translations.preloadFallback` | `boolean` | Preload fallback locale on init | `true` |\n\n### Theme Presets\n\nMaz-UI includes 4 built-in theme presets:\n\n```typescript\nimport { mazUi, ocean, pristine, obsidian } from '@maz-ui/themes'\n\n// Use in plugin options\napp.use(MazUi, {\n theme: { preset: ocean } // Clean ocean-inspired palette\n})\n```\n\n**Available Presets**:\n- `mazUi` - Default Maz-UI theme (blue primary)\n- `ocean` - Ocean-inspired (teal/cyan palette)\n- `pristine` - Clean minimalist (grayscale)\n- `obsidian` - Dark professional (charcoal/slate)\n\n---\n\n## 2. Toast Plugin\n\nA powerful toast notification system for displaying user-friendly messages.\n\n### Installation\n\n**Vue 3**:\n```typescript\nimport { createApp } from 'vue'\nimport { ToastPlugin, ToastOptions } from 'maz-ui/plugins/toast'\n\nconst app = createApp(App)\n\nconst toastOptions: ToastOptions = {\n position: 'bottom-right',\n timeout: 10_000,\n persistent: false,\n}\n\napp.use(ToastPlugin, toastOptions)\napp.mount('#app')\n```\n\n**Nuxt 3**:\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n composables: {\n useToast: true\n }\n }\n})\n```\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { useToast } from 'maz-ui/composables/useToast'\n\nconst toast = useToast()\n\n// Display different toast types\ntoast.message('Default message')\ntoast.info('Info message')\ntoast.success('Success message')\ntoast.warning('Warning message')\ntoast.error('Error message')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"toast.success('Task completed!')\">\n Show Toast\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Toast Options\n\n```typescript\ninterface ToastOptions {\n /** Position of the toast on screen\n * @default 'bottom-right'\n */\n position?: 'top' | 'top-right' | 'top-left' |\n 'bottom' | 'bottom-right' | 'bottom-left'\n\n /** Auto-close timeout in ms (false = no timeout)\n * @default 10000\n */\n timeout?: number | false\n\n /** Prevent user from closing toast\n * @default false\n */\n persistent?: boolean\n\n /** Display icon in toast\n * @default true\n */\n icon?: boolean\n\n /** Enable HTML content\n * @default false\n */\n html?: boolean\n\n /** Pause timeout on hover\n * @default true\n */\n pauseOnHover?: boolean\n\n /** Queue toasts instead of stacking\n * @default false\n */\n queue?: boolean\n\n /** Maximum number of toasts to display\n * @default false (unlimited)\n */\n maxToasts?: number | false\n\n /** Button configuration */\n button?: {\n text: string\n onClick?: () => unknown\n href?: string\n target?: '_self' | '_blank'\n closeToast?: boolean\n }\n}\n```\n\n### Toast with Actions\n\n**Link Button**:\n```typescript\ntoast.info('New feature available!', {\n button: {\n href: 'https://example.com/features',\n target: '_blank',\n text: 'Learn More',\n closeToast: true\n }\n})\n```\n\n**Action Button**:\n```typescript\ntoast.warning('Unsaved changes', {\n button: {\n onClick: async () => {\n await saveData()\n toast.success('Changes saved')\n },\n text: 'Save Now',\n closeToast: true\n }\n})\n```\n\n### Programmatic Close\n\n```typescript\n// Close toast after specific time\nconst toastInstance = toast.message('Processing...')\n\nsetTimeout(() => {\n toastInstance.close()\n}, 3000)\n```\n\n### HTML Content\n\n```typescript\ntoast.message(`\n \u003cul>\n \u003cli>Item \u003cb>1\u003c/b>\u003c/li>\n \u003cli>Item \u003cb>2\u003c/b>\u003c/li>\n \u003cli>Item \u003cb>3\u003c/b>\u003c/li>\n \u003c/ul>\n`, {\n html: true,\n position: 'top'\n})\n```\n\n---\n\n## 3. Dialog Plugin\n\nPromise-based confirmation dialogs with flexible customization.\n\n### Installation\n\n**Vue 3**:\n```typescript\nimport { createApp } from 'vue'\nimport { DialogPlugin, DialogOptions } from 'maz-ui/plugins/dialog'\n\nconst app = createApp(App)\n\napp.use(DialogPlugin)\napp.mount('#app')\n```\n\n**Nuxt 3**:\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n composables: {\n useDialog: true\n }\n }\n})\n```\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { useDialog } from 'maz-ui/composables/useDialog'\nimport { useToast } from 'maz-ui/composables/useToast'\n\nconst dialog = useDialog()\nconst toast = useToast()\n\nasync function confirmDelete() {\n dialog.open({\n title: 'Delete Item',\n message: 'Are you sure you want to delete this item?',\n acceptText: 'Delete',\n rejectText: 'Cancel',\n onAccept: () => {\n // User clicked Delete\n toast.success('Item deleted')\n },\n onReject: () => {\n // User clicked Cancel\n toast.info('Deletion cancelled')\n }\n })\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"confirmDelete\" color=\"destructive\">\n Delete Item\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Dialog Options\n\n```typescript\ninterface DialogOptions {\n /** Dialog identifier for managing multiple dialogs\n * @default 'main-dialog'\n */\n identifier?: string\n\n /** Dialog title */\n title?: string\n\n /** Dialog message/content */\n message?: string\n\n /** Text for accept button\n * @default 'Confirm'\n */\n acceptText?: string\n\n /** Text for reject button\n * @default 'Cancel'\n */\n rejectText?: string\n\n /** Custom buttons (replaces default accept/reject) */\n buttons?: DialogButton[]\n\n /** Prevent closing on outside click\n * @default false\n */\n persistent?: boolean\n\n /** Callback when dialog is accepted */\n onAccept?: (response?: unknown) => unknown\n\n /** Callback when dialog is rejected */\n onReject?: (response?: unknown) => unknown\n\n /** Callback when dialog is closed */\n onClose?: () => unknown\n}\n\ninterface DialogButton extends MazBtnProps {\n text: string\n type?: 'resolve' | 'reject'\n response?: unknown\n onClick?: () => unknown\n}\n```\n\n### Custom Buttons\n\n**With Actions**:\n```typescript\ndialog.open({\n title: 'Save Changes',\n message: 'Do you want to save your changes?',\n buttons: [\n {\n text: 'Discard',\n color: 'destructive',\n outlined: true,\n onClick: () => {\n toast.info('Changes discarded')\n }\n },\n {\n text: 'Save',\n color: 'success',\n onClick: async () => {\n await saveChanges()\n toast.success('Changes saved')\n }\n }\n ]\n})\n```\n\n**With Custom Responses**:\n```typescript\nconst { promise } = dialog.open({\n title: 'Choose Action',\n message: 'What would you like to do?',\n buttons: [\n {\n text: 'Cancel',\n type: 'reject',\n response: 'cancelled',\n color: 'contrast'\n },\n {\n text: 'Save Draft',\n type: 'resolve',\n response: 'draft',\n color: 'warning'\n },\n {\n text: 'Publish',\n type: 'resolve',\n response: 'publish',\n color: 'success'\n }\n ],\n onAccept: (response) => {\n if (response === 'draft') {\n saveDraft()\n } else if (response === 'publish') {\n publishPost()\n }\n }\n})\n```\n\n### Programmatic Close\n\n```typescript\nconst { close } = dialog.open({\n title: 'Processing',\n message: 'Please wait...',\n buttons: [],\n persistent: true\n})\n\n// Close after operation completes\nsetTimeout(() => {\n close()\n}, 5000)\n```\n\n---\n\n## 4. AOS Plugin (Animations on Scroll)\n\nScroll-triggered animations for creating engaging user experiences.\n\n### Installation\n\n**Vue 3**:\n```typescript\nimport { createApp } from 'vue'\nimport router from './router'\nimport { AosPlugin, AosOptions } from 'maz-ui/plugins/aos'\n\n// ⚠️ IMPORTANT: Import AOS styles\nimport 'maz-ui/aos-styles'\n\nconst app = createApp(App)\napp.use(router)\n\nconst aosOptions: AosOptions = {\n animation: {\n duration: 1000,\n once: false,\n delay: 0\n },\n delay: 100,\n router\n}\n\napp.use(AosPlugin, aosOptions)\napp.mount('#app')\n```\n\n**Nuxt 3**:\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n composables: {\n useAos: {\n animation: {\n duration: 1000,\n once: false,\n delay: 0\n },\n delay: 100\n }\n }\n }\n})\n```\n\n### Basic Usage\n\nAdd `data-maz-aos` attribute to any element:\n\n```vue\n\u003ctemplate>\n \u003c!-- Simple fade-up animation -->\n \u003cdiv data-maz-aos=\"fade-up\">\n \u003ch1>Animated Title\u003c/h1>\n \u003c/div>\n\n \u003c!-- With custom duration and delay -->\n \u003cdiv\n data-maz-aos=\"zoom-in\"\n data-maz-aos-duration=\"1500\"\n data-maz-aos-delay=\"300\"\n >\n \u003cp>Animated content\u003c/p>\n \u003c/div>\n\n \u003c!-- Anchor to parent element -->\n \u003cdiv id=\"parentCard\" data-maz-aos=\"scale-out\">\n \u003ch2\n data-maz-aos=\"fade-down\"\n data-maz-aos-anchor=\"#parentCard\"\n >\n Title animates relative to parent\n \u003c/h2>\n \u003c/div>\n\u003c/template>\n```\n\n### AOS Attributes\n\n| Attribute | Description | Example | Default |\n|-----------|-------------|---------|---------|\n| `data-maz-aos` | Animation name | `fade-up` | - |\n| `data-maz-aos-duration` | Animation duration (ms) | `50` to `3000` (step: 50) | `300` |\n| `data-maz-aos-delay` | Animation delay (ms) | `50` to `3000` (step: 50) | `0` |\n| `data-maz-aos-easing` | Timing function | `ease-in-sine` | `linear` |\n| `data-maz-aos-once` | Fire only once | `true` | `false` |\n| `data-maz-aos-anchor` | Anchor element (ID only) | `#selector` | `undefined` |\n\n### Animation Types\n\n**Fade Animations** (8 variants):\n- `fade-up`, `fade-down`, `fade-left`, `fade-right`\n- `fade-up-left`, `fade-up-right`, `fade-down-left`, `fade-down-right`\n\n**Zoom Animations** (10 variants):\n- `zoom-in`, `zoom-in-up`, `zoom-in-down`, `zoom-in-left`, `zoom-in-right`\n- `zoom-out`, `zoom-out-up`, `zoom-out-down`, `zoom-out-left`, `zoom-out-right`\n\n**Slide Animations** (4 variants):\n- `slide-up`, `slide-down`, `slide-left`, `slide-right`\n\n**Flip Animations** (4 variants):\n- `flip-up`, `flip-down`, `flip-left`, `flip-right`\n\n**Rotate Animations** (2 variants):\n- `rotate-left`, `rotate-right`\n\n**Scale Animations** (2 variants):\n- `scale-in`, `scale-out`\n\n### Easing Functions\n\nChoose from 19 timing functions:\n\n**Basic**: `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`\n\n**Back**: `ease-in-back`, `ease-out-back`, `ease-in-out-back`\n\n**Sine**: `ease-in-sine`, `ease-out-sine`, `ease-in-out-sine`\n\n**Quad**: `ease-in-quad`, `ease-out-quad`, `ease-in-out-quad`\n\n**Cubic**: `ease-in-cubic`, `ease-out-cubic`, `ease-in-out-cubic`\n\n**Quart**: `ease-in-quart`, `ease-out-quart`, `ease-in-out-quart`\n\n### Programmatic Animations\n\nUse `useAos()` composable to trigger animations programmatically:\n\n```vue\n\u003cscript setup>\nimport { useAos } from 'maz-ui/composables/useAos'\nimport { onMounted } from 'vue'\n\nconst aos = useAos()\n\nonMounted(() => {\n // Run animations on mount (client-side only)\n aos.runAnimations()\n})\n\n// Re-run animations after dynamic content loads\nasync function loadContent() {\n await fetchData()\n aos.runAnimations()\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv data-maz-aos=\"fade-up\">\n Dynamic content\n \u003c/div>\n\u003c/template>\n```\n\n### AOS Plugin Options\n\n```typescript\ninterface AosOptions {\n /** Router instance to trigger animations on navigation\n * @default undefined\n */\n router?: Router\n\n /** Delay before starting animations (ms)\n * @default 100\n */\n delay?: number\n\n /** Intersection Observer options */\n observer?: {\n /** Scope animations to specific parent\n * @default undefined\n */\n root?: Element | Document | null\n\n /** Margin around elements to trigger animations\n * @default undefined\n * @example \"100px\"\n */\n rootMargin?: string\n\n /** Ratio corresponding to element size\n * @default 0.2\n */\n threshold?: number | number[]\n }\n\n /** Default animation settings */\n animation?: {\n /** Fire animation only once\n * @default true\n */\n once?: boolean\n\n /** Default duration (ms)\n * @default 300\n */\n duration?: number\n\n /** Default delay (ms)\n * @default 0\n */\n delay?: number\n }\n}\n```\n\n---\n\n## 5. Wait Plugin\n\nGlobal loading state management for handling async operations.\n\n### Installation\n\n**Vue 3**:\n```typescript\nimport { createApp } from 'vue'\nimport { WaitPlugin } from 'maz-ui/plugins/wait'\n\nconst app = createApp(App)\n\napp.use(WaitPlugin)\napp.mount('#app')\n```\n\n**Nuxt 3**:\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n composables: {\n useWait: true\n }\n }\n})\n```\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\nimport { useWait } from 'maz-ui/composables/useWait'\nimport { ref } from 'vue'\n\nconst wait = useWait()\nconst submitted = ref(false)\n\nasync function submitData() {\n submitted.value = false\n wait.start('DATA_SUBMITTING')\n\n try {\n await api.submitData()\n submitted.value = true\n } finally {\n wait.stop('DATA_SUBMITTING')\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn\n @click=\"submitData\"\n :loading=\"wait.isLoading('DATA_SUBMITTING')\"\n >\n Submit Data\n \u003c/MazBtn>\n\n \u003cdiv v-if=\"submitted\">\n Data submitted successfully!\n \u003c/div>\n\u003c/template>\n```\n\n### Wait API\n\n```typescript\ninterface UseWait {\n /** Start loading state for identifier */\n start(identifier: string): void\n\n /** Stop loading state for identifier */\n stop(identifier: string): void\n\n /** Check if identifier is loading */\n isLoading(identifier: string): boolean\n\n /** Get all active loading identifiers */\n getActiveLoading(): string[]\n\n /** Stop all loading states */\n stopAll(): void\n}\n```\n\n### Multiple Loading States\n\nTrack multiple operations independently:\n\n```vue\n\u003cscript setup>\nimport { useWait } from 'maz-ui/composables/useWait'\n\nconst wait = useWait()\n\nasync function savePost() {\n wait.start('SAVE_POST')\n await api.savePost()\n wait.stop('SAVE_POST')\n}\n\nasync function publishPost() {\n wait.start('PUBLISH_POST')\n await api.publishPost()\n wait.stop('PUBLISH_POST')\n}\n\nasync function deletePost() {\n wait.start('DELETE_POST')\n await api.deletePost()\n wait.stop('DELETE_POST')\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn\n @click=\"savePost\"\n :loading=\"wait.isLoading('SAVE_POST')\"\n >\n Save\n \u003c/MazBtn>\n\n \u003cMazBtn\n @click=\"publishPost\"\n :loading=\"wait.isLoading('PUBLISH_POST')\"\n color=\"success\"\n >\n Publish\n \u003c/MazBtn>\n\n \u003cMazBtn\n @click=\"deletePost\"\n :loading=\"wait.isLoading('DELETE_POST')\"\n color=\"destructive\"\n >\n Delete\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Global Loading Indicator\n\nCheck if any operation is loading:\n\n```vue\n\u003cscript setup>\nimport { useWait } from 'maz-ui/composables/useWait'\nimport { computed } from 'vue'\n\nconst wait = useWait()\n\nconst isAnyLoading = computed(() => {\n return wait.getActiveLoading().length > 0\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazFullscreenLoader v-if=\"isAnyLoading\" />\n\n \u003cdiv v-else>\n \u003c!-- App content -->\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Plugin Installation Patterns\n\n### Vue 3 Complete Setup\n\n```typescript\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { ToastPlugin } from 'maz-ui/plugins/toast'\nimport { DialogPlugin } from 'maz-ui/plugins/dialog'\nimport { AosPlugin } from 'maz-ui/plugins/aos'\nimport { WaitPlugin } from 'maz-ui/plugins/wait'\nimport { mazUi } from '@maz-ui/themes'\nimport { en } from '@maz-ui/translations'\nimport 'maz-ui/styles'\nimport 'maz-ui/aos-styles'\nimport router from './router'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\n// Core plugin\napp.use(MazUi, {\n theme: { preset: mazUi },\n translations: { messages: { en } }\n})\n\n// Toast notifications\napp.use(ToastPlugin, {\n position: 'bottom-right',\n timeout: 5000\n})\n\n// Dialogs\napp.use(DialogPlugin)\n\n// Animations on scroll\napp.use(AosPlugin, {\n router,\n animation: { duration: 800, once: true }\n})\n\n// Loading states\napp.use(WaitPlugin)\n\napp.mount('#app')\n```\n\n### Nuxt 3 Complete Setup\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n\n mazUi: {\n // Theme configuration\n theme: {\n preset: 'ocean'\n },\n\n // Translations\n translations: {\n locale: 'en',\n messages: {\n en: () => import('@maz-ui/translations/locales/en')\n }\n },\n\n // Enable all composables\n composables: {\n useTheme: true,\n useTranslations: true,\n useToast: true,\n useDialog: true,\n useWait: true,\n useAos: {\n animation: {\n duration: 800,\n once: true\n }\n }\n }\n }\n})\n```\n\n---\n\n## Best Practices\n\n### 1. Toast Notifications\n\n**DO**:\n- Use appropriate toast types (info, success, warning, error)\n- Set reasonable timeouts (3-10 seconds)\n- Provide action buttons for important notifications\n- Use `pauseOnHover: true` for complex messages\n\n**DON'T**:\n- Display too many toasts simultaneously (use `maxToasts`)\n- Use persistent toasts without user dismissal option\n- Put critical actions in toasts (use dialogs instead)\n\n```typescript\n// ✅ Good: Clear message with action\ntoast.success('Profile updated', {\n timeout: 5000,\n button: {\n text: 'View Profile',\n href: '/profile'\n }\n})\n\n// ❌ Bad: No timeout and unclear message\ntoast.message('Done', { timeout: false })\n```\n\n### 2. Dialogs\n\n**DO**:\n- Use clear, actionable button text\n- Provide context in dialog message\n- Handle both accept and reject callbacks\n- Use `persistent: true` for critical confirmations\n\n**DON'T**:\n- Use dialogs for informational messages (use toasts)\n- Create dialogs with ambiguous buttons\n- Forget to handle rejection cases\n\n```typescript\n// ✅ Good: Clear confirmation with consequences\ndialog.open({\n title: 'Delete Account',\n message: 'This action cannot be undone. All your data will be permanently deleted.',\n acceptText: 'Delete Account',\n rejectText: 'Keep Account',\n persistent: true,\n onAccept: () => deleteAccount(),\n onReject: () => toast.info('Account deletion cancelled')\n})\n\n// ❌ Bad: Unclear dialog\ndialog.open({\n title: 'Confirm',\n message: 'Are you sure?',\n acceptText: 'Yes'\n})\n```\n\n### 3. Animations on Scroll\n\n**DO**:\n- Use `once: true` for better performance\n- Choose appropriate animation durations (300-1000ms)\n- Use anchors for synchronized animations\n- Limit animations on mobile devices\n\n**DON'T**:\n- Animate too many elements simultaneously\n- Use very long durations (> 2s)\n- Apply animations to frequently scrolled content\n\n```vue\n\u003c!-- ✅ Good: Subtle, performant animations -->\n\u003cdiv\n data-maz-aos=\"fade-up\"\n data-maz-aos-duration=\"600\"\n data-maz-aos-once=\"true\"\n>\n Content\n\u003c/div>\n\n\u003c!-- ❌ Bad: Excessive animation -->\n\u003cdiv\n data-maz-aos=\"flip-left\"\n data-maz-aos-duration=\"3000\"\n data-maz-aos-delay=\"2000\"\n>\n Content\n\u003c/div>\n```\n\n### 4. Loading States\n\n**DO**:\n- Use descriptive identifiers (e.g., `'SAVE_POST'`, `'FETCH_USERS'`)\n- Always stop loading states in `finally` blocks\n- Provide visual feedback (loading buttons, overlays)\n- Use global loading for critical operations\n\n**DON'T**:\n- Use generic identifiers (e.g., `'LOADING'`)\n- Forget to stop loading states on errors\n- Leave loading states active indefinitely\n\n```typescript\n// ✅ Good: Proper error handling\nasync function fetchData() {\n wait.start('FETCH_DATA')\n try {\n const data = await api.getData()\n return data\n } catch (error) {\n toast.error('Failed to fetch data')\n } finally {\n wait.stop('FETCH_DATA')\n }\n}\n\n// ❌ Bad: No error handling, no cleanup\nasync function fetchData() {\n wait.start('LOADING')\n const data = await api.getData()\n wait.stop('LOADING')\n return data\n}\n```\n\n---\n\n## Troubleshooting\n\n### Toast Plugin Issues\n\n**Issue**: Toasts not appearing\n\n**Causes & Solutions**:\n1. **Plugin not installed**\n ```typescript\n // Vue: Ensure ToastPlugin is installed\n app.use(ToastPlugin)\n\n // Nuxt: Enable composable\n mazUi: { composables: { useToast: true } }\n ```\n\n2. **Z-index conflicts**\n ```css\n /* Increase toast z-index in global styles */\n .m-toast {\n z-index: 10000 !important;\n }\n ```\n\n**Issue**: Toast HTML not rendering\n\n**Solution**: Enable HTML mode explicitly\n```typescript\ntoast.message('\u003cb>Bold text\u003c/b>', { html: true })\n```\n\n### Dialog Plugin Issues\n\n**Issue**: Dialog promise not resolving\n\n**Solution**: Ensure button `type` is set correctly\n```typescript\nbuttons: [\n { text: 'Cancel', type: 'reject' },\n { text: 'Confirm', type: 'resolve' }\n]\n```\n\n**Issue**: Multiple dialogs overlapping\n\n**Solution**: Use unique identifiers\n```typescript\ndialog.open({ identifier: 'delete-dialog', ... })\ndialog.open({ identifier: 'save-dialog', ... })\n```\n\n### AOS Plugin Issues\n\n**Issue**: Animations not triggering\n\n**Causes & Solutions**:\n1. **Missing CSS import**\n ```typescript\n // Add to main.ts (Vue) or nuxt.config.ts (Nuxt)\n import 'maz-ui/aos-styles'\n ```\n\n2. **Router not provided**\n ```typescript\n // Pass router to trigger animations on navigation\n app.use(AosPlugin, { router })\n ```\n\n3. **Elements not in viewport**\n ```typescript\n // Increase threshold for earlier triggering\n app.use(AosPlugin, {\n observer: { threshold: 0.5 }\n })\n ```\n\n**Issue**: Animations fire multiple times\n\n**Solution**: Use `once: true` for single-fire animations\n```html\n\u003cdiv data-maz-aos=\"fade-up\" data-maz-aos-once=\"true\">\n Content\n\u003c/div>\n```\n\n### Wait Plugin Issues\n\n**Issue**: Loading state stuck active\n\n**Solution**: Always use `finally` block\n```typescript\ntry {\n wait.start('OPERATION')\n await operation()\n} finally {\n wait.stop('OPERATION') // Guaranteed to run\n}\n```\n\n**Issue**: Multiple loading states interfering\n\n**Solution**: Use specific identifiers\n```typescript\n// ✅ Good: Specific identifiers\nwait.start('SAVE_POST')\nwait.start('FETCH_COMMENTS')\n\n// ❌ Bad: Generic identifier\nwait.start('LOADING')\n```\n\n---\n\n## SSR Compatibility\n\n### Toast Plugin\n- ✅ **SSR Safe** - Toast state is client-only\n- Mount toast calls inside `onMounted()` or client-side event handlers\n- No hydration issues\n\n### Dialog Plugin\n- ✅ **SSR Safe** - Dialog state is client-only\n- Open dialogs in response to user interactions (client-side)\n- No hydration issues\n\n### AOS Plugin\n- ⚠️ **Client-Side Only** - Requires DOM and Intersection Observer\n- In Nuxt, plugin runs automatically on client\n- Use `useAos().runAnimations()` in `onMounted()` for manual control\n\n### Wait Plugin\n- ✅ **SSR Safe** - Loading state is reactive and works server/client\n- State persists across hydration\n- No special handling needed\n\n---\n\n## Plugin Ecosystem Summary\n\n| Plugin | Purpose | Composable | SSR Safe | Key Features |\n|--------|---------|-----------|----------|--------------|\n| **MazUi** | Core setup | `useTheme()`, `useTranslations()` | ✅ | Theme, i18n, config |\n| **Toast** | Notifications | `useToast()` | ✅ | Positions, timeouts, actions |\n| **Dialog** | Confirmations | `useDialog()` | ✅ | Promises, custom buttons |\n| **AOS** | Scroll animations | `useAos()` | ⚠️ Client-only | 40+ animations, easing |\n| **Wait** | Loading states | `useWait()` | ✅ | Global state, multi-tracking |\n\n---\n\n## Related Documentation\n\n- **[Composables Reference](./composables.md)** - Detailed composable APIs (useToast, useDialog, useWait, useAos)\n- **[Theming Guide](./theming.md)** - Custom themes, CSS variables, dark mode\n- **[Translations Guide](./translations.md)** - i18n setup, lazy loading, custom locales\n- **[Setup Vue](./setup-vue.md)** - Vue 3 installation and configuration\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt 3 module setup with auto-imports\n\n---\n\n**Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-29\n**Official Docs**: https://maz-ui.com/plugins\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":25740,"content_sha256":"3cc7414f85770e0f92b768ef6a90dcd3438ba5c26329d2cb3d2779ca0454f21e"},{"filename":"references/resolvers.md","content":"# Maz-UI Auto-Import Resolvers Reference\n\nComplete guide to Maz-UI's intelligent auto-import resolvers for effortless component, directive, and composable imports in Vue 3 projects.\n\n## Overview\n\nMaz-UI provides **3 powerful auto-import resolvers** that eliminate manual imports while maintaining perfect tree-shaking and TypeScript support:\n\n1. **MazComponentsResolver** - Auto-imports all 50+ Maz-UI components\n2. **MazDirectivesResolver** - Auto-imports all 5 directives (v-tooltip, v-click-outside, etc.)\n3. **MazModulesResolver** - Auto-imports composables and utility functions\n\n**Key Benefits**:\n- ✅ **Zero Boilerplate** - No manual import statements required\n- ✅ **Perfect Tree-Shaking** - Only bundles what you actually use\n- ✅ **Type Safety** - Full TypeScript support with auto-generated definitions\n- ✅ **Conflict Prevention** - Configurable prefixes to avoid naming conflicts\n- ✅ **IntelliSense Support** - Full autocomplete and hover documentation\n\n::: tip Vue Only Feature\nAuto-import resolvers are designed for Vue 3 projects using Vite or Webpack. **Nuxt 3 users** already have everything integrated in the [@maz-ui/nuxt module](./setup-nuxt.md) and don't need manual resolver configuration.\n:::\n\n---\n\n## Quick Setup\n\n### 1. Install Required Packages\n\n```bash\n# Using pnpm\npnpm add unplugin-vue-components unplugin-auto-import\n\n# Using npm\nnpm install unplugin-vue-components unplugin-auto-import\n\n# Using yarn\nyarn add unplugin-vue-components unplugin-auto-import\n```\n\n### 2. Configure Build Tool\n\n**Vite Configuration**:\n\n```typescript\n// vite.config.ts\nimport vue from '@vitejs/plugin-vue'\nimport { defineConfig } from 'vite'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport Components from 'unplugin-vue-components/vite'\nimport {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} from 'maz-ui/resolvers'\n\nexport default defineConfig({\n plugins: [\n vue(),\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n dts: true, // Generate TypeScript definitions\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: true, // Generate TypeScript definitions\n }),\n ],\n})\n```\n\n**Webpack Configuration**:\n\n```javascript\n// webpack.config.js\nconst Components = require('unplugin-vue-components/webpack')\nconst AutoImport = require('unplugin-auto-import/webpack')\nconst {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} = require('maz-ui/resolvers')\n\nmodule.exports = {\n plugins: [\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n dts: true,\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: true,\n }),\n ],\n}\n```\n\n### 3. Start Using (No Imports Needed!)\n\n```vue\n\u003cscript setup>\n// All auto-imported - no import statements needed!\nconst text = ref('')\nconst toast = useToast()\nconst { isDark } = useTheme()\n\nfunction showSuccess() {\n toast.success('Auto-imports are working!')\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Components auto-imported -->\n \u003cMazInput v-model=\"text\" placeholder=\"Type here...\" />\n \u003cMazBtn @click=\"showSuccess\" color=\"primary\">\n Show Toast\n \u003c/MazBtn>\n\n \u003c!-- Directives auto-imported -->\n \u003cdiv v-tooltip=\"'Helpful tooltip'\">\n Hover me\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## 1. MazComponentsResolver\n\nAuto-imports all 50+ Maz-UI components without manual import statements.\n\n### Basic Usage\n\n```vue\n\u003cscript setup>\n// No imports needed!\nconst email = ref('')\nconst password = ref('')\nconst showPassword = ref(false)\n\nasync function handleLogin() {\n // Submit login\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- All components auto-imported -->\n \u003cMazCard>\n \u003ctemplate #header>\n \u003ch2>Login\u003c/h2>\n \u003c/template>\n\n \u003cMazInput\n v-model=\"email\"\n type=\"email\"\n label=\"Email\"\n placeholder=\"[email protected]\"\n />\n\n \u003cMazInput\n v-model=\"password\"\n :type=\"showPassword ? 'text' : 'password'\"\n label=\"Password\"\n placeholder=\"Enter password\"\n />\n\n \u003cMazCheckbox v-model=\"showPassword\">\n Show password\n \u003c/MazCheckbox>\n\n \u003cMazBtn @click=\"handleLogin\" color=\"primary\" block>\n Login\n \u003c/MazBtn>\n \u003c/MazCard>\n\u003c/template>\n```\n\n### All Auto-Imported Components\n\n**Forms & Inputs** (13 components):\n- `MazInput`, `MazTextarea`, `MazSelect`, `MazCheckbox`, `MazRadio`, `MazSwitch`\n- `MazSlider`, `MazInputPhoneNumber`, `MazInputCode`, `MazInputPrice`\n- `MazInputTags`, `MazDatePicker`, `MazChecklist`\n\n**UI Elements** (10 components):\n- `MazBtn`, `MazCard`, `MazBadge`, `MazAvatar`, `MazIcon`, `MazSpinner`\n- `MazTable`, `MazTabs`, `MazStepper`, `MazPagination`\n\n**Overlays & Modals** (6 components):\n- `MazDialog`, `MazDialogConfirm`, `MazDrawer`, `MazBottomSheet`\n- `MazBackdrop`, `MazPopover`, `MazDropdown`\n\n**Feedback & Animation** (9 components):\n- `MazFullscreenLoader`, `MazLoadingBar`, `MazCircularProgressBar`\n- `MazReadingProgressBar`, `MazAnimatedText`, `MazAnimatedElement`\n- `MazAnimatedCounter`, `MazCardSpotlight`\n\n**Layout & Display** (12 components):\n- `MazCarousel`, `MazGallery`, `MazAccordion`, `MazExpandAnimation`\n- `MazLazyImg`, `MazPullToRefresh`, `MazChart`\n\n### Resolver Options\n\n```typescript\ninterface MazComponentsResolverOptions {\n /**\n * Prefix for component names\n * @default '' (no prefix, use 'MazBtn')\n * @example 'Maz' → 'MazMazBtn'\n */\n prefix?: string\n\n /**\n * Enable development mode for faster builds\n * @default false\n */\n devMode?: boolean\n}\n\n// Usage\nMazComponentsResolver({\n prefix: 'Ui', // Components become UiMazBtn, UiMazInput\n devMode: process.env.NODE_ENV === 'development'\n})\n```\n\n---\n\n## 2. MazDirectivesResolver\n\nAuto-imports all 5 Maz-UI Vue directives for enhanced functionality.\n\n### Available Directives\n\n**v-tooltip**:\n```vue\n\u003ctemplate>\n \u003c!-- Simple tooltip -->\n \u003cMazBtn v-tooltip=\"'Click to save'\">\n Save\n \u003c/MazBtn>\n\n \u003c!-- Advanced tooltip with options -->\n \u003cMazBtn v-tooltip=\"{\n text: 'Delete this item permanently',\n position: 'top',\n color: 'destructive'\n }\">\n Delete\n \u003c/MazBtn>\n\u003c/template>\n```\n\n**v-click-outside**:\n```vue\n\u003cscript setup>\nconst showDropdown = ref(false)\n\nfunction handleClickOutside() {\n showDropdown.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-click-outside=\"handleClickOutside\">\n \u003cbutton @click=\"showDropdown = !showDropdown\">\n Menu\n \u003c/button>\n \u003cdiv v-if=\"showDropdown\" class=\"dropdown\">\n Dropdown content\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**v-lazy-img**:\n```vue\n\u003ctemplate>\n \u003c!-- Lazy load image with placeholder -->\n \u003cimg v-lazy-img=\"{\n src: '/images/large-photo.jpg',\n loading: '/images/placeholder.jpg',\n error: '/images/error.jpg',\n threshold: 0.5\n }\" alt=\"Photo\" />\n\u003c/template>\n```\n\n**v-zoom-img**:\n```vue\n\u003ctemplate>\n \u003c!-- Click to zoom image -->\n \u003cimg\n v-zoom-img\n src=\"/gallery/photo-1.jpg\"\n alt=\"Zoomable photo\"\n />\n\u003c/template>\n```\n\n**v-fullscreen-img**:\n```vue\n\u003ctemplate>\n \u003c!-- Fullscreen image viewer -->\n \u003cimg\n v-fullscreen-img\n src=\"/gallery/photo-1.jpg\"\n alt=\"Gallery photo\"\n />\n\u003c/template>\n```\n\n### Resolver Options\n\n```typescript\ninterface MazDirectivesResolverOptions {\n /**\n * Prefix for directive names\n * @default '' (no prefix, use v-tooltip)\n * @example 'maz' → v-maz-tooltip\n */\n prefix?: string\n\n /**\n * Enable development mode\n * @default false\n */\n devMode?: boolean\n}\n\n// Usage\nMazDirectivesResolver({\n prefix: 'maz', // Directives become v-maz-tooltip, v-maz-click-outside\n devMode: process.env.NODE_ENV === 'development'\n})\n```\n\n---\n\n## 3. MazModulesResolver\n\nAuto-imports composables and utility functions for cleaner code.\n\n### Auto-Imported Composables\n\n**UI Management**:\n```vue\n\u003cscript setup>\n// All composables auto-imported\nconst toast = useToast()\nconst dialog = useDialog()\nconst wait = useWait()\nconst { isDark, toggleDarkMode } = useTheme()\n\nasync function confirmDelete() {\n const result = await dialog.open({\n title: 'Delete Item',\n message: 'Are you sure?'\n })\n\n if (result) {\n wait.start('DELETING')\n await deleteItem()\n wait.stop('DELETING')\n toast.success('Item deleted')\n }\n}\n\u003c/script>\n```\n\n**Responsive Design**:\n```vue\n\u003cscript setup>\nconst { isMobile, isTablet, isDesktop } = useBreakpoints()\nconst { width, height } = useWindowSize()\n\nconst columns = computed(() => {\n if (isMobile.value) return 1\n if (isTablet.value) return 2\n return 3\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv :class=\"{ 'mobile-layout': isMobile }\">\n \u003cp>Window: {{ width }} x {{ height }}\u003c/p>\n \u003cdiv :style=\"{ 'grid-template-columns': `repeat(${columns}, 1fr)` }\">\n \u003c!-- Grid items -->\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n**Form Validation**:\n```vue\n\u003cscript setup>\nimport { pipe, string, nonEmpty, email, number, minValue } from 'valibot'\n\nconst schema = {\n email: pipe(\n string('Email is required'),\n nonEmpty('Email is required'),\n email('Invalid email format')\n ),\n age: pipe(\n number('Age is required'),\n minValue(18, 'Must be 18 or older')\n )\n}\n\nconst {\n model,\n errorMessages,\n isSubmitting,\n handleSubmit\n} = useFormValidator({ schema })\n\nconst onSubmit = handleSubmit(async (data) => {\n await api.submit(data)\n toast.success('Form submitted!')\n})\n\u003c/script>\n```\n\n**User Interaction**:\n```vue\n\u003cscript setup>\nconst { isIdle } = useIdleTimeout(60_000) // 60 seconds\nconst { isVisible } = useUserVisibility()\nconst { direction } = useSwipe(targetRef)\nconst { start, pause, reset, time } = useTimer()\n\nwatch(isIdle, (idle) => {\n if (idle) {\n toast.warning('Are you still there?')\n }\n})\n\nwatch(direction, (dir) => {\n if (dir === 'left') handleSwipeLeft()\n if (dir === 'right') handleSwipeRight()\n})\n\u003c/script>\n```\n\n### Auto-Imported Utilities\n\n**Formatters**:\n```vue\n\u003cscript setup>\nconst price = ref(29.99)\nconst date = ref(new Date())\n\n// Auto-imported utility functions\nconst formattedPrice = computed(() =>\n formatCurrency(price.value, { currency: 'EUR', locale: 'de-DE' })\n)\n\nconst formattedDate = computed(() =>\n formatDate(date.value, { format: 'short', locale: 'en-US' })\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cp>Price: {{ formattedPrice }}\u003c/p>\n \u003cp>Date: {{ formattedDate }}\u003c/p>\n\u003c/template>\n```\n\n**Performance Utilities**:\n```vue\n\u003cscript setup>\n// Auto-imported debounce and throttle\nconst debouncedSearch = debounce((query) => {\n console.log('Searching:', query)\n}, 300)\n\nconst throttledScroll = throttle((event) => {\n console.log('Scroll position:', window.scrollY)\n}, 100)\n\nfunction handleSearch(query) {\n debouncedSearch(query)\n}\n\nonMounted(() => {\n window.addEventListener('scroll', throttledScroll)\n})\n\nonUnmounted(() => {\n window.removeEventListener('scroll', throttledScroll)\n})\n\u003c/script>\n```\n\n**Async Utilities**:\n```vue\n\u003cscript setup>\nasync function loadSequentially() {\n await sleep(1000) // Wait 1 second\n const data1 = await fetchData1()\n\n await sleep(500) // Wait 500ms\n const data2 = await fetchData2()\n\n return [data1, data2]\n}\n\u003c/script>\n```\n\n### Composables Reference Table\n\n| Category | Composables |\n|----------|------------|\n| **UI Management** | `useToast()`, `useDialog()`, `useWait()`, `useTheme()` |\n| **Responsive** | `useBreakpoints()`, `useWindowSize()` |\n| **User Interaction** | `useUserVisibility()`, `useIdleTimeout()`, `useSwipe()` |\n| **Form Handling** | `useFormValidator()`, `useFormField()` |\n| **Utilities** | `useTimer()`, `useStringMatching()`, `useReadingTime()` |\n| **Animations** | `useAos()` |\n\n### Utilities Reference Table\n\n| Category | Functions |\n|----------|-----------|\n| **Formatters** | `formatCurrency()`, `formatDate()` |\n| **Performance** | `debounce()`, `throttle()` |\n| **Comparison** | `isEqual()` |\n| **Async** | `sleep()` |\n\n### Resolver Options\n\n```typescript\ninterface MazModulesResolverOptions {\n /**\n * Prefix for composable names (only composables, not utilities)\n * @default '' (no prefix, use useToast)\n * @example 'maz' → useMazToast (utilities NOT prefixed)\n */\n prefix?: string\n\n /**\n * Enable development mode\n * @default false\n */\n devMode?: boolean\n}\n\n// Usage\nMazModulesResolver({\n prefix: 'maz', // Composables become useMazToast, useMazTheme\n devMode: process.env.NODE_ENV === 'development'\n})\n```\n\n::: warning Prefix Limitation\nCurrently, utility functions (like `debounce`, `formatCurrency`) are **NOT prefixed** by `MazModulesResolver`. Only composables (functions starting with `use`) are prefixed. This is a known limitation that may be addressed in future versions.\n:::\n\n---\n\n## Advanced Configuration\n\n### Avoiding Naming Conflicts with Prefixes\n\nWhen using multiple UI libraries, use prefixes to prevent naming collisions:\n\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite'\nimport Components from 'unplugin-vue-components/vite'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} from 'maz-ui/resolvers'\nimport {\n ElementPlusResolver,\n AntDesignVueResolver\n} from 'unplugin-vue-components/resolvers'\n\nexport default defineConfig({\n plugins: [\n Components({\n resolvers: [\n MazComponentsResolver({ prefix: 'Maz' }),\n ElementPlusResolver({ prefix: 'El' }),\n AntDesignVueResolver({ prefix: 'A' }),\n ],\n }),\n AutoImport({\n resolvers: [\n MazModulesResolver({ prefix: 'maz' })\n ],\n }),\n ],\n})\n```\n\n**With Prefixes**:\n\n```vue\n\u003cscript setup>\n// Prefixed composables\nconst toast = useMazToast()\nconst theme = useMazTheme()\n\n// Utilities are NOT prefixed (limitation)\nconst formatted = formatCurrency(29.99) // Still unprefixed\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Prefixed components -->\n \u003cMazMazBtn>Maz UI Button\u003c/MazMazBtn>\n \u003cElButton>Element Plus Button\u003c/ElButton>\n \u003cAButton>Ant Design Button\u003c/AButton>\n\n \u003c!-- Prefixed directives -->\n \u003cdiv v-maz-tooltip=\"'Maz tooltip'\">Hover me\u003c/div>\n\u003c/template>\n```\n\n### Development Mode Optimization\n\nEnable development mode for faster builds during development:\n\n```typescript\nexport default defineConfig({\n plugins: [\n Components({\n resolvers: [\n MazComponentsResolver({\n devMode: process.env.NODE_ENV === 'development'\n }),\n MazDirectivesResolver({\n devMode: process.env.NODE_ENV === 'development'\n }),\n ],\n }),\n AutoImport({\n resolvers: [\n MazModulesResolver({\n devMode: process.env.NODE_ENV === 'development'\n }),\n ],\n }),\n ],\n})\n```\n\n**Development Mode Benefits**:\n- Faster build times\n- Better debugging output\n- More detailed error messages\n- Skip unnecessary optimizations during dev\n\n### Production-Ready Configuration\n\nComplete production configuration with all optimizations:\n\n```typescript\n// vite.config.ts\nimport vue from '@vitejs/plugin-vue'\nimport { defineConfig } from 'vite'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport Components from 'unplugin-vue-components/vite'\nimport {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} from 'maz-ui/resolvers'\n\nexport default defineConfig({\n plugins: [\n vue(),\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n dts: 'src/types/components.d.ts',\n directoryAsNamespace: true,\n deep: true,\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: 'src/types/auto-imports.d.ts',\n imports: ['vue', 'vue-router'],\n eslintrc: {\n enabled: true,\n filepath: './.eslintrc-auto-import.json',\n },\n }),\n ],\n build: {\n rollupOptions: {\n treeshake: true,\n },\n },\n})\n```\n\n---\n\n## TypeScript Integration\n\n### Auto-Generated Type Definitions\n\nResolvers automatically generate TypeScript definitions for perfect IntelliSense:\n\n**components.d.ts** (generated):\n```typescript\ndeclare module 'vue' {\n export interface GlobalComponents {\n MazBtn: typeof import('maz-ui/components')['MazBtn']\n MazInput: typeof import('maz-ui/components')['MazInput']\n MazCard: typeof import('maz-ui/components')['MazCard']\n MazDialog: typeof import('maz-ui/components')['MazDialog']\n // ... all other auto-imported components\n }\n}\n```\n\n**auto-imports.d.ts** (generated):\n```typescript\ndeclare global {\n const useToast: typeof import('maz-ui/composables')['useToast']\n const useTheme: typeof import('maz-ui/composables')['useTheme']\n const useBreakpoints: typeof import('maz-ui/composables')['useBreakpoints']\n const debounce: typeof import('maz-ui')['debounce']\n const formatCurrency: typeof import('maz-ui')['formatCurrency']\n // ... all other auto-imported functions\n}\n\nexport {}\n```\n\n### ESLint Configuration\n\nPrevent ESLint errors for auto-imported globals:\n\n```javascript\n// .eslintrc.js\nmodule.exports = {\n extends: [\n './.eslintrc-auto-import.json', // Generated by unplugin-auto-import\n ],\n rules: {\n // Allow auto-imported globals\n 'no-undef': 'off',\n },\n}\n```\n\n**Generated .eslintrc-auto-import.json**:\n```json\n{\n \"globals\": {\n \"useToast\": \"readonly\",\n \"useTheme\": \"readonly\",\n \"debounce\": \"readonly\",\n \"formatCurrency\": \"readonly\"\n }\n}\n```\n\n---\n\n## Real-World Example: Dashboard\n\nComplete dashboard implementation using all 3 resolvers:\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✨ Nothing imported - everything is auto-imported!\n\n// Composables\nconst toast = useToast()\nconst { width } = useWindowSize()\nconst { isMobile } = useBreakpoints()\n\n// State\nconst currentPage = ref(1)\nconst perPage = ref(10)\nconst isLoading = ref(false)\nconst showUserDialog = ref(false)\nconst editingUser = ref({ name: '', role: '' })\n\n// Mock data\nconst users = ref([\n { id: 1, name: 'John Doe', role: 'Admin' },\n { id: 2, name: 'Jane Smith', role: 'User' },\n { id: 3, name: 'Bob Johnson', role: 'Moderator' },\n])\n\n// Computed\nconst paginatedUsers = computed(() => {\n const start = (currentPage.value - 1) * perPage.value\n return users.value.slice(start, start + perPage.value)\n})\n\nconst totalUsers = computed(() => users.value.length)\n\nconst stats = computed(() => [\n { label: 'Total Users', value: totalUsers.value, color: 'primary' },\n { label: 'Admins', value: users.value.filter(u => u.role === 'Admin').length, color: 'success' },\n { label: 'Users', value: users.value.filter(u => u.role === 'User').length, color: 'info' },\n])\n\n// Table configuration\nconst columns = [\n { key: 'name', label: 'Name' },\n { key: 'role', label: 'Role' },\n]\n\nconst roleOptions = ['Admin', 'User', 'Moderator']\n\n// Auto-imported utility\nconst debouncedRefresh = debounce(refreshData, 1000)\n\n// Methods\nfunction refreshData() {\n isLoading.value = true\n sleep(1000).then(() => {\n isLoading.value = false\n toast.success('Data refreshed!')\n })\n}\n\nfunction closeDialog() {\n showUserDialog.value = false\n editingUser.value = { name: '', role: '' }\n}\n\nfunction saveUser() {\n toast.success('User saved successfully!')\n closeDialog()\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"dashboard\">\n \u003c!-- Stats Card -->\n \u003cMazCard class=\"stats-card\">\n \u003ctemplate #header>\n \u003cdiv class=\"flex items-center justify-between\">\n \u003ch2>Statistics\u003c/h2>\n \u003cMazBtn\n v-tooltip=\"'Refresh data'\"\n size=\"sm\"\n @click=\"refreshData\"\n >\n \u003cMazIcon name=\"refresh\" />\n \u003c/MazBtn>\n \u003c/div>\n \u003c/template>\n\n \u003cdiv class=\"grid grid-cols-3 gap-4\">\n \u003cdiv v-for=\"stat in stats\" :key=\"stat.label\">\n \u003cMazBadge :color=\"stat.color\">\n {{ stat.value }}\n \u003c/MazBadge>\n \u003cp class=\"text-sm text-muted\">\n {{ stat.label }}\n \u003c/p>\n \u003c/div>\n \u003c/div>\n \u003c/MazCard>\n\n \u003c!-- Users Table -->\n \u003cMazCard>\n \u003ctemplate #header>\n Users\n \u003c/template>\n\n \u003cMazTable\n :data=\"paginatedUsers\"\n :columns=\"columns\"\n :loading=\"isLoading\"\n />\n\n \u003ctemplate #footer>\n \u003cMazPagination\n v-model:current-page=\"currentPage\"\n :total=\"totalUsers\"\n :per-page=\"perPage\"\n />\n \u003c/template>\n \u003c/MazCard>\n\n \u003c!-- User Edit Dialog -->\n \u003cMazDialog v-model=\"showUserDialog\" title=\"User Details\">\n \u003cMazInput\n v-model=\"editingUser.name\"\n label=\"Name\"\n placeholder=\"Enter user name\"\n />\n \u003cMazSelect\n v-model=\"editingUser.role\"\n label=\"Role\"\n :options=\"roleOptions\"\n />\n\n \u003ctemplate #footer>\n \u003cMazBtn @click=\"closeDialog\">\n Cancel\n \u003c/MazBtn>\n \u003cMazBtn @click=\"saveUser\" color=\"success\">\n Save\n \u003c/MazBtn>\n \u003c/template>\n \u003c/MazDialog>\n \u003c/div>\n\u003c/template>\n\n\u003cstyle scoped>\n.dashboard {\n display: grid;\n gap: 1.5rem;\n padding: 1rem;\n}\n\n.stats-card {\n border: 1px solid var(--maz-border-color);\n border-radius: 0.5rem;\n}\n\u003c/style>\n```\n\n---\n\n## Performance Optimization\n\n### Tree-Shaking Best Practices\n\nAuto-import resolvers maintain the same tree-shaking benefits as manual imports:\n\n```typescript\n// vite.config.ts\nexport default defineConfig({\n plugins: [\n Components({\n resolvers: [MazComponentsResolver()],\n dts: true, // Generate types for better tree-shaking\n }),\n ],\n build: {\n rollupOptions: {\n treeshake: true, // Ensure tree-shaking is enabled\n },\n },\n})\n```\n\n**Bundle Size Comparison**:\n- Manual imports: `import { MazBtn } from 'maz-ui/components'` → ~5KB\n- Auto-import resolver: `\u003cMazBtn>` in template → ~5KB (identical!)\n\n### Optimize Type Generation\n\nGenerate types in a dedicated directory:\n\n```typescript\nComponents({\n resolvers: [MazComponentsResolver()],\n dts: 'src/types/components.d.ts', // Custom path\n})\n\nAutoImport({\n resolvers: [MazModulesResolver()],\n dts: 'src/types/auto-imports.d.ts', // Custom path\n})\n```\n\n**Add to .gitignore**:\n```\n# Auto-generated types\nsrc/types/components.d.ts\nsrc/types/auto-imports.d.ts\n```\n\n---\n\n## Troubleshooting\n\n### Components Not Auto-Importing\n\n**Issue**: Components show as undefined or unknown\n\n**Solutions**:\n\n1. **Verify resolver is configured**:\n ```typescript\n Components({\n resolvers: [MazComponentsResolver()], // Must be included\n })\n ```\n\n2. **Check plugin order**:\n ```typescript\n // ✅ Correct order\n plugins: [\n vue(),\n Components({ ... }),\n AutoImport({ ... }),\n ]\n\n // ❌ Wrong order\n plugins: [\n Components({ ... }),\n vue(), // vue() should be first\n ]\n ```\n\n3. **Restart dev server**:\n ```bash\n # Stop server, clear cache, restart\n rm -rf node_modules/.vite\n npm run dev\n ```\n\n### TypeScript Errors\n\n**Issue**: \"Cannot find name 'MazBtn'\" or similar TypeScript errors\n\n**Solutions**:\n\n1. **Enable DTS generation**:\n ```typescript\n Components({\n dts: true, // Generate type definitions\n })\n ```\n\n2. **Check tsconfig.json includes**:\n ```json\n {\n \"include\": [\n \"src/**/*\",\n \"src/types/**/*\" // Include generated types\n ]\n }\n ```\n\n3. **Manually run type generation**:\n ```bash\n # Trigger type generation\n npx vite build --mode development\n ```\n\n### Prefix Not Working for Utilities\n\n**Issue**: Utilities not prefixed despite `prefix: 'maz'` option\n\n**Explanation**: This is a **known limitation**. Currently, only composables (functions starting with `use`) are prefixed, not utility functions.\n\n```typescript\n// Current behavior (v4.3.3)\nMazModulesResolver({ prefix: 'maz' })\n\n// ✅ Composables ARE prefixed\nconst toast = useMazToast()\nconst theme = useMazTheme()\n\n// ❌ Utilities are NOT prefixed\nconst debounced = debounce(fn, 300) // Still unprefixed\nconst formatted = formatCurrency(99) // Still unprefixed\n```\n\n**Workaround**: Import utilities manually if prefix is required:\n```typescript\nimport { debounce as mazDebounce } from 'maz-ui'\n```\n\n### Development Performance Issues\n\n**Issue**: Slow build times in development\n\n**Solutions**:\n\n1. **Enable development mode**:\n ```typescript\n MazComponentsResolver({\n devMode: process.env.NODE_ENV === 'development'\n })\n ```\n\n2. **Disable type generation in dev**:\n ```typescript\n Components({\n dts: process.env.NODE_ENV === 'production',\n })\n ```\n\n3. **Use Vite's built-in optimizations**:\n ```typescript\n export default defineConfig({\n optimizeDeps: {\n include: ['maz-ui'], // Pre-bundle Maz-UI\n },\n })\n ```\n\n---\n\n## Migration from Manual Imports\n\n### Before (Manual Imports)\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport { MazBtn, MazCard, MazInput, MazDialog } from 'maz-ui/components'\nimport { useToast, useTheme, useBreakpoints } from 'maz-ui/composables'\nimport { vTooltip, vClickOutside } from 'maz-ui/directives'\nimport { debounce, formatCurrency, sleep } from 'maz-ui'\n\nconst toast = useToast()\nconst { isDark } = useTheme()\nconst { isMobile } = useBreakpoints()\n\nconst debouncedSearch = debounce((query) => {\n console.log('Searching:', query)\n}, 300)\n\n// ... rest of component\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCard>\n \u003cMazInput v-model=\"search\" />\n \u003cMazBtn v-tooltip=\"'Save changes'\">Save\u003c/MazBtn>\n \u003c/MazCard>\n\u003c/template>\n```\n\n### After (Auto-Import)\n\n```vue\n\u003cscript setup lang=\"ts\">\n// ✨ Nothing to import! Everything is auto-imported\n\nconst toast = useToast()\nconst { isDark } = useTheme()\nconst { isMobile } = useBreakpoints()\n\nconst debouncedSearch = debounce((query) => {\n console.log('Searching:', query)\n}, 300)\n\n// ... rest of component\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazCard>\n \u003cMazInput v-model=\"search\" />\n \u003cMazBtn v-tooltip=\"'Save changes'\">Save\u003c/MazBtn>\n \u003c/MazCard>\n\u003c/template>\n```\n\n**Benefits of Migration**:\n- 🚀 **60% less boilerplate** - No import statements\n- ✅ **Same bundle size** - Perfect tree-shaking maintained\n- 💡 **Better IntelliSense** - Auto-generated types\n- 🎯 **No breaking changes** - Code logic stays identical\n\n---\n\n## Related Documentation\n\n- **[Setup Vue](./setup-vue.md)** - Complete Vue 3 installation guide with resolver configuration\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt 3 has built-in auto-imports, no manual resolver setup needed\n- **[Composables Reference](./composables.md)** - Detailed API docs for all auto-imported composables\n- **[Directives Reference](./directives.md)** - Complete guide to all auto-imported directives\n- **[Performance Guide](./performance.md)** - Tree-shaking optimization strategies\n\n---\n\n## External Resources\n\n- **[unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)** - The underlying component auto-import system\n- **[unplugin-auto-import](https://github.com/antfu/unplugin-auto-import)** - Auto-import for composables and utilities\n- **[Official Maz-UI Resolvers Docs](https://maz-ui.com/guide/resolvers)** - Latest official documentation\n\n---\n\n**Version**: Maz-UI v4.3.3\n**Last Updated**: 2025-12-14\n**Plugin Requirements**: `unplugin-vue-components` + `unplugin-auto-import`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":26814,"content_sha256":"11dde668a3ce64aef5a9ac7bf0ec008291bb878294953882fb9193cd3bbc147a"},{"filename":"references/setup-nuxt.md","content":"# Maz-UI Nuxt 3 Setup Guide\n\nZero-configuration Nuxt module for Maz-UI with auto-imports, theming, and i18n.\n\n## Installation\n\n```bash\n# Using pnpm\npnpm add @maz-ui/nuxt\n\n# Using npm\nnpm install @maz-ui/nuxt\n\n# Using Nuxt CLI\npnpx nuxt@latest module add @maz-ui/nuxt\n```\n\n## Basic Setup\n\nAdd module to `nuxt.config.ts`:\n\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt']\n // That's it! 🎉 Everything auto-imports\n})\n```\n\n## Instant Usage (No Imports Needed)\n\n```vue\n\u003cscript setup>\n// All composables auto-imported\nconst name = ref('')\nconst toast = useToast()\nconst { toggleDarkMode, isDark } = useTheme()\nconst { start, remainingTime } = useTimer({\n timeout: 4000,\n callback: () => console.log('Done!')\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"maz-bg-background maz-p-8\">\n \u003c!-- All components auto-imported -->\n \u003cMazInput v-model=\"name\" label=\"Your Name\" />\n\n \u003cMazBtn color=\"primary\" @click=\"toast.success('Saved!')\">\n Save\n \u003c/MazBtn>\n\n \u003cMazBtn @click=\"toggleDarkMode\">\n {{ isDark ? '🌙' : '☀️' }} Toggle Theme\n \u003c/MazBtn>\n\n \u003c!-- Directives available globally -->\n \u003cdiv v-tooltip=\"'This is a tooltip'\">\n Hover me\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n## Advanced Configuration\n\n### Complete Configuration Example\n\n```typescript\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n\n mazUi: {\n // 🔧 General Settings\n general: {\n autoImportPrefix: 'Maz', // useMazToast instead of useToast\n defaultMazIconPath: '/icons', // Path for \u003cMazIcon />\n devtools: true, // Enable DevTools integration\n },\n\n // 🎨 CSS & Styling\n css: {\n injectMainCss: true, // Auto-inject Maz-UI styles\n },\n\n // 🌈 Theming System\n theme: {\n preset: 'maz-ui', // 'maz-ui' | 'dark' | 'ocean' | customTheme\n strategy: 'hybrid', // 'runtime' | 'buildtime' | 'hybrid' (recommended)\n darkModeStrategy: 'class', // 'class' | 'media' | 'auto'\n colorMode: 'auto', // 'light' | 'dark' | 'auto'\n mode: 'both', // 'light' | 'dark' | 'both'\n overrides: {\n foundation: {\n 'radius': '0.7rem',\n 'border-width': '0.0625rem',\n },\n colors: {\n light: {\n primary: '220 100% 50%',\n secondary: '220 14% 96%',\n },\n dark: {\n primary: '220 100% 70%',\n secondary: '220 14% 4%',\n }\n }\n },\n },\n\n // 🌐 Translations\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: {\n // Override or add custom messages\n },\n },\n\n // 📦 Components (enabled by default)\n components: {\n autoImport: true, // All 50+ components globally available\n },\n\n // 🔌 Plugins (disabled by default, enable as needed)\n plugins: {\n aos: true, // Animations on scroll\n dialog: true, // Programmatic dialogs\n toast: true, // Notifications\n wait: true, // Loading states\n },\n\n // 🔧 Composables (enabled by default)\n composables: {\n useTheme: true,\n useTranslations: true,\n useToast: true,\n useDialog: true,\n useBreakpoints: true,\n useWindowSize: true,\n useTimer: true,\n useFormValidator: true,\n useIdleTimeout: true,\n useUserVisibility: true,\n useSwipe: true,\n useReadingTime: true,\n useStringMatching: true,\n useDisplayNames: true,\n useFreezeValue: true,\n useInjectStrict: true,\n useInstanceUniqId: true,\n useMountComponent: true,\n },\n\n // 📌 Directives (disabled by default, enable as needed)\n directives: {\n vTooltip: { position: 'top' },\n vClickOutside: true,\n vLazyImg: { threshold: 0.1 },\n vZoomImg: true,\n vFullscreenImg: true,\n },\n }\n})\n```\n\n## Theme Strategies\n\nMaz-UI offers three theme strategies optimized for different use cases:\n\n### Hybrid Strategy (Recommended)\n\n**Best for**: SSR/SSG applications with runtime theme switching\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'hybrid', // ✅ OPTIMAL for SSR/SSG\n darkModeStrategy: 'class' // or 'media'\n }\n }\n})\n```\n\n**How it works**:\n1. **Server**: Generates critical CSS based on user preferences (cookie)\n2. **Client**: Injects critical CSS in `\u003chead>` (instant theme)\n3. **Hydration**: No flash, theme persists across page loads\n4. **Runtime**: Full theme switching without page reload\n\n**Critical CSS injection**:\n```html\n\u003c!-- Server-rendered -->\n\u003chead>\n \u003cstyle data-maz-ui-critical>\n :root {\n --maz-color-primary: 220 100% 50%;\n --maz-color-secondary: 220 14% 96%;\n /* ... critical theme variables */\n }\n \u003c/style>\n\u003c/head>\n```\n\n**Benefits**:\n- ✅ Instant theme on server render\n- ✅ No flash of unstyled content (FOUC)\n- ✅ Runtime theme switching\n- ✅ Dark mode toggle works instantly\n- ✅ User preference persistence (cookie)\n\n**Bundle Impact**: ~15KB runtime theme logic + critical CSS\n\n---\n\n### Build-time Strategy\n\n**Best for**: Static sites with no runtime theme switching\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'buildtime', // ✅ SMALLEST bundle\n }\n }\n})\n```\n\n**How it works**:\n1. **Build**: All CSS variables pre-generated at build time\n2. **Server/Client**: Static CSS loaded (no runtime logic)\n3. **Theme switching**: NOT possible (requires full rebuild)\n\n**Benefits**:\n- ✅ Smallest bundle size (~5KB smaller than hybrid)\n- ✅ Fastest initial load\n- ✅ Perfect for static themes\n- ❌ No runtime theme switching\n- ❌ No dark mode toggle\n\n**Use cases**:\n- Marketing sites with fixed branding\n- Documentation sites\n- Landing pages\n\n---\n\n### Runtime Strategy\n\n**Best for**: Apps with multiple theme presets and user preference\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'runtime', // ⚠️ LARGER bundle\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n**How it works**:\n1. **Server**: Minimal CSS (base styles only)\n2. **Client**: Full theme logic loaded\n3. **Runtime**: Complete theme switching (all presets available)\n\n**Benefits**:\n- ✅ Full runtime theme switching\n- ✅ All theme presets available\n- ✅ User preference persistence\n- ⚠️ Larger initial bundle (~20KB)\n- ⚠️ Possible FOUC on slow connections\n\n**Use cases**:\n- Apps with theme marketplace\n- Multi-tenant applications\n- User-customizable themes\n\n---\n\n### Dark Mode Strategies\n\n#### Class Strategy (Recommended)\n\nUses `class=\"dark\"` on `\u003chtml>` element:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n darkModeStrategy: 'class' // ✅ RECOMMENDED\n }\n }\n})\n```\n\n**How it works**:\n```html\n\u003c!-- Light mode -->\n\u003chtml>\n \u003cbody>...\u003c/body>\n\u003c/html>\n\n\u003c!-- Dark mode -->\n\u003chtml class=\"dark\">\n \u003cbody>...\u003c/body>\n\u003c/html>\n```\n\n**Benefits**:\n- ✅ Full control over dark mode\n- ✅ Works with JavaScript disabled\n- ✅ Persists across page loads (cookie)\n- ✅ No flash on page load\n\n---\n\n#### Media Strategy\n\nUses `prefers-color-scheme` media query:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n darkModeStrategy: 'media'\n }\n }\n})\n```\n\n**Benefits**:\n- ✅ Automatic based on system preferences\n- ✅ No JavaScript required\n- ❌ Cannot be toggled by user\n- ❌ Follows system preference only\n\n---\n\n### Theme Strategy Comparison\n\n| Feature | Hybrid | Build-time | Runtime |\n|---------|--------|------------|---------|\n| **Bundle Size** | ~15KB | ~10KB | ~25KB |\n| **Critical CSS** | ✅ Yes | ✅ Yes | ❌ No |\n| **Theme Switching** | ✅ Yes | ❌ No | ✅ Yes |\n| **Dark Mode Toggle** | ✅ Yes | ❌ No | ✅ Yes |\n| **FOUC Prevention** | ✅ Yes | ✅ Yes | ⚠️ Partial |\n| **SSR Performance** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |\n| **SSG Performance** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |\n| **Use Case** | SSR/SSG apps | Static sites | Multi-theme apps |\n\n**For detailed theme documentation**, load `references/theming.md`.\n\n---\n\n## SSR & SSG Considerations\n\nMaz-UI v4 is fully compatible with Nuxt 3's Server-Side Rendering (SSR) and Static Site Generation (SSG), but requires proper configuration to avoid common pitfalls.\n\n### Critical CSS for Instant Theming\n\nThe **hybrid strategy** (recommended) prevents Flash of Unstyled Content (FOUC) by injecting critical CSS during server rendering:\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid', // ✅ Injects critical CSS on server\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n**How it works**:\n1. Server reads user preference from cookie (`maz-ui-dark-mode`)\n2. Generates critical CSS with correct theme variables\n3. Injects `\u003cstyle data-maz-ui-critical>` in `\u003chead>`\n4. User sees correct theme instantly (no flash)\n\n### Preventing Hydration Mismatches\n\nSome Maz-UI components use browser APIs and must only render on the client:\n\n```vue\n\u003ctemplate>\n \u003c!-- ✅ CORRECT: Wrap client-only components -->\n \u003cClientOnly>\n \u003cMazDialogConfirm />\n \u003cMazToast />\n \u003cMazWaitOverlay />\n \u003c/ClientOnly>\n\n \u003c!-- ❌ WRONG: Dialog/Toast on server causes hydration errors -->\n \u003cMazDialogConfirm />\n\u003c/template>\n```\n\n**Why?** Dialog, Toast, and Wait plugins use `window`, `document` APIs not available during SSR.\n\n### Dark Mode Without Flash\n\nTo prevent dark mode flash on page load, use **hybrid strategy** with **class dark mode**:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid', // Server reads cookie\n darkModeStrategy: 'class' // class=\"dark\" on \u003chtml>\n }\n }\n})\n```\n\nServer checks `maz-ui-dark-mode` cookie → applies correct theme → no flash on hydration.\n\n### Translation Hydration Issues\n\n**CRITICAL**: Always provide initial locale immediately (not as async function) to prevent hydration mismatches:\n\n```typescript\nimport { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n messages: {\n // ✅ CORRECT: Immediate import\n fr,\n\n // ✅ Other languages can be lazy\n en: () => import('@maz-ui/translations/locales/en')\n }\n }\n }\n})\n```\n\n### Static Site Generation (SSG)\n\nFor SSG, use **buildtime strategy** for smallest bundle:\n\n```typescript\nexport default defineNuxtConfig({\n nitro: {\n prerender: {\n routes: ['/', '/about', '/contact']\n }\n },\n\n mazUi: {\n theme: {\n strategy: 'buildtime' // ✅ Smallest bundle for static sites\n }\n }\n})\n```\n\n**Trade-off**: No runtime theme switching, but optimal performance for static content.\n\n### Common SSR/SSG Pitfalls\n\n1. **Hydration mismatch**: Using `window`/`document` in SSR → Use `\u003cClientOnly>` or `onMounted()`\n2. **FOUC (Flash of Unstyled Content)**: Wrong theme strategy → Use `hybrid` strategy\n3. **Dark mode flash**: Server/client theme mismatch → Use `hybrid` + `class` dark mode\n4. **Translation errors**: Async locale in SSR → Import initial locale immediately\n\n**For comprehensive SSR/SSG patterns, troubleshooting, and advanced configurations**, load `references/ssr-ssg.md`.\n\n---\n\n## Custom Theme Creation\n\n```typescript\nimport { definePreset } from '@maz-ui/themes'\n\nexport const customTheme = definePreset({\n base: 'maz-ui',\n name: 'custom',\n foundation: {\n 'base-font-size': '14px',\n 'font-family': 'Manrope, sans-serif',\n 'radius': '0.7rem',\n 'border-width': '0.0625rem',\n },\n colors: {\n light: {\n primary: '350 100% 50%', // Pink\n secondary: '350 14% 96%',\n background: '0 0% 100%',\n foreground: '222 84% 5%',\n muted: '210 40% 96%',\n accent: '210 40% 90%',\n destructive: '0 84% 60%',\n border: '214 32% 91%',\n input: '214 32% 91%',\n ring: '350 100% 50%',\n },\n dark: {\n primary: '350 100% 70%',\n secondary: '350 14% 4%',\n background: '222 84% 5%',\n foreground: '210 40% 98%',\n muted: '217 33% 17%',\n accent: '217 33% 17%',\n destructive: '0 62% 30%',\n border: '217 33% 17%',\n input: '217 33% 17%',\n ring: '350 100% 70%',\n }\n },\n})\n\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n mazUi: {\n theme: {\n preset: customTheme,\n strategy: 'hybrid',\n }\n }\n})\n```\n\n## Translations & i18n\n\nMaz-UI includes 8 built-in languages (en, fr, es, de, it, pt, ja, zh-CN) with automatic lazy loading.\n\n### Basic Setup\n\n```typescript\nimport { fr, es } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true, // Default - preload fallback language\n messages: {\n // Import immediately to avoid hydration issues\n fr,\n es\n }\n }\n }\n})\n```\n\n### preloadFallback Option\n\n**Default (`preloadFallback: true`)** - Recommended:\n- ✅ No delay - Fallback translations immediately available\n- ✅ Smooth experience - No missing text\n- ✅ Zero hydration issues in SSR\n- ❌ Slightly larger initial bundle\n\n**Disabled (`preloadFallback: false`)** - For bundle size optimization:\n- ✅ Smaller initial bundle\n- ❌ May temporarily show translation keys\n- ❌ Requires loading state management\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: false, // Optimize bundle size\n messages: {\n // Still provide initial locale to avoid hydration issues\n fr\n }\n }\n }\n})\n```\n\n### Lazy Loading Strategies\n\n#### Method 1: Dynamic Imports (Recommended)\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'en',\n fallbackLocale: 'en',\n preloadFallback: false,\n messages: {\n // Built-in languages load automatically\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es'),\n de: () => import('@maz-ui/translations/locales/de'),\n\n // Custom language files\n nl: () => import('./locales/nl.ts').then(m => m.default)\n }\n }\n }\n})\n```\n\n#### Method 2: API-Based Loading\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'en',\n messages: {\n // Load from API\n fr: async () => {\n const response = await $fetch('/api/translations/fr')\n return response\n },\n\n // Combine multiple sources\n es: async () => {\n const [defaultTranslations, customTranslations] = await Promise.all([\n import('@maz-ui/translations/locales/es').then(m => m.default),\n $fetch('/api/translations/es/custom')\n ])\n return { ...defaultTranslations, ...customTranslations }\n }\n }\n }\n }\n})\n```\n\n#### Method 3: Mix Immediate and Lazy Loading\n\n```typescript\nimport { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n messages: {\n // French: loaded immediately (important for SSR)\n fr,\n\n // Others: loaded lazily\n en: () => import('@maz-ui/translations/locales/en'),\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n }\n})\n```\n\n### Using Translations in Components\n\n```vue\n\u003cscript setup>\nconst { locale, setLocale } = useTranslations()\nconst isLoading = ref(false)\n\n// Change language with loading state\nasync function switchLanguage(newLocale) {\n isLoading.value = true\n try {\n await setLocale(newLocale) // Loads translations if needed\n console.log(`Language changed to ${newLocale}`)\n } catch (error) {\n console.error('Failed to load translations:', error)\n } finally {\n isLoading.value = false\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003c!-- Language switcher -->\n \u003cMazBtn\n :disabled=\"isLoading\"\n @click=\"switchLanguage('fr')\"\n >\n 🇫🇷 {{ isLoading && locale === 'fr' ? 'Loading...' : 'Français' }}\n \u003c/MazBtn>\n \u003cMazBtn\n :disabled=\"isLoading\"\n @click=\"switchLanguage('es')\"\n >\n 🇪🇸 {{ isLoading && locale === 'es' ? 'Cargando...' : 'Español' }}\n \u003c/MazBtn>\n\n \u003c!-- Loading indicator -->\n \u003cdiv v-if=\"isLoading\" class=\"loading-overlay\">\n Loading translations...\n \u003c/div>\n\n \u003c!-- Current language -->\n \u003cp>Current: {{ locale }}\u003c/p>\n\n \u003c!-- Components use translations automatically -->\n \u003cMazInputPhoneNumber />\n \u003c/div>\n\u003c/template>\n```\n\n### Error Handling for Async Language Switching\n\n```vue\n\u003cscript setup>\nconst { setLocale } = useTranslations()\nconst toast = useToast()\n\nasync function switchLanguage(locale) {\n try {\n await setLocale(locale)\n toast.success(`Language changed to ${locale}`)\n } catch (error) {\n console.error('Translation loading error:', error)\n toast.error('Failed to load translations. Please try again.')\n }\n}\n\u003c/script>\n```\n\n### SSR Considerations\n\n**CRITICAL**: In SSR/SSG, always provide the initial locale in `messages` to avoid hydration mismatches:\n\n```typescript\nimport { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: {\n // ✅ Provide initial locale immediately (not as function)\n fr,\n\n // ✅ Other languages can be lazy-loaded\n en: () => import('@maz-ui/translations/locales/en'),\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n }\n})\n```\n\n**Why?** If translations load asynchronously during SSR, the server-rendered HTML won't match client-side rendering, causing hydration warnings.\n\n### Browser Language Detection\n\n```typescript\n// composables/useLanguageDetection.ts\nexport function useLanguageDetection() {\n function detectUserLanguage() {\n try {\n const browserLang = navigator.language.split('-')[0]\n const supportedLanguages = ['en', 'fr', 'es', 'de', 'it', 'pt', 'ja', 'zh']\n\n if (supportedLanguages.includes(browserLang)) {\n return browserLang\n }\n\n return 'en' // Fallback\n } catch {\n return 'en'\n }\n }\n\n return { detectUserLanguage }\n}\n```\n\nUsage in plugin:\n\n```typescript\n// plugins/language-detection.client.ts\nexport default defineNuxtPlugin(() => {\n const { detectUserLanguage } = useLanguageDetection()\n const { setLocale } = useTranslations()\n\n // Detect and set language on client side\n const detectedLang = detectUserLanguage()\n setLocale(detectedLang)\n})\n```\n\n### Custom Translation Files\n\nCreate separate files in your Nuxt project:\n\n```typescript\n// locales/fr.ts\nexport default {\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Code pays',\n error: 'Choisir le pays',\n searchPlaceholder: 'Rechercher le pays'\n },\n phoneInput: {\n placeholder: 'Numéro de téléphone',\n example: 'Exemple: {example}'\n }\n },\n dropzone: {\n dragAndDrop: 'Déposez vos fichiers',\n selectFile: 'sélectionner un fichier',\n divider: 'ou'\n }\n // You can omit translations you don't want to override\n // Default Maz-UI translations will be used automatically\n}\n```\n\nThen import in config:\n\n```typescript\nimport customFr from './locales/fr'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n messages: {\n fr: customFr // Use your custom translations\n }\n }\n }\n})\n```\n\n### Important Notes\n\n1. **8 built-in languages load automatically** - fr, es, de, it, pt, ja, zh-CN don't need to be provided unless you want to override them\n2. **Lazy loading is asynchronous** - `setLocale()` returns a Promise, use `await`\n3. **Translations are cached** - Once loaded, switching back is instant\n4. **SSR requires immediate initial locale** - Provide initial locale as object, not function\n5. **Partial translations supported** - Provide only what you want to override\n6. **Variables replaced automatically** - `{example}`, `{count}`, `{page}` handled by Maz-UI\n\nFor complete translation keys reference and advanced patterns, load `references/translations.md`.\n\n## Using Composables\n\nAll composables are auto-imported:\n\n```vue\n\u003cscript setup>\n// Theme management\nconst { toggleDarkMode, isDark, setColorMode } = useTheme()\n\n// Toast notifications\nconst toast = useToast()\ntoast.success('Operation successful!')\ntoast.error('Something went wrong')\ntoast.warning('Please be careful')\ntoast.info('Just so you know')\n\n// Dialog prompts\nconst dialog = useDialog()\nconst confirmed = await dialog.confirm({\n title: 'Delete Item',\n message: 'Are you sure?',\n confirmText: 'Delete',\n cancelText: 'Cancel'\n})\n\n// Responsive breakpoints\nconst { isMobile, isTablet, isDesktop } = useBreakpoints()\n\n// Window size\nconst { width, height } = useWindowSize()\n\n// Timer\nconst { start, stop, pause, resume, remainingTime } = useTimer({\n timeout: 5000,\n callback: () => console.log('Timer ended!')\n})\n\n// Form validation (Valibot)\nimport { string, email } from 'valibot'\n\nconst { errors, validate } = useFormValidator({\n schema: {\n email: [string(), email()],\n password: [string(), minLength(8)]\n }\n})\n\n// Translations\nconst { t, locale, setLocale } = useTranslations()\nconst greeting = t('common.greeting')\n\u003c/script>\n```\n\n## Using Plugins\n\n### Toast Plugin\n\nEnable in config:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n plugins: {\n toast: true\n }\n }\n})\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nconst toast = useToast()\n\nfunction notify() {\n toast.success('Saved successfully!', {\n timeout: 3000,\n position: 'top-right',\n button: {\n text: 'Undo',\n onClick: () => console.log('Undone'),\n closeToast: true\n }\n })\n}\n\u003c/script>\n```\n\n### Dialog Plugin\n\nEnable in config:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n plugins: {\n dialog: true\n }\n }\n})\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nconst dialog = useDialog()\n\nasync function confirmDelete() {\n const result = await dialog.confirm({\n title: 'Confirm Delete',\n message: 'This action cannot be undone.',\n confirmText: 'Delete',\n cancelText: 'Cancel',\n confirmColor: 'destructive'\n })\n\n if (result) {\n // Perform deletion\n }\n}\n\u003c/script>\n```\n\n### AOS Plugin (Animations on Scroll)\n\nEnable in config:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n plugins: {\n aos: true\n }\n }\n})\n```\n\nUsage in templates:\n\n```vue\n\u003ctemplate>\n \u003cdiv\n data-maz-aos=\"fade-in\"\n data-maz-aos-delay=\"100\"\n data-maz-aos-duration=\"300\"\n >\n Animated content\n \u003c/div>\n\u003c/template>\n```\n\n### Wait Plugin (Loading States)\n\nEnable in config:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n plugins: {\n wait: true\n }\n }\n})\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nconst wait = useWait()\n\nasync function fetchData() {\n wait.start('loading-data')\n try {\n const data = await $fetch('/api/data')\n return data\n } finally {\n wait.end('loading-data')\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn\n :loading=\"wait.is('loading-data')\"\n @click=\"fetchData\"\n >\n Fetch Data\n \u003c/MazBtn>\n\u003c/template>\n```\n\n## Using Directives\n\nEnable directives in config:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n directives: {\n vTooltip: true,\n vClickOutside: true,\n vLazyImg: true,\n vZoomImg: true,\n vFullscreenImg: true,\n }\n }\n})\n```\n\nUsage:\n\n```vue\n\u003ctemplate>\n \u003c!-- Tooltip -->\n \u003cMazBtn v-tooltip=\"'Click me for action'\">\n Action\n \u003c/MazBtn>\n\n \u003c!-- With options -->\n \u003cMazBtn v-tooltip=\"{ text: 'Bottom tooltip', position: 'bottom' }\">\n Hover me\n \u003c/MazBtn>\n\n \u003c!-- Click outside detector -->\n \u003cdiv v-click-outside=\"handleClickOutside\">\n \u003cMazBtn @click=\"isOpen = true\">Open\u003c/MazBtn>\n \u003cdiv v-if=\"isOpen\">Dropdown content\u003c/div>\n \u003c/div>\n\n \u003c!-- Lazy image loading -->\n \u003cimg v-lazy-img=\"imageUrl\" alt=\"Description\" />\n\n \u003c!-- Zoom image on click -->\n \u003cimg v-zoom-img=\"imageUrl\" alt=\"Zoomable\" />\n\n \u003c!-- Fullscreen image viewer -->\n \u003cimg v-fullscreen-img=\"imageUrl\" alt=\"Fullscreen\" />\n\u003c/template>\n```\n\n## Translations (i18n)\n\nConfigure locales:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: {\n // Add custom messages or override defaults\n fr: {\n custom: {\n greeting: 'Bonjour'\n }\n }\n }\n }\n }\n})\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nconst { t, locale, setLocale } = useTranslations()\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cp>{{ t('custom.greeting') }}\u003c/p>\n \u003cp>Current locale: {{ locale }}\u003c/p>\n\n \u003cMazBtn @click=\"setLocale('en')\">English\u003c/MazBtn>\n \u003cMazBtn @click=\"setLocale('fr')\">Français\u003c/MazBtn>\n \u003c/div>\n\u003c/template>\n```\n\n## Common Issues\n\n### 1. `useTheme` Error\n\n**Error**: `\"useTheme must be used within MazUi plugin installation\"`\n**Solution**: Ensure theme composable is enabled:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n composables: {\n useTheme: true\n },\n theme: {\n preset: 'maz-ui' // Not false\n }\n }\n})\n```\n\n### 2. Auto-Imports Not Working\n\n**Error**: Components/composables not found\n**Solution**:\n1. Clear Nuxt cache: `rm -rf .nuxt node_modules/.cache`\n2. Reinstall: `pnpm install`\n3. Restart dev server\n\n### 3. Styles Not Applied\n\n**Error**: Components render without styling\n**Solution**: Ensure CSS injection is enabled:\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n css: {\n injectMainCss: true // Must be true\n }\n }\n})\n```\n\n### 4. TypeScript Errors\n\n**Error**: Type errors with components\n**Solution**: Ensure `.nuxt` folder exists and types are generated.\nRun: `pnpm nuxi prepare`\n\n## Performance Optimization\n\n### Enable Only What You Need\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n // Disable unused composables\n composables: {\n useIdleTimeout: false,\n useReadingTime: false,\n useStringMatching: false,\n },\n // Enable only required plugins\n plugins: {\n toast: true,\n dialog: false,\n aos: false,\n wait: false,\n }\n }\n})\n```\n\n### Prefix to Avoid Conflicts\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n general: {\n autoImportPrefix: 'Maz' // useMazToast, useMazTheme, etc.\n }\n }\n})\n```\n\n## Next Steps\n\n- **Theming**: Load `theming.md` for custom themes and dark mode\n- **Components**: Load `components-*.md` for component guides\n- **Troubleshooting**: Load `troubleshooting.md` for common issues\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":26580,"content_sha256":"dfb2e9f6605fd3f69800b27c391a1903820c8312f903bb261fde7dbb42a4a4da"},{"filename":"references/setup-vue.md","content":"# Maz-UI Vue 3 Setup Guide\n\nComplete installation and configuration guide for using Maz-UI in Vue 3 projects.\n\n## Installation\n\n```bash\n# Using pnpm (recommended)\npnpm add maz-ui @maz-ui/themes\n\n# Using npm\nnpm install maz-ui @maz-ui/themes\n\n# Using yarn\nyarn add maz-ui @maz-ui/themes\n```\n\n## Basic Setup\n\n### 1. Install MazUi Plugin\n\nCreate or edit your `main.ts` file:\n\n```typescript\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes'\nimport { en } from '@maz-ui/translations'\nimport App from './App.vue'\n\n// Import Maz-UI styles BEFORE your own CSS\nimport 'maz-ui/styles'\nimport './style.css'\n\nconst app = createApp(App)\n\napp.use(MazUi, {\n theme: {\n preset: mazUi\n },\n translations: {\n messages: { en }\n }\n})\n\napp.mount('#app')\n```\n\n### 2. Use Components\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\nimport { ref } from 'vue'\n\nconst name = ref('')\n\nfunction handleSubmit() {\n console.log('Name:', name.value)\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv class=\"maz-flex maz-flex-col maz-gap-4\">\n \u003cMazInput\n v-model=\"name\"\n label=\"Your Name\"\n placeholder=\"Enter your name\"\n />\n \u003cMazBtn color=\"primary\" @click=\"handleSubmit\">\n Submit\n \u003c/MazBtn>\n \u003c/div>\n\u003c/template>\n```\n\n## Advanced Configuration\n\n### With Custom Theme\n\n```typescript\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes/presets'\nimport { fr } from '@maz-ui/translations'\nimport 'maz-ui/styles'\nimport './style.css'\n\napp.use(MazUi, {\n theme: {\n preset: mazUi, // or 'ocean' | 'pristine' | 'obsidian'\n overrides: {\n foundation: {\n 'radius': '0.7rem',\n 'border-width': '0.0625rem',\n },\n colors: {\n light: {\n primary: '220 100% 50%', // Custom blue\n },\n dark: {\n primary: '220 100% 70%',\n }\n }\n }\n },\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n messages: { fr },\n },\n})\n```\n\n## Translations & i18n\n\nMaz-UI includes 8 built-in languages (en, fr, es, de, it, pt, ja, zh-CN) with automatic lazy loading.\n\n### Basic Setup\n\n```typescript\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { fr } from '@maz-ui/translations'\nimport 'maz-ui/styles'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true, // Default - preload fallback language\n messages: {\n fr // Immediate load to avoid hydration issues\n }\n }\n})\n```\n\n### preloadFallback Option\n\n**Default (`preloadFallback: true`)** - Recommended:\n- ✅ No delay - Fallback translations immediately available\n- ✅ Smooth experience - No missing text even if translation doesn't exist\n- ❌ Slightly larger initial bundle\n\n**Disabled (`preloadFallback: false`)** - For bundle size optimization:\n- ✅ Smaller initial bundle\n- ❌ May temporarily show translation keys\n- ❌ Requires loading state management\n\n### Lazy Loading Strategies\n\n#### Method 1: Dynamic Imports (Recommended)\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'en',\n fallbackLocale: 'en',\n preloadFallback: false,\n messages: {\n // Built-in languages load automatically\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es'),\n de: () => import('@maz-ui/translations/locales/de'),\n\n // Custom language files\n nl: () => import('./locales/nl.ts').then(m => m.default)\n }\n }\n})\n```\n\n#### Method 2: API-Based Loading\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'en',\n messages: {\n // Load from API\n fr: async () => {\n const response = await fetch('/api/translations/fr')\n return response.json()\n },\n\n // Combine multiple sources\n es: async () => {\n const [defaultTranslations, customTranslations] = await Promise.all([\n import('@maz-ui/translations/locales/es').then(m => m.default),\n fetch('/api/translations/es/custom').then(r => r.json())\n ])\n return { ...defaultTranslations, ...customTranslations }\n }\n }\n }\n})\n```\n\n#### Method 3: Mix Immediate and Lazy Loading\n\n```typescript\nimport { fr } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n messages: {\n // French: loaded immediately\n fr,\n\n // Others: loaded lazily\n en: () => import('@maz-ui/translations/locales/en'),\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n})\n```\n\n### Using Translations in Components\n\n```vue\n\u003cscript setup>\nimport { useTranslations } from '@maz-ui/translations'\nimport { ref } from 'vue'\n\nconst { locale, setLocale } = useTranslations()\nconst isLoading = ref(false)\n\n// Change language with loading state\nasync function switchLanguage(newLocale) {\n isLoading.value = true\n try {\n await setLocale(newLocale) // Loads translations if needed\n console.log(`Language changed to ${newLocale}`)\n } catch (error) {\n console.error('Failed to load translations:', error)\n // Handle error (show toast, etc.)\n } finally {\n isLoading.value = false\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003c!-- Language switcher -->\n \u003cbutton\n :disabled=\"isLoading\"\n @click=\"switchLanguage('fr')\"\n >\n 🇫🇷 {{ isLoading && locale === 'fr' ? 'Loading...' : 'Français' }}\n \u003c/button>\n \u003cbutton\n :disabled=\"isLoading\"\n @click=\"switchLanguage('es')\"\n >\n 🇪🇸 {{ isLoading && locale === 'es' ? 'Cargando...' : 'Español' }}\n \u003c/button>\n\n \u003c!-- Loading indicator -->\n \u003cdiv v-if=\"isLoading\" class=\"loading-overlay\">\n Loading translations...\n \u003c/div>\n\n \u003c!-- Current language -->\n \u003cp>Current: {{ locale }}\u003c/p>\n\n \u003c!-- Components use translations automatically -->\n \u003cMazInputPhoneNumber />\n \u003c/div>\n\u003c/template>\n```\n\n### Error Handling for Async Language Switching\n\n```vue\n\u003cscript setup>\nimport { useTranslations } from '@maz-ui/translations'\nimport { useToast } from 'maz-ui/composables'\n\nconst { setLocale } = useTranslations()\nconst toast = useToast()\n\nasync function switchLanguage(locale) {\n try {\n await setLocale(locale)\n toast.success(`Language changed to ${locale}`)\n } catch (error) {\n console.error('Translation loading error:', error)\n toast.error('Failed to load translations. Please try again.')\n }\n}\n\u003c/script>\n```\n\n### Browser Language Detection\n\n```typescript\nasync function detectUserLanguage() {\n try {\n const browserLang = navigator.language.split('-')[0]\n const supportedLanguages = ['en', 'fr', 'es', 'de', 'it', 'pt', 'ja', 'zh']\n\n if (supportedLanguages.includes(browserLang)) {\n return browserLang\n }\n\n return 'en' // Fallback\n } catch {\n return 'en'\n }\n}\n\n// Use automatic detection\napp.use(MazUi, {\n translations: {\n locale: await detectUserLanguage(),\n messages: {\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n})\n```\n\n### Custom Translation Files\n\nCreate separate files for each language:\n\n```typescript\n// locales/fr.ts\nexport default {\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Code pays',\n error: 'Choisir le pays',\n searchPlaceholder: 'Rechercher le pays'\n },\n phoneInput: {\n placeholder: 'Numéro de téléphone',\n example: 'Exemple: {example}'\n }\n },\n dropzone: {\n dragAndDrop: 'Déposez vos fichiers',\n selectFile: 'sélectionner un fichier',\n divider: 'ou'\n }\n // You can omit translations you don't want to override\n // Default Maz-UI translations will be used automatically\n}\n```\n\n### Important Notes\n\n1. **8 built-in languages load automatically** - fr, es, de, it, pt, ja, zh-CN don't need to be provided unless you want to override them\n2. **Lazy loading is asynchronous** - `setLocale()` returns a Promise, use `await`\n3. **Translations are cached** - Once loaded, switching back is instant\n4. **Partial translations supported** - Provide only what you want to override\n5. **Variables replaced automatically** - `{example}`, `{count}`, `{page}` handled by Maz-UI\n\nFor complete translation keys reference and advanced patterns, load `references/translations.md`.\n\n## Auto-Import Setup (Recommended)\n\nFor optimal DX, use auto-imports to avoid manual component imports.\n\n### Install Dependencies\n\n```bash\npnpm add -D unplugin-vue-components unplugin-auto-import\n```\n\n### Configure Vite\n\nEdit `vite.config.ts`:\n\n```typescript\nimport { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport {\n MazComponentsResolver,\n MazDirectivesResolver,\n MazModulesResolver\n} from 'maz-ui/resolvers'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport Components from 'unplugin-vue-components/vite'\n\nexport default defineConfig({\n plugins: [\n vue(),\n\n // Auto-import components\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver(),\n ],\n dts: true, // Generate type definitions\n }),\n\n // Auto-import composables and utilities\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: true,\n }),\n ],\n})\n```\n\n### Use Without Imports\n\n```vue\n\u003cscript setup>\n// No imports needed! All auto-imported:\nconst name = ref('')\nconst toast = useToast() // Auto-imported composable\nconst { toggleDarkMode } = useTheme()\n\nconst debouncedSearch = debounce((query) => {\n console.log('Searching:', query)\n}, 300)\n\nfunction handleClickOutside() {\n toast.info('Clicked outside!')\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Auto-imported components -->\n \u003cMazInput v-model=\"name\" placeholder=\"Type here...\" />\n \u003cMazBtn @click=\"toggleDarkMode\">Toggle Dark Mode\u003c/MazBtn>\n\n \u003c!-- Auto-imported directives -->\n \u003cdiv v-click-outside=\"handleClickOutside\">\n Click outside detector\n \u003c/div>\n\n \u003cMazBtn v-tooltip=\"'This is a tooltip'\">\n Hover me\n \u003c/MazBtn>\n\u003c/template>\n```\n\n## Available Resolvers\n\n| Resolver | Purpose | Import |\n|----------|---------|--------|\n| `MazComponentsResolver` | Components (MazBtn, MazInput, etc.) | `'maz-ui/resolvers'` |\n| `MazDirectivesResolver` | Directives (v-click-outside, v-tooltip, etc.) | `'maz-ui/resolvers'` |\n| `MazModulesResolver` | Composables & utilities (useToast, debounce, etc.) | `'maz-ui/resolvers'` |\n\n### Resolver Options\n\nEach resolver supports advanced configuration:\n\n```typescript\nMazComponentsResolver({\n prefix: '', // Component prefix (default: '')\n exclude: [], // Exclude specific components\n include: [], // Only include specific components\n})\n\nMazDirectivesResolver({\n prefix: 'Maz', // Directive prefix (default: '')\n})\n\nMazModulesResolver({\n prefix: 'Maz', // Composable/util prefix (default: '')\n exclude: [], // Exclude specific modules\n})\n```\n\n### Avoiding Naming Conflicts\n\nUse the `prefix` option to prevent conflicts with other libraries:\n\n```typescript\nexport default defineConfig({\n plugins: [\n Components({\n resolvers: [\n MazComponentsResolver(),\n MazDirectivesResolver({ prefix: 'Maz' }), // v-maz-tooltip\n ],\n }),\n AutoImport({\n resolvers: [\n MazModulesResolver({ prefix: 'Maz' }), // useMazToast, useMazTheme\n ],\n }),\n ],\n})\n```\n\n### Advanced Resolver Configuration\n\n#### Include/Exclude Specific Components\n\n```typescript\nComponents({\n resolvers: [\n MazComponentsResolver({\n // Only auto-import form components\n include: ['MazInput', 'MazSelect', 'MazTextarea', 'MazCheckbox']\n }),\n\n // Or exclude heavy components\n MazComponentsResolver({\n exclude: ['MazCarousel', 'MazGallery', 'MazTable']\n })\n ]\n})\n```\n\n#### Multiple Resolvers for Different Namespaces\n\n```typescript\nComponents({\n resolvers: [\n // Maz-UI components\n MazComponentsResolver(),\n\n // Other UI library\n ElementPlusResolver(),\n ]\n})\n```\n\n#### Webpack Configuration\n\n```javascript\n// webpack.config.js\nconst Components = require('unplugin-vue-components/webpack')\nconst AutoImport = require('unplugin-auto-import/webpack')\nconst { MazComponentsResolver, MazModulesResolver } = require('maz-ui/resolvers')\n\nmodule.exports = {\n plugins: [\n Components({\n resolvers: [MazComponentsResolver()],\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n }),\n ],\n}\n```\n\n**For complete resolver documentation** including Rollup, esbuild configurations, and troubleshooting, load `references/resolvers.md`.\n\n## Using Plugins\n\n### Toast Plugin\n\n```typescript\n// main.ts\nimport { MazToast } from 'maz-ui/plugins/toast'\nimport 'maz-ui/styles' // Already includes toast styles\n\napp.use(MazToast, {\n position: 'top-right',\n timeout: 3000,\n})\n```\n\nUsage in components:\n\n```vue\n\u003cscript setup>\nimport { useToast } from 'maz-ui/composables'\n\nconst toast = useToast()\n\nfunction showNotification() {\n toast.success('Operation successful!')\n toast.error('Something went wrong')\n toast.warning('Please be careful')\n toast.info('Just so you know')\n}\n\u003c/script>\n```\n\n### Dialog Plugin\n\n```typescript\n// main.ts\nimport { MazDialog } from 'maz-ui/plugins/dialog'\nimport 'maz-ui/styles'\n\napp.use(MazDialog)\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nimport { useDialog } from 'maz-ui/composables'\n\nconst dialog = useDialog()\n\nasync function confirmDelete() {\n const confirmed = await dialog.confirm({\n title: 'Delete Item',\n message: 'Are you sure you want to delete this item?',\n confirmText: 'Delete',\n cancelText: 'Cancel'\n })\n\n if (confirmed) {\n // Perform deletion\n }\n}\n\u003c/script>\n```\n\n### AOS Plugin (Animations on Scroll)\n\n```typescript\n// main.ts\nimport { MazAos } from 'maz-ui/plugins/aos'\nimport 'maz-ui/styles'\n\napp.use(MazAos, {\n animation: 'fade-in',\n duration: 300,\n})\n```\n\nUsage:\n\n```vue\n\u003ctemplate>\n \u003cdiv data-maz-aos=\"fade-in\" data-maz-aos-delay=\"100\">\n Content with animation\n \u003c/div>\n\u003c/template>\n```\n\n### Wait Plugin (Loading States)\n\n```typescript\n// main.ts\nimport { MazWait } from 'maz-ui/plugins/wait'\nimport 'maz-ui/styles'\n\napp.use(MazWait)\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nimport { useWait } from 'maz-ui/composables'\n\nconst wait = useWait()\n\nasync function fetchData() {\n wait.start('fetching')\n try {\n const data = await fetch('/api/data')\n return data\n } finally {\n wait.end('fetching')\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn :loading=\"wait.is('fetching')\" @click=\"fetchData\">\n Fetch Data\n \u003c/MazBtn>\n\u003c/template>\n```\n\n## Using Directives\n\n### Tooltip\n\n```typescript\n// main.ts\nimport { vTooltip } from 'maz-ui/directives'\n\napp.directive('tooltip', vTooltip)\n```\n\nUsage:\n\n```vue\n\u003ctemplate>\n \u003cMazBtn v-tooltip=\"'Click me for action'\">\n Action\n \u003c/MazBtn>\n\n \u003c!-- With options -->\n \u003cMazBtn v-tooltip=\"{ text: 'Bottom tooltip', position: 'bottom' }\">\n Hover me\n \u003c/MazBtn>\n\u003c/template>\n```\n\n### Click Outside\n\n```typescript\n// main.ts\nimport { vClickOutside } from 'maz-ui/directives'\n\napp.directive('click-outside', vClickOutside)\n```\n\nUsage:\n\n```vue\n\u003cscript setup>\nconst isOpen = ref(false)\n\nfunction handleClickOutside() {\n isOpen.value = false\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv v-click-outside=\"handleClickOutside\">\n \u003cMazBtn @click=\"isOpen = true\">Open\u003c/MazBtn>\n \u003cdiv v-if=\"isOpen\">\n Dropdown content\n \u003c/div>\n \u003c/div>\n\u003c/template>\n```\n\n### Lazy Image\n\n```typescript\n// main.ts\nimport { vLazyImg } from 'maz-ui/directives'\n\napp.directive('lazy-img', vLazyImg)\n```\n\nUsage:\n\n```vue\n\u003ctemplate>\n \u003cimg v-lazy-img=\"imageUrl\" alt=\"Description\" />\n\u003c/template>\n```\n\n## Tree-Shaking Optimization\n\n### Direct Imports (Most Optimized)\n\n```typescript\n// ✅✅✅ Best - smallest bundle size\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazCard from 'maz-ui/components/MazCard'\nimport MazInput from 'maz-ui/components/MazInput'\nimport { useToast } from 'maz-ui/composables/useToast'\nimport { vClickOutside } from 'maz-ui/directives/vClickOutside'\n```\n\n### Index Imports (Good)\n\n```typescript\n// ✅ Good - tree-shakable\nimport { MazBtn, MazCard, MazInput } from 'maz-ui/components'\nimport { useToast, useBreakpoints } from 'maz-ui/composables'\n```\n\n### Avoid (Not Tree-Shakable)\n\n```typescript\n// ❌ Imports everything - large bundle\nimport * as MazUI from 'maz-ui'\n```\n\n## TypeScript Support\n\nMaz-UI is written in TypeScript and provides full type definitions out of the box.\n\n### Type Imports\n\n```typescript\nimport type { MazBtnProps } from 'maz-ui/components/MazBtn'\nimport type { ToastOptions } from 'maz-ui/types'\n\n// Component props types\nconst buttonProps: MazBtnProps = {\n color: 'primary',\n size: 'md',\n loading: false\n}\n\n// Toast options type\nconst toastOptions: ToastOptions = {\n position: 'top-right',\n timeout: 3000,\n persistent: false\n}\n```\n\n## Performance Optimization\n\n### Bundle Size Optimization\n\nMaz-UI v4 achieves **60-90% bundle size reduction** through optimal tree-shaking and modular architecture.\n\n#### Auto-Import with Resolvers (Recommended)\n\nUsing resolvers provides the best bundle optimization:\n\n```typescript\n// vite.config.ts\nimport Components from 'unplugin-vue-components/vite'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport { MazComponentsResolver, MazModulesResolver } from 'maz-ui/resolvers'\n\nexport default defineConfig({\n plugins: [\n Components({\n resolvers: [MazComponentsResolver()],\n dts: true\n }),\n AutoImport({\n resolvers: [MazModulesResolver()],\n dts: true\n })\n ]\n})\n```\n\n**Result**: Only imports components you actually use\n\n```vue\n\u003ctemplate>\n \u003c!-- Only MazBtn and MazInput are bundled -->\n \u003cMazBtn>Click\u003c/MazBtn>\n \u003cMazInput v-model=\"name\" />\n\u003c/template>\n```\n\n**Bundle size**: ~15KB (vs ~300KB without tree-shaking)\n\n---\n\n#### Manual Import Optimization\n\nIf not using auto-imports, prefer individual imports:\n\n```typescript\n// ✅ BEST: Individual imports\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\nimport { useToast } from 'maz-ui/composables/useToast'\n\n// ✅ GOOD: Batch imports (still tree-shakable)\nimport { MazBtn, MazInput } from 'maz-ui/components'\n\n// ❌ AVOID: Imports everything\nimport * as MazUI from 'maz-ui'\n```\n\n---\n\n### Lazy Loading Components\n\nDefer loading heavy components until needed:\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { defineAsyncComponent } from 'vue'\n\n// Lazy load heavy components\nconst MazCarousel = defineAsyncComponent(() =>\n import('maz-ui/components/MazCarousel')\n)\n\nconst MazGallery = defineAsyncComponent(() =>\n import('maz-ui/components/MazGallery')\n)\n\u003c/script>\n\n\u003ctemplate>\n \u003cSuspense>\n \u003ctemplate #default>\n \u003cMazCarousel :images=\"images\" />\n \u003c/template>\n \u003ctemplate #fallback>\n \u003cMazCircularProgressBar />\n \u003c/template>\n \u003c/Suspense>\n\u003c/template>\n```\n\n---\n\n### Code Splitting\n\nConfigure Vite for optimal code splitting:\n\n```typescript\n// vite.config.ts\nexport default defineConfig({\n build: {\n rollupOptions: {\n output: {\n manualChunks: {\n 'maz-ui-core': [\n 'maz-ui/components/MazBtn',\n 'maz-ui/components/MazInput'\n ],\n 'maz-ui-forms': [\n 'maz-ui/components/MazSelect',\n 'maz-ui/components/MazTextarea',\n 'maz-ui/components/MazCheckbox'\n ]\n }\n }\n }\n }\n})\n```\n\n---\n\n### Theme Optimization\n\nLoad only the theme you need:\n\n```typescript\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes/presets'\n\napp.use(MazUi, {\n theme: {\n preset: mazUi // ~5KB\n // Don't load other presets unless needed\n }\n})\n```\n\n---\n\n### Translation Optimization\n\nLazy load translations:\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'en',\n messages: {\n // Load French only when needed\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n})\n```\n\n---\n\n### Icon Optimization\n\nUse individual icon imports:\n\n```bash\nnpm install @maz-ui/icons\n```\n\n```typescript\n// ✅ OPTIMAL: Import specific icons\nimport { IconHome, IconUser } from '@maz-ui/icons'\n```\n\n```vue\n\u003ctemplate>\n \u003cMazIcon :src=\"IconHome\" />\n\u003c/template>\n```\n\n**Bundle**: ~1KB per icon (vs ~50KB for all icons)\n\n---\n\n### Production Build Optimization\n\n```typescript\n// vite.config.ts\nexport default defineConfig({\n build: {\n minify: 'terser',\n terserOptions: {\n compress: {\n drop_console: true, // Remove console.log\n }\n },\n cssCodeSplit: true, // Split CSS per component\n }\n})\n```\n\n---\n\n### Performance Checklist\n\n- [ ] **Auto-import resolvers** configured\n- [ ] **Tree-shaking** verified (only used components bundled)\n- [ ] **Lazy loading** for heavy components (MazCarousel, MazGallery, MazTable)\n- [ ] **Code splitting** configured\n- [ ] **Theme** loaded selectively (one preset)\n- [ ] **Translations** lazy loaded\n- [ ] **Icons** imported individually (@maz-ui/icons)\n- [ ] **Production build** minified and optimized\n- [ ] **Bundle size** \u003c250KB for full app\n\n**For comprehensive performance optimization**, load `references/performance.md`.\n\n---\n\n## Common Setup Issues\n\n### 1. Styles Not Loading\n\n**Problem**: Components render but have no styling\n**Solution**: Ensure `'maz-ui/styles'` is imported in `main.ts` BEFORE your CSS\n\n```typescript\nimport 'maz-ui/styles' // Must come first\nimport './style.css'\n```\n\n### 2. TypeScript Errors\n\n**Problem**: `Cannot find module 'maz-ui/components/MazBtn'`\n**Solution**: Add Maz-UI types to `tsconfig.json`:\n\n```json\n{\n \"compilerOptions\": {\n \"types\": [\"maz-ui/types\"]\n }\n}\n```\n\n### 3. Auto-Import Not Working\n\n**Problem**: Components not auto-imported despite resolver configuration\n**Solution**:\n1. Ensure resolvers are correctly added to `vite.config.ts`\n2. Restart dev server\n3. Check generated `.d.ts` files are created\n\n### 4. Theme Not Applied\n\n**Problem**: `useTheme()` throws error about plugin not installed\n**Solution**: Verify MazUi plugin is installed with theme config:\n\n```typescript\napp.use(MazUi, {\n theme: { preset: mazUi }\n})\n```\n\n## Next Steps\n\n- **Theming**: Load `theming.md` for custom themes and dark mode\n- **Components**: Load `components-*.md` for specific component guides\n- **i18n**: Load `translations.md` for multi-language support\n- **Nuxt**: Load `setup-nuxt.md` for Nuxt-specific setup\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":22263,"content_sha256":"ece74257e23b4ba1623ada18cbf6e85b97d760b020e95dd31054685c4a768173"},{"filename":"references/ssr-ssg.md","content":"# Maz-UI SSR & SSG Guide\n\nComplete guide to using Maz-UI with Server-Side Rendering (SSR) and Static Site Generation (SSG) in Nuxt applications.\n\n## Overview\n\nMaz-UI v4 is fully compatible with Nuxt 3's SSR and SSG modes, providing optimal performance through smart theme strategies, critical CSS injection, and hydration optimization.\n\n**Key Features**:\n- 🚀 Full SSR/SSG support\n- 🎨 Multiple theme strategies (hybrid, runtime, buildtime)\n- ⚡ Critical CSS for instant theming\n- 🌓 Dark mode without flash\n- 💧 Hydration optimization\n- 📦 Automatic code splitting\n\n---\n\n## Nuxt Module Installation\n\n### Basic Setup\n\n```bash\nnpm install @maz-ui/nuxt\n```\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'hybrid', // ✅ RECOMMENDED for SSR/SSG\n },\n }\n})\n```\n\n---\n\n## Theme Strategies\n\nMaz-UI offers three theme strategies, each optimized for different use cases:\n\n### Hybrid Strategy (Recommended)\n\n**Best for**: SSR/SSG applications with runtime theme switching\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'hybrid', // ✅ OPTIMAL for SSR/SSG\n darkModeStrategy: 'class' // or 'media'\n }\n }\n})\n```\n\n**How it works**:\n1. **Server**: Generates critical CSS based on user preferences (cookie)\n2. **Client**: Injects critical CSS in `\u003chead>` (instant theme)\n3. **Hydration**: No flash, theme persists across page loads\n4. **Runtime**: Full theme switching without page reload\n\n**Critical CSS injection**:\n```html\n\u003c!-- Server-rendered -->\n\u003chead>\n \u003cstyle data-maz-ui-critical>\n :root {\n --maz-color-primary: 220 100% 50%;\n --maz-color-secondary: 220 14% 96%;\n /* ... critical theme variables */\n }\n \u003c/style>\n\u003c/head>\n```\n\n**Benefits**:\n- ✅ Instant theme on server render\n- ✅ No flash of unstyled content (FOUC)\n- ✅ Runtime theme switching\n- ✅ Dark mode toggle works instantly\n- ✅ User preference persistence (cookie)\n\n**Bundle Impact**: ~15KB runtime theme logic + critical CSS\n\n---\n\n### Build-time Strategy\n\n**Best for**: Static sites with no runtime theme switching\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'buildtime', // ✅ SMALLEST bundle\n }\n }\n})\n```\n\n**How it works**:\n1. **Build**: All CSS variables pre-generated at build time\n2. **Server/Client**: Static CSS loaded (no runtime logic)\n3. **Theme switching**: NOT possible (requires full rebuild)\n\n**Benefits**:\n- ✅ Smallest bundle size (~5KB smaller than hybrid)\n- ✅ Fastest initial load\n- ✅ Perfect for static themes\n- ❌ No runtime theme switching\n- ❌ No dark mode toggle\n\n**Use cases**:\n- Marketing sites with fixed branding\n- Documentation sites\n- Landing pages\n\n---\n\n### Runtime Strategy\n\n**Best for**: Apps with multiple theme presets and user preference\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n strategy: 'runtime', // ⚠️ LARGER bundle\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n**How it works**:\n1. **Server**: Minimal CSS (base styles only)\n2. **Client**: Full theme logic loaded\n3. **Runtime**: Complete theme switching (all presets available)\n\n**Benefits**:\n- ✅ Full runtime theme switching\n- ✅ All theme presets available\n- ✅ User preference persistence\n- ⚠️ Larger initial bundle (~20KB)\n- ⚠️ Possible FOUC on slow connections\n\n**Use cases**:\n- Apps with theme marketplace\n- Multi-tenant applications\n- User-customizable themes\n\n---\n\n## Dark Mode Strategies\n\n### Class Strategy (Recommended)\n\nUses `class=\"dark\"` on `\u003chtml>` element:\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n darkModeStrategy: 'class' // ✅ RECOMMENDED\n }\n }\n})\n```\n\n**How it works**:\n```html\n\u003c!-- Light mode -->\n\u003chtml>\n \u003cbody>...\u003c/body>\n\u003c/html>\n\n\u003c!-- Dark mode -->\n\u003chtml class=\"dark\">\n \u003cbody>...\u003c/body>\n\u003c/html>\n```\n\n**CSS**:\n```css\n:root {\n --maz-color-bg: 255 255 255; /* white */\n}\n\n.dark {\n --maz-color-bg: 20 20 20; /* dark gray */\n}\n```\n\n**Benefits**:\n- ✅ Full control over dark mode\n- ✅ Works with JavaScript disabled\n- ✅ Persists across page loads (cookie)\n- ✅ No flash on page load\n\n---\n\n### Media Strategy\n\nUses `prefers-color-scheme` media query:\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n darkModeStrategy: 'media'\n }\n }\n})\n```\n\n**How it works**:\n```css\n:root {\n --maz-color-bg: 255 255 255;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --maz-color-bg: 20 20 20;\n }\n}\n```\n\n**Benefits**:\n- ✅ Automatic based on system preferences\n- ✅ No JavaScript required\n- ❌ Cannot be toggled by user\n- ❌ Follows system preference only\n\n---\n\n## SSR-Specific Optimizations\n\n### Critical CSS Injection\n\nWith **hybrid strategy**, critical CSS is injected during SSR:\n\n```typescript\n// plugins/maz-ui.server.ts (auto-generated by @maz-ui/nuxt)\nexport default defineNuxtPlugin((nuxtApp) => {\n // Server-only plugin\n if (import.meta.server) {\n // Read user preference from cookie\n const darkMode = useCookie('maz-ui-dark-mode').value === 'true'\n\n // Inject critical CSS based on preference\n nuxtApp.hook('app:rendered', (ctx) => {\n const criticalCss = generateCriticalCss(darkMode)\n ctx.renderContext.head.push(`\n \u003cstyle data-maz-ui-critical>\n ${criticalCss}\n \u003c/style>\n `)\n })\n }\n})\n```\n\n**Result**: User sees correct theme instantly on server render.\n\n---\n\n### Hydration Prevention\n\nSome Maz-UI components should only render on client to prevent hydration mismatches:\n\n#### Client-Only Components\n\n```vue\n\u003ctemplate>\n \u003c!-- ✅ OPTIMAL: Use \u003cClientOnly> for client-specific components -->\n \u003cClientOnly>\n \u003cMazDialogConfirm />\n \u003cMazToast />\n \u003cMazWaitOverlay />\n \u003c/ClientOnly>\n\u003c/template>\n```\n\n**Why?**:\n- Dialog, Toast, Wait plugins use browser APIs (not available on server)\n- Prevents hydration warnings\n- Improves SSR performance\n\n---\n\n#### Conditional Rendering\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst isClient = ref(false)\n\nonMounted(() => {\n isClient.value = true\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Only render on client after mount -->\n \u003cdiv v-if=\"isClient\">\n \u003cMazCarousel :images=\"images\" />\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n### Lazy Hydration\n\nFor heavy components, defer hydration until visible:\n\n```vue\n\u003ctemplate>\n \u003c!-- Lazy hydrate MazGallery when in viewport -->\n \u003cLazyMazGallery\n :images=\"galleryImages\"\n @intersect=\"onIntersect\"\n />\n\u003c/template>\n```\n\n**Benefits**:\n- ✅ Faster initial hydration\n- ✅ Components hydrate when needed\n- ✅ Reduces Time to Interactive (TTI)\n\n---\n\n## Static Site Generation (SSG)\n\n### Prerender Routes\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n nitro: {\n prerender: {\n routes: [\n '/',\n '/about',\n '/contact',\n '/blog',\n // Dynamic routes\n '/blog/post-1',\n '/blog/post-2'\n ]\n }\n },\n\n mazUi: {\n theme: {\n strategy: 'buildtime' // ✅ OPTIMAL for SSG\n }\n }\n})\n```\n\n---\n\n### Crawl Links for Prerendering\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n nitro: {\n prerender: {\n crawlLinks: true, // Auto-discover routes\n routes: ['/']\n }\n }\n})\n```\n\n---\n\n### Dynamic Routes from API\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n nitro: {\n prerender: {\n routes: async () => {\n // Fetch dynamic routes from API\n const posts = await $fetch('/api/posts')\n return posts.map(post => `/blog/${post.slug}`)\n }\n }\n }\n})\n```\n\n---\n\n## Performance Optimization for SSR/SSG\n\n### Code Splitting\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n vite: {\n build: {\n rollupOptions: {\n output: {\n manualChunks: {\n 'maz-ui-forms': [\n 'maz-ui/components/MazInput',\n 'maz-ui/components/MazSelect',\n 'maz-ui/components/MazTextarea'\n ]\n }\n }\n }\n }\n }\n})\n```\n\n---\n\n### Resource Hints\n\n```vue\n\u003c!-- app.vue -->\n\u003ctemplate>\n \u003cHead>\n \u003c!-- Preconnect to external resources -->\n \u003cLink rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n\n \u003c!-- Preload critical assets -->\n \u003cLink\n rel=\"preload\"\n href=\"/fonts/inter.woff2\"\n as=\"font\"\n type=\"font/woff2\"\n crossorigin\n />\n \u003c/Head>\n\n \u003cNuxtPage />\n\u003c/template>\n```\n\n---\n\n### Inline Critical CSS\n\nFor **buildtime strategy**, inline critical CSS:\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n experimental: {\n inlineSSRStyles: true // ✅ Inline critical CSS\n }\n})\n```\n\n---\n\n## Common SSR/SSG Issues\n\n### Issue: Hydration Mismatch\n\n**Error**: `Hydration node mismatch: client content does not match server-rendered HTML`\n\n**Cause**: Component renders differently on server vs client\n\n**Solution**:\n\n```vue\n\u003ctemplate>\n \u003c!-- ❌ WRONG: window is undefined on server -->\n \u003cdiv>Window width: {{ window.innerWidth }}\u003c/div>\n\n \u003c!-- ✅ CORRECT: Use onMounted for client-only logic -->\n \u003cdiv>Window width: {{ windowWidth }}\u003c/div>\n\u003c/template>\n\n\u003cscript setup lang=\"ts\">\nconst windowWidth = ref(0)\n\nonMounted(() => {\n windowWidth.value = window.innerWidth\n})\n\u003c/script>\n```\n\n---\n\n### Issue: Flash of Unstyled Content (FOUC)\n\n**Cause**: Theme CSS loads after initial render\n\n**Solution**: Use **hybrid strategy** with critical CSS:\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid', // ✅ Prevents FOUC\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n---\n\n### Issue: Dark Mode Flash\n\n**Cause**: Server renders light mode, client switches to dark\n\n**Solution 1: Hybrid strategy** (reads cookie on server):\n\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid', // ✅ Server reads cookie\n darkModeStrategy: 'class'\n }\n }\n})\n```\n\n**Solution 2: Blocking script** (for runtime strategy):\n\n```vue\n\u003c!-- app.vue -->\n\u003ctemplate>\n \u003cHead>\n \u003cScript>\n (function() {\n const darkMode = document.cookie.includes('maz-ui-dark-mode=true')\n if (darkMode) {\n document.documentElement.classList.add('dark')\n }\n })()\n \u003c/Script>\n \u003c/Head>\n\u003c/template>\n```\n\n---\n\n### Issue: Client-Only Plugins Not Working\n\n**Cause**: Plugin runs on server where browser APIs don't exist\n\n**Solution**: Mark plugin as client-only:\n\n```typescript\n// plugins/client-only.client.ts (note .client suffix)\nexport default defineNuxtPlugin(() => {\n // This only runs on client\n const toast = useToast()\n\n return {\n provide: {\n toast\n }\n }\n})\n```\n\n---\n\n## SSR/SSG Checklist\n\n### Pre-Deployment\n\n- [ ] **Theme strategy** chosen (hybrid recommended for SSR)\n- [ ] **Dark mode strategy** configured (class recommended)\n- [ ] **Client-only components** wrapped in `\u003cClientOnly>`\n- [ ] **Hydration mismatches** resolved (no server/client differences)\n- [ ] **Critical CSS** inlined (hybrid strategy)\n- [ ] **Resource hints** added (preconnect, preload)\n- [ ] **Code splitting** configured (manual chunks for large components)\n- [ ] **SSG routes** prerendered (if using SSG)\n- [ ] **No FOUC** verified (critical CSS loaded)\n- [ ] **No dark mode flash** verified (server reads cookie)\n\n---\n\n## Advanced SSR Patterns\n\n### Server-Side Data Fetching\n\n```vue\n\u003cscript setup lang=\"ts\">\n// Fetch data on server\nconst { data: users } = await useFetch('/api/users')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazTable :rows=\"users\" />\n\u003c/template>\n```\n\n---\n\n### Async Component with SSR\n\n```vue\n\u003cscript setup lang=\"ts\">\nconst MazCarousel = defineAsyncComponent({\n loader: () => import('maz-ui/components/MazCarousel'),\n delay: 200, // Show loading after 200ms\n timeout: 3000 // Error after 3s\n})\n\u003c/script>\n\n\u003ctemplate>\n \u003cSuspense>\n \u003ctemplate #default>\n \u003cMazCarousel :images=\"images\" />\n \u003c/template>\n \u003ctemplate #fallback>\n \u003cMazCircularProgressBar />\n \u003c/template>\n \u003c/Suspense>\n\u003c/template>\n```\n\n---\n\n### Conditional SSR Rendering\n\n```vue\n\u003ctemplate>\n \u003c!-- Render on server for SEO -->\n \u003cdiv v-if=\"$nuxt.ssrContext\">\n \u003ch1>{{ post.title }}\u003c/h1>\n \u003cp>{{ post.excerpt }}\u003c/p>\n \u003c/div>\n\n \u003c!-- Rich client experience -->\n \u003cdiv v-else>\n \u003cMazCardSpotlight>\n \u003ch1>{{ post.title }}\u003c/h1>\n \u003cMazAnimatedText>{{ post.excerpt }}\u003c/MazAnimatedText>\n \u003c/MazCardSpotlight>\n \u003c/div>\n\u003c/template>\n```\n\n---\n\n## Theme Strategy Comparison\n\n| Feature | Hybrid | Build-time | Runtime |\n|---------|--------|------------|---------|\n| **Bundle Size** | ~15KB | ~10KB | ~25KB |\n| **Critical CSS** | ✅ Yes | ✅ Yes | ❌ No |\n| **Theme Switching** | ✅ Yes | ❌ No | ✅ Yes |\n| **Dark Mode Toggle** | ✅ Yes | ❌ No | ✅ Yes |\n| **FOUC Prevention** | ✅ Yes | ✅ Yes | ⚠️ Partial |\n| **SSR Performance** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |\n| **SSG Performance** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |\n| **Use Case** | SSR/SSG apps | Static sites | Multi-theme apps |\n\n---\n\n## Related Documentation\n\n- **[Setup Nuxt](./setup-nuxt.md)** - Nuxt module configuration\n- **[Theming](./theming.md)** - Theme customization\n- **[Performance](./performance.md)** - Bundle optimization\n- **[Composables](./composables.md)** - useTheme, useTranslations\n- **[Troubleshooting](./troubleshooting.md)** - Common SSR errors\n\n---\n\n## External Resources\n\n- **[Nuxt SSR](https://nuxt.com/docs/guide/concepts/rendering)** - Official Nuxt SSR guide\n- **[Nuxt SSG](https://nuxt.com/docs/guide/concepts/rendering#static-site-generation)** - Static site generation\n- **[Critical CSS](https://web.dev/extract-critical-css/)** - Web.dev guide\n- **[Hydration](https://nuxt.com/docs/getting-started/data-fetching#clientonly-component)** - Nuxt hydration docs\n\n---\n\n**SSR/SSG Version**: Maz-UI v4.3.3 + Nuxt 3\n**Last Updated**: 2025-12-14\n\n::: tip Hybrid Strategy Recommended\nFor SSR/SSG applications, use `strategy: 'hybrid'` for optimal performance, instant theming, and runtime flexibility.\n:::\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":14197,"content_sha256":"df2bf11e62ae20ea127a07ca45b34e9dfe76ffa47ad14767d850d671e4073ba8"},{"filename":"references/theming.md","content":"# Maz-UI Theming System\n\nComplete guide to customizing themes and implementing dark mode in Maz-UI.\n\n## Built-in Theme Presets\n\nMaz-UI includes 4 professionally designed theme presets:\n\n1. **maz-ui** (default) - Modern, balanced design\n2. **ocean** - Blue ocean-inspired palette\n3. **pristine** - Clean, minimalist design\n4. **obsidian** - Dark, professional theme\n\n## Using Presets\n\n### Vue\n\n```typescript\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { ocean } from '@maz-ui/themes/presets'\n\napp.use(MazUi, {\n theme: {\n preset: ocean // or 'ocean', 'pristine', 'obsidian'\n }\n})\n```\n\n### Nuxt\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'ocean' // or 'pristine', 'obsidian', 'maz-ui'\n }\n }\n})\n```\n\n## Custom Theme Creation\n\n### Define Custom Theme\n\n```typescript\nimport { definePreset } from '@maz-ui/themes'\n\nexport const myTheme = definePreset({\n base: 'maz-ui', // Extend existing preset\n name: 'my-custom-theme',\n foundation: {\n 'base-font-size': '14px',\n 'font-family': 'Inter, sans-serif',\n 'radius': '0.5rem',\n 'border-width': '1px',\n },\n colors: {\n light: {\n primary: '220 100% 50%', // HSL format\n secondary: '220 14% 96%',\n background: '0 0% 100%',\n foreground: '222 84% 5%',\n muted: '210 40% 96%',\n accent: '210 40% 90%',\n destructive: '0 84% 60%',\n border: '214 32% 91%',\n input: '214 32% 91%',\n ring: '220 100% 50%',\n },\n dark: {\n primary: '220 100% 70%',\n secondary: '220 14% 4%',\n background: '222 84% 5%',\n foreground: '210 40% 98%',\n muted: '217 33% 17%',\n accent: '217 33% 17%',\n destructive: '0 62% 30%',\n border: '217 33% 17%',\n input: '217 33% 17%',\n ring: '220 100% 70%',\n }\n },\n})\n```\n\n### Use Custom Theme\n\n```typescript\n// Vue\napp.use(MazUi, {\n theme: {\n preset: myTheme\n }\n})\n\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: myTheme\n }\n }\n})\n```\n\n## Theme Overrides\n\nOverride specific parts without creating full theme:\n\n### Vue\n\n```typescript\nimport { mazUi } from '@maz-ui/themes'\n\napp.use(MazUi, {\n theme: {\n preset: mazUi,\n overrides: {\n foundation: {\n 'radius': '1rem',\n 'font-family': 'Poppins, sans-serif'\n },\n colors: {\n light: {\n primary: '350 100% 50%', // Pink primary color\n },\n dark: {\n primary: '350 100% 70%',\n }\n }\n }\n }\n})\n```\n\n### Nuxt\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n overrides: {\n foundation: {\n 'radius': '1rem'\n },\n colors: {\n light: {\n primary: '350 100% 50%'\n }\n }\n }\n }\n }\n})\n```\n\n## Dark Mode\n\n### Automatic Dark Mode Detection\n\n```typescript\n// Vue\napp.use(MazUi, {\n theme: {\n preset: mazUi,\n darkModeStrategy: 'auto' // 'class' | 'media' | 'auto'\n }\n})\n\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n preset: 'maz-ui',\n darkModeStrategy: 'auto'\n }\n }\n})\n```\n\n**Dark Mode Strategies**:\n- **class**: Dark mode controlled by `.dark` class on `\u003chtml>`\n- **media**: Uses OS/browser preference (`prefers-color-scheme`)\n- **auto**: Tries `class` first, falls back to `media`\n\n### Toggle Dark Mode Programmatically\n\n```vue\n\u003cscript setup>\nimport { useTheme } from 'maz-ui/composables'\n\nconst { toggleDarkMode, isDark, setColorMode } = useTheme()\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazBtn @click=\"toggleDarkMode\">\n {{ isDark ? '🌙 Dark' : '☀️ Light' }}\n \u003c/MazBtn>\n\n \u003c!-- Or set explicitly -->\n \u003cMazBtn @click=\"setColorMode('dark')\">Dark\u003c/MazBtn>\n \u003cMazBtn @click=\"setColorMode('light')\">Light\u003c/MazBtn>\n \u003cMazBtn @click=\"setColorMode('auto')\">Auto\u003c/MazBtn>\n\u003c/template>\n```\n\n## CSS Variables\n\nAll theme values are exposed as CSS custom properties:\n\n```css\n/* Foundation */\n--maz-base-font-size\n--maz-font-family\n--maz-radius\n--maz-border-width\n\n/* Colors (in HSL format) */\n--maz-primary\n--maz-secondary\n--maz-background\n--maz-foreground\n--maz-muted\n--maz-accent\n--maz-destructive\n--maz-border\n--maz-input\n--maz-ring\n```\n\n### Using CSS Variables\n\n```vue\n\u003ctemplate>\n \u003cdiv class=\"custom-card\">\n Content\n \u003c/div>\n\u003c/template>\n\n\u003cstyle scoped>\n.custom-card {\n background-color: hsl(var(--maz-background));\n border: var(--maz-border-width) solid hsl(var(--maz-border));\n border-radius: var(--maz-radius);\n padding: 1rem;\n}\n\u003c/style>\n```\n\n## Utility Classes\n\nMaz-UI provides Tailwind-style utility classes:\n\n### Background Colors\n```html\n\u003cdiv class=\"maz-bg-primary\">Primary background\u003c/div>\n\u003cdiv class=\"maz-bg-secondary\">Secondary background\u003c/div>\n\u003cdiv class=\"maz-bg-background\">Background color\u003c/div>\n```\n\n### Text Colors\n```html\n\u003cp class=\"maz-text-primary\">Primary text\u003c/p>\n\u003cp class=\"maz-text-foreground\">Foreground text\u003c/p>\n\u003cp class=\"maz-text-muted\">Muted text\u003c/p>\n```\n\n### Spacing\n```html\n\u003cdiv class=\"maz-p-4\">Padding 1rem\u003c/div>\n\u003cdiv class=\"maz-m-2\">Margin 0.5rem\u003c/div>\n\u003cdiv class=\"maz-gap-4\">Gap 1rem\u003c/div>\n```\n\n### Layout\n```html\n\u003cdiv class=\"maz-flex maz-flex-col maz-items-center\">\n Centered flex column\n\u003c/div>\n```\n\n## Rendering Strategies (Nuxt Only)\n\n### Hybrid (Recommended)\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid' // ✅ Best performance\n }\n }\n})\n```\n\n**Benefits**:\n- Zero FOUC (Flash of Unstyled Content)\n- Critical CSS injected immediately (SSR)\n- Full CSS loaded asynchronously\n- Optimal performance\n\n### Runtime\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'runtime'\n }\n }\n})\n```\n\n**When to use**: Dynamic themes that change frequently\n\n### Buildtime\n\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'buildtime'\n }\n }\n})\n```\n\n**When to use**: Static sites without theme switching\n\n## Theme Structure Reference\n\n```typescript\ninterface ThemePreset {\n name: string\n base?: 'maz-ui' | 'ocean' | 'pristine' | 'obsidian'\n foundation: {\n 'base-font-size': string\n 'font-family': string\n 'radius': string\n 'border-width': string\n }\n colors: {\n light: ThemeColors\n dark: ThemeColors\n }\n}\n\ninterface ThemeColors {\n primary: string // HSL: '220 100% 50%'\n secondary: string\n background: string\n foreground: string\n muted: string\n accent: string\n destructive: string\n border: string\n input: string\n ring: string\n}\n```\n\n## Examples\n\n### Corporate Theme\n\n```typescript\nexport const corporateTheme = definePreset({\n base: 'maz-ui',\n name: 'corporate',\n foundation: {\n 'font-family': 'Georgia, serif',\n 'radius': '0.25rem',\n },\n colors: {\n light: {\n primary: '210 100% 40%', // Navy blue\n secondary: '210 30% 96%',\n background: '0 0% 100%',\n foreground: '210 50% 10%',\n },\n dark: {\n primary: '210 100% 60%',\n secondary: '210 30% 10%',\n background: '210 50% 5%',\n foreground: '210 20% 98%',\n }\n }\n})\n```\n\n### Pastel Theme\n\n```typescript\nexport const pastelTheme = definePreset({\n base: 'maz-ui',\n name: 'pastel',\n colors: {\n light: {\n primary: '330 80% 75%', // Pastel pink\n secondary: '330 20% 95%',\n accent: '200 80% 85%', // Pastel blue\n background: '0 0% 99%',\n foreground: '330 40% 20%',\n }\n }\n})\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7345,"content_sha256":"dbab2cfaca2b8f89d7a3ed8acff8ebb8ce93d0e7d6e3f54f1a08a9d6e2aa913f"},{"filename":"references/translations.md","content":"# Maz-UI Translations & i18n Guide\n\nComplete guide to internationalization (i18n) in Maz-UI components.\n\n## Built-in Language Support\n\nMaz-UI includes **8 built-in languages** ready to use out of the box:\n\n| Language | Code | Status |\n|----------|------|--------|\n| 🇺🇸 English | `en` | Complete (default) |\n| 🇫🇷 French | `fr` | Complete |\n| 🇪🇸 Spanish | `es` | Complete |\n| 🇩🇪 German | `de` | Complete |\n| 🇮🇹 Italian | `it` | Complete |\n| 🇵🇹 Portuguese | `pt` | Complete |\n| 🇯🇵 Japanese | `ja` | Complete |\n| 🇨🇳 Chinese | `zh-CN` | Complete |\n\n## Translated Components (10)\n\nAll 8 languages include complete translations for:\n\n- 📱 **MazInputPhoneNumber** - International phone number input\n- 📁 **MazDropzone** - File upload dropzone\n- 📅 **MazDatePicker** - Date picker with shortcuts\n- 📋 **MazChecklist** - Searchable checklist\n- 📤 **MazDropdown** - Dropdown menu\n- 🔍 **MazSelect** - Select component with search\n- 🗂️ **MazTable** - Data table with pagination\n- 📄 **MazPagination** - Pagination controls\n- 🎠 **MazCarousel** - Carousel component\n- 🌍 **MazSelectCountry** - Country selector\n\n## Installation\n\n```bash\npnpm add @maz-ui/translations\n```\n\n## Basic Setup\n\n### Vue 3\n\n```typescript\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { fr } from '@maz-ui/translations'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true, // default\n messages: {\n fr // Import language to avoid hydration issues\n }\n }\n})\n\napp.mount('#app')\n```\n\n### Nuxt 3\n\n```typescript\n// nuxt.config.ts\nimport { fr, es } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'],\n\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true,\n messages: {\n fr,\n es\n }\n }\n }\n})\n```\n\n## Configuration Options\n\n### Core Options\n\n**locale** (string)\n- Starting/current language\n- Example: `'fr'`, `'en'`, `'es'`\n\n**fallbackLocale** (string, default: `'en'`)\n- Fallback language when translation is missing\n- Always falls back to English if not found\n\n**preloadFallback** (boolean, default: `true`)\n- Whether to preload fallback language at startup\n- See \"preloadFallback Option\" section below\n\n**messages** (object)\n- Translation messages (immediate or lazy-loaded)\n- Can be objects or functions (for lazy loading)\n\n## preloadFallback Option\n\nControls whether the fallback language is loaded at application startup.\n\n### Default Behavior (`preloadFallback: true`)\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true // Default\n }\n})\n```\n\n**Advantages:**\n- ✅ No delay - Fallback translations immediately available\n- ✅ Smooth experience - No missing text even if translation doesn't exist\n- ✅ Reliability - Always a translation available\n\n**Disadvantages:**\n- ❌ Slightly larger initial bundle size\n\n### Disable Preloading (`preloadFallback: false`)\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: false // Optimize bundle size\n }\n})\n```\n\n**Advantages:**\n- ✅ Smaller initial bundle\n- ✅ Load only on demand\n\n**Disadvantages:**\n- ❌ Possible delay - May temporarily show translation keys\n- ❌ Requires loading state management\n\n**Recommendation:** Keep `preloadFallback: true` unless you have strict performance constraints or manually manage loading states.\n\n## Lazy Loading Strategies\n\nAll built-in languages (fr, es, de, it, pt, ja, zh-CN) are **automatically loaded lazily** - no configuration needed!\n\n### Benefits of Lazy Loading\n\n- 🚀 **Faster startup** - Less data to load initially\n- 📦 **Smaller bundle** - Translations in separate chunks\n- 🌐 **Scalable** - Add unlimited languages without performance impact\n- 💾 **Bandwidth savings** - Users only download what they use\n\n### Method 1: Dynamic Imports (Recommended)\n\n```typescript\nimport { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\n\napp.use(MazUi, {\n translations: {\n locale: 'en',\n fallbackLocale: 'en',\n preloadFallback: false,\n messages: {\n // Built-in languages load automatically\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es'),\n de: () => import('@maz-ui/translations/locales/de'),\n\n // Custom language files\n nl: () => import('./locales/nl.ts').then(m => m.default)\n }\n }\n})\n```\n\n### Method 2: API-Based Loading\n\nLoad translations from your backend API:\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'en',\n messages: {\n // Load from API\n fr: async () => {\n const response = await fetch('/api/translations/fr')\n return response.json()\n },\n\n // Combine multiple sources\n es: async () => {\n const [defaultTranslations, customTranslations] = await Promise.all([\n // Default Maz-UI translations\n import('@maz-ui/translations/locales/es').then(m => m.default),\n // Your custom translations\n fetch('/api/translations/es/custom').then(r => r.json())\n ])\n return { ...defaultTranslations, ...customTranslations }\n }\n }\n }\n})\n```\n\n### Method 3: Mix Immediate and Lazy Loading\n\n```typescript\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n messages: {\n // French: loaded immediately (direct object)\n fr: {\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Code pays',\n error: 'Choisir le pays'\n }\n }\n },\n\n // English: loaded lazily (function)\n en: () => import('./locales/en.ts'),\n\n // Spanish: loaded lazily (function)\n es: () => import('./locales/es.ts')\n }\n }\n})\n```\n\n## Using Translations in Components\n\n### Language Switcher\n\n```vue\n\u003cscript setup>\nimport { useTranslations } from '@maz-ui/translations'\nimport { ref } from 'vue'\n\nconst { locale, setLocale } = useTranslations()\nconst isLoading = ref(false)\n\n// Function to change language with loading state\nasync function switchLanguage(newLocale) {\n isLoading.value = true\n try {\n await setLocale(newLocale) // Loads translations if needed\n console.log(`Language changed to ${newLocale}`)\n } catch (error) {\n console.error('Failed to load translations:', error)\n // Handle error (show toast, etc.)\n } finally {\n isLoading.value = false\n }\n}\n\n// Preload a language (optional)\nasync function preloadLanguage(locale) {\n try {\n await setLocale(locale)\n console.log(`Language ${locale} preloaded`)\n } catch (error) {\n console.error(`Failed to preload ${locale}:`, error)\n }\n}\n\u003c/script>\n\n\u003ctemplate>\n \u003cdiv>\n \u003cdiv class=\"language-switcher\">\n \u003cbutton\n :disabled=\"isLoading\"\n @click=\"switchLanguage('fr')\"\n >\n 🇫🇷 {{ isLoading && locale === 'fr' ? 'Loading...' : 'Français' }}\n \u003c/button>\n\n \u003cbutton\n :disabled=\"isLoading\"\n @click=\"switchLanguage('es')\"\n >\n 🇪🇸 {{ isLoading && locale === 'es' ? 'Cargando...' : 'Español' }}\n \u003c/button>\n\n \u003cbutton\n :disabled=\"isLoading\"\n @click=\"switchLanguage('de')\"\n >\n 🇩🇪 {{ isLoading && locale === 'de' ? 'Laden...' : 'Deutsch' }}\n \u003c/button>\n \u003c/div>\n\n \u003c!-- Global loading indicator -->\n \u003cdiv v-if=\"isLoading\" class=\"loading-overlay\">\n \u003cdiv class=\"loading-spinner\">\n Loading translations...\n \u003c/div>\n \u003c/div>\n\n \u003c!-- Current language -->\n \u003cp>Current language: {{ locale }}\u003c/p>\n\n \u003c!-- Maz-UI components use translations automatically -->\n \u003cMazInputPhoneNumber />\n \u003cMazDatePicker />\n \u003c/div>\n\u003c/template>\n\n\u003cstyle scoped>\n.loading-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 1000;\n}\n\n.loading-spinner {\n background: white;\n padding: 1rem 2rem;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\u003c/style>\n```\n\n### Dropdown Language Switcher\n\n```vue\n\u003cscript setup lang=\"ts\">\nimport { useTranslations } from '@maz-ui/translations'\nimport type { MazDropdownProps } from 'maz-ui/components'\n\nconst { locale, setLocale } = useTranslations()\n\nconst languages: MazDropdownProps['items'] = [\n { label: '🇺🇸 English', onClick: () => setLocale('en') },\n { label: '🇫🇷 Français', onClick: () => setLocale('fr') },\n { label: '🇪🇸 Español', onClick: () => setLocale('es') },\n { label: '🇩🇪 Deutsch', onClick: () => setLocale('de') },\n { label: '🇮🇹 Italiano', onClick: () => setLocale('it') }\n]\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazDropdown\n class=\"language-switcher\"\n :items=\"languages\"\n trigger=\"click\"\n >\n {{ locale }}\n \u003c/MazDropdown>\n\u003c/template>\n```\n\n## Creating Custom Translation Files\n\n### Translation File Structure\n\nCreate separate files for each language:\n\n```typescript\n// locales/fr.ts\nexport default {\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Code pays',\n error: 'Choisir le pays',\n searchPlaceholder: 'Rechercher le pays'\n },\n phoneInput: {\n placeholder: 'Numéro de téléphone',\n example: 'Exemple: {example}'\n }\n },\n dropzone: {\n dragAndDrop: 'Déposez vos fichiers',\n selectFile: 'sélectionner un fichier',\n divider: 'ou',\n fileMaxCount: 'Maximum {count} fichiers',\n fileMaxSize: 'Maximum {size} MB',\n fileTypes: 'Types de fichiers autorisés: {types}'\n },\n datePicker: {\n shortcuts: {\n lastSevenDays: 'Les 7 derniers jours',\n lastThirtyDays: 'Les 30 derniers jours',\n thisWeek: 'Cette semaine',\n lastWeek: 'La semaine dernière',\n thisMonth: 'Ce mois-ci',\n thisYear: 'Cette année',\n lastYear: 'L\\'année dernière'\n }\n }\n // You can omit translations you don't want to override\n // Default Maz-UI translations will be used automatically\n}\n```\n\n### Adding a New Language\n\n```typescript\n// locales/nl.ts (Dutch)\nexport default {\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Landcode',\n error: 'Kies land',\n searchPlaceholder: 'Zoek het land'\n },\n phoneInput: {\n placeholder: 'Telefoonnummer',\n example: 'Bijvoorbeeld: {example}'\n }\n },\n dropzone: {\n dragAndDrop: 'Sleep je bestanden hierheen',\n selectFile: 'bestand selecteren',\n divider: 'of'\n }\n}\n```\n\n## Complete Translation Keys Reference\n\nAll available translation keys for the 10 translated components:\n\n```typescript\nexport default {\n /**\n * MazSelectCountry component\n */\n selectCountry: {\n searchPlaceholder: 'Search country'\n },\n\n /**\n * MazInputPhoneNumber component\n */\n inputPhoneNumber: {\n countrySelect: {\n placeholder: 'Country code',\n error: 'Choose country',\n searchPlaceholder: 'Search the country'\n },\n phoneInput: {\n placeholder: 'Phone number',\n example: 'Example: {example}' // {example} replaced dynamically\n }\n },\n\n /**\n * MazDropzone component\n */\n dropzone: {\n dragAndDrop: 'Drop your files',\n selectFile: 'select file',\n divider: 'or',\n fileMaxCount: 'Maximum {count} files', // {count} replaced dynamically\n fileMaxSize: 'Maximum {size} MB', // {size} replaced dynamically\n fileTypes: 'Allowed file types: {types}' // {types} replaced dynamically\n },\n\n /**\n * MazDatePicker component\n */\n datePicker: {\n shortcuts: {\n lastSevenDays: 'Last 7 days',\n lastThirtyDays: 'Last 30 days',\n thisWeek: 'This week',\n lastWeek: 'Last week',\n thisMonth: 'This month',\n thisYear: 'This year',\n lastYear: 'Last year'\n }\n },\n\n /**\n * MazDropdown component\n */\n dropdown: {\n screenReaderDescription: 'Open menu dropdown'\n },\n\n /**\n * MazSelect component\n */\n select: {\n searchPlaceholder: 'Search'\n },\n\n /**\n * MazTable component\n */\n table: {\n noResults: 'No results',\n actionColumnTitle: 'Actions',\n searchByInput: {\n all: 'All',\n placeholder: 'Search by'\n },\n searchInput: {\n placeholder: 'Search'\n },\n pagination: {\n all: 'All',\n rowsPerPage: 'Rows per page',\n of: 'of'\n }\n },\n\n /**\n * MazPagination component\n */\n pagination: {\n navAriaLabel: 'page navigation',\n screenReader: {\n firstPage: 'First Page, page {page}', // {page} replaced dynamically\n previousPage: 'Previous Page, page {page}',\n page: 'Page {page}',\n nextPage: 'Next Page, page {page}',\n lastPage: 'Last Page, page {page}'\n }\n },\n\n /**\n * MazCarousel component\n */\n carousel: {\n ariaLabel: {\n previousButton: 'Scroll to previous items',\n nextButton: 'Scroll to next items'\n }\n },\n\n /**\n * MazChecklist component\n */\n checklist: {\n noResultsFound: 'No results found',\n searchInput: {\n placeholder: 'Search'\n }\n }\n}\n```\n\n## Variable Substitution\n\nSome translations include variables in curly braces that get replaced dynamically:\n\n| Variable | Used In | Example |\n|----------|---------|---------|\n| `{example}` | InputPhoneNumber | `\"Example: +33 6 12 34 56 78\"` |\n| `{count}` | Dropzone | `\"Maximum 5 files\"` |\n| `{size}` | Dropzone | `\"Maximum 10 MB\"` |\n| `{types}` | Dropzone | `\"Allowed file types: .jpg, .png\"` |\n| `{page}` | Pagination | `\"Page 3\"` |\n\n**Example**:\n```typescript\n// Your translation\nphoneInput: {\n example: 'Example: {example}'\n}\n\n// Becomes (dynamically)\n\"Example: +33 6 12 34 56 78\"\n```\n\nVariables are replaced automatically by Maz-UI - you don't need to handle them yourself.\n\n## Production Patterns\n\n### 1. Browser Language Detection\n\n```typescript\nasync function detectUserLanguage() {\n try {\n // Detect from browser\n const browserLang = navigator.language.split('-')[0]\n\n // Check if supported\n const supportedLanguages = ['en', 'fr', 'es', 'de', 'it', 'pt', 'ja', 'zh']\n\n if (supportedLanguages.includes(browserLang)) {\n return browserLang\n }\n\n // Fallback to English\n return 'en'\n } catch {\n return 'en'\n }\n}\n\n// Use automatic detection\napp.use(MazUi, {\n translations: {\n locale: await detectUserLanguage(),\n messages: {\n fr: () => import('@maz-ui/translations/locales/fr'),\n es: () => import('@maz-ui/translations/locales/es'),\n de: () => import('@maz-ui/translations/locales/de')\n }\n }\n})\n```\n\n### 2. Smart Caching Strategy\n\n```typescript\n// Custom cache for translations\nconst translationCache = new Map()\n\nconst messages = {\n fr: async () => {\n if (translationCache.has('fr')) {\n return translationCache.get('fr')\n }\n\n const translations = await import('./locales/fr.ts').then(m => m.default)\n translationCache.set('fr', translations)\n return translations\n }\n}\n```\n\n**Note**: Maz-UI already caches loaded translations internally. Once loaded, switching back to a previously loaded language is instant.\n\n### 3. Error Handling for Async Loading\n\n```vue\n\u003cscript setup>\nimport { useTranslations } from '@maz-ui/translations'\nimport { useToast } from 'maz-ui/composables'\n\nconst { setLocale } = useTranslations()\nconst toast = useToast()\n\nasync function switchLanguage(locale) {\n try {\n await setLocale(locale)\n toast.success(`Language changed to ${locale}`)\n } catch (error) {\n console.error('Translation loading error:', error)\n toast.error('Failed to load translations. Please try again.')\n }\n}\n\u003c/script>\n```\n\n### 4. Loading States During Language Switching\n\nSee \"Language Switcher\" example above with `isLoading` state management.\n\n### 5. Overriding Default Translations\n\n```typescript\nimport { fr as defaultFr } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n messages: {\n fr: {\n ...defaultFr,\n // Override specific keys\n inputPhoneNumber: {\n ...defaultFr.inputPhoneNumber,\n countrySelect: {\n ...defaultFr.inputPhoneNumber.countrySelect,\n placeholder: 'Code téléphonique' // Custom translation\n }\n }\n }\n }\n }\n})\n```\n\n## Best Practices & Performance\n\n### 10 Important Notes\n\n1. **All 8 built-in languages load automatically** - You don't need to provide fr, es, de, it, pt, ja, zh-CN unless you want to override them.\n\n2. **Translate only what you need** - You're not required to translate every key. Add only those for the components you use.\n\n3. **Components update automatically** - Once configured, all Maz-UI components automatically use the right language when you call `setLocale()`.\n\n4. **Variables are replaced automatically** - Don't worry about `{example}`, `{page}`, etc. - Maz-UI handles them for you.\n\n5. **Fallback to English** - If a translation is missing in your language and fallback language, it falls back to English.\n\n6. **Lazy loading is asynchronous** - When using lazy loading, `setLocale()` returns a Promise. Use `await setLocale('fr')` in your code.\n\n7. **Translations are cached** - Once a language is loaded, it stays in memory. Switching back is instant.\n\n8. **preloadFallback option** - By default (`preloadFallback: true`), fallback language is preloaded at startup for smoother experience. Set to `false` to optimize initial loading.\n\n9. **Partial translations supported** - You can provide partial translations. Maz-UI will automatically use default translations for missing keys.\n\n10. **Avoid hydration issues** - In SSR/SSG (Nuxt), always provide initial locale translations in `messages` to avoid hydration mismatches and flashes.\n\n### Performance Tips\n\n**DO:**\n- ✅ Use lazy loading for all non-initial languages\n- ✅ Set `preloadFallback: false` if bundle size is critical\n- ✅ Load only languages your users need\n- ✅ Use browser language detection\n- ✅ Cache translations once loaded\n\n**DON'T:**\n- ❌ Load all languages immediately\n- ❌ Forget to handle loading errors\n- ❌ Skip providing initial locale in SSR\n- ❌ Provide complete translations if partial is sufficient\n\n### SSR/SSG Considerations (Nuxt)\n\n```typescript\n// nuxt.config.ts\nimport { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true,\n messages: {\n // IMPORTANT: Provide initial locale to avoid hydration issues\n fr // Load immediately, not lazily\n }\n }\n }\n})\n```\n\n**Why?** In SSR, if translations load asynchronously, the server-rendered HTML won't match client-side rendering, causing hydration mismatches.\n\n## Troubleshooting\n\n### Translation Keys Show as Raw Strings\n\n**Problem**: You see `inputPhoneNumber.phoneInput.example` instead of translated text.\n\n**Causes**:\n1. Missing locale import\n2. Lazy loading not awaited\n3. Language file failed to load\n\n**Solutions**:\n```typescript\n// 1. Import locale directly\nimport { fr } from '@maz-ui/translations'\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n messages: { fr } // Not lazy-loaded\n }\n})\n\n// 2. Await setLocale\nawait setLocale('fr') // Don't forget await!\n\n// 3. Add error handling\ntry {\n await setLocale('fr')\n} catch (error) {\n console.error('Failed to load:', error)\n}\n```\n\n### Hydration Mismatch in Nuxt\n\n**Problem**: Warning about hydration mismatch in browser console.\n\n**Cause**: Initial locale not provided in SSR.\n\n**Solution**:\n```typescript\n// nuxt.config.ts\nimport { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n messages: {\n fr // Provide immediately, not as function\n }\n }\n }\n})\n```\n\n### Language Doesn't Switch\n\n**Problem**: Calling `setLocale()` doesn't update components.\n\n**Causes**:\n1. Not using `await`\n2. Translation loading failed\n3. Incorrect language code\n\n**Solutions**:\n```typescript\n// Always use await\nawait setLocale('fr')\n\n// Check for errors\ntry {\n await setLocale('fr')\n} catch (error) {\n console.error('Switch failed:', error)\n}\n\n// Verify language code\nconst supportedLanguages = ['en', 'fr', 'es', 'de', 'it', 'pt', 'ja', 'zh-CN']\nif (supportedLanguages.includes(newLocale)) {\n await setLocale(newLocale)\n}\n```\n\n## Official Resources\n\n- **Documentation**: https://maz-ui.com/guide/translations\n- **Package**: https://www.npmjs.com/package/@maz-ui/translations\n- **GitHub**: https://github.com/LouisMazel/maz-ui\n- **Discord**: https://discord.gg/maz-ui\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":20564,"content_sha256":"661c1974a4bc2dae19f8b1399bb702cc222f5741a87581d1c1ad721cd4b520c4"},{"filename":"references/troubleshooting.md","content":"# Maz-UI Troubleshooting Guide\n\nCommon errors, solutions, and debugging tips for Maz-UI.\n\n## Installation & Setup Errors\n\n### 1. Module Not Found: 'maz-ui'\n\n**Error**:\n```\nCannot find module 'maz-ui' or its corresponding type declarations\n```\n\n**Causes & Solutions**:\n\n✅ **Verify installation**:\n```bash\n# Check if installed\nnpm list maz-ui\n\n# Reinstall if needed\npnpm add maz-ui @maz-ui/themes\n```\n\n✅ **Clear cache** (if using Nuxt):\n```bash\nrm -rf .nuxt node_modules/.cache\npnpm install\n```\n\n✅ **Check import path**:\n```typescript\n// ✅ Correct\nimport MazBtn from 'maz-ui/components/MazBtn'\n\n// ❌ Wrong\nimport MazBtn from 'maz-ui/MazBtn'\n```\n\n### 2. useTheme Must Be Used Within MazUi Plugin\n\n**Error**:\n```\nuseTheme must be used within MazUi plugin installation\n```\n\n**Vue Solution**:\n```typescript\n// main.ts\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes'\n\napp.use(MazUi, {\n theme: { preset: mazUi } // Must have theme config\n})\n```\n\n**Nuxt Solution**:\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n composables: {\n useTheme: true // Must be enabled\n },\n theme: {\n preset: 'maz-ui' // Not false\n }\n }\n})\n```\n\n### 3. Styles Not Applied / Components Render Unstyled\n\n**Error**: Components render but have no styling\n\n**Vue Solution**:\n```typescript\n// main.ts - Import CSS BEFORE your own styles\nimport 'maz-ui/styles' // ✅ Must come first\nimport './style.css'\n```\n\n**Nuxt Solution**:\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n mazUi: {\n css: {\n injectMainCss: true // ✅ Must be true\n }\n }\n})\n```\n\n**Verify CSS is loaded**:\n1. Open DevTools\n2. Check Network tab for `maz-ui` CSS file\n3. Inspect element and look for `maz-` CSS classes\n\n## Component-Specific Errors\n\n### 4. MazInputPhoneNumber: Country Detection Fails\n\n**Error**: Phone input doesn't show country flags or validate\n\n**Cause**: Missing `libphonenumber-js` dependency\n\n**Solution**:\n```bash\n# Install peer dependency\npnpm add libphonenumber-js\n```\n\n**Usage**:\n```vue\n\u003ctemplate>\n \u003cMazInputPhoneNumber\n v-model=\"phone\"\n default-country-code=\"US\"\n :preferred-countries=\"['US', 'CA', 'GB']\"\n @update=\"handleUpdate\"\n />\n\u003c/template>\n```\n\n### 5. MazDialog/MazToast Not Working\n\n**Error**: Toast/Dialog functions throw errors\n\n**Vue Solution**:\n```typescript\n// Install plugins\nimport { MazToast } from 'maz-ui/plugins/toast'\nimport { MazDialog } from 'maz-ui/plugins/dialog'\n\napp.use(MazToast)\napp.use(MazDialog)\n```\n\n**Nuxt Solution**:\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n plugins: {\n toast: true,\n dialog: true\n }\n }\n})\n```\n\n### 6. MazIcon: Icons Not Displaying\n\n**Error**: Icons show as empty squares or don't render\n\n**Cause**: Icon path not configured or SVG files missing\n\n**Solution**:\n\nOption 1: **Use @maz-ui/icons package**:\n```bash\npnpm add @maz-ui/icons\n```\n\n```vue\n\u003cscript setup>\nimport MazStar from '@maz-ui/icons/star'\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazIcon :src=\"MazStar\" />\n\u003c/template>\n```\n\nOption 2: **Configure icon path**:\n```typescript\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n general: {\n defaultMazIconPath: '/icons' // Point to your icons folder\n }\n }\n})\n```\n\n## Auto-Import Issues (Nuxt)\n\n### 7. Components Not Auto-Importing\n\n**Error**: `MazBtn is not defined` despite Nuxt module installed\n\n**Solutions**:\n\n✅ **Verify module is added**:\n```typescript\n// nuxt.config.ts\nexport default defineNuxtConfig({\n modules: ['@maz-ui/nuxt'] // Must be present\n})\n```\n\n✅ **Clear Nuxt cache**:\n```bash\nrm -rf .nuxt node_modules/.cache\npnpm install\npnpm dev\n```\n\n✅ **Check generated types**:\n```bash\n# Regenerate types\npnpm nuxi prepare\n```\n\n✅ **Restart IDE** (VSCode, etc.) to reload type definitions\n\n### 8. Composables Not Auto-Importing\n\n**Error**: `useToast is not defined`\n\n**Solution**: Enable composables in config:\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n composables: {\n useToast: true,\n useTheme: true,\n // Enable others as needed\n }\n }\n})\n```\n\n### 9. Directives Not Working\n\n**Error**: `v-tooltip` or other directives not recognized\n\n**Nuxt Solution**:\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n directives: {\n vTooltip: true,\n vClickOutside: true,\n vLazyImg: true\n }\n }\n})\n```\n\n**Vue Solution**:\n```typescript\nimport { vTooltip, vClickOutside } from 'maz-ui/directives'\n\napp.directive('tooltip', vTooltip)\napp.directive('click-outside', vClickOutside)\n```\n\n## TypeScript Errors\n\n### 10. Cannot Find Type Declarations\n\n**Error**:\n```\nCould not find a declaration file for module 'maz-ui/components/MazBtn'\n```\n\n**Solutions**:\n\n✅ **Add types to tsconfig.json**:\n```json\n{\n \"compilerOptions\": {\n \"types\": [\"maz-ui/types\"]\n }\n}\n```\n\n✅ **Restart TypeScript server** in IDE\n\n✅ **Update dependencies**:\n```bash\npnpm update maz-ui @maz-ui/nuxt\n```\n\n### 11. Type Errors with v-model\n\n**Error**: Type errors when using `v-model` with Maz-UI components\n\n**Solution**: Ensure ref types match component expectations:\n```typescript\n// ✅ Correct\nconst inputValue = ref\u003cstring>('')\nconst selectValue = ref\u003cnumber | null>(null)\nconst checkboxValue = ref\u003cboolean>(false)\n\n// ❌ Wrong\nconst inputValue = ref() // Type is 'any'\n```\n\n## Theme & Styling Issues\n\n### 12. Dark Mode Not Working\n\n**Error**: Dark mode toggle doesn't switch themes\n\n**Solutions**:\n\n✅ **Check dark mode strategy**:\n```typescript\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n darkModeStrategy: 'class', // or 'auto' or 'media'\n mode: 'both' // Must support both light and dark\n }\n }\n})\n```\n\n✅ **Verify HTML class**:\n```javascript\n// Should toggle .dark class on \u003chtml>\ndocument.documentElement.classList.contains('dark')\n```\n\n✅ **Use useTheme composable correctly**:\n```vue\n\u003cscript setup>\nconst { toggleDarkMode, isDark } = useTheme()\n\n// Verify it's enabled\nconsole.log('Dark mode enabled:', isDark.value)\n\u003c/script>\n```\n\n### 13. Custom Theme Colors Not Applied\n\n**Error**: Custom colors in theme overrides don't show\n\n**Cause**: HSL format incorrect or CSS variables not loading\n\n**Solution**:\n```typescript\n// ✅ Correct HSL format (no 'hsl()' wrapper, space-separated)\ncolors: {\n light: {\n primary: '220 100% 50%' // ✅ Correct\n }\n}\n\n// ❌ Wrong formats\ncolors: {\n light: {\n primary: 'hsl(220, 100%, 50%)' // ❌ Wrong\n primary: '#3b82f6' // ❌ Use HSL, not hex\n }\n}\n```\n\n## Build & Bundle Errors\n\n### 14. Bundle Size Too Large\n\n**Problem**: Maz-UI adds significant bundle size\n\n**Solutions**:\n\n✅ **Use direct imports**:\n```typescript\n// ✅ Tree-shakable\nimport MazBtn from 'maz-ui/components/MazBtn'\n\n// ❌ Imports everything\nimport * as MazUI from 'maz-ui'\n```\n\n✅ **Disable unused features (Nuxt)**:\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n composables: {\n // Disable unused composables\n useIdleTimeout: false,\n useReadingTime: false\n },\n plugins: {\n // Enable only needed plugins\n toast: true,\n dialog: false,\n aos: false,\n wait: false\n }\n }\n})\n```\n\n### 15. SSR Hydration Mismatch\n\n**Error**: Hydration errors in Nuxt\n\n**Cause**: Client/server mismatch with theme or content\n\n**Solution**:\n```typescript\n// Use ClientOnly for client-specific content\n\u003ctemplate>\n \u003cClientOnly>\n \u003cMazComponent />\n \u003c/ClientOnly>\n\u003c/template>\n```\n\n## Performance Issues\n\n### 16. Slow Initial Load\n\n**Problem**: Page loads slowly with Maz-UI\n\n**Solutions**:\n\n✅ **Use hybrid theme strategy (Nuxt)**:\n```typescript\nexport default defineNuxtConfig({\n mazUi: {\n theme: {\n strategy: 'hybrid' // Best performance\n }\n }\n})\n```\n\n✅ **Lazy load heavy components**:\n```vue\n\u003cscript setup>\nconst MazChart = defineAsyncComponent(() =>\n import('maz-ui/components/MazChart')\n)\n\u003c/script>\n```\n\n✅ **Reduce auto-imports**:\n```typescript\n// Only import what you use\nimport MazBtn from 'maz-ui/components/MazBtn'\n```\n\n## Debugging Tips\n\n### Enable Debug Mode\n\n```typescript\n// Vue\napp.use(MazUi, {\n debug: true // Logs theme and config info\n})\n\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n debug: true\n }\n})\n```\n\n### Check Theme Variables\n\n```javascript\n// In browser console\nconst root = document.documentElement\nconst primary = getComputedStyle(root).getPropertyValue('--maz-primary')\nconsole.log('Primary color:', primary)\n```\n\n### Verify Plugin Installation\n\n```javascript\n// Check if plugins are installed\nconsole.log('Toast:', app.config.globalProperties.$toast)\nconsole.log('Dialog:', app.config.globalProperties.$dialog)\n```\n\n## Getting Help\n\nIf issues persist:\n\n1. **Check GitHub Issues**: https://github.com/LouisMazel/maz-ui/issues\n2. **Join Discord**: https://discord.gg/maz-ui\n3. **Review Documentation**: https://maz-ui.com\n4. **Check Changelog**: Look for breaking changes in updates\n\n## Common Version Conflicts\n\n```bash\n# Check installed versions\nnpm list maz-ui @maz-ui/nuxt @maz-ui/themes\n\n# Update all Maz-UI packages\npnpm update maz-ui @maz-ui/nuxt @maz-ui/themes @maz-ui/translations @maz-ui/icons\n\n# Or install specific version\npnpm add [email protected]\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9169,"content_sha256":"6e24399b65df42c06e94d6bd6b2a9d3d0e37c0f37fbf190d9b2c879df9dade31"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Maz-UI v4 - Vue & Nuxt Component Library","type":"text"}]},{"type":"paragraph","content":[{"text":"Maz-UI is a comprehensive, standalone component library for Vue 3 and Nuxt 3 applications, offering 50+ production-ready components, powerful theming, internationalization, and exceptional developer experience.","type":"text"}]},{"type":"paragraph","content":[{"text":"Latest Version","type":"text","marks":[{"type":"strong"}]},{"text":": 4.3.3 (as of 2025-12-29) ","type":"text"},{"text":"Package","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"maz-ui","type":"text","marks":[{"type":"code_inline"}]},{"text":" | ","type":"text"},{"text":"@maz-ui/nuxt","type":"text","marks":[{"type":"code_inline"}]},{"text":" | ","type":"text"},{"text":"@maz-ui/themes","type":"text","marks":[{"type":"code_inline"}]},{"text":" | ","type":"text"},{"text":"@maz-ui/translations","type":"text","marks":[{"type":"code_inline"}]},{"text":" | ","type":"text"},{"text":"@maz-ui/icons","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Start","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Vue 3 Installation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Install core packages\npnpm add maz-ui @maz-ui/themes\n\n# Or with npm\nnpm install maz-ui @maz-ui/themes","type":"text"}]},{"type":"paragraph","content":[{"text":"Setup","type":"text","marks":[{"type":"strong"}]},{"text":" in ","type":"text"},{"text":"main.ts","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import { createApp } from 'vue'\nimport { MazUi } from 'maz-ui/plugins/maz-ui'\nimport { mazUi } from '@maz-ui/themes'\nimport { en } from '@maz-ui/translations'\nimport 'maz-ui/styles'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\napp.use(MazUi, {\n theme: { preset: mazUi },\n translations: { messages: { en } }\n})\n\napp.mount('#app')","type":"text"}]},{"type":"paragraph","content":[{"text":"Use Components","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"vue"},"content":[{"text":"\u003cscript setup>\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport MazInput from 'maz-ui/components/MazInput'\nimport { ref } from 'vue'\n\nconst inputValue = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003cMazInput v-model=\"inputValue\" label=\"Name\" />\n \u003cMazBtn color=\"primary\">Submit\u003c/MazBtn>\n\u003c/template>","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Nuxt 3 Installation","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Install Nuxt module\npnpm add @maz-ui/nuxt","type":"text"}]},{"type":"paragraph","content":[{"text":"Setup","type":"text","marks":[{"type":"strong"}]},{"text":" in ","type":"text"},{"text":"nuxt.config.ts","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"export default defineNuxtConfig({\n modules: ['@maz-ui/nuxt']\n // That's it! Auto-imports enabled 🎉\n})","type":"text"}]},{"type":"paragraph","content":[{"text":"Use Components","type":"text","marks":[{"type":"strong"}]},{"text":" (no imports needed):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"vue"},"content":[{"text":"\u003cscript setup>\n// Auto-imported composables\nconst theme = useTheme()\nconst toast = useToast()\nconst inputValue = ref('')\n\u003c/script>\n\n\u003ctemplate>\n \u003c!-- Auto-imported components -->\n \u003cMazInput v-model=\"inputValue\" label=\"Name\" />\n \u003cMazBtn color=\"primary\" @click=\"toast.success('Submitted!')\">\n Submit\n \u003c/MazBtn>\n\u003c/template>","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Capabilities","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"🎨 Components (50+)","type":"text"}]},{"type":"paragraph","content":[{"text":"Forms & Inputs","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazInput","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Text input with validation states","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazSelect","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Dropdown select","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazTextarea","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Multi-line text input","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazCheckbox","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Checkbox with label","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazRadio","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Radio buttons","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazSwitch","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Toggle switch","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazSlider","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Range slider","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazInputPhoneNumber","type":"text","marks":[{"type":"code_inline"}]},{"text":" - International phone input with validation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazInputCode","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Code/PIN input","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazInputPrice","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Currency input with formatting","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazInputTags","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Tag/chip input","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazDatePicker","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Date picker","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazChecklist","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Searchable checklist","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"UI Elements","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazBtn","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Button with variants","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazCard","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Container card","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazBadge","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Label badge","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazAvatar","type":"text","marks":[{"type":"code_inline"}]},{"text":" - User avatar","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazIcon","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Icon display","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazSpinner","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Loading spinner","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazTable","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Data table with sorting/pagination","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazTabs","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Tab navigation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazStepper","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Step indicator","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazPagination","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Pagination controls","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Overlays & Modals","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazDialog","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Modal dialog","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazDialogConfirm","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Confirmation dialog","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazDrawer","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Slide-out drawer","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazBottomSheet","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Mobile bottom sheet","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazBackdrop","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Overlay backdrop","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazPopover","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Floating popover","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazDropdown","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Dropdown menu","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Feedback & Animation","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazFullscreenLoader","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Loading overlay","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazLoadingBar","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Progress bar","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazCircularProgressBar","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Circular progress","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazReadingProgressBar","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Reading progress indicator","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazAnimatedText","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Text animations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazAnimatedElement","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Element animations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazAnimatedCounter","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Number counter animation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazCardSpotlight","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Card with spotlight effect","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Layout & Display","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazCarousel","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Image carousel","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazGallery","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Image gallery","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazAccordion","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Collapsible panels","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazExpandAnimation","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Expand/collapse animation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazLazyImg","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Lazy-loaded image","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazPullToRefresh","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Pull-to-refresh gesture","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MazChart","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Chart.js integration","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"🔧 Composables (14+)","type":"text"}]},{"type":"paragraph","content":[{"text":"Theming","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useTheme()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Theme and dark mode management","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Translations","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useTranslations()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - i18n management","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"UI Interactions","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useToast()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Toast notifications","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useDialog()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Programmatic dialogs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useWait()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Loading states","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Utilities","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useBreakpoints()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Responsive breakpoints","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useWindowSize()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Window dimensions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useTimer()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Timer/countdown","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useFormValidator()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Form validation (Valibot)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useIdleTimeout()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Idle detection","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useUserVisibility()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Page visibility","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useSwipe()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Swipe gestures","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useReadingTime()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Reading time calculation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useStringMatching()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - String utilities","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"useDisplayNames()","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Localized display names","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"📌 Directives (5)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"v-tooltip","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Tooltips","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"v-click-outside","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Outside click detection","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"v-lazy-img","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Lazy loading","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"v-zoom-img","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Image zoom","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"v-fullscreen-img","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Fullscreen image viewer","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"🔌 Plugins (4)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AOS","type":"text","marks":[{"type":"strong"}]},{"text":" - Animations on scroll","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Dialog","type":"text","marks":[{"type":"strong"}]},{"text":" - Template-free dialogs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Toast","type":"text","marks":[{"type":"strong"}]},{"text":" - Notifications","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Wait","type":"text","marks":[{"type":"strong"}]},{"text":" - Global loading states","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Key Features","type":"text"}]},{"type":"paragraph","content":[{"text":"✅ ","type":"text"},{"text":"Standalone Components","type":"text","marks":[{"type":"strong"}]},{"text":" - Import only what you need, zero bloat ✅ ","type":"text"},{"text":"SSR/SSG Ready","type":"text","marks":[{"type":"strong"}]},{"text":" - Full Nuxt 3 support with auto-imports ✅ ","type":"text"},{"text":"TypeScript-First","type":"text","marks":[{"type":"strong"}]},{"text":" - Complete type safety out of the box ✅ ","type":"text"},{"text":"Dark Mode","type":"text","marks":[{"type":"strong"}]},{"text":" - Built-in dark/light theme switching ✅ ","type":"text"},{"text":"Tree-Shakable","type":"text","marks":[{"type":"strong"}]},{"text":" - Optimized bundle sizes ✅ ","type":"text"},{"text":"Responsive","type":"text","marks":[{"type":"strong"}]},{"text":" - Mobile-first design ✅ ","type":"text"},{"text":"Accessible","type":"text","marks":[{"type":"strong"}]},{"text":" - ARIA-compliant components ✅ ","type":"text"},{"text":"Themeable","type":"text","marks":[{"type":"strong"}]},{"text":" - 4 built-in presets + custom themes ✅ ","type":"text"},{"text":"i18n","type":"text","marks":[{"type":"strong"}]},{"text":" - Multi-language support with @maz-ui/translations ✅ ","type":"text"},{"text":"840+ Icons","type":"text","marks":[{"type":"strong"}]},{"text":" - Optimized SVG icon library (@maz-ui/icons)","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Template Structure","type":"text"}]},{"type":"paragraph","content":[{"text":"Maz-UI provides ","type":"text"},{"text":"two sets of production-ready templates","type":"text","marks":[{"type":"strong"}]},{"text":" organized by framework:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Vue 3 + Vite Templates (","type":"text"},{"text":"templates/vue/","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Pure Vue 3 with Vite","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Uses standard ","type":"text"},{"text":"fetch()","type":"text","marks":[{"type":"code_inline"}]},{"text":" API","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Explicit imports for all dependencies","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ No framework-specific dependencies","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Optimized for SPA development","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Use when","type":"text","marks":[{"type":"strong"}]},{"text":": Building Vue 3 applications with Vite","type":"text"}]},{"type":"paragraph","content":[{"text":"Available templates","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"setup/vite.config.ts","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Vite configuration with auto-imports","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/form-basic.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Basic form validation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/form-multi-step.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Multi-step form with stepper","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/dialog-confirm.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Dialog confirmation patterns","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/data-table.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Data table with pagination, search, sort","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Nuxt 3 Templates (","type":"text"},{"text":"templates/nuxt/","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Nuxt 3 optimized","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Uses ","type":"text"},{"text":"$fetch","type":"text","marks":[{"type":"code_inline"}]},{"text":" (Nuxt's ofetch wrapper)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Leverages auto-imports for components and composables","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Showcases SSR patterns and server routes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Optimized for full-stack Nuxt development","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Use when","type":"text","marks":[{"type":"strong"}]},{"text":": Building Nuxt 3 applications","type":"text"}]},{"type":"paragraph","content":[{"text":"Available templates","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"setup/nuxt.config.ts","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Nuxt configuration with Maz-UI module","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/form-basic.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Basic form validation (auto-imports)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/form-multi-step.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Multi-step form (auto-imports)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/dialog-confirm.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Dialog patterns (auto-imports)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components/data-table.vue","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Data table with reactive data loading","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Both template sets:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Fix all validation, type inference, and pagination issues","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Follow framework best practices","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Are production-ready and fully tested","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"✅ Include setup configs and component examples","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Load References","type":"text"}]},{"type":"paragraph","content":[{"text":"Load reference files based on what you're implementing. All 21 reference files are grouped by purpose for quick discovery:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Components (4 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components-forms.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Building forms, inputs, validation, phone numbers, dates, file uploads, MazInput, MazSelect, MazCheckbox, MazDatePicker","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components-feedback.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Adding loaders, progress bars, animations, toasts, MazFullscreenLoader, MazCircularProgressBar, MazAnimatedText, MazCardSpotlight","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components-navigation.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Implementing tabs, steppers, pagination, MazTabs, MazStepper, MazPagination","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"components-layout.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Working with cards, drawers, carousels, galleries, MazCard, MazAccordion, MazDrawer, MazCarousel, MazGallery","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Setup & Configuration (2 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"setup-vue.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Setting up Maz-UI in Vue 3 project, auto-imports with resolvers, Vite/Webpack configuration, performance optimization","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"setup-nuxt.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Integrating with Nuxt 3, module configuration, theme strategies (hybrid/buildtime/runtime), SSR/SSG considerations","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Core Features (5 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"composables.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Using all 14 composables: useToast, useTheme, useBreakpoints, useFormValidator, useTimer, useDialog, useTranslations, etc.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"directives.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Adding directives: v-tooltip, v-click-outside, v-lazy-img, v-zoom-img, v-fullscreen-img","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"plugins.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Enabling plugins: AOS (animations on scroll), Dialog, Toast, Wait (loading states)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"resolvers.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"CRITICAL","type":"text","marks":[{"type":"strong"}]},{"text":": Auto-import configuration with MazComponentsResolver, MazDirectivesResolver, MazModulesResolver for optimal tree-shaking","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"translations.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Implementing multi-language support (8 built-in languages), custom locales, lazy loading, SSR hydration","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Tools & Integrations (3 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"icons.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Using @maz-ui/icons package (840+ icons), MazIcon component, icon sizing, colors, animations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cli.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Using @maz-ui/cli (legacy v3), theme configuration, migration to v4 themes system","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"mcp.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Setting up Model Context Protocol server for AI assistant integration (Claude Code, Claude Desktop, Cursor, Windsurf)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Advanced Topics (5 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"theming.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Customizing themes, dark mode, color schemes, CSS variables, 4 built-in presets (mazUi, ocean, pristine, obsidian)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"performance.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Bundle optimization, tree-shaking, lazy loading, code splitting, reducing bundle size from ~300KB to ~15KB","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ssr-ssg.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - ","type":"text"},{"text":"Comprehensive SSR/SSG guide","type":"text","marks":[{"type":"strong"}]},{"text":": theme strategies, critical CSS, hydration prevention, dark mode without flash, static site generation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"accessibility.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - WCAG 2.1 AA compliance, keyboard navigation, screen reader support, ARIA attributes, color contrast","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"form-validation.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - useFormValidator deep dive, Valibot integration, 5 validation modes (lazy, aggressive, eager, blur, progressive), TypeScript type inference","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Troubleshooting (2 files)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"migration-v4.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Upgrading from Maz-UI v3 to v4, breaking changes, API changes, component renames, TypeScript updates","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"troubleshooting.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" - Debugging errors, common issues, configuration problems, SSR hydration, bundle size issues","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Top 6 Common Errors","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Missing Theme Plugin Error","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"\"useTheme must be used within MazUi plugin installation\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": MazUi plugin not installed or theme composable disabled ","type":"text"},{"text":"Fix","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// Vue\napp.use(MazUi, { theme: { preset: mazUi } })\n\n// Nuxt\nexport default defineNuxtConfig({\n mazUi: {\n composables: { useTheme: true },\n theme: { preset: 'maz-ui' }\n }\n})","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Auto-Import Not Working (Nuxt)","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": Components/composables not found despite Nuxt module installed ","type":"text"},{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": Module not properly configured or cache issue ","type":"text"},{"text":"Fix","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Clear Nuxt cache\nrm -rf .nuxt node_modules/.cache\npnpm install","type":"text"}]},{"type":"paragraph","content":[{"text":"Verify","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"nuxt.config.ts","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"export default defineNuxtConfig({\n modules: ['@maz-ui/nuxt']\n})","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Styles Not Applied","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": Components render but have no styling ","type":"text"},{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": CSS not imported ","type":"text"},{"text":"Fix Vue","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import 'maz-ui/styles' // Add this line","type":"text"}]},{"type":"paragraph","content":[{"text":"Fix Nuxt","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"export default defineNuxtConfig({\n mazUi: {\n css: { injectMainCss: true } // Ensure this is true\n }\n})","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. TypeScript Errors with Components","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"Cannot find module 'maz-ui/components/MazBtn'","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": Missing type definitions or incorrect import path ","type":"text"},{"text":"Fix","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// Correct import\nimport MazBtn from 'maz-ui/components/MazBtn'\n\n// Or with auto-import (Nuxt)\n// No import needed, just use \u003cMazBtn>","type":"text"}]},{"type":"paragraph","content":[{"text":"Ensure","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"tsconfig.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" includes:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"json"},"content":[{"text":"{\n \"compilerOptions\": {\n \"types\": [\"maz-ui/types\"]\n }\n}","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. Phone Input Country Detection Fails","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"MazInputPhoneNumber","type":"text","marks":[{"type":"code_inline"}]},{"text":" doesn't detect country or shows wrong flag ","type":"text"},{"text":"Cause","type":"text","marks":[{"type":"strong"}]},{"text":": Missing libphonenumber-js dependency or country data not loaded ","type":"text"},{"text":"Fix","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Install peer dependency\npnpm add libphonenumber-js","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"vue"},"content":[{"text":"\u003cMazInputPhoneNumber\n v-model=\"phone\"\n default-country-code=\"US\"\n preferred-countries=\"['US', 'CA', 'GB']\"\n/>","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"6. Translations Not Loading or Showing Raw Keys","type":"text"}]},{"type":"paragraph","content":[{"text":"Error","type":"text","marks":[{"type":"strong"}]},{"text":": Translation keys showing as raw strings like ","type":"text"},{"text":"inputPhoneNumber.phoneInput.example","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of translated text ","type":"text"},{"text":"Causes","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing locale import","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Lazy loading not awaited properly","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Language file failed to load asynchronously","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing ","type":"text"},{"text":"preloadFallback","type":"text","marks":[{"type":"code_inline"}]},{"text":" configuration","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"SSR hydration mismatch (Nuxt)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Fix Vue","type":"text","marks":[{"type":"strong"}]},{"text":" (Immediate Loading):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import { fr } from '@maz-ui/translations'\n\napp.use(MazUi, {\n translations: {\n locale: 'fr',\n fallbackLocale: 'en',\n preloadFallback: true,\n messages: { fr } // Import immediately\n }\n})","type":"text"}]},{"type":"paragraph","content":[{"text":"Fix Vue","type":"text","marks":[{"type":"strong"}]},{"text":" (Lazy Loading):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"app.use(MazUi, {\n translations: {\n locale: 'fr',\n preloadFallback: true, // Ensure fallback is preloaded\n messages: {\n fr: () => import('@maz-ui/translations/locales/fr')\n }\n }\n})\n\n// In component: ALWAYS use await\nconst { setLocale } = useTranslations()\nawait setLocale('fr') // Don't forget await!","type":"text"}]},{"type":"paragraph","content":[{"text":"Fix Nuxt","type":"text","marks":[{"type":"strong"}]},{"text":" (Avoid Hydration):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import { fr } from '@maz-ui/translations'\n\nexport default defineNuxtConfig({\n mazUi: {\n translations: {\n locale: 'fr',\n preloadFallback: true,\n messages: {\n // CRITICAL: Provide initial locale immediately (not as function)\n fr, // SSR requires immediate load\n\n // Other languages can be lazy\n es: () => import('@maz-ui/translations/locales/es')\n }\n }\n }\n})","type":"text"}]},{"type":"paragraph","content":[{"text":"Error Handling","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"vue"},"content":[{"text":"\u003cscript setup>\nconst { setLocale } = useTranslations()\nconst toast = useToast()\n\nasync function switchLanguage(locale) {\n try {\n await setLocale(locale)\n toast.success(`Language changed to ${locale}`)\n } catch (error) {\n console.error('Translation loading error:', error)\n toast.error('Failed to load translations')\n }\n}\n\u003c/script>","type":"text"}]},{"type":"paragraph","content":[{"text":"Learn More","type":"text","marks":[{"type":"strong"}]},{"text":": Load ","type":"text"},{"text":"references/translations.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for comprehensive i18n setup, lazy loading strategies, and production patterns.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tree-Shaking Best Practices","type":"text"}]},{"type":"paragraph","content":[{"text":"Direct Imports","type":"text","marks":[{"type":"strong"}]},{"text":" (Most Optimized):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// ✅✅✅ Best - smallest bundle\nimport MazBtn from 'maz-ui/components/MazBtn'\nimport { useToast } from 'maz-ui/composables/useToast'\nimport { vClickOutside } from 'maz-ui/directives/vClickOutside'","type":"text"}]},{"type":"paragraph","content":[{"text":"Index Imports","type":"text","marks":[{"type":"strong"}]},{"text":" (Good):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// ✅ Good - tree-shakable\nimport { MazBtn, MazInput } from 'maz-ui/components'\nimport { useToast, useTheme } from 'maz-ui/composables'","type":"text"}]},{"type":"paragraph","content":[{"text":"Avoid","type":"text","marks":[{"type":"strong"}]},{"text":" (Not Tree-Shakable):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// ❌ Imports everything\nimport * as MazUI from 'maz-ui'","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Advanced Topics","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Performance Optimization","type":"text"}]},{"type":"paragraph","content":[{"text":"Maz-UI can be optimized from ~300KB to ~15KB through strategic imports and tree-shaking. Use auto-import resolvers (","type":"text"},{"text":"MazComponentsResolver","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"MazDirectivesResolver","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"MazModulesResolver","type":"text","marks":[{"type":"code_inline"}]},{"text":") for optimal bundle size, lazy load components with dynamic imports, and split code by feature. Load ","type":"text"},{"text":"performance.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for comprehensive bundle optimization strategies.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"SSR & SSG","type":"text"}]},{"type":"paragraph","content":[{"text":"Full server-side rendering and static site generation support with three theme strategies: ","type":"text"},{"text":"hybrid","type":"text","marks":[{"type":"strong"}]},{"text":" (critical CSS injection, no FOUC), ","type":"text"},{"text":"buildtime","type":"text","marks":[{"type":"strong"}]},{"text":" (smallest bundle, static themes), and ","type":"text"},{"text":"runtime","type":"text","marks":[{"type":"strong"}]},{"text":" (full theme switching, larger bundle). Prevent hydration mismatches by wrapping client-only components in ","type":"text"},{"text":"\u003cClientOnly>","type":"text","marks":[{"type":"code_inline"}]},{"text":". Load ","type":"text"},{"text":"ssr-ssg.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for critical CSS patterns, dark mode without flash, and SSR/SSG checklist.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Accessibility","type":"text"}]},{"type":"paragraph","content":[{"text":"All Maz-UI components are WCAG 2.1 AA compliant with proper ARIA attributes, keyboard navigation, focus management, and screen reader support. Components include semantic HTML, color contrast ratios >4.5:1, and accessible form validation. Load ","type":"text"},{"text":"accessibility.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for keyboard shortcuts, focus trap patterns, and accessibility testing checklist.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Form Validation","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"useFormValidator()","type":"text","marks":[{"type":"code_inline"}]},{"text":" composable integrates with Valibot for type-safe schema validation with full TypeScript inference. Supports 5 validation modes (lazy, aggressive, eager, blur, progressive), async validation, custom validators, and real-time error messages. Load ","type":"text"},{"text":"form-validation.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for comprehensive validation patterns and real-world examples.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Auto-Import Resolvers","type":"text"}]},{"type":"paragraph","content":[{"text":"Critical for tree-shaking","type":"text","marks":[{"type":"strong"}]},{"text":": Use ","type":"text"},{"text":"unplugin-vue-components","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"unplugin-auto-import","type":"text","marks":[{"type":"code_inline"}]},{"text":" with Maz-UI resolvers to import only what you use. Reduces bundle size by 60-90% compared to global imports. Configure prefix handling to avoid naming conflicts with other libraries. Load ","type":"text"},{"text":"resolvers.md","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" for complete resolver configuration and troubleshooting.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Progressive Disclosure Summary","type":"text"}]},{"type":"paragraph","content":[{"text":"This SKILL.md provides:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quick Start","type":"text","marks":[{"type":"strong"}]},{"text":" - Get running in \u003c5 minutes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Core Capabilities","type":"text","marks":[{"type":"strong"}]},{"text":" - Overview of all features","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Error Prevention","type":"text","marks":[{"type":"strong"}]},{"text":" - Top 5 common issues solved","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"For detailed implementation:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Load ","type":"text"},{"text":"reference files","type":"text","marks":[{"type":"strong"}]},{"text":" based on your current task (see \"When to Load References\" above)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Each reference contains comprehensive guides, code examples, and advanced configurations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"References are organized by domain (components, setup, theming, etc.) for easy navigation","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Package Ecosystem","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"maz-ui","type":"text","marks":[{"type":"strong"}]},{"text":" - Core component library","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@maz-ui/nuxt","type":"text","marks":[{"type":"strong"}]},{"text":" - Nuxt 3 module with auto-imports","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@maz-ui/themes","type":"text","marks":[{"type":"strong"}]},{"text":" - Theming system and presets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@maz-ui/translations","type":"text","marks":[{"type":"strong"}]},{"text":" - i18n support (8 built-in languages: en, fr, es, de, it, pt, ja, zh-CN)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@maz-ui/icons","type":"text","marks":[{"type":"strong"}]},{"text":" - 840+ optimized SVG icons","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@maz-ui/mcp","type":"text","marks":[{"type":"strong"}]},{"text":" - AI agent documentation server","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Official Resources","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Documentation","type":"text","marks":[{"type":"strong"}]},{"text":": https://maz-ui.com","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"GitHub","type":"text","marks":[{"type":"strong"}]},{"text":": https://github.com/LouisMazel/maz-ui","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"NPM","type":"text","marks":[{"type":"strong"}]},{"text":": https://www.npmjs.com/package/maz-ui","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Discord","type":"text","marks":[{"type":"strong"}]},{"text":": https://discord.gg/maz-ui","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Changelog","type":"text","marks":[{"type":"strong"}]},{"text":": https://github.com/LouisMazel/maz-ui/blob/master/CHANGELOG.md","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"maz-ui","author":"@skillopedia","source":{"stars":162,"repo_name":"claude-skills","origin_url":"https://github.com/secondsky/claude-skills/blob/HEAD/plugins/maz-ui/skills/maz-ui/SKILL.md","repo_owner":"secondsky","body_sha256":"7a26bc2d5b8aff8ea0292cda402ec48e497cf124704e5cc99187eb36ae78256e","cluster_key":"25a6529a59acbd468343d73de44b595f20b536183116b2973e25db7bc5d16c3f","clean_bundle":{"format":"clean-skill-bundle-v1","source":"secondsky/claude-skills/plugins/maz-ui/skills/maz-ui/SKILL.md","attachments":[{"id":"8d415bb0-5911-55c5-93f7-c0584536da9b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8d415bb0-5911-55c5-93f7-c0584536da9b/attachment.md","path":"references/accessibility.md","size":16587,"sha256":"649543dc296e3556a8a3b94b487395ee3ee414b9099c12455577aa265771ded7","contentType":"text/markdown; charset=utf-8"},{"id":"facebcf6-dcfd-51ed-89e8-2575138b894a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/facebcf6-dcfd-51ed-89e8-2575138b894a/attachment.md","path":"references/cli.md","size":11048,"sha256":"c3a111cc1583ba227416d5326633318bcad2d967a6f7a5169c2a36f6c3004d41","contentType":"text/markdown; charset=utf-8"},{"id":"73ccd2b9-17d1-5881-a79c-83d79eeaec71","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/73ccd2b9-17d1-5881-a79c-83d79eeaec71/attachment.md","path":"references/components-feedback.md","size":19565,"sha256":"0096e0299579ba91434ad8e9c069b54e250f35a5308e6850d457f172ba7da9a5","contentType":"text/markdown; charset=utf-8"},{"id":"e7a9ac9c-f35c-5e77-84d2-71c00900760b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e7a9ac9c-f35c-5e77-84d2-71c00900760b/attachment.md","path":"references/components-forms.md","size":8556,"sha256":"cab731c47a1c580199e8e1fbea2b32cb9041062129130e0190fa8adb21fa9f48","contentType":"text/markdown; charset=utf-8"},{"id":"8521c3de-f008-5d4a-847c-b98d55bc52ad","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8521c3de-f008-5d4a-847c-b98d55bc52ad/attachment.md","path":"references/components-layout.md","size":18209,"sha256":"9bf01ff06b8d4c278965d5665e36e30ba1e33658cbd5cd76ac587b514407c276","contentType":"text/markdown; charset=utf-8"},{"id":"0972dc01-8e4f-5ee8-92db-e7c974051b51","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0972dc01-8e4f-5ee8-92db-e7c974051b51/attachment.md","path":"references/components-navigation.md","size":19923,"sha256":"dd1ff229a94bf8a5356917608c75b20260f9cdf2f2765239a2334bbf2dd7ea62","contentType":"text/markdown; charset=utf-8"},{"id":"1544e93c-31ab-50c5-a23c-ba9a90724b5b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1544e93c-31ab-50c5-a23c-ba9a90724b5b/attachment.md","path":"references/composables.md","size":28942,"sha256":"7d22c1d95f388ad3cd042d7aee673cb6a6097f21c03ec45b05516aa2745537d4","contentType":"text/markdown; charset=utf-8"},{"id":"80628139-d24b-5758-838f-32c331f4eaca","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/80628139-d24b-5758-838f-32c331f4eaca/attachment.md","path":"references/directives.md","size":17365,"sha256":"6025653b1d3e717cfff98e6d2ad736b6dc5bbc4211fa0c175a20f35937de9c8d","contentType":"text/markdown; charset=utf-8"},{"id":"78a30b98-a4b1-5f2e-a200-b1153f20a3d5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/78a30b98-a4b1-5f2e-a200-b1153f20a3d5/attachment.md","path":"references/form-validation.md","size":23210,"sha256":"9c5cbd4a96fa8283a0d5511a19c4cfc6298007bd2d41e892ec28c6eb1dd1d484","contentType":"text/markdown; charset=utf-8"},{"id":"079589ba-bb1e-5ce6-908c-acafba0f772c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/079589ba-bb1e-5ce6-908c-acafba0f772c/attachment.md","path":"references/icons.md","size":15279,"sha256":"976eeb19fa9da7f151cc84a37f62e67b67b04b3993e7c3be3b338931aea50d56","contentType":"text/markdown; charset=utf-8"},{"id":"1e9bc981-8f0e-552f-b9dc-8b0b87e3f78f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1e9bc981-8f0e-552f-b9dc-8b0b87e3f78f/attachment.md","path":"references/mcp.md","size":13904,"sha256":"ea889d69fb0d0fa15fefda4c1dee1b21a4eb65e10125abc0eec02bd33a50c106","contentType":"text/markdown; charset=utf-8"},{"id":"9af93300-f1bd-5f45-a7e7-c2771213ccf3","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9af93300-f1bd-5f45-a7e7-c2771213ccf3/attachment.md","path":"references/migration-v4.md","size":21542,"sha256":"9c8e0b4b6f7036ebb2d1bcd3da378e0bcbf090600c45e2268c946d7280518fa2","contentType":"text/markdown; charset=utf-8"},{"id":"7257df49-2bfc-593c-af00-c04c942478c4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7257df49-2bfc-593c-af00-c04c942478c4/attachment.md","path":"references/performance.md","size":17366,"sha256":"cce6d86ab3639790dda12daf4080a904f0d50c0e94c50685635a220acbddbf23","contentType":"text/markdown; charset=utf-8"},{"id":"2bb645ab-a999-57b1-83bd-72dd4bf64974","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2bb645ab-a999-57b1-83bd-72dd4bf64974/attachment.md","path":"references/plugins.md","size":25740,"sha256":"3cc7414f85770e0f92b768ef6a90dcd3438ba5c26329d2cb3d2779ca0454f21e","contentType":"text/markdown; charset=utf-8"},{"id":"2849927b-e330-5ac5-91ee-01a43121c492","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2849927b-e330-5ac5-91ee-01a43121c492/attachment.md","path":"references/resolvers.md","size":26814,"sha256":"11dde668a3ce64aef5a9ac7bf0ec008291bb878294953882fb9193cd3bbc147a","contentType":"text/markdown; charset=utf-8"},{"id":"9d5a0d1b-ec02-5087-b702-6f3f491ae62a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9d5a0d1b-ec02-5087-b702-6f3f491ae62a/attachment.md","path":"references/setup-nuxt.md","size":26580,"sha256":"dfb2e9f6605fd3f69800b27c391a1903820c8312f903bb261fde7dbb42a4a4da","contentType":"text/markdown; charset=utf-8"},{"id":"8bf3330a-aedb-5989-bf41-59c3d0fe4a8c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/8bf3330a-aedb-5989-bf41-59c3d0fe4a8c/attachment.md","path":"references/setup-vue.md","size":22263,"sha256":"ece74257e23b4ba1623ada18cbf6e85b97d760b020e95dd31054685c4a768173","contentType":"text/markdown; charset=utf-8"},{"id":"b0c5b1bb-8d0e-5bb3-91c7-7b7f402cc032","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b0c5b1bb-8d0e-5bb3-91c7-7b7f402cc032/attachment.md","path":"references/ssr-ssg.md","size":14197,"sha256":"df2bf11e62ae20ea127a07ca45b34e9dfe76ffa47ad14767d850d671e4073ba8","contentType":"text/markdown; charset=utf-8"},{"id":"48d44aec-d5c5-5ecd-9bd3-8cd4aac160ab","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/48d44aec-d5c5-5ecd-9bd3-8cd4aac160ab/attachment.md","path":"references/theming.md","size":7345,"sha256":"dbab2cfaca2b8f89d7a3ed8acff8ebb8ce93d0e7d6e3f54f1a08a9d6e2aa913f","contentType":"text/markdown; charset=utf-8"},{"id":"c564e577-ae78-5985-80ff-dc417ff04b40","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c564e577-ae78-5985-80ff-dc417ff04b40/attachment.md","path":"references/translations.md","size":20564,"sha256":"661c1974a4bc2dae19f8b1399bb702cc222f5741a87581d1c1ad721cd4b520c4","contentType":"text/markdown; charset=utf-8"},{"id":"905a4484-1b38-544a-9afb-6da68f391f13","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/905a4484-1b38-544a-9afb-6da68f391f13/attachment.md","path":"references/troubleshooting.md","size":9169,"sha256":"6e24399b65df42c06e94d6bd6b2a9d3d0e37c0f37fbf190d9b2c879df9dade31","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"956ff571494d8ea3c581d160130da1701b891de4e2ec82f8f6d61674783c5edd","attachment_count":21,"text_attachments":21,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"plugins/maz-ui/skills/maz-ui/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"v1","category":"web-development","import_tag":"clean-skills-v1","description":"Maz-UI v4 - Modern Vue & Nuxt component library with 50+ standalone components, composables, directives, theming, i18n, and SSR support. Use when building Vue/Nuxt applications with forms, dialogs, tables, animations, or need responsive design system with dark mode."}},"renderedAt":1782987552307}

Maz-UI v4 - Vue & Nuxt Component Library Maz-UI is a comprehensive, standalone component library for Vue 3 and Nuxt 3 applications, offering 50+ production-ready components, powerful theming, internationalization, and exceptional developer experience. Latest Version : 4.3.3 (as of 2025-12-29) Package : | | | | Quick Start Vue 3 Installation Setup in : Use Components : Nuxt 3 Installation Setup in : Use Components (no imports needed): Core Capabilities 🎨 Components (50+) Forms & Inputs : - - Text input with validation states - - Dropdown select - - Multi-line text input - - Checkbox with labe…