MapInstance.res.mjs

  1// Generated by ReScript, PLEASE EDIT WITH CARE
  2
  3import * as Log from "../utils/Log.res.mjs";
  4import * as Route from "../ffi/Route.res.mjs";
  5import * as State from "../State.res.mjs";
  6import * as Style from "../ffi/Style.res.mjs";
  7import * as Preact from "../ffi/Preact.res.mjs";
  8import * as Window from "../ffi/Window.res.mjs";
  9import * as MapEvents from "./MapEvents.res.mjs";
 10import * as ContextMenu from "./ContextMenu.res.mjs";
 11import * as Core__Option from "@rescript/core/lib/es6/src/Core__Option.res.mjs";
 12import * as Hooks from "preact/hooks";
 13import * as LucidePreact from "lucide-preact";
 14import * as Signals from "@preact/signals";
 15import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
 16import * as JsxRuntime from "preact/jsx-runtime";
 17import * as ReactMaplibre from "@vis.gl/react-maplibre";
 18
 19function MapInstance$WaypointMarker(props) {
 20  let lat = props.lat;
 21  let lon = props.lon;
 22  let id = props.id;
 23  return JsxRuntime.jsxs(JsxRuntime.Fragment, {
 24    children: [
 25      JsxRuntime.jsx(ReactMaplibre.Marker, {
 26        longitude: lon,
 27        latitude: lat,
 28        children: JsxRuntime.jsx(LucidePreact.LocateFixed, {
 29          size: 24,
 30          color: props.error.length === 0 ? "var(--color-blue)" : "var(--color-red)",
 31          strokeWidth: 3,
 32          className: "rounded-full bg-[#FFFFFF66]"
 33        }),
 34        anchor: "center",
 35        opacity: 1.0,
 36        opacityWhenCovered: 1.0
 37      }, id),
 38      State.zoom.value > 3.0 ? JsxRuntime.jsx(ReactMaplibre.Marker, {
 39          longitude: lon,
 40          latitude: lat,
 41          children: JsxRuntime.jsx("div", {
 42            children: props.label,
 43            className: "bg-[#333333] text-white rounded-sm px-1"
 44          }),
 45          anchor: "top-left",
 46          offset: [
 47            6,
 48            6
 49          ],
 50          color: "#333333",
 51          opacity: 1.0,
 52          opacityWhenCovered: 1.0
 53        }, id + "-text") : null
 54    ]
 55  });
 56}
 57
 58let WaypointMarker = {
 59  make: MapInstance$WaypointMarker
 60};
 61
 62let popup = Signals.signal(undefined);
 63
 64let initialRender = Signals.signal(true);
 65
 66function MapInstance(props) {
 67  let doc = props.doc;
 68  let waypoints = State.getOrCreateWaypointsSignal(doc);
 69  let cmap = Hooks.useRef(null);
 70  let flyToPoint = (point, padding) => {
 71    let match = cmap.current;
 72    if (!(match == null)) {
 73      if (padding !== undefined) {
 74        match.flyTo({
 75          center: point,
 76          padding: {
 77            bottom: padding[0],
 78            left: padding[1],
 79            top: 0,
 80            right: 0
 81          }
 82        });
 83      } else {
 84        match.flyTo({
 85          center: point
 86        });
 87      }
 88      return;
 89    }
 90  };
 91  let routeHashes = Route.extractRouteHashes(waypoints.value);
 92  let currentWaypoints = waypoints.value;
 93  let len = currentWaypoints.length;
 94  let tmp;
 95  if (len !== 1) {
 96    tmp = len !== 0 ? currentWaypoints.map(wp => {
 97        let match = wp.point;
 98        return JsxRuntime.jsx(MapInstance$WaypointMarker, {
 99          id: wp.id,
100          lon: match[0],
101          lat: match[1],
102          label: wp.label,
103          error: Core__Option.getOr(wp.error, [])
104        });
105      }) : JsxRuntime.jsx(JsxRuntime.Fragment, {});
106  } else {
107    let wp1 = currentWaypoints[0];
108    let match = wp1.point;
109    if (Window.isMobile.value) {
110      let size = Window.getSize();
111      if (size !== undefined) {
112        flyToPoint(wp1.point, [
113          size.height / 4 | 0,
114          0
115        ]);
116      } else {
117        flyToPoint(wp1.point, undefined);
118      }
119    } else {
120      let size$1 = Window.getSize();
121      if (size$1 !== undefined) {
122        flyToPoint(wp1.point, [
123          0,
124          size$1.width / 4 | 0
125        ]);
126      } else {
127        flyToPoint(wp1.point, undefined);
128      }
129    }
130    tmp = JsxRuntime.jsx(MapInstance$WaypointMarker, {
131      id: wp1.id,
132      lon: match[0],
133      lat: match[1],
134      label: wp1.label,
135      error: Core__Option.getOr(wp1.error, [])
136    });
137  }
138  return JsxRuntime.jsxs(ReactMaplibre.Map, {
139    id: "map",
140    cursor: "crosshair",
141    mapStyle: Primitive_option.some(Style.rtwStyle),
142    initialViewState: {
143      longitude: 83.85382,
144      latitude: 27.70972,
145      zoom: 8.0
146    },
147    interactiveLayerIds: routeHashes.map(hash => `route-layer-` + hash),
148    onLoad: event => {
149      if (initialRender.value && currentWaypoints.length > 0) {
150        let map = event.target;
151        let lats = currentWaypoints.map(p => p.point[1]);
152        let lons = currentWaypoints.map(p => p.point[0]);
153        let bbox_0 = Math.min(...lons);
154        let bbox_1 = Math.min(...lats);
155        let bbox_2 = Math.max(...lons);
156        let bbox_3 = Math.max(...lats);
157        let bbox = [
158          bbox_0,
159          bbox_1,
160          bbox_2,
161          bbox_3
162        ];
163        let isSinglePoint = currentWaypoints.length === 1;
164        if (Window.isMobile.value) {
165          let match = Window.getSize();
166          if (match !== undefined) {
167            if (isSinglePoint) {
168              Core__Option.getOr(Core__Option.map(currentWaypoints[0], wp => flyToPoint(wp.point, [
169                match.height / 2 | 0,
170                0
171              ])), undefined);
172            } else {
173              map.fitBounds(bbox, {
174                padding: {
175                  bottom: (match.height / 2 | 0) + 50 | 0,
176                  left: 50,
177                  top: 50,
178                  right: 50
179                }
180              });
181            }
182          } else {
183            map.fitBounds(bbox);
184          }
185        } else {
186          let match$1 = Window.getSize();
187          if (match$1 !== undefined) {
188            if (isSinglePoint) {
189              Core__Option.getOr(Core__Option.map(currentWaypoints[0], wp => flyToPoint(wp.point, [
190                0,
191                match$1.width / 4 | 0
192              ])), undefined);
193            } else {
194              map.fitBounds(bbox, {
195                padding: {
196                  bottom: 50,
197                  left: match$1.width / 4 | 0,
198                  top: 50,
199                  right: 50
200                }
201              });
202            }
203          } else {
204            map.fitBounds(bbox);
205          }
206        }
207      }
208      initialRender.value = false;
209      let center = event.target.getCenter();
210      State.center.value = [
211        center.lng,
212        center.lat
213      ];
214      State.zoom.value = event.target.getZoom();
215      cmap.current = event.target;
216    },
217    onMouseEnter: event => MapEvents.handleDistance(event, popup, currentWaypoints),
218    onMouseLeave: _event => {
219      popup.value = undefined;
220    },
221    onContextMenu: evt => {
222      ContextMenu.show.value = evt;
223    },
224    onMoveEnd: event => {
225      State.center.value = [
226        event.viewState.longitude,
227        event.viewState.latitude
228      ];
229      State.zoom.value = event.viewState.zoom;
230      Log.debug("move", {
231        lat: event.viewState.latitude.toFixed(6),
232        lng: event.viewState.longitude.toFixed(6),
233        zoom: event.viewState.zoom.toFixed(1)
234      });
235    },
236    children: [
237      routeHashes.map(hash => {
238        let paintDict = {};
239        return JsxRuntime.jsxs(JsxRuntime.Fragment, {
240          children: [
241            JsxRuntime.jsx(ReactMaplibre.Source, {
242              id: `route-` + hash,
243              type: "geojson",
244              data: Route.getGeoJSONUrl(hash)
245            }),
246            JsxRuntime.jsx(ReactMaplibre.Layer, {
247              id: `route-layer-` + hash,
248              type: "line",
249              source: `route-` + hash,
250              paint: (paintDict["line-color"] = "#205ea6", paintDict["line-width"] = 8.0, paintDict)
251            })
252          ]
253        }, `route-fragment-` + hash);
254      }),
255      tmp,
256      Preact.option(popup.value),
257      JsxRuntime.jsx(ContextMenu.make, {
258        doc: doc
259      })
260    ]
261  });
262}
263
264let make = MapInstance;
265
266export {
267  WaypointMarker,
268  popup,
269  initialRender,
270  make,
271}
272/* popup Not a pure module */