mirror of
https://github.com/supabase/supabase.git
synced 2026-05-23 01:39:34 +08:00
262 lines
6.0 KiB
TypeScript
262 lines
6.0 KiB
TypeScript
import { useRouter } from 'next/router'
|
|
import { memo, useEffect } from 'react'
|
|
import { menuState, useMenuLevelId } from '~/hooks/useMenuState'
|
|
import NavigationMenuHome from './HomeMenu'
|
|
import NavigationMenuGuideList from './NavigationMenuGuideList'
|
|
import NavigationMenuRefList from './NavigationMenuRefList'
|
|
|
|
interface BaseMenu {
|
|
id: string
|
|
path: string
|
|
type: string
|
|
}
|
|
|
|
interface HomeMenu extends BaseMenu {
|
|
type: 'home'
|
|
}
|
|
|
|
interface GuideMenu extends BaseMenu {
|
|
type: 'guide'
|
|
}
|
|
|
|
interface ReferenceMenu extends BaseMenu {
|
|
type: 'reference'
|
|
commonSectionsFile: string
|
|
specFile?: string
|
|
}
|
|
|
|
type Menu = HomeMenu | GuideMenu | ReferenceMenu
|
|
|
|
const menus: Menu[] = [
|
|
{
|
|
id: 'home',
|
|
path: '/',
|
|
type: 'home',
|
|
},
|
|
{
|
|
id: 'gettingstarted',
|
|
path: '/guides/getting-started',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'database',
|
|
path: '/guides/database',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'api',
|
|
path: '/guides/api',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'auth',
|
|
path: '/guides/auth',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'functions',
|
|
path: '/guides/functions',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'realtime',
|
|
path: '/guides/realtime',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'storage',
|
|
path: '/guides/storage',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'ai',
|
|
path: '/guides/ai',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'platform',
|
|
path: '/guides/platform',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'resources',
|
|
path: '/guides/resources',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'self_hosting',
|
|
path: '/guides/self-hosting',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'integrations',
|
|
path: '/guides/integrations',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'supabase_cli',
|
|
// TODO: Add path '/guides/cli/config'
|
|
path: '/guides/cli',
|
|
type: 'guide',
|
|
},
|
|
{
|
|
id: 'reference_javascript_v1',
|
|
path: '/reference/javascript/v1',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_js_v1.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_javascript_v2',
|
|
path: '/reference/javascript',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_js_v2.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_dart_v0',
|
|
path: '/reference/dart/v0',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_dart_v0.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_dart_v1',
|
|
path: '/reference/dart',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_dart_v1.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_csharp_v0',
|
|
path: '/reference/csharp',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_csharp_v0.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_python_v2',
|
|
path: '/reference/python',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_py_v2.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_swift_v0',
|
|
path: '/reference/swift',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_swift_v0.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_kotlin_v0',
|
|
path: '/reference/kotlin',
|
|
commonSectionsFile: 'common-client-libs-sections.json',
|
|
specFile: 'supabase_kt_v0.yml',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_cli',
|
|
path: '/reference/cli',
|
|
commonSectionsFile: 'common-cli-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_api',
|
|
path: '/reference/api',
|
|
commonSectionsFile: 'common-api-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_self_hosting_auth',
|
|
path: '/reference/self-hosting-auth',
|
|
commonSectionsFile: 'common-self-hosting-auth-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_self_hosting_storage',
|
|
path: '/reference/self-hosting-storage',
|
|
commonSectionsFile: 'common-self-hosting-storage-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_self_hosting_realtime',
|
|
path: '/reference/self-hosting-realtime',
|
|
commonSectionsFile: 'common-self-hosting-realtime-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_self_hosting_analytics',
|
|
path: '/reference/self-hosting-analytics',
|
|
commonSectionsFile: 'common-self-hosting-analytics-sections.json',
|
|
type: 'reference',
|
|
},
|
|
{
|
|
id: 'reference_self_hosting_functions',
|
|
path: '/reference/self-hosting-functions',
|
|
commonSectionsFile: 'common-self-hosting-functions-sections.json',
|
|
type: 'reference',
|
|
},
|
|
]
|
|
|
|
function getMenuById(id: string) {
|
|
return menus.find((menu) => menu.id === id)
|
|
}
|
|
|
|
function getMenuByUrl(basePath: string, url: string) {
|
|
// If multiple matches, choose the menu with the longest path
|
|
const [menu] = menus
|
|
.filter(({ path }) => url.startsWith(`${basePath}${path}`))
|
|
.sort((a, b) => b.path.length - a.path.length)
|
|
|
|
return menu
|
|
}
|
|
|
|
function getMenuElement(menu: Menu) {
|
|
const menuType = menu.type
|
|
switch (menuType) {
|
|
case 'home':
|
|
return <NavigationMenuHome />
|
|
case 'guide':
|
|
return <NavigationMenuGuideList id={menu.id} />
|
|
case 'reference':
|
|
return (
|
|
<NavigationMenuRefList
|
|
id={menu.id}
|
|
basePath={menu.path}
|
|
commonSectionsFile={menu.commonSectionsFile}
|
|
specFile={menu.specFile}
|
|
/>
|
|
)
|
|
default:
|
|
throw new Error(`Unknown menu type '${menuType}'`)
|
|
}
|
|
}
|
|
|
|
const NavigationMenu = () => {
|
|
const router = useRouter()
|
|
|
|
function handleRouteChange(url: string) {
|
|
const menu = getMenuByUrl(router.basePath, url)
|
|
if (menu) {
|
|
menuState.setMenuLevelId(menu.id)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
handleRouteChange(router.basePath + router.asPath)
|
|
// Listen for page changes after a navigation or when the query changes
|
|
router.events.on('routeChangeComplete', handleRouteChange)
|
|
return () => {
|
|
router.events.off('routeChangeComplete', handleRouteChange)
|
|
}
|
|
}, [router.events])
|
|
|
|
const level = useMenuLevelId()
|
|
const menu = getMenuById(level)
|
|
|
|
return getMenuElement(menu)
|
|
}
|
|
|
|
export default memo(NavigationMenu)
|