tessera-ui-macros 0.4.1

Macros of tessera-ui, for creating functional components.
Documentation

Tessera Macros

简体中文

The tessera_macros crate provides procedural macros for the Tessera UI framework. Currently, it contains the #[tessera] attribute macro, which is essential for creating components in the Tessera framework.

Overview

The #[tessera] macro transforms regular Rust functions into Tessera UI components by automatically integrating them into the framework's component tree and injecting necessary runtime functionality.

Features

  • Component Integration: Automatically registers functions as components in the Tessera component tree
  • Runtime Injection: Provides access to measure and input_handler functions within component functions
  • Clean Syntax: Enables declarative component definition with minimal boilerplate
  • Tree Management: Handles component tree node creation and cleanup automatically

Usage

Basic Component Definition

use tessera_macros::tessera;

#[tessera]
fn my_component() {
    // Your component logic here
    // The macro automatically provides access to:
    // - measure: for custom layout logic
    // - input_handler: for handling user interactions
}

Component with Parameters

use tessera_macros::tessera;
use std::sync::Arc;

#[tessera]
fn button_component(label: String, on_click: Arc<dyn Fn()>) {
    // Component implementation
    // The macro handles component tree integration
}

Using Measure and Input Handler

use tessera_macros::tessera;
use tessera::{ComputedData, Constraints};

#[tessera]
fn custom_component() {
    // Define custom layout behavior
    measure(Box::new(|_| {
        // Custom measurement logic
        use tessera::{ComputedData, Px};
        Ok(ComputedData {
            width: Px(100),
            height: Px(50),
        })
    }));

    // Handle user interactions
    input_handler(Box::new(|_| {
        // Handle events like clicks, key presses, etc.
    }));
}

How It Works

The #[tessera] macro performs the following transformations:

  1. Component Registration: Adds the function to the component tree with its name
  2. Runtime Access: Injects code to access the Tessera runtime
  3. Function Injection: Provides measure and input_handler functions in the component scope
  4. Tree Management: Handles pushing and popping nodes from the component tree
  5. Error Safety: Wraps the original function body to prevent early returns from breaking the component tree

Before Macro Application

#[tessera]
fn my_component() {
    // Component logic
}

After Macro Application (Conceptual)

fn my_component() {
    // Component tree registration
    TesseraRuntime::write().component_tree.add_node(ComponentNode { ... });
    
    // Inject measure and input_handler functions
    let measure = |fun: Box<MeasureFn>| { /* ... */ };
    let input_handler = |fun: Box<InputHandlerFn>| { /* ... */ };
    
    // Execute original function body safely
    let result = {
        let closure = || {
            // Original component logic here
        };
        closure()
    };
    
    // Clean up component tree
    TesseraRuntime::write().component_tree.pop_node();
    
    result
}

Examples

Simple Counter Component

use tessera_macros::tessera;
use std::sync::{Arc, atomic::{AtomicI32, Ordering}};

#[tessera]
fn counter_component(count: Arc<AtomicI32>) {
    let current_count = count.load(Ordering::Relaxed);
    
    // Use tessera_basic_components for UI
    button(
        ButtonArgs {
            on_click: Arc::new(move || {
                count.fetch_add(1, Ordering::Relaxed);
            }),
            ..Default::default()
        },
        button_state,
        move || text(format!("Count: {}", current_count)),
    );
}

Custom Layout Component

use tessera_macros::tessera;
use tessera::{ComputedData, Constraints, Px};

#[tessera]
fn custom_layout() {
    measure(Box::new(|_| {
        // Custom measurement logic
        use tessera::{ComputedData, Px};
        
        Ok(ComputedData {
            width: Px(120),
            height: Px(80),
        })
    }));
    
    // Child components
    text("Hello, World!");
}

Contributing

This crate is part of the larger Tessera project. For contribution guidelines, please refer to the main Tessera repository.

License

This project is licensed under the same terms as the main Tessera framework. See the LICENSE file for details.