1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use dioxus::prelude::*;
use freya_components::{
    ArrowIcon,
    ButtonStatus,
};
use freya_elements::{
    self as dioxus_elements,
    events::MouseEvent,
};
use freya_native_core::prelude::NodeId;

use crate::hooks::use_node_info;

#[allow(non_snake_case)]
#[component]
pub fn NodeElement(
    node_id: NodeId,
    is_selected: bool,
    is_open: Option<bool>,
    onselected: EventHandler<()>,
    onarrow: EventHandler<()>,
) -> Element {
    let mut status = use_signal(ButtonStatus::default);
    let Some(node) = use_node_info(node_id) else {
        return Ok(VNode::placeholder());
    };

    let onmousedown = move |_| onselected.call(());

    let onarrowmousedown = move |e: MouseEvent| {
        if is_open.is_some() {
            onarrow.call(());
            e.stop_propagation();
        }
    };

    let onmouseenter = move |_| {
        status.set(ButtonStatus::Hovering);
    };

    let onmouseleave = move |_| {
        status.set(ButtonStatus::default());
    };

    let background = match *status.read() {
        _ if is_selected => "rgb(100, 100, 100)",
        ButtonStatus::Idle => "transparent",
        ButtonStatus::Hovering => "rgb(80, 80, 80)",
    };

    let margin_left = (node.height * 10) as f32 - 20.;
    let id = node_id.index();

    rsx!(
        rect {
            corner_radius: "7",
            padding: "5 5 5 0",
            background,
            width: "100%",
            height: "27",
            offset_x: "{margin_left}",
            onmousedown,
            onmouseenter,
            onmouseleave,
            direction: "horizontal",
            cross_align: "center",
            rect {
                onmousedown: onarrowmousedown,
                margin: "0 8 0 0",
                if let Some(is_open) = is_open {
                    {
                        let arrow_degree = if is_open {
                            0
                        } else {
                            270
                        };
                        rsx!(
                            ArrowIcon {
                                fill: "white",
                                rotate: "{arrow_degree}"
                            }
                        )
                    }
                }
            }
            label {
                font_size: "14",
                color: "white",
                "{node.tag} ({id})"
            }
        }
    )
}