# Tessera Macros
[![简体中文][readme-cn-badge]][readme-cn-url]
[readme-cn-badge]: https://img.shields.io/badge/README-简体中文-blue.svg?style=for-the-badge&logo=readme
[readme-cn-url]: https://github.com/tessera-ui/tessera/blob/main/tessera-ui-macros/docs/README_zh-CN.md
The `tessera_macros` crate provides procedural macros for the [Tessera UI framework](https://github.com/tessera-ui/tessera). 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
```rust
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
```rust
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
```rust
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
```rust
#[tessera]
fn my_component() {
// Component logic
}
```
### After Macro Application (Conceptual)
```rust
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
```rust
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
```rust
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](https://github.com/tessera-ui/tessera).
## License
This project is licensed under the same terms as the main Tessera framework. See the [LICENSE](https://github.com/tessera-ui/tessera/blob/main/LICENSE) file for details.