Commit afde0334 authored by Michael Underwood's avatar Michael Underwood
Browse files

Initial conversion of LMap.vue to TS

parent 178c50f8
Loading
Loading
Loading
Loading
+77 −50
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import {
  provide,
  reactive,
  ref,
  type PropType,
} from "vue";
import {
  remapEvents,
@@ -26,13 +27,33 @@ import {
} from "../utils.js";
import { componentProps, setupComponent } from "../functions/component";

interface LMapBlueprint {
  ready: boolean;
  leafletRef?: L.Map;
  layerControl?: any; // TODO: Proper typing, based on argument to registerLayerControl called in LControlLayers.vue
  layersToAdd: any[]; // TODO: Proper typing
  layersInControl: any[]; // TODO: Proper typing
  lastSetBounds?: L.LatLngBounds;
  lastSetCenter?: L.LatLng;
}

interface LMapOptions extends L.MapOptions {
  beforeMapMount?: () => any;
}

interface LLayerDefinition<T extends L.Layer> extends L.Layer {
  layerType: "base" | "overlay" | undefined;
  visible: boolean;
  leafletObject: T;
}

const mapProps = {
  ...componentProps,
  /**
   * The center of the map, supports .sync modifier
   */
  center: {
    type: [Object, Array],
    type: [Object, Array] as PropType<L.PointExpression>,
  },
  /**
   * The bounds of the map, supports .sync modifier
@@ -68,19 +89,19 @@ const mapProps = {
   * The paddingBottomRight of the map
   */
  paddingBottomRight: {
    type: Array,
    type: [Object, Array] as PropType<L.PointExpression>,
  },
  /**
   * The paddingTopLeft of the map
   */
  paddingTopLeft: {
    type: Array,
    type: Object as PropType<L.PointExpression>,
  },
  /**
   * The padding of the map
   */
  padding: {
    type: Array,
    type: Object as PropType<L.PointExpression>,
  },
  /**
   * The worldCopyJump option for the map
@@ -139,29 +160,24 @@ const mapProps = {
  },
};

interface MapBlueprint {
  ready: boolean;
  leafletRef?: L.Map;
  layerControl?: L.Control.Layers;
  layersToAdd: any[]; // TODO: Proper typing
  layersInControl: any[]; // TODO: Proper typing
}
export default defineComponent({
  emits: ["ready", "update:zoom", "update:center", "update:bounds"],
  props: mapProps,
  setup(props, context) {
    const root = ref(null);
    const blueprint = reactive<MapBlueprint>({
    const root = ref<HTMLElement>();
    const blueprint = reactive<LMapBlueprint>({
      ready: false,
      leafletRef: undefined,
      layerControl: undefined,
      layersToAdd: [],
      layersInControl: [],
    });

    const { options: componentOptions } = setupComponent(props);

    const options = propsToLeafletOptions(props, mapProps, componentOptions);
    const options: LMapOptions = propsToLeafletOptions(
      props,
      mapProps,
      componentOptions
    );

    const addLayer = provideLeafletWrapper("addLayer");
    const removeLayer = provideLeafletWrapper("removeLayer");
@@ -169,6 +185,30 @@ export default defineComponent({
    const registerLayerControl = provideLeafletWrapper("registerLayerControl");
    provide(GLOBAL_LEAFLET_OPT, props.useGlobalLeaflet);

    const zoomPanOptions = computed(() => {
      const result: L.ZoomPanOptions = {};
      if (props.noBlockingAnimations) {
        result.animate = false;
      }

      return result;
    });

    const fitBoundsOptions = computed(() => {
      const result: L.FitBoundsOptions = zoomPanOptions.value;
      if (props.padding) {
        result.padding = props.padding;
      }
      if (props.paddingTopLeft) {
        result.paddingTopLeft = props.paddingTopLeft;
      }
      if (props.paddingBottomRight) {
        result.paddingBottomRight = props.paddingBottomRight;
      }

      return result;
    });

    const eventHandlers = {
      moveEndHandler: debounce(() => {
        if (!blueprint.leafletRef) return;
@@ -214,6 +254,7 @@ export default defineComponent({
          : await import("leaflet/dist/leaflet-src.esm");

      try {
        // TODO: Is beforeMapMount still needed?
        options.beforeMapMount && (await options.beforeMapMount());
      } catch (error: any) {
        console.error(
@@ -228,7 +269,7 @@ export default defineComponent({
      options.crs = optionsCrs || CRS.EPSG3857;

      const methods = {
        addLayer(layer: L.Layer) {
        addLayer(layer: LLayerDefinition<any>) {
          if (layer.layerType !== undefined) {
            if (blueprint.layerControl === undefined) {
              blueprint.layersToAdd.push(layer);
@@ -239,13 +280,13 @@ export default defineComponent({
                  layer.leafletObject._leaflet_id
              );
              if (!exist) {
                blueprint.layerControl!.addLayer(layer);
                blueprint.layerControl.addLayer(layer);
                blueprint.layersInControl.push(layer);
              }
            }
          }
          if (layer.visible !== false) {
            blueprint.leafletRef.addLayer(layer.leafletObject);
            blueprint.leafletRef!.addLayer(layer.leafletObject);
          }
        },
        removeLayer(layer) {
@@ -263,13 +304,13 @@ export default defineComponent({
              );
            }
          }
          blueprint.leafletRef.removeLayer(layer.leafletObject);
          blueprint.leafletRef!.removeLayer(layer.leafletObject);
        },

        registerLayerControl(lControlLayer) {
          blueprint.layerControl = lControlLayer;
          blueprint.layersToAdd.forEach((layer) => {
            blueprint.layerControl.addLayer(layer);
            blueprint.layerControl!.addLayer(layer);
          });
          blueprint.layersToAdd = [];

@@ -277,39 +318,26 @@ export default defineComponent({
        },

        registerControl(lControl) {
          blueprint.leafletRef.addControl(lControl.leafletObject);
          blueprint.leafletRef!.addControl(lControl.leafletObject);
        },

        setZoom(newVal) {
          const zoom = blueprint.leafletRef.getZoom();
          const zoom = blueprint.leafletRef!.getZoom();
          if (newVal !== zoom) {
            blueprint.leafletRef.setZoom(newVal, {
              animate: props.noBlockingAnimations ? false : null,
            });
            blueprint.leafletRef!.setZoom(newVal, zoomPanOptions.value);
          }
        },

        setPaddingBottomRight(newVal) {
          blueprint.paddingBottomRight = newVal;
        },
        setPaddingTopLeft(newVal) {
          blueprint.paddingTopLeft = newVal;
        },
        setPadding(newVal) {
          blueprint.padding = newVal;
        },
        setCrs(newVal) {
          const prevBounds = blueprint.leafletRef.getBounds();
          blueprint.leafletRef.options.crs = newVal;
          blueprint.leafletRef.fitBounds(prevBounds, {
          const prevBounds = blueprint.leafletRef!.getBounds();
          blueprint.leafletRef!.options.crs = newVal;
          blueprint.leafletRef!.fitBounds(prevBounds, {
            animate: false,
            padding: [0, 0],
          });
        },
        fitBounds(bounds) {
          blueprint.leafletRef.fitBounds(bounds, {
            animate: this.noBlockingAnimations ? false : null,
          });
          blueprint.leafletRef!.fitBounds(bounds, fitBoundsOptions.value);
        },
        setBounds(newVal) {
          if (!newVal) {
@@ -320,11 +348,11 @@ export default defineComponent({
            return;
          }
          const oldBounds =
            blueprint.lastSetBounds || blueprint.leafletRef.getBounds();
            blueprint.lastSetBounds || blueprint.leafletRef!.getBounds();
          const boundsChanged = !oldBounds.equals(newBounds, 0); // set maxMargin to 0 - check exact equals
          if (boundsChanged) {
            blueprint.lastSetBounds = newBounds;
            blueprint.leafletRef.fitBounds(newBounds, this.fitBoundsOptions);
            blueprint.leafletRef!.fitBounds(newBounds);
          }
        },

@@ -334,15 +362,14 @@ export default defineComponent({
          }
          const newCenter = latLng(newVal);
          const oldCenter =
            blueprint.lastSetCenter || blueprint.leafletRef.getCenter();
            blueprint.lastSetCenter || blueprint.leafletRef!.getCenter();
          if (
            oldCenter.lat !== newCenter.lat ||
            oldCenter.lng !== newCenter.lng
          ) {
            blueprint.lastSetCenter = newCenter;
            blueprint.leafletRef.panTo(newCenter, {
              animate: this.noBlockingAnimations ? false : null,
            });

            blueprint.leafletRef!.panTo(newCenter, zoomPanOptions.value);
          }
        },
      };
@@ -352,10 +379,10 @@ export default defineComponent({
      updateLeafletWrapper(registerControl, methods.registerControl);
      updateLeafletWrapper(registerLayerControl, methods.registerLayerControl);

      blueprint.leafletRef = markRaw(map(root.value, options));
      blueprint.leafletRef = markRaw(map(root.value!, options));

      propsBinder(methods, blueprint.leafletRef, props);
      const listeners = remapEvents(context.attrs);
      const listeners: any = remapEvents(context.attrs); // TODO: proper typing

      blueprint.leafletRef.on("moveend", eventHandlers.moveEndHandler);
      blueprint.leafletRef.on("overlayadd", eventHandlers.overlayAddHandler);
@@ -363,7 +390,7 @@ export default defineComponent({
        "overlayremove",
        eventHandlers.overlayRemoveHandler
      );
      DomEvent.on(blueprint.leafletRef, listeners);
      DomEvent.on(blueprint.leafletRef.getContainer(), listeners);
      blueprint.ready = true;
      nextTick(() => context.emit("ready", blueprint.leafletRef));
    });