Use our DropdownMenu component for TagAutocomplete
This commit is contained in:
parent
50519ea5c8
commit
3ad86dfb33
@ -7,11 +7,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
import { dropdownKey } from "./context-keys";
|
import { dropdownKey } from "./context-keys";
|
||||||
|
|
||||||
export let id: string | undefined = undefined;
|
export let id: string | undefined = undefined;
|
||||||
|
export let labelledby: string | undefined = undefined;
|
||||||
|
|
||||||
setContext(dropdownKey, null);
|
setContext(dropdownKey, null);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div {id} class="dropdown-menu">
|
<div {id} class="dropdown-menu" aria-labelledby={labelledby}>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -17,10 +17,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
|
|
||||||
function checkForActivation(): void {
|
function checkForActivation(): void {
|
||||||
const selection = window.getSelection()!;
|
const selection = window.getSelection()!;
|
||||||
if (selection.isCollapsed) {
|
active = selection.isCollapsed;
|
||||||
active = true;
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTag(event: Event): void {
|
function deleteTag(event: Event): void {
|
||||||
|
@ -4,28 +4,22 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
-->
|
-->
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { createEventDispatcher, onMount, onDestroy } from "svelte";
|
import { createEventDispatcher, onMount, onDestroy } from "svelte";
|
||||||
import Dropdown from "bootstrap/js/dist/dropdown";
|
|
||||||
|
import DropdownMenu from "components/DropdownMenu.svelte";
|
||||||
|
import DropdownItem from "components/DropdownItem.svelte";
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
|
export const suggestions = ["en::idioms", "anki::functionality", "math"];
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const triggerId = "tagLabel" + String(Math.random()).slice(2);
|
const triggerId = "tagLabel" + String(Math.random()).slice(2);
|
||||||
const triggerClass = "dropdown-toggle";
|
const triggerClass = "dropdown-toggle";
|
||||||
|
|
||||||
let originalName = name;
|
|
||||||
let menu: HTMLDivElement;
|
let menu: HTMLDivElement;
|
||||||
let dropdown;
|
let dropdown;
|
||||||
let activeItem = -1;
|
let activeItem = -1;
|
||||||
|
|
||||||
const tagSuggestions = ["en::idioms", "anki::functionality", "math"];
|
$: tagValues = [...suggestions, name];
|
||||||
$: tagValues = [...tagSuggestions, originalName];
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const toggle = menu.querySelector(`#${triggerId}`)!;
|
|
||||||
dropdown = new Dropdown(toggle, {
|
|
||||||
reference: "parent",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function onItemClick(event: Event) {
|
function onItemClick(event: Event) {
|
||||||
dispatch("nameChosen", { name: event.currentTarget!.innerText });
|
dispatch("nameChosen", { name: event.currentTarget!.innerText });
|
||||||
@ -43,56 +37,33 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
name = tagValues[activeItem];
|
name = tagValues[activeItem];
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (event.code === "Enter") {
|
} else if (event.code === "Enter") {
|
||||||
const dropdownActive = dropdown._element.classList.contains("show");
|
/* const dropdownActive = dropdown._element.classList.contains("show"); */
|
||||||
if (dropdownActive) {
|
/* if (dropdownActive) { */
|
||||||
if (typeof activeItem === "number") {
|
/* if (typeof activeItem === "number") { */
|
||||||
name = tagValues[activeItem];
|
/* name = tagValues[activeItem]; */
|
||||||
activeItem = null;
|
/* activeItem = null; */
|
||||||
}
|
/* } */
|
||||||
dropdown.hide();
|
/* dropdown.hide(); */
|
||||||
} else {
|
/* } else { */
|
||||||
dispatch("accept");
|
/* dispatch("accept"); */
|
||||||
}
|
/* } */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="dropdown" bind:this={menu} on:keydown={onKeydown}>
|
<div bind:this={menu} class="dropdown dropdown-reverse" on:keydown={onKeydown}>
|
||||||
<slot {triggerId} {triggerClass} {dropdown} />
|
<slot {triggerId} {triggerClass} {dropdown} />
|
||||||
|
|
||||||
<ul class="dropdown-menu" aria-labelledby={triggerId}>
|
<DropdownMenu labelledby={triggerId}>
|
||||||
{#each tagSuggestions as tag, index}
|
{#each suggestions as tag}
|
||||||
<li>
|
<DropdownItem>{tag}</DropdownItem>
|
||||||
<a
|
|
||||||
href="#/"
|
|
||||||
class="dropdown-item"
|
|
||||||
class:dropdown-item-active={activeItem === index}
|
|
||||||
on:click={onItemClick}
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
:global(.show).dropdown-menu {
|
.dropdown-reverse :global(.dropdown-menu) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
.dropdown-item {
|
|
||||||
padding: 0rem 0.3rem;
|
|
||||||
font-size: smaller;
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.dropdown-item:hover {
|
|
||||||
background-color: #c3c5c7;
|
|
||||||
}
|
|
||||||
.dropdown-item-active {
|
|
||||||
color: #1e2125;
|
|
||||||
background-color: #c3c5c7;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -22,10 +22,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
tags = tags;
|
tags = tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTag({ detail }: CustomEvent) {
|
function addTag() {
|
||||||
if (!tags.includes(detail.name) && detail.name.length > 0) {
|
if (!tags.includes(newName) && newName.length > 0) {
|
||||||
tags.push(detail.name);
|
tags.push(newName);
|
||||||
}
|
}
|
||||||
|
newName = "";
|
||||||
tags = tags;
|
tags = tags;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -16,17 +16,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function onFocus(event: FocusEvent, dropdown: Dropdown): void {
|
function onFocus(event: FocusEvent, dropdown: Dropdown): void {
|
||||||
dropdown.show();
|
/* dropdown.show(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAccept(event: Event): void {
|
function onAccept(event: Event): void {
|
||||||
dispatch("tagupdate", { name: normalizeTagname(name) });
|
name = normalizeTagname(name);
|
||||||
input.value = "";
|
dispatch("tagupdate", { name });
|
||||||
}
|
}
|
||||||
|
|
||||||
function dropdownBlur(event: Event, dropdown: Dropdown): void {
|
function dropdownBlur(event: Event, dropdown: Dropdown): void {
|
||||||
onAccept(event);
|
onAccept(event);
|
||||||
dropdown.hide();
|
/* dropdown.hide(); */
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeydown(event: KeyboardEvent, dropdown: Dropdown): void {
|
function onKeydown(event: KeyboardEvent, dropdown: Dropdown): void {
|
||||||
|
Loading…
Reference in New Issue
Block a user