grad.go

 1package styles
 2
 3import (
 4	"fmt"
 5	"image/color"
 6	"strings"
 7
 8	"charm.land/lipgloss/v2"
 9	"github.com/rivo/uniseg"
10)
11
12// ForegroundGrad returns a slice of strings representing the input string
13// rendered with a horizontal gradient foreground from color1 to color2. Each
14// string in the returned slice corresponds to a grapheme cluster in the input
15// string. If bold is true, the rendered strings will be bolded.
16func ForegroundGrad(base lipgloss.Style, input string, bold bool, color1, color2 color.Color) []string {
17	if input == "" {
18		return []string{""}
19	}
20	if len(input) == 1 {
21		style := base.Foreground(color1)
22		if bold {
23			style.Bold(true)
24		}
25		return []string{style.Render(input)}
26	}
27	var clusters []string
28	gr := uniseg.NewGraphemes(input)
29	for gr.Next() {
30		clusters = append(clusters, string(gr.Runes()))
31	}
32
33	ramp := lipgloss.Blend1D(len(clusters), color1, color2)
34	for i, c := range ramp {
35		style := base.Foreground(c)
36		if bold {
37			style.Bold(true)
38		}
39		clusters[i] = style.Render(clusters[i])
40	}
41	return clusters
42}
43
44// ApplyForegroundGrad renders a given string with a horizontal gradient
45// foreground.
46func ApplyForegroundGrad(base lipgloss.Style, input string, color1, color2 color.Color) string {
47	if input == "" {
48		return ""
49	}
50	var o strings.Builder
51	clusters := ForegroundGrad(base, input, false, color1, color2)
52	for _, c := range clusters {
53		fmt.Fprint(&o, c)
54	}
55	return o.String()
56}
57
58// ApplyBoldForegroundGrad renders a given string with a horizontal gradient
59// foreground.
60func ApplyBoldForegroundGrad(base lipgloss.Style, input string, color1, color2 color.Color) string {
61	if input == "" {
62		return ""
63	}
64	var o strings.Builder
65	clusters := ForegroundGrad(base, input, true, color1, color2)
66	for _, c := range clusters {
67		fmt.Fprint(&o, c)
68	}
69	return o.String()
70}