1/** @jsxImportSource @alchemy.run/sigil */
2import {
3 Hyperlink as SigilHyperlink,
4 Text as SigilText,
5} from "@alchemy.run/sigil";
6import type { ComponentProps } from "react";
7import { theme } from "../../../Util/Theme.ts";
8import { useCliEnvironment } from "./Environment.tsx";
9
10export type TextTone =
11 | "default"
12 | "muted"
13 | "emphasis"
14 | "brand"
15 | "accent"
16 | "info"
17 | "success"
18 | "warning"
19 | "danger";
20
21export interface TextProps extends Omit<
22 ComponentProps<typeof SigilText>,
23 "color"
24> {
25 readonly tone?: TextTone;
26 readonly color?: ComponentProps<typeof SigilText>["color"];
27}
28
29/** CliKit typography primitive. Consumers never import Sigil directly. */
30export function Text({
31 tone = "default",
32 color,
33 backgroundColor,
34 bold,
35 dimColor,
36 italic,
37 underline,
38 strikethrough,
39 inverse,
40 ...props
41}: TextProps) {
42 const { colors } = useCliEnvironment();
43 return (
44 <SigilText
45 {...props}
46 color={
47 colors
48 ? (color ??
49 (tone === "default" || tone === "muted"
50 ? undefined
51 : theme.color[tone]))
52 : undefined
53 }
54 backgroundColor={colors ? backgroundColor : undefined}
55 bold={colors ? bold : undefined}
56 dimColor={colors ? (dimColor ?? tone === "muted") : undefined}
57 italic={colors ? italic : undefined}
58 underline={colors ? underline : undefined}
59 strikethrough={colors ? strikethrough : undefined}
60 inverse={colors ? inverse : undefined}
61 />
62 );
63}
64
65type LinkProps = {
66 readonly href: string;
67 readonly children?: string;
68};
69
70export function Link({ href, children }: LinkProps) {
71 const { colors } = useCliEnvironment();
72 const label = children ?? href;
73 return (
74 <SigilHyperlink
75 url={href}
76 fallback={label !== href}
77 color={colors ? theme.color.info : undefined}
78 underline={colors || undefined}
79 >
80 {label}
81 </SigilHyperlink>
82 );
83}