### Integrate Bubblezone with Lipgloss for Styled Buttons Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Integrates Bubblezone with Lipgloss to create clickable, styled elements in the terminal. This example shows how to apply styles using Lipgloss and then mark the styled content as a clickable zone using Bubblezone. ```ruby require "lipgloss" require "bubblezone" Bubblezone.new_global button_style = Lipgloss::Style.new .background("#7D56F4") .foreground("#FFFFFF") .padding(0, 3) styled_button = button_style.render("Click Me") clickable_button = Bubblezone.mark("btn", styled_button) output = Bubblezone.scan(clickable_button) ``` -------------------------------- ### Install Bubblezone Gem Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Installs the Bubblezone gem, which is a helper utility for Bubble Tea to track mouse events in terminal applications. This can be done by adding it to your Gemfile or installing it directly using the gem command. ```ruby gem "bubblezone" ``` ```bash gem install bubblezone ``` -------------------------------- ### Bubble Tea Clickable App with Mouse Support (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt A complete example integrating Bubblezone with Bubble Tea to create a clickable terminal application that supports mouse interactions. It demonstrates handling user input, mouse events, and rendering interactive elements. ```ruby require "bubbletea" require "bubblezone" Bubblezone.new_global class ClickableApp include Bubbletea::Model ITEMS = [ { id: "item_1", title: "Raspberry Pi's", desc: "I have 'em all over my house" }, { id: "item_2", title: "Nutella", desc: "It's good on toast" }, { id: "item_3", title: "Cats", desc: "Usually" }, ].freeze def initialize @cursor = 0 @selected = nil @prefix = Bubblezone.new_prefix end def init [self, nil] end def update(message) case message when Bubbletea::KeyMessage case message.to_s when "q", "ctrl+c" [self, Bubbletea.quit] when "up", "k" @cursor = (@cursor - 1) % ITEMS.length [self, nil] when "down", "j" @cursor = (@cursor + 1) % ITEMS.length [self, nil] when "enter", " " @selected = @cursor [self, nil] else [self, nil] end when Bubbletea::MouseMessage handle_mouse(message) else [self, nil] end end def view lines = ["", " Click on an item to select it", ""] ITEMS.each_with_index do |item, i| cursor = i == @cursor ? "> " : " " check = i == @selected ? "[x]" : "[ ]" title = Bubblezone.mark(item[:id], item[:title]) lines << " #{cursor}#{check} #{title} - #{item[:desc]}" end lines << "" lines << " j/k: navigate | click: select | enter: confirm | q: quit" if @selected lines << "" lines << " Selected: #{ITEMS[@selected][:title]}" end Bubblezone.scan(lines.join("\n")) end private def handle_mouse(message) # Only handle left button release return [self, nil] unless message.release? return [self, nil] unless message.left? || message.button.zero? # Check each item zone ITEMS.each_with_index do |item, i| zone = Bubblezone.get(item[:id]) if zone&.in_bounds?(message.x, message.y) @cursor = i @selected = i break end end [self, nil] end end # Run with mouse support enabled # Bubbletea.run(ClickableApp.new, alt_screen: true, mouse_cell_motion: true) ``` -------------------------------- ### Integrate Bubblezone with Bubbletea for Mouse Clicks Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Integrates Bubblezone with Bubbletea to handle mouse clicks within the terminal UI. This example demonstrates how to update the application state based on which marked zone was clicked, using mouse event messages. ```ruby require "bubbletea" require "bubblezone" Bubblezone.new_global class ClickableApp include Bubbletea::Model ITEMS = ["Option A", "Option B", "Option C"] def initialize @selected = nil @prefix = Bubblezone.new_prefix end def init [self, nil] end def update(message) case message when Bubbletea::MouseMessage if message.release? && (message.left? || message.button == 0) result = Bubblezone.find_in_bounds(message.x, message.y) if result id, _zone = result @selected = id.sub(@prefix, "").to_i end end [self, nil] when Bubbletea::KeyMessage return [self, Bubbletea.quit] if message.to_s == "q" [self, nil] else [self, nil] end end def view lines = ITEMS.map.with_index do |item, i| marker = i == @selected ? "[x]" : "[ ]" content = "#{marker} #{item}" Bubblezone.mark("#{@prefix}#{i}", content) end Bubblezone.scan(lines.join("\n")) end end Bubbletea.run(ClickableApp.new, alt_screen: true, mouse_cell_motion: true) ``` -------------------------------- ### Get Zone Information (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt The `get` method retrieves a `ZoneInfo` object for a registered zone, containing its bounding coordinates (start/end x, y, width, height). It returns `nil` if the zone does not exist. A small delay might be needed for asynchronous processing. ```ruby require "bubblezone" Bubblezone.new_global # Create and scan a layout layout = "Header\n#{Bubblezone.mark("my_button", "Click Me")}\nFooter" Bubblezone.scan(layout) sleep(0.01) # Small delay for zone registration zone = Bubblezone.get("my_button") if zone puts "Zone bounds:" puts " Start: (#{zone.start_x}, #{zone.start_y})" # => Start: (0, 1) puts " End: (#{zone.end_x}, #{zone.end_y})" # => End: (7, 1) puts " Size: #{zone.width}x#{zone.height}" # => Size: 8x1 puts zone.to_s # => "ZoneInfo(start: (0, 1), end: (7, 1))" end # Check for non-existent zone unknown = Bubblezone.get("nonexistent") puts unknown.nil? # => true ``` -------------------------------- ### Get Zone Information by ID Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Retrieves information about a previously marked zone using its unique ID. This function returns a zone object that contains details such as its starting and ending coordinates. ```ruby zone = Bubblezone.get("my_button") if zone puts "Zone bounds: (#{zone.start_x}, #{zone.start_y}) to (#{zone.end_x}, #{zone.end_y})" end ``` -------------------------------- ### Mark Text with Zone ID (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt The `mark` method wraps text content with invisible markers to identify a clickable zone. These markers are stripped during scanning but allow the library to track the zone's position. This example demonstrates marking a single button and multiple items in an array. ```ruby require "bubblezone" Bubblezone.new_global # Mark a simple button button = Bubblezone.mark("submit_btn", "Submit") puts button.include?("Submit") # => true (original text preserved) puts button == "Submit" # => false (contains invisible markers) # Mark multiple items with unique IDs items = ["Apple", "Banana", "Cherry"] marked_items = items.map.with_index do |item, i| Bubblezone.mark("item_#{i}", item) end layout = marked_items.join("\n") puts layout # Apple # Banana # Cherry ``` -------------------------------- ### Check Mouse Coordinates Against Zone (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt The `in_bounds?` method on a `ZoneInfo` object checks if given x,y coordinates fall within the zone's bounds, useful for detecting mouse clicks. It also provides the `pos` method to get the relative position within the zone and `zero?` to check if coordinates are valid. ```ruby require "bubblezone" Bubblezone.new_global # Create a simple UI layout = Bubblezone.mark("clickable", "Click Here") Bubblezone.scan(layout) sleep(0.01) zone = Bubblezone.get("clickable") # Simulate mouse coordinates from a click event mouse_x, mouse_y = 5, 0 # Within "Click Here" text if zone&.in_bounds?(mouse_x, mouse_y) puts "Zone clicked!" # Get relative position within zone rel_x, rel_y = zone.pos(mouse_x, mouse_y) puts "Clicked at relative position: (#{rel_x}, #{rel_y})" end # Check coordinates outside the zone puts zone.in_bounds?(100, 100) # => false # Check if zone has valid position data puts zone.zero? # => false (zone has been scanned and has coordinates) ``` -------------------------------- ### ZoneInfo Properties and Methods (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Demonstrates the `ZoneInfo` class in Bubblezone, explaining its properties for position and dimensions, and its methods for coordinate checking and relative positioning. This is useful for handling sub-zone interactions. ```ruby require "bubblezone" Bubblezone.new_global # Create a zone and scan it layout = "Prefix: #{Bubblezone.mark("example", "ABCDEFGH")} Suffix" Bubblezone.scan(layout) sleep(0.01) zone = Bubblezone.get("example") # Position properties (0-indexed coordinates) puts "Start X: #{zone.start_x}" # Column where zone begins puts "Start Y: #{zone.start_y}" # Row where zone begins puts "End X: #{zone.end_x}" # Column where zone ends (inclusive) puts "End Y: #{zone.end_y}" # Row where zone ends (inclusive) # Dimension methods puts "Width: #{zone.width}" # end_x - start_x + 1 puts "Height: #{zone.height}" # end_y - start_y + 1 puts "Size: #{zone.size}" # [width, height] array # Coordinate checking puts zone.in_bounds?(zone.start_x, zone.start_y) # => true (start corner) puts zone.in_bounds?(zone.end_x, zone.end_y) # => true (end corner) puts zone.in_bounds?(zone.end_x + 1, zone.start_y) # => false (outside) # Relative positioning (useful for sub-zone click handling) rel_x, rel_y = zone.pos(zone.start_x + 2, zone.start_y) puts "Relative position: (#{rel_x}, #{rel_y})" # => (2, 0) # Check if zone has valid coordinates puts zone.zero? # => false (has been scanned with valid position) # String representations puts zone.to_s # => "ZoneInfo(start: (8, 0), end: (15, 0))" puts zone.inspect # => "#" ``` -------------------------------- ### Create and Use a Dedicated Manager Instance Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Creates a dedicated Bubblezone manager instance instead of using the global one. This allows for better isolation and management of zones, especially in complex applications. The manager provides the same API as the global manager. ```ruby manager = Bubblezone::Manager.new marked = manager.mark("zone_id", "Content") output = manager.scan(marked) zone = manager.get("zone_id") manager.each_in_bounds(x, y) { |id, zone| ... } manager.close ``` -------------------------------- ### Create Independent Manager Instances in Bubblezone (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Illustrates how to create and use independent `Bubblezone::Manager` instances, allowing for isolated zone registries within complex applications. This approach is beneficial for managing distinct sets of zones without interference. ```ruby require "bubblezone" # Create independent managers manager1 = Bubblezone::Manager.new manager2 = Bubblezone::Manager.new # Each manager tracks its own zones manager1.mark("shared_id", "Manager 1 Content") manager2.mark("shared_id", "Manager 2 Content") # Zone IDs are isolated puts manager1.zone_ids # => ["shared_id"] puts manager2.zone_ids # => ["shared_id"] # Scan and get zones independently output1 = manager1.scan(manager1.mark("btn", "Button 1")) output2 = manager2.scan(manager2.mark("btn", "Button 2")) sleep(0.01) zone1 = manager1.get("btn") zone2 = manager2.get("btn") # zone1 and zone2 have different coordinates # Same iteration methods available manager1.each_in_bounds(0, 0) { |id, zone| puts "Manager1: #{id}" } result = manager2.find_in_bounds(0, 0) # Enable/disable per manager manager1.enabled = false puts manager1.enabled? # => false # Generate prefixes per manager prefix = manager1.new_prefix # Cleanup manager1.clear_all manager1.close manager2.close ``` -------------------------------- ### Initialize Global Zone Manager (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Initializes the global zone manager for Bubblezone, which is required before using any other Bubblezone functions. It also shows how to check, enable, and disable zone tracking, and retrieve version information. The manager can be closed for cleanup. ```ruby require "bubblezone" # Initialize the global zone manager (required before any other operations) Bubblezone.new_global # Check if zone tracking is enabled (default: true) puts Bubblezone.enabled? # => true # Disable/enable zone tracking Bubblezone.enabled = false Bubblezone.enabled = true # Get version information puts Bubblezone.version # => "bubblezone v0.1.0 (upstream v1.0.0) [Go native extension]" # Close the global manager when done (cleanup) # Bubblezone.close ``` -------------------------------- ### Initialize Global Zone Manager Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Initializes the global zone manager for Bubblezone. This manager is used to track all marked regions within the terminal application. It should be called once at the beginning of the application. ```ruby require "bubblezone" Bubblezone.new_global ``` -------------------------------- ### Scan Layout to Register Zones Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Scans the provided layout string to register all marked zones. This function processes the layout, identifies the marked regions, and makes them available for interaction. The output is the processed layout ready for display. ```ruby layout = "Header\n#{button}\nFooter" output = Bubblezone.scan(layout) puts output ``` -------------------------------- ### Generate Unique Zone Prefixes in Bubblezone (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Explains how to use the `new_prefix` method in Bubblezone to generate unique prefixes, preventing zone ID collisions between different components. This is crucial for creating reusable and modular components. ```ruby require "bubblezone" Bubblezone.new_global # Each call generates a new unique prefix prefix1 = Bubblezone.new_prefix prefix2 = Bubblezone.new_prefix puts prefix1 # => "zone_1__" puts prefix2 # => "zone_2__" # Use prefixes in components to avoid ID conflicts class ListComponent def initialize(items) @items = items @prefix = Bubblezone.new_prefix end def view @items.map.with_index do |item, i| Bubblezone.mark("#{@prefix}#{i}", item) end.join("\n") end def handle_click(x, y) @items.each_with_index do |item, i| zone = Bubblezone.get("#{@prefix}#{i}") if zone&.in_bounds?(x, y) puts "Clicked: #{item}" return i end end nil end end list1 = ListComponent.new(["Apple", "Banana"]) list2 = ListComponent.new(["Red", "Blue"]) # Both lists can coexist without ID collisions layout = "#{list1.view}\n---\n#{list2.view}" Bubblezone.scan(layout) ``` -------------------------------- ### Iterate Zones at Coordinates in Bubblezone (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Demonstrates how to find all zones containing specific coordinates using Bubblezone's iteration methods. This is useful for handling overlapping zones or efficient multi-zone checks. It covers `each_in_bounds`, `any_in_bounds?`, and `find_in_bounds`. ```ruby require "bubblezone" Bubblezone.new_global # Create overlapping zones (nested marks) outer = Bubblezone.mark("outer", Bubblezone.mark("inner", "Nested Content")) Bubblezone.scan(outer) sleep(0.01) mouse_x, mouse_y = 2, 0 # Iterate all zones containing the coordinates Bubblezone.each_in_bounds(mouse_x, mouse_y) do |id, zone| puts "Hit zone: #{id} at (#{zone.start_x}-#{zone.end_x})" end # Output: # Hit zone: inner at (0-13) # Hit zone: outer at (0-13) # Use as an Enumerator zones = Bubblezone.each_in_bounds(mouse_x, mouse_y).to_a puts "Found #{zones.length} zones" # => Found 2 zones # Check if any zone contains coordinates if Bubblezone.any_in_bounds?(mouse_x, mouse_y) puts "Something was clicked" end # Get only the first matching zone result = Bubblezone.find_in_bounds(mouse_x, mouse_y) if result id, zone = result puts "First match: #{id}" # => First match: inner end ``` -------------------------------- ### Create a Unique Zone Prefix Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Creates a unique prefix for zone IDs to prevent conflicts when multiple components or instances manage their own zones. This ensures that zone IDs remain unique across different parts of the application. ```ruby class MyComponent def initialize @prefix = Bubblezone.new_prefix end def view items = ["Apple", "Banana", "Cherry"] items.map.with_index do |item, i| Bubblezone.mark("#{@prefix}#{i}", item) end.join("\n") end end ``` -------------------------------- ### Mark a Region with an ID Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Marks a specific region of text with a unique ID. This allows the application to later identify and interact with this region. The marked region is then used when building the terminal layout. ```ruby button = Bubblezone.mark("my_button", "Click Me") ``` -------------------------------- ### Find the First Zone Containing Coordinates Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Finds the first marked zone that contains the given mouse coordinates. Returns the ID and zone object of the first matching zone, or nil if no zone contains the coordinates. ```ruby result = Bubblezone.find_in_bounds(x, y) if result id, zone = result puts "First hit: #{id}" end ``` -------------------------------- ### Scan Layout to Register Zones (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt The `scan` method processes marked text to register zone coordinates and returns the clean output with markers removed. This method should be called on the final rendered view of your application. It registers zones like buttons within a layout. ```ruby require "bubblezone" Bubblezone.new_global # Build a layout with marked zones header = "=== My App ===" button1 = Bubblezone.mark("btn1", "[ OK ]") button2 = Bubblezone.mark("btn2", "[ Cancel ]") layout = "#{header}\n#{button1} #{button2}" # Scan to register zones and get clean output output = Bubblezone.scan(layout) puts output # === My App === # [ OK ] [ Cancel ] # Zones are now registered with their coordinates # btn1 is at row 1, columns 0-5 # btn2 is at row 1, columns 8-17 ``` -------------------------------- ### Iterate Over Zones Containing Coordinates Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Iterates over all marked zones that contain the given mouse coordinates. This allows for handling interactions with multiple overlapping zones. ```ruby Bubblezone.each_in_bounds(x, y) do |id, zone| puts "Hit zone: #{id}" end ``` -------------------------------- ### Manage Zone IDs in Bubblezone (Ruby) Source: https://context7.com/marcoroth/bubblezone-ruby/llms.txt Details methods for managing registered zone IDs within Bubblezone, including retrieving all IDs, clearing specific zones, and clearing all zones. This functionality is useful for debugging and managing application state, especially during screen transitions. ```ruby require "bubblezone" Bubblezone.new_global # Mark several zones Bubblezone.mark("zone_a", "A") Bubblezone.mark("zone_b", "B") Bubblezone.mark("zone_c", "C") # Get all tracked zone IDs ids = Bubblezone.zone_ids puts ids.inspect # => ["zone_a", "zone_b", "zone_c"] # Clear a specific zone Bubblezone.clear("zone_b") puts Bubblezone.zone_ids.include?("zone_b") # => false # Clear all zones (useful between screen transitions) Bubblezone.clear_all puts Bubblezone.zone_ids.empty? # => true ``` -------------------------------- ### Check if Any Zone Contains Coordinates Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Checks if any of the marked zones contain the given mouse coordinates. Returns true if at least one zone contains the coordinates, false otherwise. ```ruby if Bubblezone.any_in_bounds?(x, y) puts "Something was clicked" end ``` -------------------------------- ### Check if Coordinates are Within a Zone Source: https://github.com/marcoroth/bubblezone-ruby/blob/main/README.md Checks if a given set of mouse coordinates (x, y) falls within the boundaries of a specific zone. This is useful for detecting clicks on marked regions. ```ruby x, y = message.x, message.y zone = Bubblezone.get("my_button") if zone&.in_bounds?(x, y) puts "Button clicked!" end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.