### Run Button Click Example Source: https://github.com/charmbracelet/x/blob/main/pony/examples/buttons/README.md Execute the main Go program to run the button click example. This will allow you to interact with buttons using your mouse. ```bash go run main.go ``` -------------------------------- ### Install GolangCI-Lint in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Install the golangci-lint tool using the 'task lint:install' command. ```bash task lint:install ``` -------------------------------- ### Basic Pony TUI Example Source: https://github.com/charmbracelet/x/blob/main/pony/README.md A simple 'Hello, World!' example demonstrating the basic structure of a Pony template and its rendering. It uses a generic interface{} for data, suitable for simple templates. ```go package main import ( "fmt" "github.com/charmbracelet/x/pony" ) func main() { const tmpl = ` Hello, World! Welcome to pony! ` t := pony.MustParse[interface{}](tmpl) output := t.Render(nil, 80, 24) fmt.Print(output) } ``` -------------------------------- ### Logic and Behavior Test Example Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md Demonstrates standard Go testing assertions for verifying logic and behavior, such as layout calculations. Use `t.Errorf` for failures. ```go func TestLayout(t *testing.T) { size := elem.Layout(constraints) if size.Width != expected { t.Errorf("got %d, want %d", size.Width, expected) } } ``` -------------------------------- ### Install pony Package Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Use this command to add the pony package to your Go project. ```bash go get github.com/charmbracelet/x/pony ``` -------------------------------- ### Render Image in Terminal with Mosaic Source: https://github.com/charmbracelet/x/blob/main/mosaic/README.md Use this example to load an image, initialize a Mosaic renderer with specified dimensions, and render the image to the terminal. Ensure the image file exists at the specified path. ```go package main import ( "fmt" "image" "image/jpeg" "os" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/x/mosaic" ) func main() { dogImg, err := loadImage("./pekinas.jpg") if err != nil { fmt.Print(err) os.Exit(1) } m := mosaic.New().Width(80).Height(40) fmt.Println(lipgloss.JoinVertical(lipgloss.Right, lipgloss.JoinHorizontal(lipgloss.Center, m.Render(dogImg)))) } func loadImage(path string) (image.Image, error) { f, err := os.Open(path) defer f.Close() if err != nil { return nil, err } return jpeg.Decode(f) } ``` -------------------------------- ### Bubble Tea Integration Example in Go Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Integrate Pony components with Bubble Tea by defining a model that manages state, handles messages (like window size and key presses), and renders the UI. Imports for Bubble Tea and Pony are required. ```go import ( tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/pony" ) type ViewData struct { Count int } type model struct { template *pony.Template[ViewData] count int width int height int } func (m model) Init() tea.Cmd { return tea.RequestWindowSize } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height case tea.KeyPressMsg: if msg.String() == "space" { m.count++ } } return m, nil } func (m model) View() tea.View { data := ViewData{Count: m.count} output := m.template.Render(data, m.width, m.height) return tea.NewView(output) } ``` -------------------------------- ### Golden File Test Example Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md Compares the rendered output of a template against a golden file. The golden file is automatically generated or updated using the `-update` flag. ```go func TestMyRender(t *testing.T) { output := myTemplate.Render(data, 80, 24) golden.RequireEqual(t, output) // Compares against testdata/TestMyRender.golden } ``` -------------------------------- ### Get Component from Registry Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Retrieves a registered component factory by its name. ```go pony.GetComponent(name) ``` -------------------------------- ### Button Click Example Architecture Source: https://github.com/charmbracelet/x/blob/main/pony/examples/buttons/README.md Illustrates the architecture for handling button clicks using Bubble Tea's View callback. The View function renders elements and returns a callback that performs hit testing on mouse events, emitting custom messages with element IDs to the Update function. ```text View() renders -> returns (screen, boundsMap) -> creates View with callback that captures boundsMap -> callback does hit testing on mouse events -> returns Cmd with element ID Update() receives element ID message -> updates model based on which button was clicked ``` -------------------------------- ### Get All Registered Components Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Returns a map of all currently registered component names and their factories. ```go pony.RegisteredComponents() ``` -------------------------------- ### Utilize Props Helper Type for Property Access Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Use the Props map with helper methods like Get, GetOr, GetInt, and GetBool for convenient property access and parsing. ```go type Props map[string]string props.Get("key") // Get value (empty if missing) props.GetOr("key", "def") // Get with default props.GetInt("key", 10) // Parse int with default props.GetBool("key") // Parse bool (default false) ``` -------------------------------- ### Add Template Function in Go Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md To add a new template function, modify the `defaultTemplateFuncs` in `template.go`. This example shows how to add an `upper` function and a custom `myFunc`. ```go func defaultTemplateFuncs() template.FuncMap { return template.FuncMap{ "upper": strings.ToUpper, "myFunc": func(arg string) string { ... }, } } ``` -------------------------------- ### BoundsMap API Usage in Go Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Utilize the BoundsMap API to perform hit testing at specific coordinates, retrieve elements by their IDs, get bounds information, or list all elements with their bounds. ```go // Hit test - find element at coordinates // Prefers elements with explicit IDs over auto-generated ones elem := boundsMap.HitTest(x, y) // Returns Element or nil // Get element by ID elem, ok := boundsMap.GetByID("button-id") // Get bounds for element ID bounds, ok := boundsMap.GetBounds("button-id") // Get all elements with bounds elements := boundsMap.AllElements() // []ElementWithBounds ``` -------------------------------- ### Request Initial Window Size in Bubble Tea Init Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md Use `tea.RequestWindowSize` in the Init function to prompt Bubble Tea to send the initial window dimensions to the application. ```go func (m model) Init() tea.Cmd { return tea.RequestWindowSize } ``` -------------------------------- ### Creating and Registering Custom Components Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md Illustrates how to define and register a custom component using pony primitives. Custom components can be composed from existing elements and styled using helper methods. ```go func NewMyComponent(props Props, children []Element) Element { return pony.NewBox( pony.NewVStack(children...), ).WithBorder("rounded").WithPadding(1) } pony.Register("mycomp", NewMyComponent) ``` -------------------------------- ### Apply Text Styling (New Way) Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates the modern, SwiftUI-style approach to applying text styles like foreground color, background color, bold, italic, and underline. ```go // New way (SwiftUI-style) text := pony.NewText("Hello"). ForegroundColor(pony.Hex("#FF5555")). BackgroundColor(pony.RGB(40, 42, 54)). Bold(). Italic(). Underline() ``` -------------------------------- ### Configure Box and Text Elements with Fluent API Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Use method chaining for configuring elements like Box and Text. Ensure all elements use the fluent API pattern for consistent configuration. ```go box := NewBox(child). WithBorder("rounded"). WithPadding(2). WithMargin(1) text := NewText("Hello"). WithStyle(style). WithAlignment"center") ``` -------------------------------- ### Rendering to Screen Buffer Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Templates render to a `uv.ScreenBuffer` which can then be converted to a string for output. `RenderWithBounds` provides the screen buffer and a `BoundsMap`. ```go scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height) output := scr.Render() // Convert to string ``` -------------------------------- ### Create Basic Text Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Constructs a new text element with specified content. ```go pony.NewText(content) ``` -------------------------------- ### Render Pony Template with Data in Bubble Tea View Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md In the View function, prepare the data for the template and use `RenderToSize` to generate the output based on the current window dimensions. Return the rendered output as a Bubble Tea View. ```go func (m model) View() tea.View { // Prepare data for template data := map[string]interface{}{ "Count": m.count, "Items": m.items, } // Render pony with window size output := m.template.RenderToSize(data, m.width, m.height) // Return as Bubble Tea View return tea.NewView(output) } ``` -------------------------------- ### Create Panel Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Constructs a panel layout with a child element, border style, and padding. ```go // Basic layouts pony.Panel(child, border, padding) ``` -------------------------------- ### Render Template Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Shows how to render a parsed Pony template with provided data, slots, and dimensions. ```go // Render output := tmpl.Render(data, width, height) output := tmpl.RenderWithSlots(data, slots, width, height) ``` -------------------------------- ### Fluent API for Button Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Illustrates configuring a button's appearance and behavior, including its border, padding, custom style, width, and setting a unique ID. ```go button := pony.NewButton("Click Me"). Border("rounded"). Padding(1). Style(style). Width(pony.NewFixedConstraint(20)) button.SetID("my-button") ``` -------------------------------- ### List Available Tasks in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md List all available tasks by running 'task' without any arguments. ```bash task ``` -------------------------------- ### Template Parsing and Rendering Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates how to parse markup into a template, render it with data, and render it with slots and bounds for mouse event handling. ```APIDOC ## Template Parsing and Rendering ### Description Parse markup into a template with type safety, render it with data, or render it with slots and bounds for mouse event handling. ### Parse with Type Safety ```go // Parse with type safety tmpl, err := pony.Parse[YourDataType](markup) tmpl := pony.MustParse[YourDataType](markup) ``` ### Render ```go // Render output := tmpl.Render(data, width, height) output := tmpl.RenderWithSlots(data, slots, width, height) ``` ### Render with Bounds for Mouse Handling ```go // Render with bounds for mouse handling scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height) ``` ``` -------------------------------- ### Handle Mouse Clicks with Bounds Tracking in Go Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Implement mouse click handling by rendering with bounds, enabling mouse events, and using a callback to hit test clicked elements. This allows for stateless interaction handling. ```go type buttonClickMsg string func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case buttonClickMsg: switch msg { case "submit-btn": return m, m.submitForm() case "cancel-btn": return m, tea.Quit } } return m, nil } func (m model) View() tea.View { data := ViewData{...} // Render and get bounds map scr, boundsMap := m.template.RenderWithBounds(data, nil, m.width, m.height) view := tea.NewView(scr.Render()) view.MouseMode = tea.MouseModeAllMotion // Enable mouse events // Callback captures boundsMap - no model mutation! view.Callback = func(msg tea.Msg) tea.Cmd { if click, ok := msg.(tea.MouseClickMsg); ok { mouse := click.Mouse() // Find which element was clicked if elem := boundsMap.HitTest(mouse.X, mouse.Y); elem != nil { return func() tea.Msg { return buttonClickMsg(elem.ID()) } } } return nil } return view } ``` -------------------------------- ### Render Template with Bounds for Mouse Handling Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Renders a Pony template and returns the screen output along with a BoundsMap, which is essential for implementing mouse event handling like hover detection. ```go // Render with bounds for mouse handling scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height) ``` -------------------------------- ### Create Button Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Creates a button element with specified text. ```go pony.NewButton(text) ``` -------------------------------- ### Fluent API for Flex Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates configuring a flex item's properties such as grow, shrink, and basis within a flex layout. ```go flex := pony.NewFlex(child). Grow(1). Shrink(0). Basis(20) ``` -------------------------------- ### Create Overlay Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Generates an overlay layout using a ZStack with default alignment, suitable for layering elements. ```go // Advanced layouts pony.Overlay(children...) ``` -------------------------------- ### Fluent API for Text Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Shows how to apply various text styling options like foreground color, bold, italic, and alignment using a fluent API. ```go text := pony.NewText("Hello"). ForegroundColor(pony.Hex("#FF5555")). Bold(). Italic(). Alignment(pony.AlignmentCenter). Wrap(true) ``` -------------------------------- ### Create Section Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Creates a section layout with a header, header color, and child elements. ```go pony.Section(header, headerColor, children...) ``` -------------------------------- ### Fluent API for Element Configuration Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Illustrates the use of the fluent API for configuring element properties like borders, padding, margins, and dimensions. ```APIDOC ## Fluent API ### Description Chainable methods for configuring element properties. ### Example: Box Element ```go box := pony.NewBox(child). Border("rounded"). Padding(2). Margin(1). MarginTop(2). Width(pony.NewFixedConstraint(50)). BorderColor(pony.Hex("#00FFFF")) ``` ### Example: Text Element ```go text := pony.NewText("Hello"). ForegroundColor(pony.Hex("#FF5555")). Bold(). Italic(). Alignment(pony.AlignmentCenter). Wrap(true) ``` ### Example: Button Element ```go button := pony.NewButton("Click Me"). Border("rounded"). Padding(1). Style(style). Width(pony.NewFixedConstraint(20)) button.SetID("my-button") ``` ### Example: Flex Element ```go flex := pony.NewFlex(child). Grow(1). Shrink(0). Basis(20) ``` ### Example: Positioned Element ```go positioned := pony.NewPositioned(child, 10, 5). Right(2). Bottom(1) ``` ``` -------------------------------- ### Fluent API for Box Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates chaining methods on a Box element for configuring its border, padding, margin, and width. ```go box := pony.NewBox(child). Border("rounded"). Padding(2). Margin(1). MarginTop(2). Width(pony.NewFixedConstraint(50)). BorderColor(pony.Hex("#00FFFF")) ``` -------------------------------- ### Run All Tests in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Execute all tests using the 'task test' command or standard Go tooling. For verbose output, use 'go test -v ./...'. ```bash task test go test ./... go test -v ./... ``` -------------------------------- ### Create Panel with Margin Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Creates a panel layout that includes a child, border, padding, and an additional margin. ```go pony.PanelWithMargin(child, border, padding, margin) ``` -------------------------------- ### Stateful Component Implementation Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md Demonstrates the structure of a stateful component in pony, including its `Update` and `Render` methods. State is managed within the component, and its output can be rendered into templates using slots. ```go type MyComp struct { state string } func (c *MyComp) Update(msg tea.Msg) { /* handle events */ } func (c *MyComp) Render() pony.Element { return pony.NewText(c.state) } // In template: // In View: slots["comp"] = m.comp.Render() ``` -------------------------------- ### Build Style with API Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Construct styles programmatically using the pony.NewStyle() API. This allows for dynamic styling in code. ```go style := pony.NewStyle(). Fg(pony.Hex("#FF5555")), Bg(pony.RGB(40, 42, 54)), Bold(). Italic(). Build() ``` -------------------------------- ### Create Card Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Constructs a card layout with a title, title color, border color, and multiple child elements. ```go pony.Card(title, titleColor, borderColor, children...) ``` -------------------------------- ### Run All Pony Tests Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md Execute all tests within the Pony project using the standard Go testing tool. ```bash go test ./... ``` -------------------------------- ### Type-Safe Template Rendering Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md Demonstrates how to use type-safe templates with custom data structures for rendering dynamic content. Ensure the terminal size is passed to the Render function. ```go type ViewData struct { Title string Count int } tmpl := pony.MustParse[ViewData](markup) output := tmpl.Render(ViewData{Title: "App", Count: 42}, 80, 24) ``` -------------------------------- ### Implement Table-Driven Tests with Subtests Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Organize tests using table-driven approaches and subtests for clarity and maintainability. Test both logic (Layout) and rendering (Draw/golden). ```go func TestElement(t *testing.T) { tests := []struct { name string // ... fields }{ {name: "case1", ...}, {name: "case2", ...}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // test logic }) } } ``` -------------------------------- ### Render Template with Slots in Go Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Render a template by providing a map of slot names to Pony elements. This allows dynamic content to be injected into predefined template areas. ```go func (m model) View() tea.View { slots := map[string]pony.Element{ "input": m.inputComp.Render(), } output := m.template.RenderWithSlots(data, slots, m.width, m.height) return tea.NewView(output) } ``` -------------------------------- ### Full UI Structure in Markup Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md Define the complete UI layout using XML markup, including headers, scrollable content, and instructional text. This demonstrates a declarative approach to UI building. ```xml Title {{ range .Items }} {{ end }} Press q to quit ``` -------------------------------- ### Parse and Render Pony Template Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates parsing a Pony template with a specific data structure and rendering it. Ensure the ViewData struct matches the template's expected data. ```go type ViewData struct { Title string Count int } const tmpl = ` {{ .Title }} Count: {{ .Count }} ` tmpl := pony.MustParse[ViewData](tmpl) output := tmpl.Render(ViewData{Title: "My App", Count: 42}, 80, 24) ``` -------------------------------- ### Fluent API for Positioned Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Shows how to configure a positioned element's offset from the right and bottom edges. ```go positioned := pony.NewPositioned(child, 10, 5). Right(2). Bottom(1) ``` -------------------------------- ### Bubble Tea Integration with Pony Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md Shows a minimal integration pattern for using pony templates within a Bubble Tea application. Handles window resize events to update the rendering dimensions. ```go type model struct { template *pony.Template[ViewData] width int height int } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.width, m.height = msg.Width, msg.Height } return m, nil } func (m model) View() tea.View { output := m.template.Render(data, m.width, m.height) return tea.NewView(output) ``` -------------------------------- ### Go Template Loops Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Iterate over data collections and render elements for each item using Go's `range` template syntax. ```xml {{ range .Items }} • {{ . }} {{ end }} ``` -------------------------------- ### Implement Draw() Method with SetBounds() Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Always call SetBounds() at the beginning of the Draw() method. This is required for hit testing and proper rendering. ```go func (e *MyElement) Draw(scr uv.Screen, area uv.Rectangle) { e.SetBounds(area) // REQUIRED for hit testing // ... rest of drawing logic } ``` -------------------------------- ### Register a Functional Component Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Register a simple functional component using pony.Register. This approach is suitable for less complex components. ```go pony.Register("card", func(props pony.Props, children []pony.Element) pony.Element { return pony.NewBox( pony.NewVStack(children...), ).Border("rounded").Padding(1) }) ``` -------------------------------- ### Model with Stateful Components in Go Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md Defines the main model structure holding a Pony template and instances of the stateful username and email input components. ```go type model struct { template *pony.Template[ViewData] username *Input // Stateful component email *Input // Stateful component focused string } ``` -------------------------------- ### Register Custom Component in Go Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md Define and register a custom component in Go to be used within markup. Ensure the registration function is called during initialization. ```go type ListItem struct { pony.BaseElement Text string Selected bool } func NewListItemFromProps(props pony.Props, children []pony.Element) pony.Element { text := props.Get("text") selected := props.Get("selected") == "true" return NewListItem(text, selected) } func init() { pony.Register("listitem", NewListItemFromProps) } ``` -------------------------------- ### Run Linter in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Execute the linter using 'task lint'. For auto-fixing issues, use 'task lint:fix'. ```bash task lint task lint:fix ``` -------------------------------- ### Fluent API for Text Styling Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Style text elements programmatically using a fluent API in Go. This allows for chaining style modifications. ```go text := pony.NewText("Hello"). ForegroundColor(pony.Hex("#FF5555")). BackgroundColor(pony.RGB(40, 42, 54)). Bold(). Italic(). Alignment(pony.AlignmentCenter) ``` -------------------------------- ### Define and Register a Type-Based Component Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Implement a type-based component for more control, embedding BaseElement and defining Draw, Layout, and Children methods. Register the component using pony.Register. ```go type Card struct { BaseElement // Required Title string Content []Element } func NewCard(props Props, children []Element) Element { return &Card{ Title: props.Get("title"), Content: children, } } func (c *Card) Draw(scr uv.Screen, area uv.Rectangle) { c.SetBounds(area) // Required // Build composed structure and draw card := NewBox(NewVStack(c.Content...)).Border("rounded") card.Draw(scr, area) } func (c *Card) Layout(constraints Constraints) Size { // Delegate to composed structure card := NewBox(NewVStack(c.Content...)).Border("rounded") return card.Layout(constraints) } func (c *Card) Children() []Element { return c.Content } // Register pony.Register("card", NewCard) ``` -------------------------------- ### Store Pony Template in Bubble Tea Model Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md Initialize the Pony template within your Bubble Tea model. Ensure the template is parsed once during initialization for efficiency. ```go type model struct { template *pony.Template // ... your app state } func initialModel() model { return model{ template: pony.MustParse(markup), } } ``` -------------------------------- ### Run Tests with Coverage in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Generate test coverage reports using the 'task test:coverage' command. ```bash task test:coverage ``` -------------------------------- ### View Fills Slots with Rendered Components in Go Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md Implements the View method to render the template with slots filled by the rendered output of the username and email components. It passes ViewData and component elements to the template. ```go func (m model) View() tea.View { data := ViewData{Title: "My Form"} slots := map[string]pony.Element{ "username": m.username.Render(), // Render to Element! "email": m.email.Render(), } output := m.template.RenderWithSlots(data, slots, m.width, m.height) return tea.NewView(output) } ``` -------------------------------- ### Create Z-Stack Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Constructs a z-stack element that layers its children on top of each other. ```go pony.NewZStack(children...) ``` -------------------------------- ### Run Pony Tests with Coverage Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md Execute tests and generate a coverage report to assess test coverage. ```bash go test -cover ``` -------------------------------- ### Go Template Conditionals Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Conditionally render UI elements based on data properties using Go's `if/else` template syntax. ```xml {{ if .IsOnline }} ● Online {{ else }} ○ Offline {{ end }} ``` -------------------------------- ### Regenerate Golden Files Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Use the `go test -update ./...` command to regenerate all golden files. This command should be run whenever rendering output changes intentionally. ```bash go test -update ./... ``` -------------------------------- ### Register Custom Component Type Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Define and register a custom component by creating a struct that implements the necessary Pony interfaces. This allows for state management and custom drawing/layout logic. ```go // Or create a custom type for more control type Card struct { pony.BaseElement // Required for ID and bounds tracking Title string Color string Content []pony.Element } func NewCard(props pony.Props, children []pony.Element) pony.Element { return &Card{ Title: props.Get("title"), Color: props.GetOr("color", "blue"), Content: children, } } func (c *Card) Draw(scr uv.Screen, area uv.Rectangle) { c.SetBounds(area) // Track bounds for mouse interaction // Build composed structure themeColor := pony.Hex("#00FFFF") card := pony.NewBox( pony.NewVStack( pony.NewText(c.Title).ForegroundColor(themeColor).Bold(), pony.NewDivider(), pony.NewVStack(c.Content...), ), ).Border("rounded").BorderColor(themeColor).Padding(1) card.Draw(scr, area) } func (c *Card) Layout(constraints pony.Constraints) pony.Size { // Delegate to composed structure themeColor := pony.Hex("#00FFFF") card := pony.NewBox( pony.NewVStack( pony.NewText(c.Title).ForegroundColor(themeColor).Bold(), pony.NewDivider(), pony.NewVStack(c.Content...), ), ).Border("rounded").BorderColor(themeColor).Padding(1) return card.Layout(constraints) } func (c *Card) Children() []pony.Element { return c.Content } // Register it pony.Register("card", NewCard) ``` -------------------------------- ### Handle Window Resize in Bubble Tea Update Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md Update the model's width and height properties when a `tea.WindowSizeMsg` is received. This ensures that subsequent renders use the correct dimensions. ```go func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height } return m, nil } ``` -------------------------------- ### Using Slots for Dynamic Content Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Slots enable dynamic content injection into templates. Define a slot in the XML markup and provide the corresponding `Element` in the `slots` map during rendering. ```xml ``` ```go slots := map[string]Element{ "input": myInputComponent.Render(), } output := tmpl.RenderWithSlots(data, slots, w, h) ``` -------------------------------- ### Format Code in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Format code using 'task fmt', which applies gofumpt and goimports. ```bash task fmt ``` -------------------------------- ### Flexible Layout with Flex Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Employ the flex component within an HStack to allow content to grow and fill available space. ```xml Fixed sidebar Main content (grows) ``` -------------------------------- ### Clean Build Artifacts in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Clean build artifacts and test cache using 'task clean'. ```bash task clean ``` -------------------------------- ### Element Constructors Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Provides a list of constructors for creating various UI elements within the Pony templating engine. ```APIDOC ## Element Constructors ### Description Constructors for creating various UI elements. ### Constructors ```go p পার্থক্য.NewText(content) p পার্থক্য.NewBox(child) p পার্থক্য.NewVStack(children...) p পার্থক্য.NewHStack(children...) p পার্থক্য.NewZStack(children...) p পার্থক্য.NewButton(text) p পার্থক্য.NewDivider() p পার্থক্য.NewSpacer() p পার্থক্য.NewFlex(child) p পার্থক্য.NewPositioned(child, x, y) p পার্থক্য.NewSlot(name) p পার্থক্য.NewScrollView(child) ``` ``` -------------------------------- ### Register Component Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Registers a custom component factory with the component registry using a given name. ```go pony.Register(name, factory) ``` -------------------------------- ### Tidy Dependencies in Pony Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Tidy dependencies using 'task tidy' or 'go mod tidy'. ```bash task tidy go mod tidy ``` -------------------------------- ### Layout Helpers Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Utility functions for common layout patterns like panels, cards, sections, and overlays. ```APIDOC ## Layout Helpers ### Description Helper functions for creating common layout structures. ### Basic Layouts ```go // Basic layouts p পার্থক্য.Panel(child, border, padding) p পার্থক্য.PanelWithMargin(child, border, padding, margin) p পার্থক্য.Card(title, titleColor, borderColor, children...) p পার্থক্য.Section(header, headerColor, children...) p পার্থক্য.Separated(children...) ``` ### Advanced Layouts ```go // Advanced layouts p পার্থক্য.Overlay(children...) // ZStack with default alignment p পার্থক্য.FlexGrow(child, grow) p পার্থক্য.Position(child, x, y) p পার্থক্য.PositionRight(child, right, y) p পার্থক্য.PositionBottom(child, x, bottom) p পার্থক্য.PositionCorner(child, right, bottom) ``` ``` -------------------------------- ### Use Custom Component in Markup Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md Utilize a custom component registered in Go within your XML markup. Pass properties to customize its appearance and behavior. ```xml ``` -------------------------------- ### Create Separated Layout Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Arranges multiple child elements with separators between them. ```go pony.Separated(children...) ``` -------------------------------- ### Apply Position Layout Helper Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Positions a child element at specific X and Y coordinates. ```go pony.Position(child, x, y) ``` -------------------------------- ### Stateful Component for Scrolling Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md Create a stateful component to manage scroll position dynamically. This approach allows for interactive and dynamic scrolling, but requires state management. ```go type ScrollableLog struct { content []string offset int height int } func (s *ScrollableLog) Update(msg tea.Msg) { switch msg := msg.(type) { case tea.KeyPressMsg: if msg.String() == "down" { s.offset++ } } } func (s *ScrollableLog) Render() pony.Element { items := /* build elements from content */ return &pony.ScrollView{ Child: pony.NewVStack(items...), OffsetY: s.offset, // Dynamic offset! Height: pony.NewFixedConstraint(s.height), } } // In template // In View slots["log"] = m.log.Render() ``` -------------------------------- ### Markup-Based Scrolling Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md Demonstrates how to use the `` element directly in markup for static scrolling. ```APIDOC ## Markup-Based Scrolling Use `` directly in markup: ```xml Line 1 Line 2 ``` **Pros**: Simple, declarative **Cons**: Static offset (set via `offset-y` attribute) ``` -------------------------------- ### Perform Golden File Rendering Tests Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md Use golden files for rendering tests by comparing the output of tmpl.Render against a stored golden file. Regenerate golden files with `go test -update ./...` when rendering changes are intentional. ```go func TestMyRender(t *testing.T) { output := tmpl.Render(data, 80, 24) golden.RequireEqual(t, output) // Compares against testdata/TestMyRender.golden } ``` -------------------------------- ### Mouse Support for Scrolling Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md Explains how to enable and handle mouse events, specifically the scroll wheel, for interactive scrolling. ```APIDOC ## Mouse Support Enable mouse in Bubble Tea: ```go func (m model) View() tea.View { output := m.template.Render(data, m.width, m.height) view := tea.NewView(output) view.MouseMode = tea.MouseModeCellMotion // Enable mouse! return view } ``` Then handle mouse events: ```go func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.MouseWheelMsg: m := msg.Mouse() if m.Button == tea.MouseWheelUp { m.scrollable.ScrollUp(3) } else if m.Button == tea.MouseWheelDown { m.scrollable.ScrollDown(3) } } } ``` ``` -------------------------------- ### Component Registry Source: https://github.com/charmbracelet/x/blob/main/pony/README.md APIs for registering, unregistering, and retrieving components from the component registry. ```APIDOC ## Component Registry ### Description Manage custom components within the Pony engine. ### Register Component ```go pony.Register(name, factory) ``` ### Unregister Component ```go pony.Unregister(name) ``` ### Get Component ```go pony.GetComponent(name) ``` ### List Registered Components ```go pony.RegisteredComponents() ``` ``` -------------------------------- ### Stateful Component Scrolling Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md Illustrates creating a stateful component to manage scroll position interactively. ```APIDOC ## Stateful Component Scrolling Create a stateful component that manages scroll position: ```go type ScrollableLog struct { content []string offset int height int } func (s *ScrollableLog) Update(msg tea.Msg) { switch msg := msg.(type) { case tea.KeyPressMsg: if msg.String() == "down" { s.offset++ } } } func (s *ScrollableLog) Render() pony.Element { items := /* build elements from content */ return &pony.ScrollView{ Child: pony.NewVStack(items...), OffsetY: s.offset, // Dynamic offset! Height: pony.NewFixedConstraint(s.height), } } // In template // In View slots["log"] = m.log.Render() ``` **Pros**: Interactive, dynamic scrolling **Cons**: Requires state management ``` -------------------------------- ### ProgressView Component Source: https://github.com/charmbracelet/x/blob/main/pony/README.md The progressview component visualizes progress. Configure its value, maximum, width, and style. ```xml ``` -------------------------------- ### Parse Template with Type Safety Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Demonstrates how to parse a Pony template with generic type safety or using a panic-on-error approach. ```go // Parse with type safety tmpl, err := pony.Parse[YourDataType](markup) tmpl := pony.MustParse[YourDataType](markup) ``` -------------------------------- ### Registering a New Component Functionally Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md To add a new built-in component that can be used in markup, register a functional component with a unique name and a function that returns an `Element`. ```go Register("badge", func(props Props, children []Element) Element { ... }) ``` -------------------------------- ### Flexible Layout with Spacer Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Use the spacer component within a VStack to create flexible spacing that grows to fill available space. ```xml Header Footer ``` -------------------------------- ### Register Functional Component Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Register a new UI component using a simple functional approach. This is suitable for stateless components. ```go // Simple functional component pony.Register("card", func(props pony.Props, children []pony.Element) pony.Element { return pony.NewBox( pony.NewVStack( pony.NewText(props.Get("title")).Bold(), pony.NewDivider(), pony.NewVStack(children...), ), ).Border("rounded").Padding(1) }) ``` -------------------------------- ### Create Divider Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Inserts a visual divider element. ```go pony.NewDivider() ``` -------------------------------- ### Run Pony Tests with Verbose Output Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md Run all tests with verbose output enabled to see detailed test execution information. ```bash go test -v ``` -------------------------------- ### Define Stateful Input Component in Go Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md Defines a stateful input component with value, cursor, and focus management. It handles key press events to update its value and renders as a styled Pony element. ```go type Input struct { value string cursor int focused bool } // Update handles events (state management) func (i *Input) Update(msg tea.Msg) { switch msg := msg.(type) { case tea.KeyPressMsg: i.value += msg.String() i.cursor++ } } // Render returns pony Element (no size needed!) func (i *Input) Render() pony.Element { style, _ := pony.ParseStyle("fg:white") return pony.NewBox( pony.NewText(i.value).WithStyle(style), ).WithBorder("rounded").WithPadding(1) ``` -------------------------------- ### Go Template Variables Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Embed dynamic data into text elements using Go template syntax for variable substitution. ```xml Hello, {{ .Username }}! ``` -------------------------------- ### New Feature Golden File Test Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md A template for writing new golden file tests for rendering output. Ensure the output is compared against the correct golden file. ```go func TestNewFeature(t *testing.T) { output := tmpl.Render(data, width, height) golden.RequireEqual(t, output) } ``` -------------------------------- ### Template with Slots in XML Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Define a template structure using XML, incorporating slots where dynamic content will be rendered. The "input" slot is defined here. ```xml Username: ``` -------------------------------- ### Create Positioned Element Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Creates a positioned element with explicit X and Y coordinates. ```go pony.NewPositioned(child, x, y) ``` -------------------------------- ### Apply Flex Grow Layout Helper Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Applies a flex grow factor to a child element within a flex container. ```go pony.FlexGrow(child, grow) ``` -------------------------------- ### Button Component Source: https://github.com/charmbracelet/x/blob/main/pony/README.md Create clickable buttons using the button component. Customize text, border, and padding. ```xml