grouped.go

 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}