Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/ui/src/components/base/Combobox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
:name="searchName"
:placeholder="searchPlaceholder || placeholder"
:disabled="disabled"
:clearable="clearable"
:autocomplete="searchAutocomplete"
:autocorrect="searchAutocorrect"
:autocapitalize="searchAutocapitalize"
Expand All @@ -38,6 +39,7 @@
@focusin="handleSearchFocus"
@focusout="handleSearchFocusout"
@click="handleSearchClick"
@clear="handleSearchClear"
>
<template v-if="showChevron" #right>
<ChevronLeftIcon
Expand Down Expand Up @@ -274,6 +276,7 @@ const props = withDefaults(
placeholder?: string
disabled?: boolean
searchable?: boolean
clearable?: boolean
searchPlaceholder?: string
listbox?: boolean
showChevron?: boolean
Expand Down Expand Up @@ -316,6 +319,7 @@ const props = withDefaults(
placeholder: 'Select an option',
disabled: false,
searchable: false,
clearable: false,
searchPlaceholder: 'Search...',
listbox: true,
showChevron: true,
Expand Down Expand Up @@ -838,6 +842,12 @@ function handleSearchInput() {
}
}

function handleSearchClear() {
userHasTyped.value = true
emit('searchInput', searchQuery.value)
closeDropdown()
}

function handleSearchFocus(event: FocusEvent) {
const target = event.target
if (props.selectSearchTextOnFocus && target instanceof HTMLInputElement) {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/base/StyledInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
type="button"
class="absolute right-0.5 z-[1] p-2 touch-manipulation bg-transparent border-none text-secondary hover:text-contrast transition-colors cursor-pointer select-none"
aria-label="Clear input"
@click="clear"
@click.stop="clear"
>
<XIcon class="h-5 w-5" />
</button>
Expand Down
21 changes: 18 additions & 3 deletions packages/ui/src/components/project/ProjectCombobox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:no-options-message="searchLoading ? loadingMessage : noResultsMessage"
:disable-search-filter="true"
:disabled="disabled"
:clearable="clearable"
show-icon-in-selected
@search-input="(query) => handleSearch(query)"
/>
Expand All @@ -32,12 +33,13 @@ export type ProjectType =
| 'plugin'
| 'server'

interface SearchHit {
export interface SearchHit {
project_id: string
title: string
icon_url?: string
project_type: string
slug: string
author?: string
}

const props = withDefaults(
Expand All @@ -54,6 +56,8 @@ const props = withDefaults(
noResultsMessage?: string
/** Whether the combobox is disabled */
disabled?: boolean
/** Whether to show a button for clearing the search input */
clearable?: boolean
/** Maximum number of results to show */
limit?: number
/** Project IDs to exclude from results */
Expand Down Expand Up @@ -83,6 +87,10 @@ const searchResultsCache = ref<Map<string, SearchHit>>(new Map())

const { labrinth } = injectModrinthClient()

function isAllowedProjectType(projectType: string): boolean {
return !props.projectTypes || props.projectTypes.includes(projectType as ProjectType)
}

const userProjectHits = ref<SearchHit[]>([])
const userProjectsFuse = ref<Fuse<SearchHit> | null>(null)

Expand Down Expand Up @@ -163,7 +171,7 @@ watch(
} else {
try {
const project = await labrinth.projects_v2.get(newId)
if (project) {
if (project && isAllowedProjectType(project.project_type)) {
hit = {
project_id: project.id,
title: project.title,
Expand All @@ -178,6 +186,9 @@ watch(
return
}
}
if (hit && !isAllowedProjectType(hit.project_type)) {
hit = null
}

selectedProject.value = hit
if (hit && !options.value.some((o) => o.value === hit!.project_id)) {
Expand Down Expand Up @@ -220,7 +231,11 @@ const search = async (query: string) => {
const uniqueHits: SearchHit[] = []

for (const hit of allHits) {
if (!seenIds.has(hit.project_id) && !excludeSet.has(hit.project_id)) {
if (
isAllowedProjectType(hit.project_type) &&
!seenIds.has(hit.project_id) &&
!excludeSet.has(hit.project_id)
) {
seenIds.add(hit.project_id)
uniqueHits.push(hit)
searchResultsCache.value.set(hit.project_id, hit)
Expand Down
Loading
Loading