mirror of
https://github.com/ankitects/anki.git
synced 2025-11-11 15:17:12 -05:00
Add SelectedTagBadge to offer context items for selected tags
This commit is contained in:
parent
00de99880b
commit
874a315f83
5 changed files with 107 additions and 3 deletions
|
|
@ -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;
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ copy_mdi_icons(
|
|||
"tag-outline.svg",
|
||||
"tag.svg",
|
||||
"tag-plus.svg",
|
||||
"dots-vertical.svg",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
|
|
|||
64
ts/editor/SelectedTagBadge.svelte
Normal file
64
ts/editor/SelectedTagBadge.svelte
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import Badge from "components/Badge.svelte";
|
||||
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
|
||||
import WithShortcut from "components/WithShortcut.svelte";
|
||||
import DropdownMenu from "components/DropdownMenu.svelte";
|
||||
import DropdownItem from "components/DropdownItem.svelte";
|
||||
|
||||
import { withSpan, withButton } from "components/helpers";
|
||||
import { appendInParentheses } from "./helpers";
|
||||
import { dotsIcon } from "./icons";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const copyLabel = "Copy tags";
|
||||
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>
|
||||
|
||||
<DropdownMenu id={menuId}>
|
||||
<WithShortcut shortcut="C" let:createShortcut let:shortcutLabel>
|
||||
<DropdownItem
|
||||
on:click={() => dispatch("tagcopy")}
|
||||
on:mount={withButton(createShortcut)}
|
||||
>{appendInParentheses(copyLabel, shortcutLabel)}</DropdownItem
|
||||
>
|
||||
</WithShortcut>
|
||||
<WithShortcut shortcut="Backspace" let:createShortcut let:shortcutLabel>
|
||||
<DropdownItem
|
||||
on:click={() => dispatch("tagdelete")}
|
||||
on:mount={withButton(createShortcut)}
|
||||
>{appendInParentheses(removeLabel, shortcutLabel)}</DropdownItem
|
||||
>
|
||||
</WithShortcut>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</WithDropdownMenu>
|
||||
|
||||
<style lang="scss">
|
||||
.more-icon {
|
||||
line-height: 1;
|
||||
|
||||
:global(svg) {
|
||||
cursor: pointer;
|
||||
fill: currentColor;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
:global(svg:hover) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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();
|
||||
}
|
||||
</script>
|
||||
|
||||
<StickyBottom>
|
||||
|
|
@ -330,8 +362,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
{size}
|
||||
on:focusout={deselectIfLeave}
|
||||
>
|
||||
<div class="pb-1">
|
||||
<div class="pb-1" on:mousedown|preventDefault>
|
||||
{#if tags.some((tag) => tag.selected)}
|
||||
<SelectedTagBadge
|
||||
on:tagcopy={copySelectedTags}
|
||||
on:tagdelete={deleteSelectedTags}
|
||||
/>
|
||||
{:else}
|
||||
<AddTagBadge on:click={appendEmptyTag} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#each tags as tag, index (tag.id)}
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
Loading…
Reference in a new issue