Decouple TagInput from TagAutocomplete completely

This commit is contained in:
Henrik Giesel 2021-06-25 18:09:58 +02:00
parent 8d95503189
commit 808d01c4fb
5 changed files with 81 additions and 39 deletions

View File

@ -11,7 +11,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export { className as class };
export let tooltip: string | undefined = undefined;
export let tabbable: boolean = true;
export let tabbable: boolean = false;
let buttonRef: HTMLButtonElement;
@ -54,7 +54,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
.btn-day {
color: black;
&:active {
&:active,
&.active {
background-color: button.$focus-color;
color: white;
}
@ -64,11 +65,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
color: white;
&:hover,
&:focus {
&:focus,
&.focus {
@include button.btn-night-base;
}
&:active {
&:active,
&.active {
background-color: button.$focus-color;
color: white;
}

View File

@ -0,0 +1,51 @@
<!--
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;
setContext(dropdownKey, {
dropdown: true,
"data-bs-toggle": "dropdown",
"aria-expanded": "false",
});
const menuId = Math.random().toString(36).substring(2);
let dropdown: Dropdown;
function activateDropdown(): void {
if (!disabled) {
dropdown.toggle();
}
}
/* 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 });
const menu = (element.getRootNode() as Document) /* or shadow root */
.getElementById(menuId);
if (!menu) {
console.log(`Could not find menu "${menuId}" for dropdown menu.`);
} else {
dropdown = new Dropdown(element);
/* Set custom menu without using common element with .dropdown */
(dropdown as any)._menu = menu;
}
return dropdown;
}
</script>
<slot {createDropdown} {activateDropdown} {menuId} />

View File

@ -4,10 +4,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import ButtonToolbar from "components/ButtonToolbar.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
import DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte";
export const suggestions = ["en::idioms", "anki::functionality", "math"];
export let suggestions: string[];
export let size: number;
let className: string = "";
@ -29,22 +30,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
event.preventDefault();
}
}
function updateActiveItem(event: FocusEvent): void {
event.preventDefault();
}
</script>
<ButtonToolbar class={`dropup ${className}`} {size}>
<slot />
<WithDropdownMenu let:menuId let:createDropdown let:activateDropdown>
<slot {createDropdown} {activateDropdown} />
<DropdownMenu class="d-flex flex-column-reverse">
{#each suggestions as tag}
<DropdownItem
tabbable={false}
on:focus={updateActiveItem}
on:keydown={switchUpDown}>{tag}</DropdownItem
>
{/each}
</DropdownMenu>
<DropdownMenu id={menuId} class="d-flex flex-column-reverse">
{#each suggestions as tag}
<DropdownItem on:keydown={switchUpDown}>{tag}</DropdownItem>
{/each}
</DropdownMenu>
</WithDropdownMenu>
</ButtonToolbar>

View File

@ -12,6 +12,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { attachId, getName } from "./tags";
export let initialNames = ["en::foobar", "test", "def"];
export let suggestions = ["en::idioms", "anki::functionality", "math"];
export let size = isApplePlatform() ? 1.6 : 2.0;
let tags = initialNames.map(attachId);
@ -90,7 +92,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<StickyBottom>
<div class="row-gap">
<TagAutocomplete class="d-flex flex-wrap align-items-center" {size}>
<TagAutocomplete
class="d-flex flex-wrap align-items-center"
{suggestions}
{size}
let:createDropdown
let:activateDropdown
>
<AddTagBadge on:click={focusNewInput} />
{#each tags as tag, index (tag.id)}
@ -107,6 +115,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<TagInput
bind:input={newInput}
bind:name={newName}
on:focus={(event) => createDropdown(event.currentTarget)}
on:tagupdate={appendTag}
on:tagadd={appendTag}
on:tagjoinprevious={joinWithLastTag}

View File

@ -6,27 +6,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { createEventDispatcher, onMount } from "svelte";
import { normalizeTagname } from "./tags";
import TagAutocomplete from "./TagAutocomplete.svelte";
export let name: string;
export let input: HTMLInputElement;
const dispatch = createEventDispatcher();
function onFocus(): void {
/* dropdown.show(); */
}
function onAccept(): void {
name = normalizeTagname(name);
dispatch("tagupdate", { name });
}
function dropdownBlur(): void {
onAccept();
/* dropdown.hide(); */
}
function onBackspace(event: KeyboardEvent) {
if (input.selectionStart === 0 && input.selectionEnd === 0) {
dispatch("tagjoinprevious");
@ -99,21 +88,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
onMount(() => dispatch("mount", { input }));
</script>
<label
class="ps-2 pe-1"
data-value={name}
data-bs-toggle="dropdown"
aria-expanded="false"
>
<label class="ps-2 pe-1" data-value={name}>
<input
bind:this={input}
type="text"
tabindex="-1"
size="1"
bind:value={name}
on:focus={onFocus}
on:blur={dropdownBlur}
on:focus
on:focusout
on:blur={onAccept}
on:keydown={onKeydown}
on:paste={onPaste}
on:click