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 indexMap: make(map[string]int),
41 renderedItems: map[string]renderedItem{},
42 }
43 for _, opt := range opts {
44 opt(list.confOptions)
45 }
46
47 return &groupedList[T]{
48 list: list,
49 }
50}
51
52func (g *groupedList[T]) Init() tea.Cmd {
53 g.convertItems()
54 return g.render()
55}
56
57func (l *groupedList[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
58 u, cmd := l.list.Update(msg)
59 l.list = u.(*list[Item])
60 return l, cmd
61}
62
63func (g *groupedList[T]) SelectedItem() *T {
64 item := g.list.SelectedItem()
65 if item == nil {
66 return nil
67 }
68 dRef := *item
69 c, ok := any(dRef).(T)
70 if !ok {
71 return nil
72 }
73 return &c
74}
75
76func (g *groupedList[T]) convertItems() {
77 var items []Item
78 for _, g := range g.groups {
79 items = append(items, g.Section)
80 for _, g := range g.Items {
81 items = append(items, g)
82 }
83 }
84 g.items = items
85}
86
87func (g *groupedList[T]) SetGroups(groups []Group[T]) tea.Cmd {
88 g.groups = groups
89 g.convertItems()
90 return g.SetItems(g.items)
91}
92
93func (g *groupedList[T]) Groups() []Group[T] {
94 return g.groups
95}
96
97func (g *groupedList[T]) Items() []Item {
98 return g.list.Items()
99}