Files
misode.github.io/src/app/components/Header.tsx
Misode 0dee553d7e
Some checks failed
Deploy to GitHub Pages / build (push) Has been cancelled
Deploy to GitHub Pages / deploy (push) Has been cancelled
Add generator aliases for search
2025-01-30 00:10:06 +01:00

96 lines
3.2 KiB
TypeScript

import { getCurrentUrl, Link } from 'preact-router'
import { useCallback } from 'preact/hooks'
import type { ConfigGenerator } from '../Config.js'
import config from '../Config.js'
import { useLocale, useTheme, useTitle, useVersion } from '../contexts/index.js'
import { cleanUrl, getGenerator, SOURCE_REPO_URL } from '../Utils.js'
import { FancyMenu } from './FancyMenu.jsx'
import { searchGenerators } from './generator/GeneratorList.jsx'
import { Btn, BtnMenu, Icons, Octicon } from './index.js'
const Themes: Record<string, keyof typeof Octicon> = {
system: 'device_desktop',
dark: 'moon',
light: 'sun',
}
export function Header() {
const { lang, locale, changeLocale: changeLanguage } = useLocale()
const { theme, changeTheme } = useTheme()
const { title } = useTitle()
const url = getCurrentUrl()
const gen = getGenerator(url)
return <header>
<div class="title flex items-center">
<Link class="home-link pr-1" href="/" aria-label={locale('home')}>{Icons.home}</Link>
{gen
? <GeneratorTitle title={title} gen={gen} />
: <h1 class="font-bold px-1 text-lg sm:text-2xl">{title}</h1>}
</div>
<nav>
<ul>
<li>
<BtnMenu icon="globe" tooltip={locale('language')}>
{config.languages.map(({ code, name }) =>
<Btn label={name} active={code === lang}
onClick={() => changeLanguage(code)} />
)}
</BtnMenu>
</li>
<li>
<BtnMenu icon={Themes[theme]} tooltip={locale('theme')}>
{Object.entries(Themes).map(([th, icon]) =>
<Btn icon={icon} label={locale(`theme.${th}`)} active={th === theme}
onClick={() => changeTheme(th)} />
)}
</BtnMenu>
</li>
<li class="dimmed">
<a href={SOURCE_REPO_URL} target="_blank" rel="noreferrer" class="tooltipped tip-sw" aria-label={locale('github')}>
{Octicon.mark_github}
</a>
</li>
</ul>
</nav>
</header>
}
interface GeneratorTitleProps {
title: string
gen: ConfigGenerator
}
function GeneratorTitle({ title, gen }: GeneratorTitleProps) {
const { locale } = useLocale()
const { version } = useVersion()
const icon = Object.keys(Icons).includes(gen.id) ? gen.id as keyof typeof Icons : undefined
const getGenerators = useCallback((search: string, close: () => void) => {
let results = config.generators
.filter(g => !g.dependency)
.map(g => ({ ...g, name: locale(`generator.${g.id}`).toLowerCase() }))
results = searchGenerators(results, search)
if (results.length === 0) {
return [<span class="note">{locale('generators.no_results')}</span>]
}
return results.map(g =>
<Link class="flex items-center cursor-pointer no-underline rounded p-1" href={cleanUrl(g.url)} onClick={close}>
{locale(`generator.${g.id}`)}
{Object.keys(Icons).includes(g.id) ? Icons[g.id as keyof typeof Icons] : undefined}
<div class="m-auto"></div>
{g.tags?.filter(t => t === 'assets').map(t =>
<div class="badge ml-2 mr-0 text-sm" style="--color: #555;">{t}</div>
)}
</Link>
)
}, [locale, version])
return <FancyMenu getResults={getGenerators} placeholder={locale('generators.search')}>
<h1 class="font-bold flex items-center cursor-pointer text-lg sm:text-2xl">
{title}
{icon && Icons[icon]}
</h1>
</FancyMenu>
}