ContextMenu.res
1let show: Preact.Signal.t<option<Maplibre.mapLayerMouseEvent>> = Preact.Signal.make(None)
2let handleWaypoint = async (lon: float, lat: float, editor: option<Tiptap.t>) => {
3 let params: Waldo.Reverse.params = {lon, lat}
4
5 switch await Waldo.Reverse.geocode(~params) {
6 | Success(results) => switch results->Array.get(0) {
7 | Some(result) => {
8 let waypointContent = Obj.magic({
9 "type": "waypoint",
10 "attrs": {
11 "id": NanoID.make(),
12 "point": (lon, lat),
13 "label": result.name,
14 "country": result.country,
15 "gid": Int.toString(result.gid),
16 "from": None,
17 "cons": [],
18 "nonroutable": false,
19 "error": None,
20 },
21 })
22
23 let textContent = Obj.magic({"type": "text", "content": " "})
24
25 switch editor {
26 | Some(ed) => {
27 ed->Tiptap.Commands.insertContent(waypointContent)
28 ed->Tiptap.Commands.insertContent(textContent)
29 }
30 | None => ()
31 }
32 }
33 | None => Log.warn(
34 "Reverse geocode returned no results",
35 ~kv={
36 "lon": Float.toString(lon),
37 "lat": Float.toString(lat),
38 },
39 )
40 }
41 | Error(msg) => Log.error(
42 "Reverse geocode error",
43 ~kv={
44 "error": msg,
45 "lon": Float.toString(lon),
46 "lat": Float.toString(lat),
47 },
48 )
49 | NetworkError(msg) => Log.error(
50 "Reverse geocode network error",
51 ~kv={
52 "error": msg,
53 "lon": Float.toString(lon),
54 "lat": Float.toString(lat),
55 },
56 )
57 }
58
59 show->Preact.Signal.set(None)
60}
61
62@jsx.component
63let make = (~doc: string) => {
64 let editor = State.Editor.get(doc)
65 let (lon, lat) = switch show->Preact.Signal.get {
66 | Some(evt) => (evt.lngLat.lng, evt.lngLat.lat)
67 | None => (0.0, 0.0)
68 }
69 show->Preact.Signal.get->Option.isSome
70 ? <>
71 <Maplibre.Marker latitude={lat} longitude={lon}>
72 <Icons.Dot className="text-(--color-orange)" strokeWidth={6} />
73 </Maplibre.Marker>
74 <Maplibre.Popup
75 anchor={TopLeft}
76 longitude={lon}
77 latitude={lat}
78 closeButton={false}
79 onClose={_ => show->Preact.Signal.set(None)}
80 closeOnClick={true}
81 closeOnMove={true}
82 className="m-0 p-0 bg-[#FFFFFF00]"
83 style={{"margin": 0, "padding": 0, "background": "#FFFFFF00"}}
84 >
85 <style>
86 {"
87 .maplibregl-popup-content {
88 margin: 0;
89 padding: 0;
90 padding-top: 2px;
91 }
92 "->Preact.string}
93 </style>
94 <div
95 className="flex flex-col m-0 p-0 rounded-b-sm rounded-r-sm gap-1 justify-start items-start"
96 >
97 <div className="flex flex-row gap-1 hover:bg-blue-100 justify-start px-1 w-full">
98 <Icons.MapPinned className="my-auto" />
99 <a
100 className="w-full px-2 py-1 text-md"
101 href={`https://www.google.com/maps/@${lat->Float.toString},${lon->Float.toString},15z`}
102 target="_blank"
103 onClick={_ => show->Preact.Signal.set(None)}
104 >
105 {"Open Google Maps"->Preact.string}
106 </a>
107 </div>
108 <div className="flex flex-row gap-1 hover:bg-blue-100 justify-start px-1 w-full">
109 <Icons.Waypoint className="my-auto" />
110 <button
111 className="w-full py-1 px-2 text-md"
112 onClick={_ => {
113 let _ = handleWaypoint(lon, lat, editor)
114 }}
115 >
116 {"Add waypoint"->Preact.string}
117 </button>
118 </div>
119 </div>
120 </Maplibre.Popup>
121 </>
122 : Preact.null
123}