Files
lemonspace_app/hooks/CLAUDE.md
Matthias Meister 456b910532 feat(docs): update LemonSpace manifest and PRD for v2.0 release
- Updated version from v1.5 to v2.0 in both the LemonSpace Manifest and PRD documents.
- Expanded Phase 1 scope to include video and asset nodes, and integrated non-destructive image editing capabilities.
- Enhanced node taxonomy to reflect 6 categories with 27 node types.
- Added details on offline sync features and optimistic updates in the documentation.
- Improved clarity and structure of the product vision and problem statement sections.
2026-04-06 22:27:21 +02:00

161 lines
4.4 KiB
Markdown

# hooks/ — Custom React Hooks
Geteilte React-Hooks. Nur client-side (`"use client"`).
---
## Hooks im Überblick
### `use-auth-query.ts`
```typescript
useAuthQuery(query, ...args)
```
Wrapper um Convex `useQuery`, der automatisch `"skip"` setzt wenn der Auth-Token noch nicht bereit ist. Verhindert `Unauthenticated`-Fehler bei Queries mit `requireAuth` im Backend.
**Warum nicht direkt `useQuery`?** Ohne `initialToken` würde Convex kurz eine unauthentifizierte Query feuern und eine Error-Toast anzeigen. Mit `useAuthQuery` wird gewartet bis `isAuthenticated === true`.
**Wann nutzen:** Immer wenn eine Convex-Query `requireAuth` aufruft. Für öffentliche Queries ist normales `useQuery` in Ordnung.
---
### `use-centered-flow-node-position.ts`
Berechnet die Canvas-Position für einen neuen Node, sodass er im aktuellen Viewport-Zentrum erscheint. Wird beim Einfügen eines Nodes aus der Palette oder Command Palette genutzt.
**Verwendung:**
```typescript
const centeredPosition = useCenteredFlowNodePosition(viewport)
const onNodeDragStop = (node) => {
// Node wird im Viewport-Zentrum erstellt
}
```
---
### `use-debounced-callback.ts`
Standard-Debounce-Hook. Wird für teure Operationen wie Canvas-Snapshots und Convex-Mutations beim Resizen/Bewegen von Nodes verwendet.
**Verwendung:**
```typescript
const debouncedUpdate = useDebouncedCallback(() => {
// Nur alle 300ms ausgeführt
updateCanvasSnapshot()
}, 300)
```
---
### `use-ai-generation-status.ts`
Hook für AI-Generation-Status-Tracking. Überwacht Node-Status-Änderungen und zeigt Toasts bei Fehlern.
**Features:**
- Schwellenwert-basiertes Fehler-Tracking
- Auto-Hiding Toasts nach 5 Sekunden
- Fehler-Kategorisierung (Credits, Timeout, Provider, etc.)
**Verwendung:**
```typescript
const { status, statusMessage } = useAiGenerationStatus()
```
---
### `use-adjustment-presets.ts`
Hook für Adjustment-Preset-Management. Bündelt Preset-Queries und bietet helper-Funktionen für Preset-Validierung.
**Verwendung:**
```typescript
const { presets, isLoading } = useAdjustmentPresets(nodeType)
const savePreset = (name, params) => { /* ... */ }
```
---
### `use-canvas-sync-status.ts`
Hook für Canvas-Sync-Status (Online/Offline). Zeigt Banner oder Icons basierend auf der Verbindungsqualität.
**Verwendung:**
```typescript
const { isOnline, pendingOps, syncStatus } = useCanvasSyncStatus()
```
---
## Konventionen
- Hooks immer mit `use-` Prefix im Dateinamen
- Nur wiederverwendbare Hooks hier — canvas-spezifische Inline-Logik bleibt in `canvas.tsx`
- Kein direkter Convex-Zugriff in Hooks wenn möglich — Queries/Mutations von der aufrufenden Komponente übergeben lassen
- Hooks immer mit `"use client"` am Anfang der Datei markieren
- TypeScript-Typen immer definieren und exportieren
- Hooks dokumentieren mit JSDoc für bessere IDE-Unterstützung
---
## Best Practices
1. **Keine Side Effects außerhalb von useEffect:** Alle Nebeneffekte in useEffect oder custom hooks implementieren
2. **Type Safety:** Hook-Props und Return-Werte immer typisieren
3. **Performance:** useMemo und useCallback für teure Berechnungen nutzen
4. **Error Handling:** Hooks sollten keine Exceptions werfen, sondern Fehler via Callbacks propagieren
5. **Dependencies:** useMemo/useCallback Dependencies immer korrekt angeben
6. **Testing:** Hooks sollen unit-testbar sein (keine React-Abhängigkeiten außer Callbacks)
---
## Examples
### Custom Hook für Node-Resizing
```typescript
// hooks/use-node-resize.ts
export function useNodeResize(nodeId, updateNode) {
const debouncedUpdate = useDebouncedCallback(
(newData) => updateNode(nodeId, newData),
200
)
const handleResize = (newDimensions) => {
debouncedUpdate({
width: newDimensions.width,
height: newDimensions.height,
})
}
return { handleResize }
}
```
### Custom Hook für LocalStorage-Backups
```typescript
// hooks/use-local-storage.ts
export function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key)
return item ? JSON.parse(item) : initialValue
} catch (error) {
return initialValue
}
})
const setValue = (value: T) => {
try {
setStoredValue(value)
window.localStorage.setItem(key, JSON.stringify(value))
} catch (error) {
console.error(error)
}
}
return [storedValue, setValue] as const
}
```