diff --git a/ts/components/WithDropdownMenu.svelte b/ts/components/WithDropdownMenu.svelte index 7d31c1f27..86c4666f5 100644 --- a/ts/components/WithDropdownMenu.svelte +++ b/ts/components/WithDropdownMenu.svelte @@ -53,7 +53,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html /* Set custom menu without using common element with .dropdown */ (dropdown as any)._menu = menu; Object.defineProperty(dropdown, "isVisible", { value: isVisible }); - return dropdown as Dropdown; } diff --git a/ts/editor/BUILD.bazel b/ts/editor/BUILD.bazel index c2f4705fb..2d25e998c 100644 --- a/ts/editor/BUILD.bazel +++ b/ts/editor/BUILD.bazel @@ -134,6 +134,7 @@ copy_mdi_icons( "tag-outline.svg", "tag.svg", "tag-plus.svg", + "dots-vertical.svg", ], visibility = ["//visibility:public"], ) diff --git a/ts/editor/SelectedTagBadge.svelte b/ts/editor/SelectedTagBadge.svelte new file mode 100644 index 000000000..596edc84f --- /dev/null +++ b/ts/editor/SelectedTagBadge.svelte @@ -0,0 +1,64 @@ + + + + + + + + diff --git a/ts/editor/TagEditor.svelte b/ts/editor/TagEditor.svelte index 431a51b17..7e7c6f8c4 100644 --- a/ts/editor/TagEditor.svelte +++ b/ts/editor/TagEditor.svelte @@ -8,6 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { bridgeCommand } from "lib/bridgecommand"; import StickyBottom from "components/StickyBottom.svelte"; import AddTagBadge from "./AddTagBadge.svelte"; + import SelectedTagBadge from "./SelectedTagBadge.svelte"; import Tag from "./Tag.svelte"; import TagInput from "./TagInput.svelte"; import WithAutocomplete from "./WithAutocomplete.svelte"; @@ -322,6 +323,37 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html deselect(); } } + + /* TODO replace with navigator.clipboard once available */ + function copyToClipboard(content: string): void { + const textarea = document.createElement("textarea"); + textarea.value = content; + textarea.setAttribute("readonly", ""); + textarea.style.position = "absolute"; + textarea.style.left = "-9999px"; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); + } + + function copySelectedTags() { + const content = tags + .filter((tag) => tag.selected) + .map((tag) => tag.name) + .join("\n"); + copyToClipboard(content); + deselect(); + } + + function deleteSelectedTags() { + tags.map((tag, index) => [tag.selected, index]) + .filter(([selected]) => selected) + .reverse() + .forEach(([, index]) => deleteTagAt(index as number)); + deselect(); + saveTags(); + } @@ -330,8 +362,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html {size} on:focusout={deselectIfLeave} > -
- +
+ {#if tags.some((tag) => tag.selected)} + + {:else} + + {/if}
{#each tags as tag, index (tag.id)} diff --git a/ts/editor/icons.ts b/ts/editor/icons.ts index a693c87c3..7386dcb2c 100644 --- a/ts/editor/icons.ts +++ b/ts/editor/icons.ts @@ -33,6 +33,7 @@ export { default as xmlIcon } from "./xml.svg"; export { default as tagIcon } from "./tag.svg"; export { default as addTagIcon } from "./tag-plus.svg"; +export { default as dotsIcon } from "./dots-vertical.svg"; export { default as deleteIcon } from "./x.svg"; export const arrowIcon =