orbital-core-components 0.1.1

Themed Orbital UI components for Leptos applications
Documentation
use super::node::RichTreeNode;

pub(crate) fn reorder_nodes(
    roots: &mut Vec<RichTreeNode>,
    source_id: &str,
    target_id: &str,
    order: usize,
) {
    let Some((node, parent_id)) = extract_node(roots, source_id) else {
        return;
    };
    match parent_id {
        Some(parent_id) => {
            let _ = insert_under_parent(roots, &parent_id, node, target_id, order);
        }
        None => {
            if let Some(index) = roots.iter().position(|n| n.id == target_id) {
                let insert_at = if order == 0 { index } else { index + 1 };
                roots.insert(insert_at.min(roots.len()), node);
            }
        }
    }
}

fn insert_under_parent(
    nodes: &mut [RichTreeNode],
    parent_id: &str,
    node: RichTreeNode,
    target_id: &str,
    order: usize,
) -> Result<(), RichTreeNode> {
    for child in nodes.iter_mut() {
        if child.id == parent_id {
            insert_relative(&mut child.children, node, target_id, order);
            return Ok(());
        }
    }
    let mut node = node;
    for child in nodes.iter_mut() {
        match insert_under_parent(&mut child.children, parent_id, node, target_id, order) {
            Ok(()) => return Ok(()),
            Err(returned) => node = returned,
        }
    }
    Err(node)
}

#[allow(clippy::ptr_arg)]
fn extract_node(nodes: &mut Vec<RichTreeNode>, id: &str) -> Option<(RichTreeNode, Option<String>)> {
    if let Some(index) = nodes.iter().position(|node| node.id == id) {
        return Some((nodes.remove(index), None));
    }
    for node in nodes.iter_mut() {
        if let Some(index) = node.children.iter().position(|child| child.id == id) {
            let removed = node.children.remove(index);
            return Some((removed, Some(node.id.clone())));
        }
        if let Some(found) = extract_node(&mut node.children, id) {
            return Some(found);
        }
    }
    None
}

fn insert_relative(
    siblings: &mut Vec<RichTreeNode>,
    node: RichTreeNode,
    target_id: &str,
    order: usize,
) {
    if let Some(index) = siblings.iter().position(|sibling| sibling.id == target_id) {
        let insert_at = if order == 0 { index } else { index + 1 };
        siblings.insert(insert_at.min(siblings.len()), node);
    }
}