mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Use fancy menu for presets
This commit is contained in:
@@ -4,10 +4,12 @@ import { useFocus } from '../hooks/index.js'
|
||||
|
||||
interface Props {
|
||||
placeholder?: string
|
||||
relative?: boolean
|
||||
class?: string
|
||||
getResults: (search: string, close: () => void) => ComponentChildren
|
||||
children: ComponentChildren
|
||||
}
|
||||
export function FancyMenu({ placeholder, getResults, children }: Props) {
|
||||
export function FancyMenu({ placeholder, relative, class: clazz, getResults, children }: Props) {
|
||||
const [active, setActive] = useFocus()
|
||||
const [search, setSearch] = useState('')
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
@@ -51,13 +53,13 @@ export function FancyMenu({ placeholder, getResults, children }: Props) {
|
||||
}
|
||||
}, [setActive, inputRef])
|
||||
|
||||
return <div class="px-1 relative">
|
||||
return <div class={`px-1 ${relative ? 'relative' : ''}`}>
|
||||
<div onClick={open}>
|
||||
{children}
|
||||
</div>
|
||||
<div class={`fancy-menu absolute flex flex-col gap-2 p-2 rounded-lg drop-shadow-xl ${active ? '' : 'hidden'}`} onKeyDown={handleKeyDown}>
|
||||
<div class={`fancy-menu absolute flex flex-col gap-2 p-2 rounded-lg drop-shadow-xl ${clazz} ${active ? '' : 'hidden'}`} onKeyDown={handleKeyDown}>
|
||||
<input ref={inputRef} type="text" class="py-1 px-2 w-full rounded" value={search} placeholder={placeholder} onInput={(e) => setSearch((e.target as HTMLInputElement).value)} onClick={(e) => e.stopPropagation()} />
|
||||
{active && <div ref={resultsRef} class="overflow-y-auto overscroll-none flex flex-col pr-2 h-96 max-h-max min-w-max">
|
||||
{active && <div ref={resultsRef} class="fancy-menu-results overflow-y-auto overscroll-none flex flex-col pr-2 h-96 max-h-max w-max max-w-full">
|
||||
{results}
|
||||
</div>}
|
||||
</div>
|
||||
|
||||
@@ -82,7 +82,7 @@ function GeneratorTitle({ title, gen }: GeneratorTitleProps) {
|
||||
return [<span class="note">{locale('generators.no_results')}</span>]
|
||||
}
|
||||
return results.map(g =>
|
||||
<Link class="gen-result flex items-center cursor-pointer no-underline rounded p-1" href={cleanUrl(g.url)} onClick={close}>
|
||||
<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>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useMemo, useState } from 'preact/hooks'
|
||||
import { Btn, BtnInput } from '../index.js'
|
||||
|
||||
interface Props {
|
||||
values?: string[],
|
||||
onSelect?: (value: string) => unknown,
|
||||
searchPlaceholder?: string,
|
||||
noResults?: string,
|
||||
}
|
||||
export function SearchList({ values, onSelect, searchPlaceholder, noResults }: Props) {
|
||||
const [search, setSearch] = useState('')
|
||||
const results = useMemo(() => {
|
||||
const terms = search.trim().split(' ')
|
||||
return values?.filter(v => terms.every(t => v.includes(t))) ?? []
|
||||
}, [values, search])
|
||||
|
||||
return <>
|
||||
<BtnInput icon="search" large value={search} onChange={setSearch} doSelect={1} placeholder={searchPlaceholder ?? 'Search'} />
|
||||
<div class="result-list">
|
||||
{results.map(v => <Btn key={v} label={v} onClick={() => onSelect?.(v)} />)}
|
||||
{results.length === 0 && <Btn label={noResults ?? 'No results'}/>}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './Checkbox.js'
|
||||
export * from './Input.js'
|
||||
export * from './SearchList.js'
|
||||
|
||||
@@ -13,7 +13,8 @@ import { checkVersion, fetchDependencyMcdoc, fetchPreset, fetchRegistries, getSn
|
||||
import { DEPENDENCY_URI } from '../../services/Spyglass.js'
|
||||
import { Store } from '../../Store.js'
|
||||
import { cleanUrl, genPath } from '../../Utils.js'
|
||||
import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileView, Footer, HasPreview, Octicon, PreviewPanel, ProjectPanel, SearchList, SourcePanel, TextInput, VersionSwitcher } from '../index.js'
|
||||
import { FancyMenu } from '../FancyMenu.jsx'
|
||||
import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileView, Footer, HasPreview, Octicon, PreviewPanel, ProjectPanel, SourcePanel, TextInput, VersionSwitcher } from '../index.js'
|
||||
import { getRootDefault } from './McdocHelpers.js'
|
||||
|
||||
export const SHARE_KEY = 'share'
|
||||
@@ -199,6 +200,23 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
return entries.map(e => e.startsWith('minecraft:') ? e.slice(10) : e)
|
||||
}, [version, gen.id])
|
||||
|
||||
const getPresets = useCallback((search: string, close: () => void) => {
|
||||
if (presets === undefined) {
|
||||
return <span class="w-80 note">{locale('loading')}</span>
|
||||
}
|
||||
if (!presets || presets.length === 0) {
|
||||
return <span class="w-80 note">{locale('presets.no_results')}</span>
|
||||
}
|
||||
const terms = search.trim().split(' ')
|
||||
const results = presets?.filter(v => terms.every(t => v.includes(t))).slice(0, 100) ?? []
|
||||
if (results.length === 0) {
|
||||
return <span class="w-80 note">{locale('presets.no_results_for_query')}</span>
|
||||
}
|
||||
return results.map(r => <button class="w-80 flex items-center cursor-pointer no-underline rounded p-1" onClick={() => {selectPreset(r); close()}}>
|
||||
{r}
|
||||
</button>)
|
||||
}, [presets])
|
||||
|
||||
const selectPreset = (id: string) => {
|
||||
Analytics.loadPreset(gen.id, id)
|
||||
setSharedSnippetId(undefined, true)
|
||||
@@ -372,9 +390,9 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
{Octicon.mortar_board}
|
||||
<span>{locale('wiki')}</span>
|
||||
</a>}
|
||||
<BtnMenu icon="archive" label={locale('presets')} relative={false}>
|
||||
<SearchList searchPlaceholder={locale('search')} noResults={locale('no_presets')} values={presets} onSelect={selectPreset}/>
|
||||
</BtnMenu>
|
||||
<FancyMenu placeholder={locale('search')} getResults={getPresets} relative={false} class="right-0 mt-2">
|
||||
<Btn icon="archive" label={locale('presets')} />
|
||||
</FancyMenu>
|
||||
<VersionSwitcher value={version} onChange={selectVersion} allowed={allowedVersions} />
|
||||
<BtnMenu icon="kebab_horizontal" tooltip={locale('more')}>
|
||||
<Btn icon="history" label={locale('reset_default')} onClick={reset} />
|
||||
|
||||
@@ -184,7 +184,6 @@
|
||||
"move_down": "Move down",
|
||||
"move_up": "Move up",
|
||||
"no_file_chosen": "No file chosen",
|
||||
"no_presets": "No presets",
|
||||
"normalize": "Normalize",
|
||||
"not_found.description": "The page you were looking for does not exist.",
|
||||
"output_settings": "Output settings",
|
||||
@@ -196,6 +195,8 @@
|
||||
"partner.ohthetreesyoullgrow": "Oh The Trees You'll Grow",
|
||||
"partner.sky_aesthetics": "Sky Aesthetics",
|
||||
"presets": "Presets",
|
||||
"presets.no_results": "No presets",
|
||||
"presets.no_results_for_query": "No presets for this query",
|
||||
"preview": "Visualize",
|
||||
"preview.auto_scroll": "Auto scroll",
|
||||
"preview.biome": "Biome",
|
||||
|
||||
@@ -226,6 +226,7 @@ nav li .btn svg {
|
||||
}
|
||||
|
||||
.fancy-menu {
|
||||
max-width: calc(100vw - 32px);
|
||||
background-color: var(--background-2);
|
||||
color: var(--text-2);
|
||||
}
|
||||
@@ -234,11 +235,11 @@ nav li .btn svg {
|
||||
background-color: var(--background-1);
|
||||
}
|
||||
|
||||
.gen-result {
|
||||
.fancy-menu-results > * {
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.gen-result svg {
|
||||
.fancy-menu-results > * svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--nav);
|
||||
@@ -247,13 +248,13 @@ nav li .btn svg {
|
||||
transition: margin 0.2s;
|
||||
}
|
||||
|
||||
.gen-result:focus-visible,
|
||||
.gen-result:hover {
|
||||
.fancy-menu-results > *:focus-visible,
|
||||
.fancy-menu-results > *:hover {
|
||||
background-color: var(--background-3);
|
||||
}
|
||||
|
||||
.gen-result:focus-visible svg,
|
||||
.gen-result:hover svg {
|
||||
.fancy-menu-results > *:focus-visible svg,
|
||||
.fancy-menu-results > *:hover svg {
|
||||
margin-left: 14px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user