mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 22:42:25 -04:00
Bubble up some functionality from Tag to TagWithTooltip and TagDeleteBadge
This commit is contained in:
parent
fd89f296dd
commit
4fc3e059be
4 changed files with 112 additions and 87 deletions
|
@ -5,23 +5,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { onMount, getContext, createEventDispatcher } from "svelte";
|
import { onMount, getContext, createEventDispatcher } from "svelte";
|
||||||
import { nightModeKey } from "components/context-keys";
|
import { nightModeKey } from "components/context-keys";
|
||||||
import Badge from "components/Badge.svelte";
|
|
||||||
import { deleteIcon } from "./icons";
|
|
||||||
import { controlPressed, shiftPressed } from "lib/keys";
|
|
||||||
|
|
||||||
let className: string = "";
|
let className: string = "";
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
export let name: string;
|
|
||||||
export let tooltip: string | undefined = undefined;
|
export let tooltip: string | undefined = undefined;
|
||||||
export let selected: boolean = false;
|
export let selected: boolean = false;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function deleteTag(): void {
|
|
||||||
dispatch("tagdelete");
|
|
||||||
}
|
|
||||||
|
|
||||||
let flashing: boolean = false;
|
let flashing: boolean = false;
|
||||||
|
|
||||||
export function flash(): void {
|
export function flash(): void {
|
||||||
|
@ -29,26 +21,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
setTimeout(() => (flashing = false), 300);
|
setTimeout(() => (flashing = false), 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
let control = false;
|
|
||||||
let shift = false;
|
|
||||||
|
|
||||||
function setDeleteIcon(event: KeyboardEvent | MouseEvent): void {
|
|
||||||
control = controlPressed(event);
|
|
||||||
shift = shiftPressed(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
$: selectMode = control || shift;
|
|
||||||
|
|
||||||
function onClick(): void {
|
|
||||||
if (shift) {
|
|
||||||
dispatch("tagrange");
|
|
||||||
} else if (control) {
|
|
||||||
dispatch("tagselect");
|
|
||||||
} else {
|
|
||||||
dispatch("tagedit");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const nightMode = getContext<boolean>(nightModeKey);
|
const nightMode = getContext<boolean>(nightModeKey);
|
||||||
|
|
||||||
let button: HTMLButtonElement;
|
let button: HTMLButtonElement;
|
||||||
|
@ -56,30 +28,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
onMount(() => dispatch("mount", { button }));
|
onMount(() => dispatch("mount", { button }));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:body on:keydown={setDeleteIcon} on:keyup={setDeleteIcon} />
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
bind:this={button}
|
bind:this={button}
|
||||||
class="tag btn d-inline-flex align-items-center text-nowrap ps-2 pe-1 {className}"
|
class="tag btn d-inline-flex align-items-center text-nowrap ps-2 pe-1 {className}"
|
||||||
class:selected
|
class:selected
|
||||||
class:flashing
|
class:flashing
|
||||||
class:select-mode={selectMode}
|
|
||||||
class:btn-day={!nightMode}
|
class:btn-day={!nightMode}
|
||||||
class:btn-night={nightMode}
|
class:btn-night={nightMode}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
on:mousemove={setDeleteIcon}
|
on:mousemove
|
||||||
on:click={onClick}
|
on:click
|
||||||
>
|
>
|
||||||
<span>{name}</span>
|
<slot />
|
||||||
<Badge
|
|
||||||
class="delete-icon rounded-circle d-flex align-items-center ms-1"
|
|
||||||
on:click={() => {
|
|
||||||
if (!selectMode) {
|
|
||||||
deleteTag();
|
|
||||||
}
|
|
||||||
}}>{@html deleteIcon}</Badge
|
|
||||||
>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -118,33 +79,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
animation: flash 0.3s linear;
|
animation: flash 0.3s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.select-mode {
|
|
||||||
cursor: crosshair;
|
|
||||||
|
|
||||||
&:hover :global(.delete-icon) {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
box-shadow: 0 0 0 2px var(--focus-shadow);
|
box-shadow: 0 0 0 2px var(--focus-shadow);
|
||||||
--border-color: var(--focus-border);
|
--border-color: var(--focus-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.delete-icon > svg:hover) {
|
|
||||||
$white-translucent: rgba(255 255 255 / 0.5);
|
|
||||||
$dark-translucent: rgba(0 0 0 / 0.2);
|
|
||||||
|
|
||||||
.btn-day & {
|
|
||||||
background-color: $dark-translucent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-night & {
|
|
||||||
background-color: $white-translucent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include button.btn-day(
|
@include button.btn-day(
|
||||||
$with-active: false,
|
$with-active: false,
|
||||||
$with-disabled: false,
|
$with-disabled: false,
|
||||||
|
|
15
ts/editor/TagDeleteBadge.svelte
Normal file
15
ts/editor/TagDeleteBadge.svelte
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!--
|
||||||
|
Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
-->
|
||||||
|
<script lang="typescript">
|
||||||
|
import Badge from "components/Badge.svelte";
|
||||||
|
import { deleteIcon } from "./icons";
|
||||||
|
|
||||||
|
let className: string = "";
|
||||||
|
export { className as class };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Badge class="rounded-circle d-flex align-items-center ms-1 {className}" on:click
|
||||||
|
>{@html deleteIcon}</Badge
|
||||||
|
>
|
|
@ -490,6 +490,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="position-relative tag-margins hide-tag zero-width-tag">
|
<div class="position-relative tag-margins hide-tag zero-width-tag">
|
||||||
|
<!-- makes sure footer does not resize when adding first tag -->
|
||||||
<Tag name="SPACER" />
|
<Tag name="SPACER" />
|
||||||
</div>
|
</div>
|
||||||
</ButtonToolbar>
|
</ButtonToolbar>
|
||||||
|
|
|
@ -5,7 +5,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import WithTooltip from "components/WithTooltip.svelte";
|
import WithTooltip from "components/WithTooltip.svelte";
|
||||||
import Tag from "./Tag.svelte";
|
import Tag from "./Tag.svelte";
|
||||||
|
import TagDeleteBadge from "./TagDeleteBadge.svelte";
|
||||||
|
|
||||||
|
import { createEventDispatcher, getContext } from "svelte";
|
||||||
|
import { nightModeKey } from "components/context-keys";
|
||||||
|
import { controlPressed, shiftPressed } from "lib/keys";
|
||||||
import { delimChar } from "./tags";
|
import { delimChar } from "./tags";
|
||||||
|
|
||||||
export let name: string;
|
export let name: string;
|
||||||
|
@ -20,6 +24,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
export let flash: () => void;
|
export let flash: () => void;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function deleteTag(): void {
|
||||||
|
dispatch("tagdelete");
|
||||||
|
}
|
||||||
|
|
||||||
|
let control = false;
|
||||||
|
let shift = false;
|
||||||
|
|
||||||
|
$: selectMode = control || shift;
|
||||||
|
|
||||||
|
function setDeleteIcon(event: KeyboardEvent | MouseEvent): void {
|
||||||
|
control = controlPressed(event);
|
||||||
|
shift = shiftPressed(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClick(): void {
|
||||||
|
if (shift) {
|
||||||
|
dispatch("tagrange");
|
||||||
|
} else if (control) {
|
||||||
|
dispatch("tagselect");
|
||||||
|
} else {
|
||||||
|
dispatch("tagedit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function processTagName(name: string): string {
|
function processTagName(name: string): string {
|
||||||
const parts = name.split(delimChar);
|
const parts = name.split(delimChar);
|
||||||
|
|
||||||
|
@ -33,33 +63,72 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
function hasMultipleParts(name: string): boolean {
|
function hasMultipleParts(name: string): boolean {
|
||||||
return name.split(delimChar).length > 1;
|
return name.split(delimChar).length > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onClickDelete() {
|
||||||
|
if (!selectMode) {
|
||||||
|
deleteTag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nightMode = getContext<boolean>(nightModeKey);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if active}
|
<svelte:body on:keydown={setDeleteIcon} on:keyup={setDeleteIcon} />
|
||||||
<Tag class={className} {name} />
|
|
||||||
{:else if shorten && hasMultipleParts(name)}
|
<div class:select-mode={selectMode} class:night-mode={nightMode}>
|
||||||
<WithTooltip {tooltip} placement="auto" let:createTooltip>
|
{#if active}
|
||||||
|
<Tag class={className} on:mousemove={setDeleteIcon} on:click={onClick}>
|
||||||
|
{name}
|
||||||
|
<TagDeleteBadge class="delete-icon" on:click={onClickDelete} />
|
||||||
|
</Tag>
|
||||||
|
{:else if shorten && hasMultipleParts(name)}
|
||||||
|
<WithTooltip {tooltip} placement="auto" let:createTooltip>
|
||||||
|
<Tag
|
||||||
|
class={className}
|
||||||
|
bind:flash
|
||||||
|
bind:selected
|
||||||
|
on:mousemove={setDeleteIcon}
|
||||||
|
on:click={onClick}
|
||||||
|
on:mount={(event) => createTooltip(event.detail.button)}
|
||||||
|
>
|
||||||
|
<span>{processTagName(name)}</span>
|
||||||
|
<TagDeleteBadge class="delete-icon" on:click={onClickDelete} />
|
||||||
|
</Tag>
|
||||||
|
</WithTooltip>
|
||||||
|
{:else}
|
||||||
<Tag
|
<Tag
|
||||||
class={className}
|
class={className}
|
||||||
name={processTagName(name)}
|
|
||||||
bind:flash
|
bind:flash
|
||||||
bind:selected
|
bind:selected
|
||||||
on:tagedit
|
on:mousemove={setDeleteIcon}
|
||||||
on:tagselect
|
on:click={onClick}
|
||||||
on:tagrange
|
>
|
||||||
on:tagdelete
|
<span>{name}</span>
|
||||||
on:mount={(event) => createTooltip(event.detail.button)}
|
<TagDeleteBadge class="delete-icon" on:click={onClickDelete} />
|
||||||
/>
|
</Tag>
|
||||||
</WithTooltip>
|
{/if}
|
||||||
{:else}
|
</div>
|
||||||
<Tag
|
|
||||||
class={className}
|
<style lang="scss">
|
||||||
{name}
|
.select-mode :global(button) {
|
||||||
bind:flash
|
display: contents;
|
||||||
bind:selected
|
cursor: crosshair;
|
||||||
on:tagedit
|
|
||||||
on:tagselect
|
:global(.delete-icon) {
|
||||||
on:tagrange
|
opacity: 0;
|
||||||
on:tagdelete
|
}
|
||||||
/>
|
}
|
||||||
{/if}
|
|
||||||
|
:global(.delete-icon):hover {
|
||||||
|
$white-translucent: rgba(255 255 255 / 0.5);
|
||||||
|
$dark-translucent: rgba(0 0 0 / 0.2);
|
||||||
|
|
||||||
|
div & {
|
||||||
|
background-color: $dark-translucent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.night-mode & {
|
||||||
|
background-color: $white-translucent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue