1package selection
2
3import (
4 tea "github.com/charmbracelet/bubbletea"
5 "github.com/charmbracelet/lipgloss"
6)
7
8type SelectedMsg struct {
9 Name string
10 Index int
11}
12
13type ActiveMsg struct {
14 Name string
15 Index int
16}
17
18type Bubble struct {
19 NormalStyle lipgloss.Style
20 SelectedStyle lipgloss.Style
21 Cursor string
22 Items []string
23 SelectedItem int
24}
25
26func NewBubble(items []string, normalStyle, selectedStyle lipgloss.Style, cursor string) *Bubble {
27 return &Bubble{
28 NormalStyle: normalStyle,
29 SelectedStyle: selectedStyle,
30 Cursor: cursor,
31 Items: items,
32 }
33}
34
35func (b *Bubble) Init() tea.Cmd {
36 return nil
37}
38
39func (b Bubble) View() string {
40 s := ""
41 for i, item := range b.Items {
42 if i == b.SelectedItem {
43 s += b.Cursor
44 s += b.SelectedStyle.Render(item)
45 } else {
46 s += b.NormalStyle.Render(item)
47 }
48 if i < len(b.Items)-1 {
49 s += "\n"
50 }
51 }
52 return s
53}
54
55func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
56 cmds := make([]tea.Cmd, 0)
57 switch msg := msg.(type) {
58 case tea.KeyMsg:
59 switch msg.String() {
60 case "k", "up":
61 if b.SelectedItem > 0 {
62 b.SelectedItem--
63 cmds = append(cmds, b.sendActiveMessage)
64 }
65 case "j", "down":
66 if b.SelectedItem < len(b.Items)-1 {
67 b.SelectedItem++
68 cmds = append(cmds, b.sendActiveMessage)
69 }
70 case "enter":
71 cmds = append(cmds, b.sendSelectedMessage)
72 }
73 }
74 return b, tea.Batch(cmds...)
75}
76
77func (b *Bubble) sendActiveMessage() tea.Msg {
78 if b.SelectedItem >= 0 && b.SelectedItem < len(b.Items) {
79 return ActiveMsg{
80 Name: b.Items[b.SelectedItem],
81 Index: b.SelectedItem,
82 }
83 }
84 return nil
85}
86
87func (b *Bubble) sendSelectedMessage() tea.Msg {
88 if b.SelectedItem >= 0 && b.SelectedItem < len(b.Items) {
89 return SelectedMsg{
90 Name: b.Items[b.SelectedItem],
91 Index: b.SelectedItem,
92 }
93 }
94 return nil
95}