Files
low-code-react-app-b/src/hooks/use-navigation-menu.ts
johndoe6345789 a78943a854 feat: migrate NavigationMenu to JSON (Tier 2 - Organism 2)
- Create NavigationMenuProps interface for type safety
- Implement useNavigationMenu hook with:
  - expandedGroups state management
  - toggleGroup, expandAll, collapseAll actions
  - isItemVisible, getVisibleItemsCount, getItemBadge utilities
  - handleItemHover, handleItemLeave with route preloading
- Create comprehensive JSON definition with:
  - Nested Collapsible groups for navigation sections
  - Dynamic item rendering with visibility filtering
  - Badge support for error count and item badges
  - Active state styling and hover effects
- Register hook in hooks-registry
- Export from json-components.ts with hook integration
- Update json-components-registry.json (source: organisms, jsonCompatible: true)

All state management delegated to useNavigationMenu hook.
Navigation logic fully expressible in JSON with custom hooks.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-21 01:28:33 +00:00

91 lines
2.6 KiB
TypeScript

import { useState } from 'react'
import { navigationGroups, NavigationItemData } from '@/lib/navigation-config'
import { FeatureToggles } from '@/types/project'
import { useRoutePreload } from './use-route-preload'
interface UseNavigationMenuState {
expandedGroups: Set<string>
toggleGroup: (groupId: string) => void
expandAll: () => void
collapseAll: () => void
isItemVisible: (item: NavigationItemData) => boolean
getVisibleItemsCount: (groupId: string) => number
getItemBadge: (item: NavigationItemData, errorCount: number) => number | undefined
handleItemHover: (value: string) => void
handleItemLeave: (value: string) => void
}
export function useNavigationMenu(featureToggles: FeatureToggles, errorCount: number = 0): UseNavigationMenuState {
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(
new Set(['overview', 'development', 'automation', 'design', 'backend', 'testing', 'tools'])
)
const { preloadRoute, cancelPreload } = useRoutePreload({ delay: 100 })
const isItemVisible = (item: NavigationItemData) => {
if (!item.featureKey) return true
return featureToggles[item.featureKey]
}
const getVisibleItemsCount = (groupId: string) => {
const group = navigationGroups.find((g) => g.id === groupId)
if (!group) return 0
return group.items.filter(isItemVisible).length
}
const getItemBadge = (item: NavigationItemData, errorCount: number) => {
if (item.id === 'errors') return errorCount
return item.badge
}
const toggleGroup = (groupId: string) => {
setExpandedGroups((prev) => {
const newSet = new Set(prev)
if (newSet.has(groupId)) {
newSet.delete(groupId)
} else {
newSet.add(groupId)
}
return newSet
})
}
const expandAll = () => {
const allGroupIds = navigationGroups
.filter((group) =>
group.items.some((item) => {
if (!item.featureKey) return true
return featureToggles[item.featureKey]
})
)
.map((group) => group.id)
setExpandedGroups(new Set(allGroupIds))
}
const collapseAll = () => {
setExpandedGroups(new Set())
}
const handleItemHover = (value: string) => {
console.log(`[NAV] 🖱️ Hover detected on: ${value}`)
preloadRoute(value)
}
const handleItemLeave = (value: string) => {
console.log(`[NAV] 👋 Hover left: ${value}`)
cancelPreload(value)
}
return {
expandedGroups,
toggleGroup,
expandAll,
collapseAll,
isItemVisible,
getVisibleItemsCount,
getItemBadge,
handleItemHover,
handleItemLeave,
}
}