72 lines
2.3 KiB
Go
72 lines
2.3 KiB
Go
// Package panes contains the lazygit-style bordered panes.
|
||
package panes
|
||
|
||
import (
|
||
"strings"
|
||
|
||
"charm.land/lipgloss/v2"
|
||
"github.com/charmbracelet/x/ansi"
|
||
|
||
"git.kebcloud.no/keb/lazysecrets/internal/ui/styles"
|
||
)
|
||
|
||
// Box draws a rounded border of exactly w×h cells with the title embedded in
|
||
// the top edge and an optional footer in the bottom edge. The title is
|
||
// rendered as given, so callers style it (see TitleStyle). Body lines are
|
||
// truncated or padded to fit; extra lines are dropped.
|
||
func Box(st styles.Styles, title, footer string, body []string, w, h int, focused bool) string {
|
||
return BoxCounted(st, title, footer, "", body, w, h, focused)
|
||
}
|
||
|
||
// BoxCounted is Box with a counter like "3 of 12" at the right end of the
|
||
// bottom edge, where lazygit puts it.
|
||
func BoxCounted(st styles.Styles, title, footer, counter string, body []string, w, h int, focused bool) string {
|
||
if w < 4 || h < 2 {
|
||
return ""
|
||
}
|
||
border := st.BorderBlurred
|
||
if focused {
|
||
border = st.BorderFocused
|
||
}
|
||
plain := func(s ...string) string { return strings.Join(s, "") }
|
||
inner := w - 2
|
||
|
||
edge := func(left, right, label string, styled func(...string) string) string {
|
||
if label == "" {
|
||
return border.Render(left + strings.Repeat("─", inner) + right)
|
||
}
|
||
label = ansi.Truncate(" "+label+" ", inner-1, "…")
|
||
fill := inner - 1 - ansi.StringWidth(label)
|
||
return border.Render(left+"─") + styled(label) + border.Render(strings.Repeat("─", fill)+right)
|
||
}
|
||
|
||
var b strings.Builder
|
||
b.WriteString(edge("╭", "╮", title, plain))
|
||
side := border.Render("│")
|
||
for i := range h - 2 {
|
||
line := ""
|
||
if i < len(body) {
|
||
line = ansi.Truncate(body[i], inner, "…")
|
||
}
|
||
b.WriteString("\n" + side + line + strings.Repeat(" ", inner-ansi.StringWidth(line)) + side)
|
||
}
|
||
bottom := edge("╰", "╯", footer, border.Render)
|
||
if counter != "" {
|
||
// Overwrite the end of the bottom edge: "… 3 of 12 ─╯".
|
||
label := " " + counter + " "
|
||
if keep := w - 2 - ansi.StringWidth(label); keep > 2 {
|
||
bottom = ansi.Truncate(bottom, keep, "") + border.Render(label+"─╯")
|
||
}
|
||
}
|
||
b.WriteString("\n" + bottom)
|
||
return b.String()
|
||
}
|
||
|
||
// TitleStyle returns the style for a pane title.
|
||
func TitleStyle(st styles.Styles, focused bool) lipgloss.Style {
|
||
if focused {
|
||
return st.TitleFocused
|
||
}
|
||
return st.TitleBlurred
|
||
}
|