| Crates.io | waterui-macros |
| lib.rs | waterui-macros |
| version | 0.2.1 |
| created_at | 2025-12-14 08:10:35.957139+00 |
| updated_at | 2025-12-14 11:30:58.737728+00 |
| description | Macro for WaterUI |
| homepage | |
| repository | https://github.com/water-rs/waterui |
| max_upload_size | |
| id | 1984007 |
| size | 45,133 |
Procedural macros for the WaterUI framework, providing automatic derive implementations and code generation for forms, reactive projections, string formatting, and hot reload functionality.
This crate is the macro engine behind WaterUI's ergonomic APIs. It provides four main categories of macros:
#[derive(FormBuilder)] and #[form]#[derive(Project)]s! macro#[hot_reload]This crate is typically accessed through the main waterui crate via use waterui::prelude::*; rather than being used directly.
Add to your Cargo.toml:
[dependencies]
waterui = "0.2"
The derive macros are automatically available when you import the prelude:
use waterui::prelude::*;
#[derive(FormBuilder)]Automatically implements the FormBuilder trait for structs, generating form UI components based on field types.
Type-to-Component Mapping:
| Rust Type | UI Component | Description |
|---|---|---|
String, Str |
TextField |
Text input with optional placeholder |
bool |
Toggle |
Boolean switch/checkbox |
i8..isize, u8..usize |
Stepper |
Numeric stepper with increment/decrement |
f32, f64 |
Slider |
Slider (0.0-1.0 range) |
Color |
ColorPicker |
Color selection widget |
Example from /Users/lexoliu/Coding/waterui/examples/form/src/lib.rs:
use waterui::prelude::*;
use waterui::reactive::binding;
#[form]
struct RegistrationForm {
/// Full name of the user
full_name: String,
/// Email address for account
email: String,
/// Age in years
age: i32,
/// Whether to receive marketing emails
newsletter: bool,
/// Preferred volume level (0.0 - 1.0)
volume: f64,
}
fn registration_view() -> impl View {
let registration = RegistrationForm::binding();
vstack((
form(®istration),
// Live preview using projected bindings
hstack(("Name: ", text!("{}", registration.project().full_name))),
hstack(("Email: ", text!("{}", registration.project().email))),
hstack(("Age: ", text!("{}", registration.project().age))),
))
}
How it works:
snake_case field names to "Title Case" labels (e.g., full_name → "Full Name")Project::project() on the binding to access individual fieldsVStack containing all generated form controls#[form]Convenience attribute macro that combines multiple common derives for form structs.
Equivalent to:
#[derive(Default, Clone, Debug, FormBuilder, Project)]
Example from /Users/lexoliu/Coding/waterui/examples/form/src/lib.rs:
#[form]
struct AppSettings {
/// Application theme brightness
brightness: f64,
/// Enable dark mode
dark_mode: bool,
/// Font size multiplier
font_scale: f32,
/// Auto-save interval (minutes)
auto_save_minutes: i32,
/// Enable notifications
notifications_enabled: bool,
}
#[derive(Project)]Implements the Project trait, enabling decomposition of struct bindings into separate bindings for each field. This is essential for reactive form handling where each field needs independent mutation.
Supports:
Example from /Users/lexoliu/Coding/waterui/derive/src/lib.rs documentation:
use waterui::reactive::{Binding, binding, project::Project};
use waterui_macros::Project;
#[derive(Project, Clone)]
struct Person {
name: String,
age: u32,
}
let person_binding: Binding<Person> = binding(Person {
name: "Alice".to_string(),
age: 30,
});
let projected = person_binding.project();
projected.name.set("Bob".to_string());
projected.age.set(25u32);
let person = person_binding.get();
assert_eq!(person.name, "Bob");
assert_eq!(person.age, 25);
Generated code:
For a struct MyForm, the macro generates:
MyFormProjected struct with each field wrapped in Binding<T>Project implementation that creates mapped bindings for each field'static) on generic parameterss! - Reactive String FormattingFunction-like procedural macro for creating formatted string signals with automatic variable capture. Powers the text! macro in WaterUI.
Features:
Usage patterns:
use waterui::reactive::{binding, constant};
use waterui::s;
let name = binding("Alice");
let age = binding(25);
// Named variable capture (automatic)
let msg = s!("Hello {name}, you are {age} years old");
// Positional arguments
let msg2 = s!("Hello {}, you are {}", name, age);
// Static strings (returns constant signal)
let static_msg = s!("No variables here");
Used internally by text! macro:
// From /Users/lexoliu/Coding/waterui/src/lib.rs
#[macro_export]
macro_rules! text {
($($arg:tt)*) => {
{
$crate::text::Text::new($crate::s!($($arg)*))
}
};
}
Implementation details:
zip combinator to merge multiple reactive signals__format! macro for actual formattingComputed<Str> for reactive values, Constant<Str> for static strings#[hot_reload]Attribute macro that enables per-function hot reloading during development. When the library is rebuilt via water run, only the annotated function is updated without restarting the app.
Example from /Users/lexoliu/Coding/waterui/src/debug/hot_reload.rs documentation:
use waterui::prelude::*;
#[hot_reload]
fn sidebar() -> impl View {
vstack((
text("Sidebar"),
text("Content"),
))
}
fn main() -> impl View {
hstack((
sidebar(), // This view will hot reload when modified
content_panel(),
))
}
How it works:
HotReloadView that registers with the hot reload system--cfg waterui_hot_reload_lib):
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_hot_reload_sidebar() -> *mut ()
module_path!() + function name as unique identifier (e.g., "my_crate::sidebar")Requirements:
impl ViewWATERUI_HOT_RELOAD_HOST and WATERUI_HOT_RELOAD_PORT environment variables (set by water run)RUSTFLAGS="--cfg waterui_hot_reload_lib" cargo buildFormBuilder - Generate form UI from struct definitionProject - Enable field-level reactive bindings#[form] - Convenience macro for form structs (combines multiple derives)#[hot_reload] - Enable per-function hot reloadings!(...) - Create reactive formatted strings with automatic variable captureThis is a proc-macro crate with no optional features. All macros are always available.
syn ^2.0, quote ^1.0, proc-macro2 ^1.0The macros perform extensive compile-time validation:
FormBuilder: Requires named struct fieldss!: Detects mismatched placeholder/argument counts, mixed positional/named usageProject: Rejects enums and unions (only works with structs)form: Requires structs with named fieldsForm Builder:
Quote::quote! for generating trait implementationsProject trait bounds for field accessProject:
Projected suffixBinding::mapping for bidirectional field synchronization'static bounds to generic parametersString Formatting:
zip calls for multiple signal combinationTo test changes to the macros:
# Run tests (uses waterui as dev-dependency)
cargo test -p waterui-macros
# Check macro expansion
cargo expand --package waterui-macros
# Test in a real project
cargo install --path cli
water create --playground --name macro-test
# Add #[form] to a struct and run
water run --platform ios