feat: person @mentions edit-mode infrastructure (PR-B1, #362) #369

Merged
marcel merged 26 commits from feat/person-mentions-issue-362-frontend-b1 into main 2026-04-29 08:05:49 +02:00
Showing only changes of commit 86ad5ca9b3 - Show all commits

View File

@@ -37,6 +37,7 @@ let query: string | null = $state(null);
let results: Person[] = $state([]);
let highlightedIndex = $state(0);
let mentionStart = $state(0);
let loading = $state(false);
let textarea: HTMLTextAreaElement | null = null;
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
@@ -90,8 +91,10 @@ function scheduleSearch(q: string) {
// Empty query: keep popup open with last results so the user can browse,
// but don't fire a backend call until they actually type something.
results = [];
loading = false;
return;
}
loading = true;
debounceTimer = setTimeout(async () => {
try {
// SECURITY: relies on the SvelteKit Vite proxy injecting the auth_token
@@ -108,6 +111,8 @@ function scheduleSearch(q: string) {
}
} catch {
results = [];
} finally {
loading = false;
}
}, 200);
}
@@ -140,6 +145,7 @@ function closePopup() {
query = null;
results = [];
highlightedIndex = 0;
loading = false;
clearTimeout(debounceTimer);
}
@@ -208,7 +214,9 @@ const popupOpen = $derived(query !== null);
role="listbox"
aria-label={m.person_mention_btn_label()}
>
{#if results.length === 0}
{#if loading}
<p class="px-3 py-2 font-sans text-sm text-ink-3">{m.comp_typeahead_loading()}</p>
{:else if results.length === 0}
<p class="px-3 py-2 font-sans text-sm text-ink-3">{m.person_mention_popup_empty()}</p>
{:else}
{#each results as person, i (person.id)}