v0.1.0 initial commit

This commit is contained in:
2026-07-12 17:01:37 -04:00
commit c3ca2ebb63
64 changed files with 10453 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
package tui
// ScrollState tracks scroll position for a scrollable container
type ScrollState struct {
Offset int // First visible item index
Total int // Total item count
Visible int // Visible item count (viewport height)
Selection int // Currently selected item, -1 if none
}
// NewScrollState creates initialized scroll state
func NewScrollState(total, visible int) *ScrollState {
return &ScrollState{
Total: total,
Visible: visible,
Selection: -1,
}
}
// --- Scroll manipulation ---
// ScrollBy adjusts offset by delta, clamping to valid range
func (s *ScrollState) ScrollBy(delta int) {
s.Offset += delta
s.Clamp()
}
// ScrollTo sets offset to specific position
func (s *ScrollState) ScrollTo(pos int) {
s.Offset = pos
s.Clamp()
}
// EnsureVisible adjusts offset to make item at pos visible
func (s *ScrollState) EnsureVisible(pos int) {
if pos < s.Offset {
s.Offset = pos
} else if pos >= s.Offset+s.Visible {
s.Offset = pos - s.Visible + 1
}
s.Clamp()
}
// Clamp ensures offset is within valid range
func (s *ScrollState) Clamp() {
s.Offset = ClampScroll(s.Offset, s.Visible, s.Total)
}
// --- Page navigation ---
// PageUp scrolls up by half visible height
func (s *ScrollState) PageUp() {
s.ScrollBy(-PageDelta(s.Visible))
}
// PageDown scrolls down by half visible height
func (s *ScrollState) PageDown() {
s.ScrollBy(PageDelta(s.Visible))
}
// --- State updates ---
// SetTotal updates total count and reclamps
func (s *ScrollState) SetTotal(total int) {
s.Total = total
s.Clamp()
if s.Selection >= total {
s.Selection = total - 1
}
}
// SetVisible updates visible count and reclamps
func (s *ScrollState) SetVisible(visible int) {
s.Visible = visible
s.Clamp()
}
// --- Positions queries ---
// AtTop returns true if scrolled to top
func (s *ScrollState) AtTop() bool {
return s.Offset == 0
}
// AtBottom returns true if scrolled to bottom
func (s *ScrollState) AtBottom() bool {
if s.Total <= s.Visible {
return true
}
return s.Offset >= s.Total-s.Visible
}
// --- Selection management ---
// Select sets selection and ensures it's visible
func (s *ScrollState) Select(idx int) {
s.Selection = ClampCursor(idx, s.Total)
s.EnsureVisible(s.Selection)
}
// SelectNext moves selection down
func (s *ScrollState) SelectNext() {
if s.Selection < s.Total-1 {
s.Selection++
s.EnsureVisible(s.Selection)
}
}
// SelectPrev moves selection up
func (s *ScrollState) SelectPrev() {
if s.Selection > 0 {
s.Selection--
s.EnsureVisible(s.Selection)
}
}