dioxus_leaflet/components/
map.rs

1use crate::{LatLng, MapOptions, MapPosition, interop, types::Id};
2use dioxus::{core::{use_drop, spawn_forever}, 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: Element,
40) -> Element {
41    let id = use_context_provider(|| Rc::new(Id::map(dioxus_core::current_scope_id().0)));
42    let options = options.unwrap_or(MapOptions::default());
43    let leaflet_css = options.leaflet_resources.css_url();
44    let leaflet_js = options.leaflet_resources.js_url();
45
46    let id2 = id.clone();
47    let load_error = use_resource(move || {
48        let id = id2.clone();
49        let pos = initial_position.clone();
50        let opts = options.clone();
51        async move {
52            interop::update_map(&id, &pos, &opts).await.map_err(|e| e.to_string())
53        }
54    });
55
56    let id2 = id.clone();
57    let _click_handle = use_resource(move || {
58        let id = id2.clone();
59        async move {
60            if let Some(on_click) = on_click {
61                interop::on_map_click(&id, on_click).await
62            }
63            else {
64                Ok(())
65            }
66        }
67    });
68
69    let id2 = id.clone();
70    let _move_handle = use_resource(move || {
71        let id = id2.clone();
72        async move {
73            if let Some(on_move) = on_move {
74                interop::on_map_move(&id, on_move).await
75            }
76            else {
77                Ok(())
78            }
79        }
80    });
81
82    let id2 = id.clone();
83    use_drop(move || {
84        let id = id2.clone();
85        spawn_forever(async move {
86            _ = interop::delete_map(&id).await;
87        });
88    });
89
90    rsx! {
91        // Leaflet CSS
92        document::Style { href: leaflet_css }
93
94        document::Style { href: MAP_CSS }
95
96        // Leaflet JavaScript
97        document::Script { src: leaflet_js }
98
99        // boot logic
100        document::Script { src: interop::DL_JS }
101
102        if let Some(Err(err)) = load_error() {
103            p {
104                "{err}"
105            }
106        }
107        else {
108            // Map container
109            div {
110                class: "dioxus-leaflet-container {class.as_ref().map(|c| c.as_str()).unwrap_or(\"\")}",
111
112                // Element taken over by leaflet
113                div {
114                    id: "dioxus-leaflet-{id}",
115                    class: "dioxus-leaflet-map",
116                    {children}
117                }
118            }
119        }
120    }
121}