mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00
Rename TagAutocomplete to WithAutocomplete
It's general enough to be used in other cases too
This commit is contained in:
parent
a9538ce6a7
commit
ed1f19048d
2 changed files with 28 additions and 27 deletions
|
@ -10,7 +10,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import AddTagBadge from "./AddTagBadge.svelte";
|
import AddTagBadge from "./AddTagBadge.svelte";
|
||||||
import Tag from "./Tag.svelte";
|
import Tag from "./Tag.svelte";
|
||||||
import TagInput from "./TagInput.svelte";
|
import TagInput from "./TagInput.svelte";
|
||||||
import TagAutocomplete from "./TagAutocomplete.svelte";
|
import WithAutocomplete from "./WithAutocomplete.svelte";
|
||||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||||
import type { Tag as TagType } from "./tags";
|
import type { Tag as TagType } from "./tags";
|
||||||
import { attachId, getName } from "./tags";
|
import { attachId, getName } from "./tags";
|
||||||
|
@ -45,6 +45,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSuggestions(): void {}
|
||||||
|
|
||||||
function updateWithTagName(tag: TagType): void {
|
function updateWithTagName(tag: TagType): void {
|
||||||
tag.name = activeName;
|
tag.name = activeName;
|
||||||
tags = tags;
|
tags = tags;
|
||||||
|
@ -217,11 +219,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
{#each tags as tag, index (tag.id)}
|
{#each tags as tag, index (tag.id)}
|
||||||
{#if index === active}
|
{#if index === active}
|
||||||
<TagAutocomplete
|
<WithAutocomplete
|
||||||
class="d-flex flex-column-reverse"
|
class="d-flex flex-column-reverse"
|
||||||
{suggestions}
|
{suggestions}
|
||||||
search={tags[active ?? -1]?.name ?? ""}
|
|
||||||
on:autocomplete={onAutocomplete}
|
on:autocomplete={onAutocomplete}
|
||||||
|
on:update={updateSuggestions}
|
||||||
let:updateAutocomplete
|
let:updateAutocomplete
|
||||||
>
|
>
|
||||||
<TagInput
|
<TagInput
|
||||||
|
@ -248,7 +250,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
decideNextActive();
|
decideNextActive();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</TagAutocomplete>
|
</WithAutocomplete>
|
||||||
{:else}
|
{:else}
|
||||||
<Tag
|
<Tag
|
||||||
name={tag.name}
|
name={tag.name}
|
||||||
|
|
|
@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { createEventDispatcher, onDestroy } from "svelte";
|
import { createEventDispatcher, onDestroy, tick } from "svelte";
|
||||||
|
|
||||||
import type Dropdown from "bootstrap/js/dist/dropdown";
|
import type Dropdown from "bootstrap/js/dist/dropdown";
|
||||||
|
|
||||||
|
@ -15,11 +15,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
export let suggestions: string[];
|
export let suggestions: string[];
|
||||||
export let search: string;
|
|
||||||
|
|
||||||
let autocomplete: Dropdown | undefined;
|
let autocomplete: Dropdown | undefined;
|
||||||
|
|
||||||
let displayed: string[] = [];
|
|
||||||
let selected: number | null = null;
|
let selected: number | null = null;
|
||||||
|
|
||||||
// blue highlight
|
// blue highlight
|
||||||
|
@ -29,12 +26,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
const updateAutocomplete =
|
const updateAutocomplete =
|
||||||
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
||||||
(event: KeyboardEvent): Dropdown => {
|
async (event: KeyboardEvent): Promise<void> => {
|
||||||
const target = event.target as HTMLInputElement;
|
const target = event.target as HTMLInputElement;
|
||||||
autocomplete = createDropdown(target);
|
|
||||||
autocomplete.show();
|
|
||||||
|
|
||||||
displayed = suggestions;
|
if (!autocomplete) {
|
||||||
|
autocomplete = createDropdown(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
autocomplete.update();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
event.code === "ArrowDown" ||
|
event.code === "ArrowDown" ||
|
||||||
|
@ -42,55 +41,55 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (selected === null) {
|
if (selected === null) {
|
||||||
selected = displayed.length - 1;
|
selected = suggestions.length - 1;
|
||||||
} else if (selected === 0) {
|
} else if (selected === 0) {
|
||||||
selected = null;
|
selected = null;
|
||||||
} else {
|
} else {
|
||||||
selected--;
|
selected--;
|
||||||
}
|
}
|
||||||
|
|
||||||
const choice = displayed[selected ?? -1];
|
const choice = suggestions[selected ?? -1];
|
||||||
dispatch("autocomplete", { choice });
|
dispatch("autocomplete", { choice });
|
||||||
} else if (event.code === "ArrowUp" || event.code === "Tab") {
|
} else if (event.code === "ArrowUp" || event.code === "Tab") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (selected === null) {
|
if (selected === null) {
|
||||||
selected = 0;
|
selected = 0;
|
||||||
} else if (selected >= displayed.length - 1) {
|
} else if (selected >= suggestions.length - 1) {
|
||||||
selected = null;
|
selected = null;
|
||||||
} else {
|
} else {
|
||||||
selected++;
|
selected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const choice = displayed[selected ?? -1];
|
const choice = suggestions[selected ?? -1];
|
||||||
dispatch("autocomplete", { choice });
|
dispatch("autocomplete", { choice });
|
||||||
} else if (event.code === "Enter") {
|
} else if (event.code === "Enter") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
active = true;
|
active = true;
|
||||||
} else {
|
} else {
|
||||||
search = target.value;
|
dispatch("update");
|
||||||
}
|
}
|
||||||
|
|
||||||
return autocomplete;
|
await tick();
|
||||||
|
|
||||||
|
if (suggestions.length > 0) {
|
||||||
|
autocomplete.show();
|
||||||
|
} else {
|
||||||
|
autocomplete.hide();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => autocomplete?.dispose());
|
||||||
if (!autocomplete) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
autocomplete.hide();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WithDropdownMenu let:menuId let:createDropdown>
|
<WithDropdownMenu let:menuId let:createDropdown>
|
||||||
<slot updateAutocomplete={updateAutocomplete(createDropdown)} />
|
<slot updateAutocomplete={updateAutocomplete(createDropdown)} />
|
||||||
|
|
||||||
<DropdownMenu id={menuId} class={className}>
|
<DropdownMenu id={menuId} class={className}>
|
||||||
{#each displayed as tag, i}
|
{#each suggestions as suggestion, i}
|
||||||
<div class="suggestion-item">
|
<div class="suggestion-item">
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
class={i === selected ? (active ? "active" : "focus") : ""}
|
class={i === selected ? (active ? "active" : "focus") : ""}
|
||||||
on:click>{tag}</DropdownItem
|
on:click>{suggestion}</DropdownItem
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
Loading…
Reference in a new issue