dioxus_leaflet/
components.rs1use dioxus::prelude::*;
2use crate::types::*;
3use crate::interop;
4
5pub fn generate_map_id() -> String {
7 format!("dioxus_leaflet_map_{}", fastrand::u32(..))
8}
9
10#[derive(Props, Clone, PartialEq)]
11pub struct MapProps {
12 #[props(default = MapPosition::default())]
14 pub initial_position: MapPosition,
15
16 #[props(default = vec![])]
18 pub markers: ReadOnlySignal<Vec<MapMarker>>,
19
20 #[props(default = vec![])]
22 pub polygons: ReadOnlySignal<Vec<Polygon>>,
23
24 #[props(default = "500px".to_string())]
26 pub height: String,
27
28 #[props(default = "100%".to_string())]
30 pub width: String,
31
32 #[props(default = MapOptions::default())]
34 pub options: MapOptions,
35
36 #[props(default = "".to_string())]
38 pub class: String,
39
40 #[props(default = "".to_string())]
42 pub style: String,
43
44 pub on_marker_click: Option<EventHandler<MapMarker>>,
46
47 pub on_map_click: Option<EventHandler<MapPosition>>,
49
50 pub on_map_move: Option<EventHandler<MapPosition>>,
52}
53
54#[component]
56pub fn Map(props: MapProps) -> Element {
57 let map_id: Signal<String> = use_signal(generate_map_id);
58 let mut load_error: Signal<Option<String>> = use_signal(|| None);
59
60 let container_style = format!(
61 "position: relative; width: {}; height: {}; {}",
62 props.width, props.height, props.style
63 );
64
65 let container_class = if props.class.is_empty() {
66 "dioxus-leaflet-container".to_string()
67 } else {
68 format!("dioxus-leaflet-container {}", props.class)
69 };
70
71 let css_path = if let Some(_) = props.options.leaflet_resources.css_integrity() {
72 props.options.leaflet_resources.css_url()
73 } else {
74 props.options.leaflet_resources.css_url()
75 };
76
77 let js_path = if let Some(_) = props.options.leaflet_resources.js_integrity() {
78 props.options.leaflet_resources.js_url()
79 } else {
80 props.options.leaflet_resources.js_url()
81 };
82
83 use_effect(move || {
84 let id = map_id();
85 let pos = props.initial_position.clone();
86 let markers = (props.markers)();
87 let gons = (props.polygons)();
88 let opts = props.options.clone();
89 spawn(async move {
90 if let Err(e) = interop::update(&id, &pos, &markers, &gons, &opts).await {
91 load_error.set(Some(e));
92 }
93 });
94 });
95
96 rsx! {
97 document::Style { href: css_path }
99
100 document::Script { src: js_path }
102
103 document::Script { src: interop::DL_JS }
105
106 if let Some(err) = &*load_error.read() {
107 p {
108 "{err}"
109 }
110 }
111 else {
112 div {
113 class: "{container_class}",
114 style: "{container_style}",
115
116 div {
118 id: "{map_id}",
119 class: "dioxus-leaflet-map",
120 style: "width: 100%; height: 100%; z-index: 1;",
121 }
122 }
123 }
124 }
125}