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}