use sim_kernel::Expr;
pub use sim_value::build::{float, int, list, map, sym, text, vector};
use crate::model::node;
pub const RESERVED_DATA_KEYS: &[&str] = &["kind"];
pub fn stack(dir: &str, children: Vec<Expr>) -> Expr {
node(
"stack",
vec![("dir", sym(dir)), ("children", list(children))],
)
}
pub fn box_(role: &str, children: Vec<Expr>) -> Expr {
node(
"box",
vec![("role", sym(role)), ("children", list(children))],
)
}
pub fn badge(status: &str, label: &str) -> Expr {
node(
"badge",
vec![("status", sym(status)), ("label", text(label))],
)
}
pub fn text_node(content: impl Into<String>) -> Expr {
node("text", vec![("text", text(content.into()))])
}
pub fn data_map(entries: Vec<(&str, Expr)>) -> Expr {
debug_assert!(
entries
.iter()
.all(|(key, _)| !RESERVED_DATA_KEYS.contains(key)),
"data_map: a plain data map must not use a reserved scene-node key (e.g. 'kind'); \
rename the field"
);
map(entries)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scene_shape_helpers_validate() {
let scene = stack(
"column",
vec![box_("summary", vec![text_node("hi"), badge("ok", "done")])],
);
crate::model::validate_scene(&scene).expect("helper scenes validate");
}
#[test]
fn data_map_allows_non_reserved_keys() {
let value = data_map(vec![("style", sym("line")), ("at", int(3))]);
assert!(matches!(value, Expr::Map(_)));
}
#[test]
#[should_panic(expected = "reserved scene-node key")]
fn data_map_rejects_a_reserved_key_in_debug() {
let _ = data_map(vec![("kind", sym("line"))]);
}
}