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

View File

@@ -1,23 +1,23 @@
<script lang="ts">
import { parseColorText, getPlainText } from './utils';
import { themeColors } from '$lib/stores/theme';
import TuiLine from './TuiLine.svelte';
import type { TerminalLine } from './types';
import { parseColorText, getPlainText } from "./utils";
import { themeColors } from "$lib/stores/theme";
import TuiLine from "./TuiLine.svelte";
import type { GroupLine } from "./types";
interface Props {
line: TerminalLine;
line: GroupLine;
inline?: boolean;
onButtonClick?: (idx: number) => void;
onHoverButton?: (idx: number) => void;
onLinkClick?: (idx: number) => void;
}
let {
line,
let {
line,
inline = false,
onButtonClick = () => {},
onHoverButton = () => {},
onLinkClick = () => {}
onLinkClick = () => {},
}: Props = $props();
// Get colorMap from current theme
@@ -25,33 +25,50 @@
// Parse children with current colorMap
const parsedChildren = $derived(
(line.children || []).map(child => {
(line.children || []).map((child) => {
const segments = parseColorText(child.content, colorMap);
return { line: child, segments, plainText: getPlainText(segments) };
})
}),
);
// Style for the group container
const groupStyle = $derived(() => {
const styles: string[] = [];
if (line.groupDirection === 'column') styles.push('flex-direction: column');
if (line.groupAlign) {
const alignMap: Record<string, string> = { start: 'flex-start', center: 'center', end: 'flex-end' };
styles.push(`align-items: ${alignMap[line.groupAlign] || 'flex-start'}`);
// Only apply flex styles if not grid or block
if (line.display !== "grid" && line.display !== "block") {
if (line.groupDirection === "column")
styles.push("flex-direction: column");
if (line.groupAlign) {
const alignMap: Record<string, string> = {
start: "flex-start",
center: "center",
end: "flex-end",
};
styles.push(
`align-items: ${alignMap[line.groupAlign] || "flex-start"}`,
);
}
}
if (line.groupGap) styles.push(`gap: ${line.groupGap}`);
return styles.join('; ');
return styles.join("; ");
});
</script>
<div class="tui-group" class:inline style={groupStyle()} id={line.id}>
<div
class="tui-group"
class:inline
class:grid={line.display === "grid"}
class:block={line.display === "block"}
style={groupStyle()}
id={line.id}
>
{#each parsedChildren as parsed, idx (idx)}
<TuiLine
line={parsed.line}
index={idx}
segments={parsed.segments}
complete={true}
showImage={parsed.line.type === 'image'}
showImage={parsed.line.type === "image"}
selectedIndex={-1}
inline={parsed.line.inline !== false}
{onButtonClick}
@@ -74,9 +91,26 @@
display: inline-flex;
}
.tui-group.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
width: 100%;
}
.tui-group.block {
display: block;
width: 100%;
}
@keyframes lineSlideIn {
from { opacity: 0; transform: translateX(-5px); }
to { opacity: 1; transform: translateX(0); }
from {
opacity: 0;
transform: translateX(-5px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@media (max-width: 768px) {
@@ -84,5 +118,9 @@
flex-direction: column;
align-items: stretch;
}
.tui-group.grid {
grid-template-columns: 1fr;
}
}
</style>