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

Clean up typing in GridLayer

parent 848acef2
Loading
Loading
Loading
Loading
+15 −39
Original line number Diff line number Diff line
<script lang="ts">
import type L from "leaflet";
import {
  type PropType,
  defineComponent,
  h,
  inject,
  markRaw,
  nextTick,
  onMounted,
  onUnmounted,
  ref,
  render,
} from "vue";

import { gridLayerProps, setupGridLayer } from "@src/functions/gridLayer";
import {
  CreateVueGridLayer,
  type VueGridLayerTileRenderer,
  gridLayerProps,
  setupGridLayer,
} from "@src/functions/gridLayer";
import {
  AddLayerInjection,
  UseGlobalLeafletInjection,
@@ -28,13 +32,12 @@ export default defineComponent({
  props: {
    ...gridLayerProps,
    childRender: {
      type: Function,
      type: Function as PropType<VueGridLayerTileRenderer>,
      required: true,
    },
  },
  setup(props, context) {
    const leafletObject = ref<L.GridLayer>();
    const tileComponents = ref({}); // TODO: typing
    const root = ref(null);
    const ready = ref(false);

@@ -44,44 +47,21 @@ export default defineComponent({
    const { options, methods } = setupGridLayer(props, leafletObject, context);

    onMounted(async () => {
      const { GridLayer, DomUtil }: typeof L = useGlobalLeaflet
      const { GridLayer, DomUtil, Util }: typeof L = useGlobalLeaflet
        ? WINDOW_OR_GLOBAL.L
        : await import("leaflet/dist/leaflet-src.esm");

      methods.onUnload = (e) => {
        const key = leafletObject.value._tileCoordsToKey(e.coords);
        if (tileComponents[key]) {
          tileComponents[key].innerHTML = "";
          tileComponents[key] = undefined;
        }
      };

      methods.setTileComponent = () => {
        leafletObject.value.redraw();
      };

      const GLayer = GridLayer.extend({
        createTile(coords) {
          const key = leafletObject.value._tileCoordsToKey(coords);
          tileComponents[key] = DomUtil.create("div");

          let vNode = h(
            { setup: props.childRender, props: ["coords"] },
            { coords }
      const GLayer = CreateVueGridLayer(
        GridLayer,
        DomUtil,
        Util,
        props.childRender
      );
          render(vNode, tileComponents[key]);

          return tileComponents[key];
        },
      });

      leafletObject.value = markRaw<L.GridLayer>(new GLayer(options));

      const listeners = remapEvents(context.attrs);
      leafletObject.value.on(listeners);

      leafletObject.value.on("tileunload", methods.onUnload);

      propsBinder(methods, leafletObject.value, props);
      addLayer({
        ...props,
@@ -92,10 +72,6 @@ export default defineComponent({
      nextTick(() => context.emit("ready", leafletObject.value));
    });

    onUnmounted(() => {
      leafletObject.value.off("tileunload", methods.onUnload);
    });

    return { root, ready, leafletObject };
  },
  render() {
+45 −1
Original line number Diff line number Diff line
import type L from "leaflet";
import type { PropType } from "vue";
import { type PropType, onUnmounted } from "vue";
import { type VNode, h, render } from "vue";

import { propsToLeafletOptions } from "@src/utils";

import { layerProps, setupLayer } from "./layer";

export type VueGridLayerTileRenderer = (props: {
  coords: L.Point;
}) => () => VNode;

export const gridLayerProps = {
  ...layerProps,
  opacity: {
@@ -43,7 +48,46 @@ export const setupGridLayer = (props, leafletRef, context) => {

  const methods = {
    ...layerMethods,
    setTileComponent() {
      leafletRef.value?.redraw();
    },
  };

  onUnmounted(() => {
    leafletRef.value.off();
  });

  return { options, methods };
};

export const CreateVueGridLayer = (
  GridLayer: typeof L.GridLayer,
  DomUtil: typeof L.DomUtil,
  Util: typeof L.Util,
  childRenderer: VueGridLayerTileRenderer
) =>
  GridLayer.extend({
    initialize(options: L.GridLayerOptions) {
      this.tileComponents = {};
      this.on("tileunload", this._unloadTile);
      Util.setOptions(this, options);
    },

    createTile(coords: L.Point): HTMLElement {
      const key = this._tileCoordsToKey(coords);
      this.tileComponents[key] = DomUtil.create("div");

      const vNode = h({ setup: childRenderer, props: ["coords"] }, { coords });
      render(vNode, this.tileComponents[key]);

      return this.tileComponents[key];
    },

    _unloadTile(e: L.TileEvent): void {
      const key = this._tileCoordsToKey(e.coords);
      if (this.tileComponents[key]) {
        this.tileComponents[key].innerHTML = "";
        this.tileComponents[key] = undefined;
      }
    },
  });