feat: Implement inline grouping for TuiLine components within TuiGroup, enhancing layout and music player UI.
This commit is contained in:
@@ -24,7 +24,8 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tui-inline-group:has(.inline-image) .inline-content {
|
.tui-inline-group:has(.inline-image) .inline-content,
|
||||||
|
.tui-inline-group:has(.inline-image) .tui-group {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,9 +94,7 @@
|
|||||||
<span class="card-title">
|
<span class="card-title">
|
||||||
{#each titleSegments as segment}
|
{#each titleSegments as segment}
|
||||||
{#if getSegmentStyle(segment)}
|
{#if getSegmentStyle(segment)}
|
||||||
<span style={getSegmentStyle(segment)}
|
<span style={getSegmentStyle(segment)}>{segment.text}</span>
|
||||||
>{segment.text}</span
|
|
||||||
>
|
|
||||||
{:else}
|
{:else}
|
||||||
{segment.text}
|
{segment.text}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -107,11 +105,7 @@
|
|||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{#if line.image}
|
{#if line.image}
|
||||||
<img
|
<img src={line.image} alt={line.imageAlt || ""} class="card-image" />
|
||||||
src={line.image}
|
|
||||||
alt={line.imageAlt || ""}
|
|
||||||
class="card-image"
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
{#each segments as segment}
|
{#each segments as segment}
|
||||||
@@ -249,7 +243,10 @@
|
|||||||
|
|
||||||
.card-children.grid {
|
.card-children.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
grid-template-columns: repeat(
|
||||||
|
auto-fill,
|
||||||
|
minmax(max(200px, calc((100% - 5rem) / 6)), 1fr)
|
||||||
|
);
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,47 @@
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Group consecutive inline elements
|
||||||
|
const processedChildren = $derived.by(() => {
|
||||||
|
const groups: Array<
|
||||||
|
| { kind: "single"; index: number; line: TerminalLine }
|
||||||
|
| {
|
||||||
|
kind: "inline";
|
||||||
|
items: Array<{ index: number; line: TerminalLine }>;
|
||||||
|
}
|
||||||
|
> = [];
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
while (i < parsedChildren.length) {
|
||||||
|
const child = parsedChildren[i];
|
||||||
|
const isInline = child.line.inline || child.line.display === "inline";
|
||||||
|
|
||||||
|
if (isInline) {
|
||||||
|
const inlineItems: Array<{
|
||||||
|
index: number;
|
||||||
|
line: TerminalLine;
|
||||||
|
}> = [];
|
||||||
|
while (i < parsedChildren.length) {
|
||||||
|
const nextChild = parsedChildren[i];
|
||||||
|
const nextIsInline =
|
||||||
|
nextChild.line.inline || nextChild.line.display === "inline";
|
||||||
|
if (!nextIsInline) break;
|
||||||
|
|
||||||
|
inlineItems.push({
|
||||||
|
index: i,
|
||||||
|
line: nextChild.line,
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
groups.push({ kind: "inline", items: inlineItems });
|
||||||
|
} else {
|
||||||
|
groups.push({ kind: "single", index: i, line: child.line });
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
});
|
||||||
|
|
||||||
// Style for the group container
|
// Style for the group container
|
||||||
const groupStyle = $derived(() => {
|
const groupStyle = $derived(() => {
|
||||||
const styles: string[] = [];
|
const styles: string[] = [];
|
||||||
@@ -64,20 +105,39 @@
|
|||||||
style={groupStyle()}
|
style={groupStyle()}
|
||||||
id={line.id}
|
id={line.id}
|
||||||
>
|
>
|
||||||
{#each parsedChildren as parsed, idx (idx)}
|
{#each processedChildren as group}
|
||||||
|
{#if group.kind === "inline"}
|
||||||
|
<div class="tui-inline-group">
|
||||||
|
{#each group.items as item}
|
||||||
<TuiLine
|
<TuiLine
|
||||||
line={parsed.line}
|
line={item.line}
|
||||||
index={idx}
|
index={item.index}
|
||||||
segments={parsed.segments}
|
segments={parseColorText(item.line.content)}
|
||||||
complete={true}
|
complete={true}
|
||||||
showImage={parsed.line.type === "image"}
|
showImage={item.line.type === "image"}
|
||||||
selectedIndex={-1}
|
selectedIndex={-1}
|
||||||
inline={parsed.line.inline !== false}
|
inline={true}
|
||||||
{onButtonClick}
|
{onButtonClick}
|
||||||
{onHoverButton}
|
{onHoverButton}
|
||||||
{onLinkClick}
|
{onLinkClick}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<TuiLine
|
||||||
|
line={group.line}
|
||||||
|
index={group.index}
|
||||||
|
segments={parseColorText(group.line.content)}
|
||||||
|
complete={true}
|
||||||
|
showImage={group.line.type === "image"}
|
||||||
|
selectedIndex={-1}
|
||||||
|
inline={false}
|
||||||
|
{onButtonClick}
|
||||||
|
{onHoverButton}
|
||||||
|
{onLinkClick}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -95,7 +155,10 @@
|
|||||||
|
|
||||||
.tui-group.grid {
|
.tui-group.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
grid-template-columns: repeat(
|
||||||
|
auto-fill,
|
||||||
|
minmax(max(200px, calc((100% - 3.75rem) / 6)), 1fr)
|
||||||
|
);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
<img
|
<img
|
||||||
src={line.image}
|
src={line.image}
|
||||||
alt={line.imageAlt || "Image"}
|
alt={line.imageAlt || "Image"}
|
||||||
style="max-width: {line.imageWidth || 300}px"
|
style="width: {line.imageWidth + "px" || "100%"}"
|
||||||
/>
|
/>
|
||||||
{#if line.content}<span class="image-caption">{line.content}</span>{/if}
|
{#if line.content}<span class="image-caption">{line.content}</span>{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -74,6 +74,28 @@
|
|||||||
const song = songs[currentSongIndex];
|
const song = songs[currentSongIndex];
|
||||||
|
|
||||||
terminal.updateById("music-player", {
|
terminal.updateById("music-player", {
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "image",
|
||||||
|
content: "",
|
||||||
|
image: song.thumbnail,
|
||||||
|
imageAlt: song.title,
|
||||||
|
inline: true,
|
||||||
|
imageWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "group",
|
||||||
|
content: "",
|
||||||
|
groupDirection: "column",
|
||||||
|
groupAlign: "stretch",
|
||||||
|
inline: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "group",
|
||||||
|
content: "",
|
||||||
|
groupDirection: "row",
|
||||||
|
groupAlign: "center",
|
||||||
|
inline: false,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: "output",
|
type: "output",
|
||||||
@@ -87,7 +109,15 @@
|
|||||||
inline: true,
|
inline: true,
|
||||||
external: true,
|
external: true,
|
||||||
},
|
},
|
||||||
{ type: "blank", content: "" },
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "group",
|
||||||
|
content: "",
|
||||||
|
groupDirection: "row",
|
||||||
|
groupAlign: "center",
|
||||||
|
inline: false,
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
type: "output",
|
type: "output",
|
||||||
content: `(&primary)Artist:(&)`,
|
content: `(&primary)Artist:(&)`,
|
||||||
@@ -100,6 +130,8 @@
|
|||||||
inline: true,
|
inline: true,
|
||||||
external: true,
|
external: true,
|
||||||
},
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "progress",
|
type: "progress",
|
||||||
content: "",
|
content: "",
|
||||||
@@ -108,6 +140,8 @@
|
|||||||
inline: false,
|
inline: false,
|
||||||
progressStyle: "text",
|
progressStyle: "text",
|
||||||
},
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "group",
|
type: "group",
|
||||||
content: "",
|
content: "",
|
||||||
|
|||||||
Reference in New Issue
Block a user