Skip to main content

kozan_macros/
lib.rs

1//! Derive macros for Kozan node types.
2//!
3//! - [`Node`] — for non-element nodes (`TextNode`, `CommentNode`)
4//! - [`Element`] — for element nodes (Button, Div, Input)
5//! - [`Props`] — generates getters/setters from data structs
6
7mod crate_path;
8mod derive_element;
9mod derive_event;
10mod derive_node;
11mod derive_props;
12
13use proc_macro::TokenStream;
14use syn::{DeriveInput, parse_macro_input};
15
16/// Derive the [`Node`] trait for a newtype wrapper around `Handle`.
17///
18/// Use this for **non-element** node types that cannot have children
19/// or attributes (e.g., `TextNode`, `CommentNode`).
20///
21/// # Example
22///
23/// ```ignore
24/// #[derive(Copy, Clone, Node)]
25/// pub struct TextNode(Handle);
26/// ```
27///
28/// Generates `impl Node for TextNode` and `impl Debug for TextNode`.
29#[proc_macro_derive(Node)]
30pub fn derive_node(input: TokenStream) -> TokenStream {
31    let input = parse_macro_input!(input as DeriveInput);
32    derive_node::expand(&input).into()
33}
34
35/// Derive `Node`, `ContainerNode`, and `Element` traits for an element type.
36///
37/// Use this for **element** node types that can have children, attributes,
38/// and element-specific data.
39///
40/// # Attributes
41///
42/// - `tag = "..."` — **(required)** the HTML tag name
43/// - `focusable` — mark the element as focusable by default
44/// - `data = TypeName` — the element-specific data type (default: `()`)
45///
46/// # Example
47///
48/// ```ignore
49/// #[derive(Copy, Clone, Element)]
50/// #[element(tag = "button", focusable, data = ButtonData)]
51/// pub struct Button(Handle);
52/// ```
53#[proc_macro_derive(Element, attributes(element))]
54pub fn derive_element(input: TokenStream) -> TokenStream {
55    let input = parse_macro_input!(input as DeriveInput);
56    derive_element::expand(&input)
57        .unwrap_or_else(|e| e.to_compile_error())
58        .into()
59}
60
61/// Generate getters and setters on an element type from its data struct.
62///
63/// Fields marked with `#[prop]` get a getter (`fn field(&self) -> T`)
64/// and a setter (`fn set_field(&self, value: impl Into<T>)`).
65///
66/// # Attributes
67///
68/// - `element = TypeName` — **(required)** the element handle type
69///
70/// # Example
71///
72/// ```ignore
73/// #[derive(Default, Props)]
74/// #[props(element = Button)]
75/// pub struct ButtonData {
76///     #[prop]
77///     pub label: String,
78///     #[prop]
79///     pub disabled: bool,
80/// }
81/// ```
82/// Derive the [`Event`] trait for an event struct.
83///
84/// # Attributes
85///
86/// - `bubbles` — the event bubbles up through the tree
87/// - `cancelable` — the event can be cancelled via `prevent_default()`
88///
89/// # Example
90///
91/// ```ignore
92/// #[derive(Event)]
93/// #[event(bubbles, cancelable)]
94/// pub struct ClickEvent {
95///     pub x: f32,
96///     pub y: f32,
97/// }
98/// ```
99#[proc_macro_derive(Event, attributes(event))]
100pub fn derive_event(input: TokenStream) -> TokenStream {
101    let input = parse_macro_input!(input as DeriveInput);
102    derive_event::expand(&input)
103        .unwrap_or_else(|e| e.to_compile_error())
104        .into()
105}
106
107#[proc_macro_derive(Props, attributes(props, prop))]
108pub fn derive_props(input: TokenStream) -> TokenStream {
109    let input = parse_macro_input!(input as DeriveInput);
110    derive_props::expand(&input)
111        .unwrap_or_else(|e| e.to_compile_error())
112        .into()
113}