@@ -790,15 +790,28 @@ func (l *list[T]) blurSelectedItem() tea.Cmd {
790 return tea.Batch(cmds...)
790 return tea.Batch(cmds...)
793+// renderFragment holds updated rendered view fragments
794+type renderFragment struct {
793−// render iterator renders items starting from the specific index and limits hight if limitHeight != -1
799+// renderIterator renders items starting from the specific index and limits height if limitHeight != -1
794// returns the last index and the rendered content so far
800// returns the last index and the rendered content so far
795// we pass the rendered content around and don't use l.rendered to prevent jumping of the content
801// we pass the rendered content around and don't use l.rendered to prevent jumping of the content
796func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string) (string, int) {
802func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string) (string, int) {
803+ var fragments []renderFragment
797 currentContentHeight := lipgloss.Height(rendered) - 1
805 currentContentHeight := lipgloss.Height(rendered) - 1
798 itemsLen := l.items.Len()
806 itemsLen := l.items.Len()
807+ finalIndex := itemsLen
809+ // first pass: accumulate all fragments to render until the height limit is
799 for i := startInx; i < itemsLen; i++ {
811 for i := startInx; i < itemsLen; i++ {
800− if currentContentHeight >= l.height && limitHeight {
812+ if limitHeight && currentContentHeight >= l.height {
801− return rendered, i
813+ finalIndex = i
803 // cool way to go through the list in both directions
816 // cool way to go through the list in both directions
@@ -811,6 +824,7 @@ func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string
814 var rItem renderedItem
828 var rItem renderedItem
815 if cache, ok := l.renderedItems.Get(item.ID()); ok {
829 if cache, ok := l.renderedItems.Get(item.ID()); ok {
816 rItem = cache
830 rItem = cache
@@ -820,19 +834,42 @@ func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string
820 rItem.end = currentContentHeight + rItem.height - 1
834 rItem.end = currentContentHeight + rItem.height - 1
821 l.renderedItems.Set(item.ID(), rItem)
835 l.renderedItems.Set(item.ID(), rItem)
823 gap := l.gap + 1
838 gap := l.gap + 1
824 if inx == itemsLen-1 {
839 if inx == itemsLen-1 {
828− if l.direction == DirectionForward {
843+ fragments = append(fragments, renderFragment{view: rItem.view, gap: gap})
829− rendered += rItem.view + strings.Repeat("\n", gap)
844+
831− rendered = rItem.view + strings.Repeat("\n", gap) + rendered
833 currentContentHeight = rItem.end + 1 + l.gap
845 currentContentHeight = rItem.end + 1 + l.gap
835− return rendered, itemsLen
847+
848+ // second pass: build rendered string efficiently
849+ var b strings.Builder
850+ if l.direction == DirectionForward {
851+ b.WriteString(rendered)
852+ for _, f := range fragments {
853+ b.WriteString(f.view)
859+ return b.String(), finalIndex
862+ // iterate backwards as fragments are in reversed order
863+ for i := len(fragments) - 1; i >= 0; i-- {
865+ b.WriteString(f.view)
870+ b.WriteString(rendered)
872+ return b.String(), finalIndex
838func (l *list[T]) renderItem(item Item) renderedItem {
875func (l *list[T]) renderItem(item Item) renderedItem {