Skip to main content

euv_macros/
lib.rs

1//! euv_macros
2//!
3//! Procedural macros for the euv UI framework, including the `html!` macro
4//! for declarative UI syntax, the `class!` macro for CSS class definitions,
5//! the `css_vars!` macro for CSS custom properties, the `watch!` macro for
6//! reactive side effects, and the `component` attribute macro.
7
8mod class;
9mod css_vars;
10mod html;
11mod kebab;
12mod var;
13mod watch;
14
15pub(crate) use {class::*, css_vars::*, html::*, kebab::*, watch::*};
16
17use {
18    proc_macro::TokenStream,
19    proc_macro2::Span,
20    quote::{ToTokens, quote, quote_spanned},
21    syn::{
22        Expr, Ident, LitStr, Token, Type, Visibility, braced,
23        parse::{Parse, ParseStream},
24        token::{Colon, Paren, Semi},
25    },
26};
27
28/// The `html!` macro for writing declarative UI in euv.
29///
30/// This macro accepts a syntax similar to Dioxus HTML:
31///
32/// ```ignore
33/// html! {
34///     div {
35///         class: c_container()
36///         h1 { "Hello, euv!" }
37///         button {
38///             onclick: move |_| { /* handle click */ },
39///             "Click me"
40///         }
41///     }
42/// }
43/// ```
44#[proc_macro]
45pub fn html(input: TokenStream) -> TokenStream {
46    html::parse_html(input)
47}
48
49/// The `class!` macro for defining CSS classes with style properties.
50///
51/// Each class definition creates a `CssClass` function that can be used
52/// in `html!` via the `class:` attribute. Styles are automatically injected
53/// into the DOM on first use.
54///
55/// ```ignore
56/// class! {
57///     pub container {
58///         max_width: "800px";
59///         margin: "0 auto";
60///     }
61///     pub(crate) header {
62///         font_size: "28px";
63///     }
64///     hidden {
65///         display: "none";
66///     }
67/// }
68/// ```
69#[proc_macro]
70pub fn class(input: TokenStream) -> TokenStream {
71    class::parse_class(input)
72}
73
74/// The `watch!` macro for creating reactive side effects.
75///
76/// Watches one or more signals and executes a closure whenever any of them changes.
77/// The closure is also executed once immediately with the current signal values
78/// during initialisation. This initial execution is wrapped in a suppressed-update
79/// scope so that any `.set()` calls inside the body do not trigger unnecessary
80/// DynamicNode re-renders.
81///
82/// The number of signal expressions must match the number of closure parameters.
83/// Each closure parameter receives the current value (via `.get()`) of the
84/// corresponding signal.
85///
86/// ```ignore
87/// let count = use_signal(|| 0_i32);
88/// let name = use_signal(|| String::from("euv"));
89/// watch!(count, name, |count_val, name_val| {
90///     web_sys::console::log_1(&format!("count={}, name={}", count_val, name_val).into());
91/// });
92/// ```
93#[proc_macro]
94pub fn watch(input: TokenStream) -> TokenStream {
95    watch::parse_watch(input)
96}
97
98/// The `css_vars!` macro for defining CSS custom properties.
99///
100/// Each variable block creates a `CssClass` function that, when called,
101/// injects the CSS custom properties into the DOM. Variable names are
102/// automatically prefixed with `--`.
103///
104/// Variable names can be written as unquoted kebab-case identifiers
105/// (e.g., `bg-primary`) or as quoted string literals (e.g., `"bg-primary"`).
106///
107/// ```ignore
108/// css_vars! {
109///     pub c_theme_light {
110///         bg-primary: "#f8f9fb";
111///         text-primary: "#1a1a2e";
112///     }
113/// }
114/// ```
115#[proc_macro]
116pub fn css_vars(input: TokenStream) -> TokenStream {
117    css_vars::parse_css_vars(input)
118}
119
120/// The `var!` macro for referencing CSS custom properties defined via `css_vars!`.
121///
122/// The variable name can be written as an unquoted kebab-case identifier
123/// (e.g., `bg-primary`) or as a quoted string literal (e.g., `"bg-primary"`),
124/// and expands to the CSS string `"var(--bg-primary)"`.
125///
126/// ```ignore
127/// css_vars! {
128///     pub c_theme {
129///         bg-primary: "#f8f9fb";
130///     }
131/// }
132/// class! {
133///     pub c_container {
134///         background: var!(bg-primary);
135///     }
136/// }
137/// ```
138#[proc_macro]
139pub fn var(input: TokenStream) -> TokenStream {
140    var::parse_var(input)
141}
142
143/// The `component` attribute macro for marking component functions.
144#[proc_macro_attribute]
145pub fn component(_attr: TokenStream, item: TokenStream) -> TokenStream {
146    item
147}