Switch WithAutocomplete to WithDropdown and fix SelectedTagBadge

This commit is contained in:
Henrik Giesel 2021-07-01 20:26:41 +02:00
parent 874a315f83
commit 3dff89fda5
5 changed files with 37 additions and 99 deletions

View File

@ -19,12 +19,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
});
let dropdown: Dropdown;
let dropdownObject: Dropdown;
let api: Dropdown & { isVisible: () => boolean };
function isVisible() {
return (dropdown as any)._menu
? (dropdown as any)._menu.classList.contains("show")
: false;
}
const noop = () => {};
function createDropdown(toggle: HTMLElement): Dropdown {
/* avoid focusing element toggle on menu activation */
toggle.focus = noop;
dropdown = new Dropdown(toggle, {
autoClose,
popperConfig: (defaultConfig: Record<string, any>) => ({
@ -37,22 +44,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
dropdown.show();
}
dropdownObject = {
let api = {
show: dropdown.show.bind(dropdown),
toggle: dropdown.toggle.bind(dropdown),
hide: dropdown.hide.bind(dropdown),
update: dropdown.update.bind(dropdown),
dispose: dropdown.dispose.bind(dropdown),
isVisible,
};
return dropdownObject;
return api;
}
onDestroy(() => dropdown?.dispose());
</script>
<div class="dropdown">
<slot {createDropdown} {dropdownObject} />
<slot {createDropdown} dropdownObject={api} />
</div>
<style lang="scss">

View File

@ -1,60 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import Dropdown from "bootstrap/js/dist/dropdown";
import { setContext } from "svelte";
import { dropdownKey } from "./contextKeys";
export let disabled = false;
export let toggleOnClick = true;
setContext(dropdownKey, {
dropdown: true,
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
});
const menuId = Math.random().toString(36).substring(2);
let dropdown: Dropdown | undefined;
function activateDropdown(): void {
if (dropdown && !disabled) {
dropdown.toggle();
}
}
function isVisible(): boolean {
return (dropdown as any)._menu.classList.contains("show");
}
/* Normally dropdown and trigger are associated with a
/* common ancestor with .dropdown class */
function createDropdown(element: HTMLElement): Dropdown {
/* Prevent focus on menu activation */
const noop = () => {};
Object.defineProperty(element, "focus", { value: noop, configurable: true });
const menu = (element.getRootNode() as Document | ShadowRoot).getElementById(
menuId
);
if (!menu) {
throw Error(`Could not find menu "${menuId}" for dropdown menu.`);
}
if (!toggleOnClick) {
(Dropdown.prototype as any)._addEventListeners = noop;
}
dropdown = new Dropdown(element);
/* Set custom menu without using common element with .dropdown */
(dropdown as any)._menu = menu;
Object.defineProperty(dropdown, "isVisible", { value: isVisible });
return dropdown as Dropdown;
}
</script>
<slot {createDropdown} {activateDropdown} {menuId} />

View File

@ -6,7 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { createEventDispatcher } from "svelte";
import Badge from "components/Badge.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
import WithDropdown from "components/WithDropdown.svelte";
import WithShortcut from "components/WithShortcut.svelte";
import DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte";
@ -20,15 +20,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const removeLabel = "Remove tags";
</script>
<WithDropdownMenu let:menuId let:createDropdown>
<div class="dropdown">
<div class="more-icon">
<Badge class="me-1" on:mount={withSpan(createDropdown)}
>{@html dotsIcon}</Badge
>
</div>
<WithDropdown let:createDropdown>
<div class="more-icon">
<Badge class="me-1" on:mount={withSpan(createDropdown)}>{@html dotsIcon}</Badge>
<DropdownMenu id={menuId}>
<DropdownMenu>
<WithShortcut shortcut="C" let:createShortcut let:shortcutLabel>
<DropdownItem
on:click={() => dispatch("tagcopy")}
@ -45,7 +41,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</WithShortcut>
</DropdownMenu>
</div>
</WithDropdownMenu>
</WithDropdown>
<style lang="scss">
.more-icon {

View File

@ -33,6 +33,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let activeName = "";
let activeInput: HTMLInputElement;
let autocomplete: any;
let suggestionsPromise: Promise<string[]> = Promise.resolve([]);
function updateSuggestions(): void {
@ -104,8 +105,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
async function enterBehavior(
index: number,
start: number,
end: number,
autocomplete: any
end: number
): Promise<void> {
if (autocomplete.isVisible()) {
autocomplete.chooseSelected();
@ -227,7 +227,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
return event.code === "Backspace" || event.code === "Delete";
}
function onKeydown(event: KeyboardEvent, autocomplete: any): void {
function onKeydown(event: KeyboardEvent): void {
const visible = autocomplete.isVisible();
const printable = isPrintableKey(event);
const deletion = isDeletionKey(event);
@ -274,7 +274,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
}
function onKeyup(_event: KeyboardEvent, autocomplete: any): void {
function onKeyup(_event: KeyboardEvent): void {
if (activeName.length === 0) {
autocomplete.hide();
}
@ -384,7 +384,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
onAutocomplete(detail.selected)}
on:choose={({ detail }) => onChosen(detail.chosen)}
let:createAutocomplete
let:autocomplete
>
<TagInput
id={tag.id}
@ -392,18 +391,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:input={activeInput}
on:focus={() => {
activeName = tag.name;
createAutocomplete(activeInput);
autocomplete = createAutocomplete(activeInput);
}}
on:keydown={(event) => onKeydown(event, autocomplete)}
on:keyup={(event) => onKeyup(event, autocomplete)}
on:keydown={onKeydown}
on:keyup={onKeyup}
on:input={() => updateTagName(tag)}
on:tagsplit={({ detail }) =>
enterBehavior(
index,
detail.start,
detail.end,
autocomplete
)}
enterBehavior(index, detail.start, detail.end)}
on:tagadd={() => insertTag(index)}
on:tagdelete={() => deleteTagAt(index)}
on:tagjoinprevious={() => joinWithPreviousTag(index)}

View File

@ -7,7 +7,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type Dropdown from "bootstrap/js/dist/dropdown";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
import WithDropdown from "components/WithDropdown.svelte";
import DropdownMenu from "components/DropdownMenu.svelte";
import AutocompleteItem from "./AutocompleteItem.svelte";
@ -18,7 +18,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
let target: HTMLElement;
let dropdown: Dropdown;
let autocomplete: any;
let selected: number | null = null;
let active: boolean = false;
@ -82,10 +81,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
(element: HTMLElement): any => {
target = element;
dropdown = createDropdown(element);
autocomplete = {
hide: dropdown.hide.bind(dropdown),
show: dropdown.show.bind(dropdown),
toggle: dropdown.toggle.bind(dropdown),
const api = {
hide: dropdown.hide,
show: dropdown.show,
toggle: dropdown.toggle,
isVisible: (dropdown as any).isVisible,
selectPrevious,
selectNext,
@ -93,7 +93,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
update,
};
return autocomplete;
return api;
};
onDestroy(() => dropdown?.dispose());
@ -114,10 +114,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
</script>
<WithDropdownMenu toggleOnClick={false} let:menuId let:createDropdown>
<slot createAutocomplete={createAutocomplete(createDropdown)} {autocomplete} />
<WithDropdown let:createDropdown>
<slot createAutocomplete={createAutocomplete(createDropdown)} />
<DropdownMenu id={menuId} class={className}>
<DropdownMenu class={className}>
{#await suggestionsPromise}
<AutocompleteItem>...</AutocompleteItem>
{:then suggestions}
@ -132,4 +132,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{/each}
{/await}
</DropdownMenu>
</WithDropdownMenu>
</WithDropdown>