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