1package list
2
3import (
4 tea "github.com/charmbracelet/bubbletea/v2"
5 "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6 "github.com/charmbracelet/crush/internal/tui/util"
7)
8
9type Group[T Item] struct {
10 Section ItemSection
11 Items []T
12}
13type GroupedList[T Item] interface {
14 util.Model
15 layout.Sizeable
16 Items() []Item
17 Groups() []Group[T]
18 SetGroups([]Group[T]) tea.Cmd
19 MoveUp(int) tea.Cmd
20 MoveDown(int) tea.Cmd
21 GoToTop() tea.Cmd
22 GoToBottom() tea.Cmd
23 SelectItemAbove() tea.Cmd
24 SelectItemBelow() tea.Cmd
25 SetSelected(string) tea.Cmd
26 SelectedItem() *T
27}
28type groupedList[T Item] struct {
29 *list[Item]
30 groups []Group[T]
31}
32
33func NewGroupedList[T Item](groups []Group[T], opts ...ListOption) GroupedList[T] {
34 list := &list[Item]{
35 confOptions: &confOptions{
36 direction: DirectionForward,
37 keyMap: DefaultKeyMap(),
38 focused: true,
39 },
40 items: []Item{},
41 indexMap: make(map[string]int),
42 renderedItems: make(map[string]renderedItem),
43 }
44 for _, opt := range opts {
45 opt(list.confOptions)
46 }
47
48 return &groupedList[T]{
49 list: list,
50 }
51}
52
53func (g *groupedList[T]) Init() tea.Cmd {
54 g.convertItems()
55 return g.render()
56}
57
58func (l *groupedList[T]) Update(msg tea.Msg) (util.Model, tea.Cmd) {
59 u, cmd := l.list.Update(msg)
60 l.list = u.(*list[Item])
61 return l, cmd
62}
63
64func (g *groupedList[T]) SelectedItem() *T {
65 item := g.list.SelectedItem()
66 if item == nil {
67 return nil
68 }
69 dRef := *item
70 c, ok := any(dRef).(T)
71 if !ok {
72 return nil
73 }
74 return &c
75}
76
77func (g *groupedList[T]) convertItems() {
78 var items []Item
79 for _, g := range g.groups {
80 items = append(items, g.Section)
81 for _, g := range g.Items {
82 items = append(items, g)
83 }
84 }
85 g.items = items
86}
87
88func (g *groupedList[T]) SetGroups(groups []Group[T]) tea.Cmd {
89 g.groups = groups
90 g.convertItems()
91 return g.SetItems(g.items)
92}
93
94func (g *groupedList[T]) Groups() []Group[T] {
95 return g.groups
96}
97
98func (g *groupedList[T]) Items() []Item {
99 return g.list.Items()
100}