86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { TextAttributes, RGBA } from "@opentui/core"
|
|
import { For, type JSX } from "solid-js"
|
|
import { useTheme, tint } from "@tui/context/theme"
|
|
import { logo, marks } from "@/cli/logo"
|
|
|
|
// Shadow markers (rendered chars in parens):
|
|
// _ = full shadow cell (space with bg=shadow)
|
|
// ^ = letter top, shadow bottom (▀ with fg=letter, bg=shadow)
|
|
// ~ = shadow top only (▀ with fg=shadow)
|
|
const SHADOW_MARKER = new RegExp(`[${marks}]`)
|
|
|
|
export function Logo() {
|
|
const { theme } = useTheme()
|
|
|
|
const renderLine = (line: string, fg: RGBA, bold: boolean): JSX.Element[] => {
|
|
const shadow = tint(theme.background, fg, 0.25)
|
|
const attrs = bold ? TextAttributes.BOLD : undefined
|
|
const elements: JSX.Element[] = []
|
|
let i = 0
|
|
|
|
while (i < line.length) {
|
|
const rest = line.slice(i)
|
|
const markerIndex = rest.search(SHADOW_MARKER)
|
|
|
|
if (markerIndex === -1) {
|
|
elements.push(
|
|
<text fg={fg} attributes={attrs} selectable={false}>
|
|
{rest}
|
|
</text>,
|
|
)
|
|
break
|
|
}
|
|
|
|
if (markerIndex > 0) {
|
|
elements.push(
|
|
<text fg={fg} attributes={attrs} selectable={false}>
|
|
{rest.slice(0, markerIndex)}
|
|
</text>,
|
|
)
|
|
}
|
|
|
|
const marker = rest[markerIndex]
|
|
switch (marker) {
|
|
case "_":
|
|
elements.push(
|
|
<text fg={fg} bg={shadow} attributes={attrs} selectable={false}>
|
|
{" "}
|
|
</text>,
|
|
)
|
|
break
|
|
case "^":
|
|
elements.push(
|
|
<text fg={fg} bg={shadow} attributes={attrs} selectable={false}>
|
|
▀
|
|
</text>,
|
|
)
|
|
break
|
|
case "~":
|
|
elements.push(
|
|
<text fg={shadow} attributes={attrs} selectable={false}>
|
|
▀
|
|
</text>,
|
|
)
|
|
break
|
|
}
|
|
|
|
i += markerIndex + 1
|
|
}
|
|
|
|
return elements
|
|
}
|
|
|
|
return (
|
|
<box>
|
|
<For each={logo.left}>
|
|
{(line, index) => (
|
|
<box flexDirection="row" gap={1}>
|
|
<box flexDirection="row">{renderLine(line, theme.textMuted, false)}</box>
|
|
<box flexDirection="row">{renderLine(logo.right[index()], theme.text, true)}</box>
|
|
</box>
|
|
)}
|
|
</For>
|
|
</box>
|
|
)
|
|
}
|