dioxus_leaflet/components/
map.rs

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