mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-30 06:12:47 -07:00
feat: create basic router
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { useRouterStore } from '../hooks/useRouterStore'
|
||||
import type { AnchorHTMLAttributes, MouseEvent } from 'react'
|
||||
|
||||
export default function Link(
|
||||
props: AnchorHTMLAttributes<HTMLAnchorElement>,
|
||||
): JSX.Element {
|
||||
const handleTransition = (e: MouseEvent<HTMLAnchorElement>): void => {
|
||||
e.preventDefault()
|
||||
props.onClick?.(e)
|
||||
useRouterStore.setState({ location: { pathname: props.href || '' } })
|
||||
window.history.pushState('', '', props.href)
|
||||
}
|
||||
return (
|
||||
<a {...props} onClick={handleTransition}>
|
||||
{props.children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as React from 'react'
|
||||
import { useRouter } from '../hooks/useRouter'
|
||||
import { useRouterStore } from '../hooks/useRouterStore'
|
||||
|
||||
export function Matches(): JSX.Element | undefined {
|
||||
const matchId = useRouterStore.getState().matches[0]?.id
|
||||
|
||||
//if (!matchId) return <></>
|
||||
|
||||
return (
|
||||
<React.Suspense>
|
||||
<Match id={matchId} />
|
||||
</React.Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
interface MatchProps {
|
||||
id: string
|
||||
}
|
||||
|
||||
const Match = React.memo(function ({ id }: MatchProps) {
|
||||
const location = useRouterStore((st) => st.location)
|
||||
const router = useRouter()
|
||||
|
||||
console.log(router, location)
|
||||
|
||||
const route = router.routesById[location?.pathname]
|
||||
|
||||
return route.component()
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const Outlet = React.memo(function Outlet() {
|
||||
return <h1>Outlet</h1>
|
||||
})
|
||||
|
||||
export default Outlet
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as React from 'react'
|
||||
import type { Router } from '../router'
|
||||
|
||||
const routerContext = React.createContext<Router>(null!)
|
||||
|
||||
const ROUTER_DOM_CONTEXT = '__TUONO_ROUTER__CONTEXT__'
|
||||
|
||||
export function getRouterContext(): any {
|
||||
if (typeof document === 'undefined') {
|
||||
return routerContext
|
||||
}
|
||||
|
||||
if (window[ROUTER_DOM_CONTEXT as any]) {
|
||||
return window[ROUTER_DOM_CONTEXT as any]
|
||||
}
|
||||
|
||||
window[ROUTER_DOM_CONTEXT as any] = routerContext as any
|
||||
|
||||
return routerContext
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import * as React from 'react'
|
||||
import { getRouterContext } from './RouterContext'
|
||||
import { Matches } from './Matches'
|
||||
|
||||
type Router = any
|
||||
|
||||
interface RouterContextProviderProps {
|
||||
router: Router
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
function RouterContextProvider({
|
||||
router,
|
||||
children,
|
||||
...rest
|
||||
}: RouterContextProviderProps): JSX.Element {
|
||||
// Allow the router to update options on the router instance
|
||||
router.update({
|
||||
...router.options,
|
||||
...rest,
|
||||
context: {
|
||||
...router.options.context,
|
||||
...rest.context,
|
||||
},
|
||||
})
|
||||
|
||||
const routerContext = getRouterContext()
|
||||
|
||||
const pendingElement = router.options.defaultPendingComponent ? (
|
||||
<router.options.defaultPendingComponent />
|
||||
) : null
|
||||
|
||||
const provider = (
|
||||
<React.Suspense fallback={pendingElement}>
|
||||
<routerContext.Provider value={router}>{children}</routerContext.Provider>
|
||||
</React.Suspense>
|
||||
)
|
||||
|
||||
// NOTE: verify usefulness
|
||||
if (router.options.Wrap) {
|
||||
return <router.options.Wrap>{provider}</router.options.Wrap>
|
||||
}
|
||||
|
||||
return provider
|
||||
}
|
||||
|
||||
interface RouterProviderProps {
|
||||
router: Router
|
||||
}
|
||||
|
||||
export function RouterProvider({
|
||||
router,
|
||||
...rest
|
||||
}: RouterProviderProps): JSX.Element {
|
||||
return (
|
||||
<RouterContextProvider router={router} {...rest}>
|
||||
<Matches />
|
||||
</RouterContextProvider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user