// Copyright (c) Microsoft. All rights reserved. using Harness.ConsoleReactiveFramework; namespace Harness.ConsoleReactiveComponents; /// /// Props for . /// public record TextScrollPanelProps : ConsoleReactiveProps { /// Gets the items to render in the scroll panel. Each item is a pre-rendered /// console string (may include ANSI escape sequences and newlines). public IReadOnlyList Items { get; init; } = []; } /// /// State for . /// /// The number of items already rendered. public record TextScrollPanelState(int RenderedCount = 0) : ConsoleReactiveState; /// /// A component that renders pre-rendered string items within a scroll area. /// All items are considered finalized — only new items since the last render are output. /// Use to force a full re-render. /// public class TextScrollPanel : ConsoleReactiveComponent { /// /// Initializes a new instance of the class. /// public TextScrollPanel() { this.State = new TextScrollPanelState(); } /// /// Resets the panel so all items will be re-rendered on the next Render call. /// public void Reset() { this.State = new TextScrollPanelState(); } /// public override void RenderCore(TextScrollPanelProps props, TextScrollPanelState state) { if (props.Items.Count == 0) { return; } // Move cursor to the bottom of the scroll area Console.Write(AnsiEscapes.MoveCursor(props.Y + props.Height - 1, props.X)); // Output only new items since last rendered for (int i = state.RenderedCount; i < props.Items.Count; i++) { Console.Write(props.Items[i]); } // Update state to track what we've rendered this.State = new TextScrollPanelState(props.Items.Count); } }