mirror of
https://github.com/ankitects/anki.git
synced 2025-11-12 15:47:12 -05:00
Have WithAutocomplete export its API
allows it to be used in more contexts
This commit is contained in:
parent
ed1f19048d
commit
bbef2ab6b4
2 changed files with 115 additions and 59 deletions
|
|
@ -45,7 +45,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
}
|
||||
|
||||
function updateSuggestions(): void {}
|
||||
let addOrPop = true;
|
||||
function updateSuggestions(): void {
|
||||
if (suggestions.length === 0) {
|
||||
addOrPop = false;
|
||||
} else if (suggestions.length > 3) {
|
||||
addOrPop = true;
|
||||
}
|
||||
|
||||
if (addOrPop) {
|
||||
suggestions.pop();
|
||||
suggestions = suggestions;
|
||||
} else {
|
||||
suggestions = suggestions.concat(["another"]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateWithTagName(tag: TagType): void {
|
||||
tag.name = activeName;
|
||||
|
|
@ -210,6 +224,38 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
active = activeAfterBlur;
|
||||
activeAfterBlur = null;
|
||||
}
|
||||
|
||||
function update(event: KeyboardEvent, autocomplete): void {
|
||||
switch (event.code) {
|
||||
case "ArrowUp":
|
||||
autocomplete.selectNext();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case "ArrowDown":
|
||||
autocomplete.selectPrevious();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case "Tab":
|
||||
if (event.shiftKey) {
|
||||
autocomplete.selectNext();
|
||||
} else {
|
||||
autocomplete.selectPrevious();
|
||||
}
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case "Enter":
|
||||
autocomplete.chooseSelected();
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
autocomplete.update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<StickyBottom>
|
||||
|
|
@ -224,14 +270,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
{suggestions}
|
||||
on:autocomplete={onAutocomplete}
|
||||
on:update={updateSuggestions}
|
||||
let:updateAutocomplete
|
||||
let:createAutocomplete
|
||||
let:autocomplete
|
||||
>
|
||||
<TagInput
|
||||
id={tag.id}
|
||||
bind:name={activeName}
|
||||
bind:input={activeInput}
|
||||
on:focus={() => (activeName = tag.name)}
|
||||
on:keydown={updateAutocomplete}
|
||||
on:focus={() => {
|
||||
activeName = tag.name;
|
||||
createAutocomplete(activeInput);
|
||||
}}
|
||||
on:keydown={(event) => update(event, autocomplete)}
|
||||
on:input={() => updateWithTagName(tag)}
|
||||
on:tagsplit={({ detail }) =>
|
||||
splitTag(index, detail.start, detail.end)}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
export let suggestions: string[];
|
||||
|
||||
let autocomplete: Dropdown | undefined;
|
||||
let dropdown: Dropdown | undefined;
|
||||
let selected: number | null = null;
|
||||
|
||||
// blue highlight
|
||||
|
|
@ -24,65 +24,71 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const updateAutocomplete =
|
||||
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
||||
async (event: KeyboardEvent): Promise<void> => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
|
||||
if (!autocomplete) {
|
||||
autocomplete = createDropdown(target);
|
||||
}
|
||||
|
||||
autocomplete.update();
|
||||
|
||||
if (
|
||||
event.code === "ArrowDown" ||
|
||||
(event.code === "Tab" && event.shiftKey)
|
||||
) {
|
||||
event.preventDefault();
|
||||
if (selected === null) {
|
||||
selected = suggestions.length - 1;
|
||||
} else if (selected === 0) {
|
||||
selected = null;
|
||||
} else {
|
||||
selected--;
|
||||
}
|
||||
|
||||
const choice = suggestions[selected ?? -1];
|
||||
dispatch("autocomplete", { choice });
|
||||
} else if (event.code === "ArrowUp" || event.code === "Tab") {
|
||||
event.preventDefault();
|
||||
if (selected === null) {
|
||||
selected = 0;
|
||||
} else if (selected >= suggestions.length - 1) {
|
||||
selected = null;
|
||||
} else {
|
||||
selected++;
|
||||
}
|
||||
|
||||
const choice = suggestions[selected ?? -1];
|
||||
dispatch("autocomplete", { choice });
|
||||
} else if (event.code === "Enter") {
|
||||
event.preventDefault();
|
||||
active = true;
|
||||
} else {
|
||||
dispatch("update");
|
||||
}
|
||||
|
||||
await tick();
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
autocomplete.show();
|
||||
} else {
|
||||
autocomplete.hide();
|
||||
}
|
||||
const createAutocomplete =
|
||||
(createDropdown: (target: HTMLElement) => Dropdown) =>
|
||||
(target: HTMLElement): void => {
|
||||
dropdown = createDropdown(target);
|
||||
};
|
||||
|
||||
onDestroy(() => autocomplete?.dispose());
|
||||
function selectPrevious() {
|
||||
if (selected === null) {
|
||||
selected = suggestions.length - 1;
|
||||
} else if (selected === 0) {
|
||||
selected = null;
|
||||
} else {
|
||||
selected--;
|
||||
}
|
||||
|
||||
const choice = suggestions[selected ?? -1];
|
||||
dispatch("dropdown", { choice });
|
||||
}
|
||||
|
||||
function selectNext() {
|
||||
if (selected === null) {
|
||||
selected = 0;
|
||||
} else if (selected >= suggestions.length - 1) {
|
||||
selected = null;
|
||||
} else {
|
||||
selected++;
|
||||
}
|
||||
|
||||
const choice = suggestions[selected ?? -1];
|
||||
dispatch("autocomplete", { choice });
|
||||
}
|
||||
|
||||
function chooseSelected() {
|
||||
active = true;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
dropdown = dropdown as Dropdown;
|
||||
dropdown.update();
|
||||
dispatch("update");
|
||||
|
||||
await tick();
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
dropdown.show();
|
||||
} else {
|
||||
dropdown.hide();
|
||||
}
|
||||
}
|
||||
|
||||
const autocomplete = {
|
||||
hide: () => dropdown!.hide(),
|
||||
show: () => dropdown!.show(),
|
||||
toggle: () => dropdown!.toggle(),
|
||||
selectPrevious,
|
||||
selectNext,
|
||||
chooseSelected,
|
||||
update,
|
||||
};
|
||||
|
||||
onDestroy(() => dropdown?.dispose());
|
||||
</script>
|
||||
|
||||
<WithDropdownMenu let:menuId let:createDropdown>
|
||||
<slot updateAutocomplete={updateAutocomplete(createDropdown)} />
|
||||
<slot createAutocomplete={createAutocomplete(createDropdown)} {autocomplete} />
|
||||
|
||||
<DropdownMenu id={menuId} class={className}>
|
||||
{#each suggestions as suggestion, i}
|
||||
|
|
|
|||
Loading…
Reference in a new issue