# Troubleshooting Guide

Common issues and solutions when using Grimoire v3.

---

## 🔍 Quick Diagnosis

### Symptoms by Category

- **[Ref Access Issues](#ref-access-issues)** - "Cannot read property X of null/undefined"
- **[Import Errors](#import-errors)** - Module not found, type errors
- **[Icon Issues](#icon-issues)** - Icons not showing or wrong color
- **[TypeScript Errors](#typescript-errors)** - Type errors, inference issues
- **[Build Errors](#build-errors)** - Build/compilation failures
- **[Runtime Errors](#runtime-errors)** - Errors in the console at runtime
- **[Styling Issues](#styling-issues)** - Components not styled correctly

---

## 🎯 Ref Access Issues

### Issue: "Cannot read property 'open' of null"

**Symptom:**

```javascript
dropdownRef.value.open(); // TypeError: Cannot read property 'open' of null
```

**Cause:** Trying to access ref before component is mounted.

**Fix:**

Use optional chaining:

```javascript
// ✅ Correct
dropdownRef.value?.open();
```

Or wait for mount:

```javascript
import { onMounted } from 'vue';

onMounted(() => {
  dropdownRef.value?.open(); // Safe
});
```

---

### Issue: "Cannot read property 'open' of undefined"

**Symptom:**

```javascript
dropdownRef.open(); // TypeError: Cannot read property 'open' of undefined
```

**Cause:** Forgot `.value` in Composition API.

**Fix:**

```javascript
// ❌ Wrong - missing .value
dropdownRef.open();

// ✅ Correct
dropdownRef.value.open();
```

---

### Issue: "@refMounted event not firing"

**Symptom:** In v3, `@refMounted` doesn't work anymore.

**Cause:** `@refMounted` was removed in v3.

**Fix:** Use direct refs instead.

**OLD (v2):**

```vue
<StyledDropdown @refMounted="dropdown = $event" />
```

**NEW (v3):**

```vue
<StyledDropdown ref="dropdown" />
```

See [`v2-to-v3-migration-guide.md`](./v2-to-v3-migration-guide.md) for complete migration guide.

---

## 📦 Import Errors

### Issue: "Cannot find module '@twentyfourg/grimoire/composables'"

**Symptom:**

```
Error: Cannot find module '@twentyfourg/grimoire/composables'
```

**Cause:** Package not built or wrong version.

**Fix:**

1. Update to v3:

```bash
pnpm update @twentyfourg/grimoire@^3.0.0
```

2. Clear node_modules:

```bash
rm -rf node_modules pnpm-lock.yaml
pnpm install
```

3. Restart dev server

---

### Issue: "Cannot find module '@twentyfourg/grimoire/plugin'"

**Symptom:**

```
Error: Cannot find module '@twentyfourg/grimoire/plugin'
```

**Cause:** Using old default import syntax.

**Fix:**

**OLD (v2):**

```javascript
import GrimoirePlugin from '@twentyfourg/grimoire/plugin';
```

**NEW (v3):**

```javascript
import { GrimoirePlugin } from '@twentyfourg/grimoire/plugin';
```

---

### Issue: "Module has no exported member 'GButton'"

**Symptom:**

```
Module '"@twentyfourg/grimoire"' has no exported member 'GButton'
```

**Cause:** Component doesn't exist or wrong package.

**Fix:**

Check component name:

```javascript
// ✅ Correct - capitalized G
import { GButton, GInput } from '@twentyfourg/grimoire';

// ❌ Wrong
import { Button, Input } from '@twentyfourg/grimoire';
```

Verify component exists:

```bash
# List all exports
cat node_modules/@twentyfourg/grimoire/dist/index.d.ts
```

---

## 🎨 Icon Issues

### Issue: Icons not showing

**Symptom:** `<GIcon>` renders but no icon visible.

**Cause:** Icons not registered with plugin.

**Fix:**

```javascript
// main.ts
import { GrimoirePlugin } from '@twentyfourg/grimoire/plugin';
import { icons } from './icons-bundle.js'; // Make sure this exists

app.use(GrimoirePlugin, { icons }); // Register icons
```

Check console for warnings:

```
[Iconify] Icon not found: app:home
```

---

### Issue: Icons not updating after SVG changes

**Symptom:** Changed SVG file but icon doesn't update.

**Cause:** Vite not rebuilding icon bundle.

**Fix:**

1. Enable verbose mode:

```typescript
viteIconBundlePlugin({
  verbose: true, // See build logs
  sources: [...]
});
```

2. Restart dev server:

```bash
pnpm dev
```

3. Force rebuild:

```bash
rm -rf node_modules/.vite
pnpm dev
```

---

### Issue: Icons wrong color

**Symptom:** Icon shows original color when it should inherit text color.

**Cause:** Using colored variant instead of monotone.

**Fix:**

```vue
<!-- Wrong: colored version -->
<div class="text-blue-500">
  <GIcon icon="app:home" /> <!-- Shows original color -->
</div>

<!-- Right: monotone version -->
<div class="text-blue-500">
  <GIcon icon="mono-app:home" /> <!-- Blue -->
</div>
```

Or configure monotone variant:

```typescript
viteIconBundlePlugin({
  sources: [
    {
      type: 'folder',
      path: 'icons',
      prefix: 'app',
      variants: 'monotone', // Only create monotone version
    },
  ],
});
```

---

## 🔧 TypeScript Errors

### Issue: "Property 'value' does not exist on type 'Ref'"

**Symptom:**

```typescript
const buttonRef = ref(null);
buttonRef.value.focus(); // Error
```

**Cause:** Incorrect ref typing.

**Fix:**

```typescript
import { ref } from 'vue';
import type { ComponentPublicInstance } from 'vue';
import { GButton } from '@twentyfourg/grimoire';

// ✅ Correct
const buttonRef = ref<ComponentPublicInstance | null>(null);

// Or
const buttonRef = ref<InstanceType<typeof GButton> | null>(null);
```

---

### Issue: "Type 'string' is not assignable to type 'never'"

**Symptom:**

```typescript
const form = reactive({
  name: '',
  email: '',
}); // Type error
```

**Cause:** TypeScript can't infer type from empty strings.

**Fix:**

Be explicit:

```typescript
interface Form {
  name: string;
  email: string;
}

const form = reactive<Form>({
  name: '',
  email: '',
});
```

---

### Issue: "Cannot find name 'GButtonProps'"

**Symptom:**

```typescript
import { GButtonProps } from '@twentyfourg/grimoire';
```

**Cause:** Using value import instead of type import.

**Fix:**

```typescript
// ✅ Correct - type import
import type { GButtonProps } from '@twentyfourg/grimoire';

// ❌ Wrong - value import
import { GButtonProps } from '@twentyfourg/grimoire';
```

---

## 🏗️ Build Errors

### Issue: "Failed to resolve module specifier"

**Symptom:**

```
Failed to resolve module specifier "@twentyfourg/grimoire/composables"
```

**Cause:** Build tool configuration issue.

**Fix:**

Check `vite.config.ts`:

```typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': '/src',
    },
  },
});
```

---

### Issue: "Unexpected token 'export'"

**Symptom:**

```
SyntaxError: Unexpected token 'export'
```

**Cause:** Node/build tool doesn't support ES modules.

**Fix:**

1. Check `package.json`:

```json
{
  "type": "module"
}
```

2. Check `tsconfig.json`:

```json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}
```

---

### Issue: Icon bundle build fails

**Symptom:**

```
Error: Failed to build icon bundle
```

**Cause:** Missing dependencies or invalid SVGs.

**Fix:**

1. Install peer dependencies:

```bash
pnpm add -D @iconify/tools @iconify/utils prettier
```

2. Check SVG files are valid XML

3. Enable verbose mode:

```typescript
viteIconBundlePlugin({
  verbose: true,
  sources: [...]
});
```

---

## ⚡ Runtime Errors

### Issue: "app.use is not a function"

**Symptom:**

```javascript
app.use(GrimoirePlugin); // TypeError
```

**Cause:** Wrong import or app not created.

**Fix:**

```javascript
import { createApp } from 'vue';
import { GrimoirePlugin } from '@twentyfourg/grimoire/plugin';
import App from './App.vue';

const app = createApp(App);
app.use(GrimoirePlugin, { icons: {...} });
app.mount('#app');
```

---

### Issue: "Component is not properly defined"

**Symptom:**

```
[Vue warn]: Failed to resolve component: GButton
```

**Cause:** Component not imported.

**Fix:**

```vue
<script setup>
// ✅ Must import components
import { GButton } from '@twentyfourg/grimoire';
</script>
```

Or use auto-import:

```typescript
// vite.config.ts
import Components from 'unplugin-vue-components/vite';

export default defineConfig({
  plugins: [
    Components({
      resolvers: [
        (name) => {
          if (name.startsWith('G')) {
            return { name, from: '@twentyfourg/grimoire' };
          }
        },
      ],
    }),
  ],
});
```

---

### Issue: "Maximum call stack size exceeded"

**Symptom:** Browser freezes or infinite recursion error.

**Cause:** Circular reference in reactive data or computed property.

**Fix:**

Check for circular dependencies:

```javascript
// ❌ Bad - circular
const a = computed(() => b.value + 1);
const b = computed(() => a.value + 1);

// ✅ Good
const a = ref(1);
const b = computed(() => a.value + 1);
```

---

## 🎨 Styling Issues

### Issue: Styles not applying

**Symptom:** Component renders but no styles.

**Cause:** StyledComponent not created or imported.

**Fix:**

Grimoire components are headless. Create styled wrappers:

```vue
<!-- theme/StyledButton.vue -->
<template>
  <GButton ref="buttonRef" v-bind="mergedProps" class="styled-button">
    <slot />
  </GButton>
</template>

<script setup>
import { ref } from 'vue';
import { GButton } from '@twentyfourg/grimoire';
import { useStyledComponent } from '@twentyfourg/grimoire/composables';

const props = defineProps({
  ...GButton.props,
});

const buttonRef = ref(null);
const { mergedProps, expose } = useStyledComponent(buttonRef, props);
defineExpose(expose);
</script>

<style scoped>
.styled-button {
  /* Your styles */
}
</style>
```

See [`styling-guide.md`](./styling-guide.md) for complete guide.

---

### Issue: `:deep()` not working

**Symptom:** Can't style child components.

**Cause:** Wrong syntax or Vue version.

**Fix:**

```scss
// ✅ Correct - Vue 3 syntax
.styled-dropdown {
  :deep(.multiselect-option) {
    padding: 0.5rem;
  }
}

// ❌ Wrong - Vue 2 syntax
.styled-dropdown {
  /deep/ .multiselect-option {
    padding: 0.5rem;
  }
}
```

---

### Issue: CSS variables not working

**Symptom:** `var(--my-variable)` doesn't apply.

**Cause:** Variable not defined or wrong scope.

**Fix:**

Define in `:root` or component:

```scss
:root {
  --primary-color: #007bff;
}

// Or in component
.styled-button {
  --button-bg: #007bff;
  background: var(--button-bg);
}
```

---

## 🔄 Migration Issues

### Issue: v2 code not working in v3

**Symptom:** Various errors after upgrading.

**Cause:** Breaking changes in v3.

**Fix:** See complete migration guide at [`v2-to-v3-migration-guide.md`](./v2-to-v3-migration-guide.md).

Key changes:

1. `@refMounted` → direct refs
2. Plugin import changed to named export
3. Vue ^3.3.0 required

---

### Issue: "Cannot access X method on StyledComponent"

**Symptom:**

```javascript
styledButtonRef.value.focus(); // Error
```

**Cause:** StyledComponent not using v3 pattern.

**Fix:**

Update StyledComponent to use `useStyledComponent`:

```vue
<script setup>
import { ref } from 'vue';
import { GButton } from '@twentyfourg/grimoire';
import { useStyledComponent } from '@twentyfourg/grimoire/composables';

const buttonRef = ref(null);
const { mergedProps, expose } = useStyledComponent(buttonRef, props);

// Important: Must expose!
defineExpose(expose);
</script>
```

See [`../../STYLED_COMPONENT_MIGRATION_GUIDE.md`](../../STYLED_COMPONENT_MIGRATION_GUIDE.md) for details.

---

## 🆘 Still Having Issues?

### 1. Check Version

```bash
npm list @twentyfourg/grimoire
# Should show ^3.x.x
```

### 2. Clear Cache

```bash
# Clear Vite cache
rm -rf node_modules/.vite

# Clear node_modules
rm -rf node_modules pnpm-lock.yaml
pnpm install
```

### 3. Check Dependencies

```bash
# Vue must be ^3.3.0
npm list vue
```

### 4. Enable Debug Mode

```typescript
// vite.config.ts
export default defineConfig({
  plugins: [
    vue(),
    viteIconBundlePlugin({
      verbose: true, // See what's happening
      sources: [...]
    }),
  ],
});
```

### 5. Check Console

Open browser console (F12) and check for:

- Errors
- Warnings
- Network failures

### 6. Search GitHub Issues

Check if it's a known issue:

```
https://github.com/twentyfourg/grimoire/issues
```

### 7. Create Minimal Reproduction

Create a minimal example that reproduces the issue:

- Single component
- Minimal code
- Clear steps to reproduce

### 8. Report Bug

If you found a bug, open an issue with:

- Grimoire version
- Vue version
- Minimal reproduction
- Error messages
- What you expected vs what happened

---

## 📚 Related Documentation

- **[Migration Guide](./v2-to-v3-migration-guide.md)** - Upgrading from v2
- **[Component Usage](./component-usage.md)** - How to use components
- **[TypeScript Usage](./typescript-usage.md)** - TypeScript patterns
- **[Breaking Changes](./v2-to-v3-breaking-changes.md)** - All breaking changes
- **[Iconify Setup](./iconify-setup.md)** - Icon issues

---

## 💡 Prevention Tips

### Before Upgrading

1. Read [`v2-to-v3-breaking-changes.md`](./v2-to-v3-breaking-changes.md)
2. Search for `@refMounted` in your code
3. Create a new branch for migration
4. Test incrementally

### During Development

1. Use TypeScript for type safety
2. Enable strict mode in tsconfig
3. Use ESLint with Vue plugin
4. Check console for warnings

### Best Practices

1. Always use optional chaining for refs: `ref.value?.method()`
2. Import types with `import type {...}`
3. Keep dependencies up to date
4. Read error messages carefully

---

**Need more help? Check [`README.md`](./README.md) for all documentation links.**



