Decouple Autocomplete from TagInput:

Allows to only have one autocompletion for all tags, rather than every
tag having its own
This commit is contained in:
Henrik Giesel 2021-06-25 15:44:44 +02:00
parent c5b10c1117
commit 1ba6909495
4 changed files with 72 additions and 73 deletions

View File

@ -16,23 +16,30 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<WithShortcut shortcut="Control+Shift+T" let:createShortcut let:shortcutLabel>
<Badge
class="add-icon d-flex me-1"
tooltip={appendInParentheses(tooltip, shortcutLabel)}
on:click
on:mouseenter={() => (theTagIcon = addTagIcon)}
on:mouseleave={() => (theTagIcon = tagIcon)}
on:mount={withSpan(createShortcut)}>{@html theTagIcon}</Badge
>
<div class="add-icon">
<Badge
class="me-1"
tooltip={appendInParentheses(tooltip, shortcutLabel)}
on:click
on:mouseenter={() => (theTagIcon = addTagIcon)}
on:mouseleave={() => (theTagIcon = tagIcon)}
on:mount={withSpan(createShortcut)}>{@html theTagIcon}</Badge
>
</div>
</WithShortcut>
<style lang="scss">
:global(.add-icon > svg) {
cursor: pointer;
opacity: 0.6;
}
.add-icon {
line-height: 1;
:global(.add-icon > svg:hover) {
opacity: 1;
:global(svg) {
cursor: pointer;
fill: currentColor;
opacity: 0.6;
}
:global(svg:hover) {
opacity: 1;
}
}
</style>

View File

@ -8,8 +8,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export const suggestions = ["en::idioms", "anki::functionality", "math"];
const triggerId = "tagLabel" + String(Math.random()).slice(2);
const triggerClass = "dropdown-toggle";
let className: string = "";
export { className as class };
let menu: HTMLDivElement;
@ -33,10 +33,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function updateActiveItem(even: FocusEvent): void {}
</script>
<div bind:this={menu} class="dropup dropdown-reverse">
<slot {triggerId} {triggerClass} />
<div bind:this={menu} class={`dropup dropdown-reverse ${className}`}>
<slot />
<DropdownMenu labelledby={triggerId}>
<DropdownMenu>
{#each suggestions as tag}
<DropdownItem on:focus={updateActiveItem} on:keydown={switchUpDown}
>{tag}</DropdownItem

View File

@ -6,6 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import StickyBottom from "components/StickyBottom.svelte";
import AddTagBadge from "./AddTagBadge.svelte";
import Tag from "./Tag.svelte";
import TagAutocomplete from "./TagAutocomplete.svelte";
import TagInput from "./TagInput.svelte";
import { attachId, getName } from "./tags";
@ -86,33 +87,38 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script>
<StickyBottom>
<div class="d-flex flex-wrap">
<AddTagBadge on:click={focusNewInput} />
<div class="font-size-13 row-gap">
<TagAutocomplete class="d-flex flex-wrap align-items-center row-gap">
<AddTagBadge on:click={focusNewInput} />
{#each tags as tag, index (tag.id)}
<Tag
bind:name={tag.name}
on:tagupdate={() => checkForDuplicateAt(index)}
on:tagadd={() => insertTagAt(index)}
on:tagdelete={() => deleteTagAt(index)}
on:tagjoinprevious={() => joinWithPreviousTag(index)}
on:tagjoinnext={() => joinWithNextTag(index)}
{#each tags as tag, index (tag.id)}
<Tag
bind:name={tag.name}
on:tagupdate={() => checkForDuplicateAt(index)}
on:tagadd={() => insertTagAt(index)}
on:tagdelete={() => deleteTagAt(index)}
on:tagjoinprevious={() => joinWithPreviousTag(index)}
on:tagjoinnext={() => joinWithNextTag(index)}
/>
{/each}
<TagInput
bind:input={newInput}
bind:name={newName}
on:tagupdate={appendTag}
on:tagadd={appendTag}
on:tagjoinprevious={joinWithLastTag}
/>
{/each}
<TagInput
bind:input={newInput}
bind:name={newName}
on:tagupdate={appendTag}
on:tagadd={appendTag}
on:tagjoinprevious={joinWithLastTag}
/>
</TagAutocomplete>
</div>
</StickyBottom>
<style lang="scss">
div {
.font-size-13 {
font-size: 13px;
fill: currentColor;
}
.row-gap > :global(.d-flex > *) {
margin-bottom: 2px;
}
</style>

View File

@ -96,43 +96,29 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
}
function setTagname({ detail }: CustomEvent): void {
name = detail.name;
}
onMount(() => dispatch("mount", { input }));
</script>
<TagAutocomplete
bind:name
let:triggerId
let:triggerClass
on:nameChosen={setTagname}
on:accept={onAccept}
<label
class="ps-2 pe-1"
data-value={name}
data-bs-toggle="dropdown"
aria-expanded="false"
>
<label
id={triggerId}
class={`ps-2 pe-1 ${triggerClass}`}
data-value={name}
data-bs-toggle="dropdown"
aria-expanded="false"
data-bs-reference="parent"
>
<input
bind:this={input}
type="text"
tabindex="-1"
size="1"
bind:value={name}
on:focus={onFocus}
on:blur={dropdownBlur}
on:focusout
on:keydown={onKeydown}
on:paste={onPaste}
on:click
/>
</label>
</TagAutocomplete>
<input
bind:this={input}
type="text"
tabindex="-1"
size="1"
bind:value={name}
on:focus={onFocus}
on:blur={dropdownBlur}
on:focusout
on:keydown={onKeydown}
on:paste={onPaste}
on:click
/>
</label>
<style lang="scss">
label {