webapp/src/stores/router.ts

101 lines
2.3 KiB
TypeScript
Raw Normal View History

2022-09-22 09:37:49 +00:00
import type { Accessor } from 'solid-js'
2022-09-09 13:30:25 +00:00
import { createRouter, createSearchParams } from '@nanostores/router'
2022-09-09 11:53:35 +00:00
import { isServer } from 'solid-js/web'
2022-09-22 09:37:49 +00:00
import { useStore } from '@nanostores/solid'
2022-09-09 11:53:35 +00:00
2022-09-22 09:37:49 +00:00
// TODO: more
export interface Routes {
home: void
2022-09-09 11:53:35 +00:00
topics: void
2022-09-22 09:37:49 +00:00
topic: 'slug'
2022-09-09 11:53:35 +00:00
authors: void
2022-09-22 09:37:49 +00:00
author: 'slug'
2022-09-09 11:53:35 +00:00
feed: void
article: 'slug'
search: 'q'
2022-09-23 18:27:05 +00:00
dogma: void
guide: void
help: void
manifest: void
partners: void
projects: void
termsOfUse: void
thanks: void
2022-09-09 11:53:35 +00:00
}
2022-09-22 09:37:49 +00:00
const searchParamsStore = createSearchParams()
const routerStore = createRouter<Routes>(
2022-09-09 11:53:35 +00:00
{
home: '/',
topics: '/topics',
2022-09-22 09:37:49 +00:00
topic: '/topic/:slug',
2022-09-09 11:53:35 +00:00
authors: '/authors',
2022-09-22 09:37:49 +00:00
author: '/author/:slug',
2022-09-09 11:53:35 +00:00
feed: '/feed',
search: '/search/:q?',
2022-09-23 18:27:05 +00:00
article: '/:slug',
dogma: '/about/dogma',
guide: '/about/guide',
help: '/about/help',
manifest: '/about/manifest',
partners: '/about/partners',
projects: '/about/projects',
termsOfUse: '/about/terms-of-use',
thanks: '/about/thanks'
2022-09-09 11:53:35 +00:00
},
{
2022-09-22 09:37:49 +00:00
search: false,
2022-09-09 11:53:35 +00:00
links: false
}
)
2022-09-22 09:37:49 +00:00
export const router = routerStore
export const handleClientRouteLinkClick = (event) => {
const link = event.target.closest('a')
if (
link &&
event.button === 0 &&
link.target !== '_blank' &&
link.rel !== 'external' &&
!link.download &&
!event.metaKey &&
!event.ctrlKey &&
!event.shiftKey &&
!event.altKey
) {
const url = new URL(link.href)
if (url.origin === location.origin) {
event.preventDefault()
// TODO: search params
routerStore.open(url.pathname)
}
}
}
export const initRouter = (pathname: string, search: string) => {
routerStore.open(pathname)
const params = Object.fromEntries(new URLSearchParams(search))
searchParamsStore.open(params)
2022-09-09 11:53:35 +00:00
}
if (!isServer) {
2022-09-14 11:28:43 +00:00
const { pathname, search } = window.location
2022-09-22 09:37:49 +00:00
initRouter(pathname, search)
}
export const useRouter = <TSearchParams extends Record<string, string> = Record<string, string>>() => {
const getPage = useStore(routerStore)
const getSearchParams = useStore(searchParamsStore) as unknown as Accessor<TSearchParams>
const changeSearchParam = <TKey extends keyof TSearchParams>(key: TKey, value: TSearchParams[TKey]) => {
searchParamsStore.open({ ...searchParamsStore.get(), [key]: value })
}
return {
getPage,
getSearchParams,
changeSearchParam
}
2022-09-09 11:53:35 +00:00
}