Skip to content

Commit 01d9577

Browse files
committed
sort suggestions by comparison score
1 parent 5893849 commit 01d9577

2 files changed

Lines changed: 24 additions & 13 deletions

File tree

src/components/Selection.svelte

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import ChipGroup from './ChipGroup.svelte'
33
import Chip from './Chip.svelte'
4-
import { normalize_text } from '$lib/client/utils'
4+
import { get_comparison_score, normalize_text } from '$lib/client/utils'
55
66
type Props = {
77
title?: string
@@ -27,18 +27,17 @@
2727
2828
const id = $props.id()
2929
30-
let suggestions = $derived(
31-
selected_items.length >= max ? [] : allowed_items.filter(is_suggestion),
32-
)
33-
34-
let suggestions_element = $state<HTMLDivElement | null>(null)
35-
36-
function is_suggestion(allowed_item: string) {
37-
return (
38-
!selected_items.includes(allowed_item) &&
39-
normalize_text(allowed_item).includes(normalize_text(item.trim()))
40-
)
41-
}
30+
let suggestions = $derived.by(() => {
31+
if (selected_items.length >= max) return []
32+
const q = item.trim()
33+
if (!q) return []
34+
return allowed_items
35+
.filter((a) => !selected_items.includes(a))
36+
.map((a) => ({ a, r: get_comparison_score(a, q) }))
37+
.filter((x) => x.r > 0)
38+
.sort((x, y) => y.r - x.r || x.a.localeCompare(y.a))
39+
.map((x) => x.a)
40+
})
4241
4342
function is_valid(item: string) {
4443
return (
@@ -63,6 +62,8 @@
6362
active_index = 0
6463
}
6564
65+
let suggestions_element = $state<HTMLDivElement | null>(null)
66+
6667
function handle_blur(e: FocusEvent) {
6768
const is_suggestion_click = suggestions_element?.contains(e.relatedTarget as Node)
6869
if (!is_suggestion_click) show_suggestions = false

src/lib/client/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ export function normalize_text(txt: string) {
2727
.replace(/\p{Diacritic}/gu, '')
2828
}
2929

30+
export function get_comparison_score(value: string, query: string) {
31+
if (!query) return -1
32+
const v = normalize_text(value)
33+
const q = normalize_text(query)
34+
if (v === q) return 3
35+
if (v.startsWith(q)) return 2
36+
if (v.includes(q)) return 1
37+
return 0
38+
}
39+
3040
export const resize_textarea: Attachment = (textarea) => {
3141
if (!(textarea instanceof HTMLTextAreaElement)) return
3242

0 commit comments

Comments
 (0)