Implement accepting suggestions via Enter

This commit is contained in:
Henrik Giesel 2021-06-29 02:10:32 +02:00
parent b93646209a
commit a29d21f4fd
4 changed files with 44 additions and 17 deletions

View file

@ -51,8 +51,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
border: none; border: none;
&.active { &.active {
background-color: button.$focus-color; background-color: button.$focus-color !important;
color: white; color: white !important;
} }
} }

View file

@ -32,13 +32,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let activeName = ""; let activeName = "";
let activeInput: HTMLInputElement; let activeInput: HTMLInputElement;
function onAutocomplete({ detail }) {
const activeTag = tags[active!];
const selected = detail.selected;
activeName = selected ?? activeTag.name;
}
let suggestionsPromise: Promise<string[]> = Promise.resolve([]); let suggestionsPromise: Promise<string[]> = Promise.resolve([]);
function updateSuggestions(): void { function updateSuggestions(): void {
@ -49,6 +42,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
]); ]);
} }
function onAutocomplete(selected: string): void {
const activeTag = tags[active!];
activeName = selected ?? activeTag.name;
activeInput.setSelectionRange(Infinity, Infinity);
}
function onChosen(chosen: string) {
onAutocomplete(chosen);
splitTag(active!, Infinity, Infinity);
}
function updateWithTagName(tag: TagType): void { function updateWithTagName(tag: TagType): void {
tag.name = activeName; tag.name = activeName;
tags = tags; tags = tags;
@ -96,13 +101,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
contained contained
); );
if (contained >= 0) { if (contained >= 0) {
tags[contained].flash(); tags[contained >= index ? contained + 1 : contained].flash();
return false; return false;
} }
return true; return true;
} }
async function enterBehavior(
index: number,
start: number,
end: number,
autocomplete: any
): Promise<void> {
if (autocomplete.isVisible()) {
autocomplete.chooseSelected();
} else {
splitTag(index, start, end);
}
}
async function splitTag(index: number, start: number, end: number): Promise<void> { async function splitTag(index: number, start: number, end: number): Promise<void> {
const current = activeName.slice(0, start); const current = activeName.slice(0, start);
const splitOff = activeName.slice(end); const splitOff = activeName.slice(end);
@ -271,8 +289,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<WithAutocomplete <WithAutocomplete
class="d-flex flex-column-reverse" class="d-flex flex-column-reverse"
{suggestionsPromise} {suggestionsPromise}
on:autocomplete={onAutocomplete}
on:update={updateSuggestions} on:update={updateSuggestions}
on:autocomplete={({ detail }) =>
onAutocomplete(detail.selected)}
on:choose={({ detail }) => onChosen(detail.chosen)}
let:createAutocomplete let:createAutocomplete
let:autocomplete let:autocomplete
> >
@ -280,7 +300,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
id={tag.id} id={tag.id}
bind:name={activeName} bind:name={activeName}
bind:input={activeInput} bind:input={activeInput}
on:click={(event) => event.stopPropagation()}
on:focus={() => { on:focus={() => {
activeName = tag.name; activeName = tag.name;
createAutocomplete(activeInput); createAutocomplete(activeInput);
@ -288,7 +307,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
on:keydown={(event) => update(event, autocomplete)} on:keydown={(event) => update(event, autocomplete)}
on:input={() => updateWithTagName(tag)} on:input={() => updateWithTagName(tag)}
on:tagsplit={({ detail }) => on:tagsplit={({ detail }) =>
splitTag(index, detail.start, detail.end)} enterBehavior(
index,
detail.start,
detail.end,
autocomplete
)}
on:tagadd={() => insertTag(index)} on:tagadd={() => insertTag(index)}
on:tagdelete={() => deleteTagAt(index)} on:tagdelete={() => deleteTagAt(index)}
on:tagjoinprevious={() => joinWithPreviousTag(index)} on:tagjoinprevious={() => joinWithPreviousTag(index)}

View file

@ -87,6 +87,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function onEnter(event: Event): void { function onEnter(event: Event): void {
event.preventDefault(); event.preventDefault();
dispatch("tagsplit", { start: input.selectionStart, end: input.selectionEnd }); dispatch("tagsplit", { start: input.selectionStart, end: input.selectionEnd });
event.preventDefault();
} }
function onKeydown(event: KeyboardEvent): void { function onKeydown(event: KeyboardEvent): void {

View file

@ -19,9 +19,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let target: HTMLElement; let target: HTMLElement;
let dropdown: Dropdown; let dropdown: Dropdown;
let autocomplete: any; let autocomplete: any;
let selected: number | null = null;
// blue highlight let selected: number | null = null;
let active: boolean = false; let active: boolean = false;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -54,8 +53,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
dispatch("autocomplete", { selected: suggestions[selected ?? -1] }); dispatch("autocomplete", { selected: suggestions[selected ?? -1] });
} }
function chooseSelected() { async function chooseSelected() {
const suggestions = await suggestionsPromise;
active = true; active = true;
dispatch("choose", { chosen: suggestions[selected ?? -1] });
} }
async function update() { async function update() {
@ -102,7 +104,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
async function chooseIndex(index: number): Promise<void> { async function chooseIndex(index: number): Promise<void> {
const suggestions = await suggestionsPromise; const suggestions = await suggestionsPromise;
dispatch("autocomplete", { selected: suggestions[index] }); dispatch("autocomplete", { name: suggestions[index] });
} }
function selectIfMousedown(event: MouseEvent, index: number): void { function selectIfMousedown(event: MouseEvent, index: number): void {