Fix bug where sometimes Autocomplete menu would not show even though suggestions exist
This commit is contained in:
parent
8d8a559f73
commit
8fd4412dbe
@ -11,11 +11,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
export { className as class };
|
||||
|
||||
export let labelledby: string | undefined = undefined;
|
||||
export let show = false;
|
||||
|
||||
setContext(dropdownKey, null);
|
||||
</script>
|
||||
|
||||
<div {id} class="dropdown-menu" aria-labelledby={labelledby}>
|
||||
<div {id} class="dropdown-menu" class:show aria-labelledby={labelledby}>
|
||||
<div class="dropdown-content {className}">
|
||||
<slot />
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
export let toggleOpen = true;
|
||||
export let drop: "down" | "up" = "down";
|
||||
|
||||
let placement: string;
|
||||
let placement: "bottom" | "top";
|
||||
$: switch (drop) {
|
||||
case "down":
|
||||
placement = "bottom";
|
||||
@ -52,10 +52,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
dropdown = new Dropdown(toggle, {
|
||||
autoClose,
|
||||
popperConfig: (defaultConfig: Record<string, any>) => ({
|
||||
...defaultConfig,
|
||||
placement,
|
||||
}),
|
||||
popperConfig: { placement },
|
||||
} as any);
|
||||
|
||||
if (autoOpen) {
|
||||
|
@ -14,7 +14,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import Tag from "./Tag.svelte";
|
||||
import WithAutocomplete from "./WithAutocomplete.svelte";
|
||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||
import { controlPressed } from "lib/keys";
|
||||
import type { Tag as TagType } from "./tags";
|
||||
import {
|
||||
attachId,
|
||||
@ -34,12 +33,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
tags = names.map(replaceWithUnicodeSeparator).map(attachId);
|
||||
}
|
||||
|
||||
const noSuggestions = Promise.resolve([]);
|
||||
let suggestionsPromise: Promise<string[]> = noSuggestions;
|
||||
|
||||
function saveTags(): void {
|
||||
bridgeCommand(
|
||||
`saveTags:${JSON.stringify(
|
||||
tags.map((tag) => tag.name).map(replaceWithColons)
|
||||
)}`
|
||||
);
|
||||
|
||||
suggestionsPromise = noSuggestions;
|
||||
}
|
||||
|
||||
let active: number | null = null;
|
||||
@ -48,9 +52,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
let activeInput: HTMLInputElement;
|
||||
|
||||
let autocomplete: any;
|
||||
|
||||
const noSuggestions = Promise.resolve([]);
|
||||
let suggestionsPromise: Promise<string[]> = noSuggestions;
|
||||
let autocompleteDisabled: boolean = false;
|
||||
|
||||
async function fetchSuggestions(input: string): Promise<string[]> {
|
||||
const data = await postRequest(
|
||||
@ -67,12 +69,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
const activeTag = tags[active!];
|
||||
const activeName = activeTag.name;
|
||||
|
||||
suggestionsPromise =
|
||||
activeName.length === 0
|
||||
autocompleteDisabled = activeName.length === 0;
|
||||
suggestionsPromise = autocompleteDisabled
|
||||
? noSuggestions
|
||||
: fetchSuggestions(activeTag.name).then((names: string[]): string[] =>
|
||||
names.map(replaceWithUnicodeSeparator)
|
||||
);
|
||||
: fetchSuggestions(activeTag.name).then((names: string[]): string[] => {
|
||||
autocompleteDisabled = names.length === 0;
|
||||
return names.map(replaceWithUnicodeSeparator);
|
||||
});
|
||||
}
|
||||
|
||||
function onAutocomplete(selected: string): void {
|
||||
@ -254,27 +257,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
activeAfterBlur = null;
|
||||
}
|
||||
|
||||
function isPrintableKey(event: KeyboardEvent): boolean {
|
||||
return event.key.length === 1 && !controlPressed(event);
|
||||
}
|
||||
|
||||
function isDeletionKey(event: KeyboardEvent): boolean {
|
||||
return event.code === "Backspace" || event.code === "Delete";
|
||||
}
|
||||
|
||||
function onKeydown(event: KeyboardEvent): void {
|
||||
const visible = autocomplete.isVisible();
|
||||
const printable = isPrintableKey(event);
|
||||
const deletion = isDeletionKey(event);
|
||||
|
||||
if (!visible) {
|
||||
if (printable || deletion) {
|
||||
autocomplete.show();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (event.code) {
|
||||
case "ArrowUp":
|
||||
autocomplete.selectPrevious();
|
||||
@ -464,12 +447,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
on:select={({ detail }) => onAutocomplete(detail.selected)}
|
||||
on:choose={({ detail }) => onAutocomplete(detail.chosen)}
|
||||
let:createAutocomplete
|
||||
let:disabled
|
||||
>
|
||||
<TagInput
|
||||
id={tag.id}
|
||||
class="tag-input position-absolute start-0 top-0 ps-2 py-0"
|
||||
{disabled}
|
||||
disabled={autocompleteDisabled}
|
||||
bind:name={activeName}
|
||||
bind:input={activeInput}
|
||||
on:focus={() => {
|
||||
|
@ -17,17 +17,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
export let drop: "down" | "up" = "down";
|
||||
export let suggestionsPromise: Promise<string[]>;
|
||||
|
||||
let disabled = true;
|
||||
let dropdown: Dropdown;
|
||||
let show = false;
|
||||
|
||||
let suggestionsItems: string[] = [];
|
||||
$: suggestionsPromise.then((items) => {
|
||||
if (items.length > 0) {
|
||||
disabled = false;
|
||||
show = items.length > 0;
|
||||
|
||||
if (show) {
|
||||
dropdown.show();
|
||||
} else {
|
||||
dropdown.hide();
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
suggestionsItems = items;
|
||||
@ -83,7 +83,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
async function chooseSelected() {
|
||||
active = true;
|
||||
dispatch("choose", { chosen: suggestionsItems[selected ?? -1] });
|
||||
|
||||
await tick();
|
||||
show = false;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
@ -97,10 +99,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
return selected !== null;
|
||||
}
|
||||
|
||||
function disable(): void {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
const createAutocomplete =
|
||||
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
||||
(element: HTMLElement): any => {
|
||||
@ -116,7 +114,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
chooseSelected,
|
||||
update,
|
||||
hasSelected,
|
||||
disable,
|
||||
};
|
||||
|
||||
return api;
|
||||
@ -141,14 +138,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
setSelected(index);
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(() => dropdown?.dispose());
|
||||
</script>
|
||||
|
||||
<WithDropdown {drop} toggleOpen={false} let:createDropdown>
|
||||
<slot createAutocomplete={createAutocomplete(createDropdown)} {disabled} />
|
||||
<slot createAutocomplete={createAutocomplete(createDropdown)} />
|
||||
|
||||
<DropdownMenu class={className}>
|
||||
<DropdownMenu class={className} {show}>
|
||||
{#each suggestionsItems as suggestion, index}
|
||||
<AutocompleteItem
|
||||
selected={index === selected}
|
||||
|
Loading…
Reference in New Issue
Block a user