TUI Renderer, Element Types, and Page Updates

This commit is contained in:
2025-11-30 18:26:56 -05:00
parent f09c198f17
commit 1167c686e2
31 changed files with 1642 additions and 809 deletions
+75 -13
View File
@@ -1,17 +1,31 @@
<script lang="ts">
import Icon from '@iconify/svelte';
import { getButtonStyle, parseColorText, getSegmentStyle } from './utils';
import type { TerminalLine } from './types';
import '$lib/assets/css/tui-card.css';
import Icon from "@iconify/svelte";
import { getButtonStyle, parseColorText, getSegmentStyle } from "./utils";
import type { CardLine } from "./types";
import TuiLine from "./TuiLine.svelte";
import "$lib/assets/css/tui-card.css";
export let line: TerminalLine;
interface Props {
line: CardLine;
inline?: boolean;
}
$: segments = parseColorText(line.content);
$: titleSegments = line.cardTitle ? parseColorText(line.cardTitle) : [];
$: footerSegments = line.cardFooter ? parseColorText(line.cardFooter) : [];
let { line, inline = false }: Props = $props();
const segments = $derived(parseColorText(line.content));
const titleSegments = $derived(
line.cardTitle ? parseColorText(line.cardTitle) : [],
);
const footerSegments = $derived(
line.cardFooter ? parseColorText(line.cardFooter) : [],
);
</script>
<div class="tui-card" style="--card-accent: {getButtonStyle(line.style)}">
<div
class="tui-card"
class:inline
style="--card-color: {getButtonStyle(line.style)}"
>
{#if line.cardTitle}
<div class="card-header">
{#if line.icon}
@@ -20,7 +34,9 @@
<span class="card-title">
{#each titleSegments as segment}
{#if getSegmentStyle(segment)}
<span style={getSegmentStyle(segment)}>{segment.text}</span>
<span style={getSegmentStyle(segment)}
>{segment.text}</span
>
{:else}
{segment.text}
{/if}
@@ -28,10 +44,14 @@
</span>
</div>
{/if}
<div class="card-body">
{#if line.image}
<img src={line.image} alt={line.imageAlt || ''} class="card-image" />
<img
src={line.image}
alt={line.imageAlt || ""}
class="card-image"
/>
{/if}
<div class="card-content">
{#each segments as segment}
@@ -42,6 +62,25 @@
{/if}
{/each}
</div>
{#if line.children && line.children.length > 0}
<div
class="card-children"
class:flex={line.display === "flex"}
class:grid={line.display === "grid"}
>
{#each line.children as child, i}
<TuiLine
line={child}
index={i}
segments={parseColorText(child.content)}
complete={true}
showImage={true}
selectedIndex={-1}
inline={false}
/>
{/each}
</div>
{/if}
</div>
{#if line.cardFooter}
@@ -61,7 +100,11 @@
.tui-card {
border: 1px solid var(--terminal-border);
border-radius: 6px;
background: color-mix(in srgb, var(--terminal-bg) 80%, var(--card-accent) 5%);
background: color-mix(
in srgb,
var(--terminal-bg) 80%,
var(--card-accent) 5%
);
margin: 0.5rem 0;
overflow: hidden;
transition: border-color 0.2s ease;
@@ -109,6 +152,25 @@
white-space: pre-wrap;
}
.card-children {
margin-top: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.card-children.flex {
flex-direction: row;
flex-wrap: wrap;
gap: 1rem;
}
.card-children.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
.card-footer {
padding: 0.5rem 0.75rem;
border-top: 1px solid var(--terminal-border);