dioxus_leaflet/components/
map.rs

1use crate::{LatLng, MapOptions, MapPosition, interop, types::Id};
2use dioxus::{core::use_drop, prelude::*};
3use std::rc::Rc;
4
5const MAP_CSS: Asset = asset!("/assets/dioxus_leaflet.scss");
6
7/// Main map component using Leaflet
8#[component]
9pub fn Map(
10    /// Initial position of the map
11    #[props(default = MapPosition::default())]
12    initial_position: MapPosition,
13
14    /// Height of the map container
15    #[props(into)]
16    height: Option<String>,
17
18    /// Width of the map container
19    #[props(into)]
20    width: Option<String>,
21
22    /// Map configuration options
23    options: Option<MapOptions>,
24
25    /// Custom CSS class for the map container
26    #[props(into)]
27    class: Option<String>,
28
29    /// Custom CSS styles for the map container
30    #[props(into)]
31    style: Option<String>,
32
33    /// Callback when map is clicked
34    on_click: Option<EventHandler<LatLng>>,
35
36    /// Callback when map is moved
37    on_move: Option<EventHandler<MapPosition>>,
38
39    children: Option<Element>,
40) -> Element {
41    let id = use_context_provider(|| Rc::new(Id::map(dioxus_core::current_scope_id().0)));
42    let mut load_error: Signal<Option<String>> = use_signal(|| None);
43    let options = options.unwrap_or(MapOptions::default());
44    let leaflet_css = options.leaflet_resources.css_url();
45    let leaflet_js = options.leaflet_resources.js_url();
46
47    let id2 = id.clone();
48    use_effect(move || {
49        let id = id2.clone();
50        let pos = initial_position.clone();
51        let opts = options.clone();
52        spawn(async move {
53            if let Err(e) = interop::update_map(&id, &pos, &opts).await {
54                load_error.set(Some(e.to_string()));
55            }
56            if let Some(cb) = on_click {
57                interop::on_map_click(&id, cb);
58            }
59        });
60    });
61
62    let id2 = id.clone();
63    use_drop(move || {
64        let id = id2.clone();
65        spawn(async move {
66            if let Err(e) = interop::delete_map(&id).await {
67                load_error.set(Some(e.to_string()));
68            }
69        });
70    });
71
72    rsx! {
73        // Leaflet CSS
74        document::Style { href: leaflet_css }
75
76        document::Style { href: MAP_CSS }
77
78        // Leaflet JavaScript
79        document::Script { src: leaflet_js }
80
81        // boot logic
82        document::Script { src: interop::DL_JS }
83
84        if let Some(err) = load_error() {
85            p {
86                "{err}"
87            }
88        }
89        else {
90            // Map container
91            div {
92                class: "dioxus-leaflet-container {class.as_ref().map(|c| c.as_str()).unwrap_or(\"\")}",
93
94                // Element taken over by leaflet
95                div {
96                    id: "dioxus-leaflet-{id}",
97                    class: "dioxus-leaflet-map",
98                    {children}
99                }
100            }
101        }
102    }
103}