use crate::accessibility;
use crate::prop_value::PropValue;
use crate::surface::SurfaceNode;
pub struct ScrollListBuilder {
items: PropValue,
render: PropValue,
key: PropValue,
on_reorder: Option<PropValue>,
dividers: Option<bool>,
}
impl ScrollListBuilder {
pub fn new(items: PropValue, render: PropValue, key: PropValue) -> Self {
Self {
items,
render,
key,
on_reorder: None,
dividers: None,
}
}
pub fn on_reorder(mut self, on_reorder: PropValue) -> Self {
self.on_reorder = Some(on_reorder);
self
}
pub fn dividers(mut self, dividers: bool) -> Self {
self.dividers = Some(dividers);
self
}
pub fn build(self) -> SurfaceNode {
let mut node = SurfaceNode::new("ScrollList");
node.set_prop("items", self.items);
node.set_prop("render", self.render);
node.set_prop("key", self.key);
if let Some(on_reorder) = self.on_reorder {
node.set_prop("on_reorder", on_reorder);
}
if let Some(dividers) = self.dividers {
node.set_prop("dividers", PropValue::Bool(dividers));
}
accessibility::ensure_accessible(&mut node);
node
}
}
pub fn validate_list_node(node: &SurfaceNode) -> Vec<String> {
match node.component_type.as_str() {
"ScrollList" => validate_scroll_list(node),
_ => vec![format!("Unknown list component: {}", node.component_type)],
}
}
fn validate_scroll_list(node: &SurfaceNode) -> Vec<String> {
let mut errors = Vec::new();
match node.props.get("items") {
Some(PropValue::List(_)) => {}
Some(other) => errors.push(format!(
"ScrollList.items: expected list, got {}",
other.type_name()
)),
None => errors.push("ScrollList.items: required prop missing".to_string()),
}
match node.props.get("render") {
Some(PropValue::Lambda { .. }) => {}
Some(other) => errors.push(format!(
"ScrollList.render: expected lambda, got {}",
other.type_name()
)),
None => errors.push("ScrollList.render: required prop missing".to_string()),
}
match node.props.get("key") {
Some(PropValue::Lambda { .. }) => {}
Some(other) => errors.push(format!(
"ScrollList.key: expected lambda, got {}",
other.type_name()
)),
None => errors.push("ScrollList.key: required prop missing".to_string()),
}
if let Some(prop) = node.props.get("on_reorder") {
if !matches!(prop, PropValue::Lambda { .. }) {
errors.push(format!(
"ScrollList.on_reorder: expected lambda, got {}",
prop.type_name()
));
}
}
if let Some(prop) = node.props.get("dividers") {
if !matches!(prop, PropValue::Bool(_)) {
errors.push(format!(
"ScrollList.dividers: expected bool, got {}",
prop.type_name()
));
}
}
if !node.children.is_empty() {
errors.push(format!(
"ScrollList: does not accept children, but got {}",
node.children.len()
));
}
if let Some(prop) = node.props.get("accessible") {
errors.extend(accessibility::validate_accessible_prop("ScrollList", prop));
}
for key in node.props.keys() {
if !matches!(
key.as_str(),
"items" | "render" | "key" | "on_reorder" | "dividers" | "accessible"
) {
errors.push(format!("ScrollList: unknown prop '{key}'"));
}
}
errors
}