bubble.go

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