124 lines
2.7 KiB
Svelte
124 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
import Icon from "../utils/Icon.svelte";
|
|
import { fade } from "svelte/transition";
|
|
|
|
export let title: string | undefined = undefined;
|
|
export let content: string;
|
|
export let buttonMode: boolean = false;
|
|
|
|
let contentNode: HTMLElement;
|
|
let copiedOverlay: HTMLElement;
|
|
|
|
|
|
function selectAll() {
|
|
const selection = window.getSelection();
|
|
if (contentNode && selection) {
|
|
selection.selectAllChildren(contentNode);
|
|
}
|
|
}
|
|
|
|
function copy() {
|
|
const selection = window.getSelection();
|
|
if (contentNode && selection) {
|
|
selectAll();
|
|
navigator.clipboard.writeText(contentNode.innerText);
|
|
showOverlay();
|
|
}
|
|
}
|
|
|
|
let showCopiedOverlay = false;
|
|
function showOverlay() {
|
|
showCopiedOverlay = true;
|
|
}
|
|
function releaseOverlay() {
|
|
showCopiedOverlay = false;
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import "../../scss/helpers";
|
|
.copyable-text {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: row;
|
|
margin: 8px;
|
|
padding: 0;
|
|
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
|
|
.title {
|
|
padding: 8px;
|
|
}
|
|
|
|
.content {
|
|
width: 0;
|
|
flex-grow: 1;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
padding: 8px;
|
|
}
|
|
|
|
.copy-button {
|
|
margin: 0;
|
|
padding: 0;
|
|
border-radius: 0;
|
|
|
|
:global(.icon) {
|
|
--icon-size: 20px;
|
|
margin: 8px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.button-mode-button {
|
|
position: relative;
|
|
}
|
|
|
|
.copied-overlay {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 8px;
|
|
|
|
text-align: center;
|
|
background-color: var(--success);
|
|
}
|
|
|
|
.content.hidden {
|
|
pointer-events: none;
|
|
overflow: hidden;
|
|
width: 0;
|
|
height: 0;
|
|
margin: 0;
|
|
padding: 0;
|
|
position: absolute;
|
|
}
|
|
</style>
|
|
|
|
|
|
{#if buttonMode}
|
|
<div class="content hidden" bind:this={contentNode} on:click={selectAll}>{content}</div>
|
|
<button class="bold button-mode-button" on:click={copy} title="{content}">
|
|
<Icon name="copy"/>
|
|
|
|
{#if showCopiedOverlay}
|
|
<div class="copied-overlay" bind:this={copiedOverlay} out:fade on:mouseleave={releaseOverlay}><Icon name="check"/></div>
|
|
{/if}
|
|
</button>
|
|
{:else}
|
|
<div class="copyable-text panel">
|
|
{#if title}
|
|
<div class="title">{title}</div>
|
|
{/if}
|
|
<div class="content" bind:this={contentNode} on:click={selectAll}>{content}</div>
|
|
<button class="bold copy-button" on:click={copy}><Icon name="copy"/></button>
|
|
|
|
{#if showCopiedOverlay}
|
|
<div class="copied-overlay" bind:this={copiedOverlay} out:fade on:mouseleave={releaseOverlay}>Copied!</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|