84 lines
1.9 KiB
Svelte
84 lines
1.9 KiB
Svelte
<script lang="ts">
|
|
import Icon from '@iconify/svelte';
|
|
import { getButtonStyle, parseColorText, getSegmentStyle } from './utils';
|
|
import type { TerminalLine } from './types';
|
|
import '$lib/assets/css/tui-link.css';
|
|
|
|
export let line: TerminalLine;
|
|
export let onClick: () => void;
|
|
|
|
// Determine if this is an external link
|
|
$: isExternal = line.external || (line.href && (line.href.startsWith('http://') || line.href.startsWith('https://')));
|
|
|
|
// Parse color formatting in content
|
|
$: segments = parseColorText(line.content);
|
|
</script>
|
|
|
|
<span class="tui-link" style="--link-color: {getButtonStyle(line.style)}">
|
|
{#if line.icon}
|
|
<Icon icon={line.icon} width="14" class="link-icon" />
|
|
{/if}
|
|
<button class="link-text" on:click={onClick}>
|
|
{#each segments as segment}
|
|
{#if segment.icon}
|
|
<Icon icon={segment.icon} width="14" class="inline-icon" />
|
|
{:else if getSegmentStyle(segment)}
|
|
<span style={getSegmentStyle(segment)}>{segment.text}</span>
|
|
{:else}
|
|
{segment.text}
|
|
{/if}
|
|
{/each}
|
|
</button>
|
|
{#if isExternal}
|
|
<Icon icon="mdi:open-in-new" width="12" class="link-external" />
|
|
{/if}
|
|
</span>
|
|
|
|
<style>
|
|
.tui-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
:global(.link-icon) {
|
|
color: var(--link-color);
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.link-text {
|
|
background: none;
|
|
border: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
font-family: inherit;
|
|
font-size: inherit;
|
|
color: var(--link-color);
|
|
text-decoration: underline;
|
|
text-decoration-style: dotted;
|
|
text-underline-offset: 2px;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.link-text:hover {
|
|
text-decoration-style: solid;
|
|
filter: brightness(1.2);
|
|
}
|
|
|
|
:global(.link-external) {
|
|
color: var(--link-color);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.tui-link:hover :global(.link-external) {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
:global(.inline-icon) {
|
|
display: inline-block;
|
|
vertical-align: middle;
|
|
margin: 0 0.15em;
|
|
}
|
|
</style>
|