git diff --cached --name-status | while read status file; do
  echo "# $file"
  echo '````'
  if [ "$status" = "D" ]; then
    git show HEAD:$file 2>/dev/null || echo "[deleted]"
  else
    git show :$file 2>/dev/null || echo "[binary]"
  fi
  echo '````'
  echo ""
done | clip
  git diff --cached --name-status | while read status file; do
    echo "# [staged] $file"
    echo '````'
    if [ "$status" = "D" ]; then
      git show HEAD:$file 2>/dev/null || echo "[deleted]"
    else
      git show :$file 2>/dev/null || echo "[binary]"
    fi
    echo '````'
    echo ""
  done | clip
{
  # === STAGED ===
  git diff --cached --name-status | while read status file; do
    echo "# [staged] $file"
    echo '````'
    if [ "$status" = "D" ]; then
      git show HEAD:$file 2>/dev/null || echo "[deleted]"
    else
      git show :$file 2>/dev/null || echo "[binary]"
    fi
    echo '````'
    echo ""
  done

  # === UNSTAGED ===
  git diff --name-status | while read status file; do
    echo "# [unstaged] $file"
    echo '````'
    if [ "$status" = "D" ]; then
      cat $file 2>/dev/null || echo "[deleted]"
    else
      cat $file 2>/dev/null || echo "[binary or missing]"
    fi
    echo '````'
    echo ""
  done
} | clip
/* eslint-disable @typescript-eslint/no-namespace */

  

declare const L: typeof import("leaflet");

  

type LatLng = import("leaflet").LatLng;

type LatLngTuple = import("leaflet").LatLngTuple;

type LatLngBoundsExpression = import("leaflet").LatLngBoundsExpression;

type LeafletMouseEvent = import("leaflet").LeafletMouseEvent;

type Polyline = import("leaflet").Polyline;

type Tooltip = import("leaflet").Tooltip;

type CircleMarker = import("leaflet").CircleMarker;

type LayerGroup = import("leaflet").LayerGroup;

type Map = import("leaflet").Map;

type Marker = import("leaflet").Marker;

type ControlOptions = import("leaflet").ControlOptions;

  

// eslint-disable-next-line @typescript-eslint/no-namespace

declare namespace iconify {

    const loadIcon: (iconName: string) => Promise<FullIconifyIcon>;

    type FullIconifyIcon = object;

}

  

type Coordinates = `${number}, ${number}`;

  

interface MarkerDataSet {

    name: string;

    link: string;

    coordinates: Coordinates;

    icon: string;

    colour: string;

    minZoom: string;

    maxZoom: string;

}

  

interface MapDataSet {

    src: string;

    osmMode: string;

    startCoordinate: string;

    height: string;

    minZoom: string;

    maxZoom: string;

    defaultZoom: string;

    zoomDelta: string;

    scale: string;

    unit: string;

    enableCopyTool: string;

}

  

const C = {

    map: {

        default: {

            minZoom: "0",

            maxZoom: "2",

            zoomDelta: "0.5",

            zoomSnap: "0.01",

            height: "600",

            scale: "1",

            unit: "",

            enableCopyTool: "false",

        },

    },

    tiles: {

        light: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",

        dark: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",

        attribution:

            '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors ' +

            '&copy; <a href="https://carto.com/attributions">CARTO</a>',

        subdomains: "abcd",

        maxZoom: 20,

    },

} as const;

  

function getCurrentTheme(): "light" | "dark" {

    return document.documentElement.getAttribute("saved-theme") === "dark" ? "dark" : "light";

}

  

async function loadScript(urls: string[]): Promise<void> {

    for (const url of urls) {

        try {

            await new Promise<void>((resolve, reject) => {

                const script = document.createElement("script");

                script.src = url;

                script.onload = () => resolve();

                script.onerror = () => reject(new Error(`Failed to load: ${url}`));

                document.head.appendChild(script);

            });

            return;

        } catch {

            // Try next URL

        }

    }

    throw new Error(`All CDN sources failed for: ${urls.join(", ")}`);

}

  

async function loadDependencies(): Promise<void> {

    if (typeof L === "undefined") {

        await loadScript([

            "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js",

            "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",

        ]);

    }

    if (typeof iconify === "undefined") {

        await loadScript([

            "https://cdn.jsdelivr.net/npm/iconify-icon@3.0.2/dist/iconify-icon.min.js",

            "https://unpkg.com/iconify-icon@3.0.2/dist/iconify-icon.min.js",

            "https://code.iconify.design/iconify-icon/3.0.2/iconify-icon.min.js",

        ]);

    }

}

  

function isNonEmptyObject(value: unknown): value is { [key: string]: string } {

    if (!value || typeof value !== "object" || Array.isArray(value)) return false;

    return (

        Object.keys(value).length > 0 &&

        Object.values(value).every((value) => typeof value === "string")

    );

}

  

function parseCoordinates(coordinates: string): LatLngTuple {

    const parsedCoordinates = coordinates

        .replace(/\s/g, "")

        .split(",")

        .map((coordinate) => parseFloat(coordinate));

  

    if (!isLatLngTuple(parsedCoordinates)) {

        throw new Error("Coordinates not properly validated");

    }

  

    return parsedCoordinates;

}

  

function isLatLngTuple(value: unknown): value is LatLngTuple {

    return (

        !!value &&

        Array.isArray(value) &&

        value.length === 2 &&

        value.every((value) => typeof value === "number" && !isNaN(value))

    );

}

  

function distance(a: LatLng, b: LatLng): number {

    const square = (value: number) => value * value;

    return Math.sqrt(square(a.lat - b.lat) + square(a.lng - b.lng));

}

  

function isMarkerDataSet(dataset: unknown): dataset is MarkerDataSet {

    if (!isNonEmptyObject(dataset)) return false;

    if (

        !dataset["name"] ||

        !dataset["link"] ||

        !dataset["coordinates"] ||

        !dataset["icon"] ||

        !dataset["colour"] ||

        !dataset["minZoom"] ||

        !dataset["maxZoom"]

    ) {

        return false;

    }

    return true;

}

  

function getMarkerData(map: HTMLElement): MarkerDataSet[] {

    const markers: NodeListOf<HTMLElement> = map.querySelectorAll("div.leaflet-marker");

    const data: MarkerDataSet[] = [];

    markers.forEach((marker) => {

        if (isMarkerDataSet(marker.dataset)) {

            data.push(marker.dataset);

        }

        marker.remove();

    });

    return data;

}

  

function prepareIconName(icon: string) {

    // Obsidian build-in icons are prefixed with `lucide-` instead of `lucide:`

    return icon.replace(/^lucide-/g, "lucide:");

}

  

function buildMarkerIcon(link: string, icon: string, colour: string) {

    return L.divIcon({

        className: "leaflet-marker-icon",

        html: `

            <a href="${link}">

                <svg class="leaflet-marker-pin" style="fill:${colour}" viewBox="0 0 32 48">

                    <path d="m32,19c0,12 -12,24 -16,29c-4,-5 -16,-16 -16,-29a16,19 0 0 1 32,0"/>

                </svg>

                <iconify-icon class="icon leaflet-marker-inner-icon" icon="${prepareIconName(icon)}" width="19px" height="19px"></iconify-icon>

            </a>

        `,

        iconSize: [32, 48],

        iconAnchor: [16, 48],

        tooltipAnchor: [17, -30],

    });

}

  

function addMarker(markerData: MarkerDataSet, mapItem: Map, wrapHorizontally: boolean = false) {

    const { link, icon, colour, minZoom, maxZoom, coordinates, name } = markerData;

    const markerMinZoom = parseFloat(minZoom);

    const markerMaxZoom = parseFloat(maxZoom);

    const [lat, lng] = parseCoordinates(coordinates);

    const tolerance = 0.00001;

  

    const instances = new Map<number, Marker>();

  

    function ensureInstance(offset: number): Marker {

        let marker = instances.get(offset);

        if (!marker) {

            const options = { icon: buildMarkerIcon(link, icon, colour) };

            marker = L.marker([lat, lng + offset * 360], options).bindTooltip(name);

            instances.set(offset, marker);

        }

        return marker;

    }

  

    function update() {

        const z = mapItem.getZoom();

        const zoomVisible = z >= markerMinZoom - tolerance && z <= markerMaxZoom + tolerance;

  

        if (!zoomVisible) {

            for (const marker of instances.values()) marker.remove();

            return;

        }

  

        if (!wrapHorizontally) {

            ensureInstance(0).addTo(mapItem);

            return;

        }

  

        const bounds = mapItem.getBounds();

        const west = bounds.getWest();

        const east = bounds.getEast();

        const minOffset = Math.floor((west - lng) / 360);

        const maxOffset = Math.ceil((east - lng) / 360);

  

        for (const [offset, marker] of instances) {

            if (offset < minOffset || offset > maxOffset) {

                marker.remove();

                instances.delete(offset);

            }

        }

        for (let offset = minOffset; offset <= maxOffset; offset++) {

            ensureInstance(offset).addTo(mapItem);

        }

    }

  

    update();

    mapItem.on("zoomend", update);

    mapItem.on("moveend", update);

}

  

interface SubControlOptions {

    index: number;

    map: Map;

    onSelectCallback: (index: number) => void;

}

  

class SubControl {

    readonly index: number;

    readonly map: Map;

  

    private onSelectCallback: (index: number) => void = () => {};

    protected button: HTMLDivElement | undefined;

    protected options: MapDataSet = {

        ...C.map.default,

        defaultZoom: C.map.default.minZoom,

        src: "",

        osmMode: "false",

        startCoordinate: "",

    };

    private _isSelected: boolean = false;

    get isSelected(): boolean {

        return this._isSelected;

    }

  

    constructor(options: SubControlOptions) {

        this.index = options.index;

        this.map = options.map;

        this.onSelectCallback = options.onSelectCallback;

    }

  

    setSelected(isSelected: boolean): void {

        if (this._isSelected === isSelected) return;

  

        this._isSelected = isSelected;

        if (isSelected) {

            this.button?.classList.add("selected");

            this.onSelected();

        } else {

            this.button?.classList.remove("selected");

            this.onDeselected();

        }

    }

  

    onAdd(containerEl: HTMLElement): void {

        this.button = L.DomUtil.create("div", "leaflet-control-button", containerEl);

        this.button.addEventListener("click", () => this.onSelectCallback(this.index));

        L.DomEvent.disableClickPropagation(containerEl);

        this.onAdded();

    }

  

    onRemove(): void {

        this.onRemoved();

        this.button?.removeEventListener("click", () => {});

        this.button?.replaceChildren();

    }

  

    updateSettings(options: MapDataSet): void {

        this.options = { ...this.options, ...options };

    }

  

    protected onAdded(): void {

        throw new Error("Not implemented");

    }

  

    protected onRemoved(): void {}

    protected onSelected(): void {}

    protected onDeselected(): void {}

  

    mapClicked(_event: LeafletMouseEvent): void {

        throw new Error("Not implemented");

    }

}

  

class PanControl extends SubControl {

    override onAdded(): void {

        if (this.button) {

            this.button.innerHTML = `<iconify-icon icon="lucide:mouse-pointer-2" width="19px" height="19px"></iconify-icon>`;

            this.button.ariaLabel = "Pan";

        }

    }

  

    override mapClicked(_event: LeafletMouseEvent): void {}

}

  

enum MeasureState {

    Ready,

    Measuring,

    Finishing,

    Done,

}

  

class MeasureControl extends SubControl {

    private state: MeasureState = MeasureState.Ready;

    private pathItems: LatLng[] = [];

    private distance: number = 0;

  

    private lineLayer: LayerGroup | undefined;

    private pointLayer: LayerGroup | undefined;

    private pathLine: Polyline | undefined;

    private previewLine: Polyline | undefined;

    private previewTooltip: Tooltip | undefined;

    private lastElement: CircleMarker | undefined;

  

    override onAdded(): void {

        if (this.button) {

            this.button.innerHTML = `<iconify-icon icon="lucide:ruler" width="19px" height="19px"></iconify-icon>`;

            this.button.ariaLabel = "Measure";

        }

  

        this.lineLayer = L.layerGroup().addTo(this.map);

        this.pointLayer = L.layerGroup().addTo(this.map);

  

        this.pathLine = L.polyline([]).addTo(this.lineLayer);

        this.previewLine = L.polyline([], { dashArray: "8" }).addTo(this.lineLayer);

        this.previewTooltip = this.getTooltip(true).setLatLng([0, 0]);

    }

  

    override onSelected(): void {

        this.map.getContainer().style.cursor = "crosshair";

        this.map.on("mousemove", (event: LeafletMouseEvent) => {

            this.renderPreview(event.latlng);

        });

    }

  

    override onDeselected(): void {

        this.map.getContainer().style.cursor = "";

        this.map.removeEventListener("mousemove");

        this.resetPath();

        this.state = MeasureState.Ready;

    }

  

    override mapClicked(event: LeafletMouseEvent): void {

        if (!this.lineLayer) throw new Error("Line layer not initialised");

        switch (this.state) {

            case MeasureState.Ready:

            case MeasureState.Measuring: {

                this.state = MeasureState.Measuring;

                this.pathItems.push(event.latlng);

                this.renderPath();

                this.previewTooltip?.addTo(this.lineLayer);

                this.renderPreview(event.latlng);

                break;

            }

            case MeasureState.Finishing: {

                this.state = MeasureState.Done;

                this.lastElement?.bindTooltip(this.getTooltip(true)).bringToFront();

                this.previewTooltip?.remove();

                break;

            }

            case MeasureState.Done: {

                this.resetPath();

                this.state = MeasureState.Ready;

            }

        }

    }

  

    private renderPath(): void {

        this.cleanLastElement();

        this.updatePolyline(this.pathLine, this.pathItems);

  

        const lastCoordinate = this.pathItems.at(-1);

        if (lastCoordinate === undefined) return;

  

        this.lastElement = this.getCircleMarker(lastCoordinate);

  

        const secondLastCoordinate = this.pathItems.at(-2);

        if (secondLastCoordinate === undefined) return;

  

        this.distance +=

            distance(lastCoordinate, secondLastCoordinate) * parseFloat(this.options.scale);

    }

  

    private renderPreview(mouseCoordinate: LatLng): void {

        if (this.state !== MeasureState.Measuring) return;

  

        const lastCoordinate = this.pathItems.at(-1);

        if (lastCoordinate === undefined) return;

  

        this.updatePolyline(this.previewLine, [lastCoordinate, mouseCoordinate]);

        this.previewTooltip = this.previewTooltip

            ?.setLatLng(mouseCoordinate)

            .setContent(

                this.getContent(

                    this.distance +

                        distance(lastCoordinate, mouseCoordinate) * parseFloat(this.options.scale),

                ),

            );

    }

  

    private resetPath(): void {

        this.pathItems = [];

        this.distance = 0;

        this.cleanLastElement();

        this.pointLayer?.clearLayers();

        this.updatePolyline(this.pathLine, []);

        this.updatePolyline(this.previewLine, []);

        this.previewTooltip?.remove();

    }

  

    private updatePolyline(line: Polyline | undefined, coordinates: LatLng[]): void {

        line?.setLatLngs(coordinates).redraw();

        line?.getElement()?.classList.remove("leaflet-interactive");

    }

  

    private cleanLastElement(): void {

        this.lastElement?.removeEventListener("click");

        this.lastElement?.getElement()?.classList.remove("leaflet-interactive");

    }

  

    private getTooltip(permanent: boolean = false): Tooltip {

        return L.tooltip({ permanent, offset: [15, 0] }).setContent(this.getContent(this.distance));

    }

  

    private getCircleMarker(coordinate: LatLng): CircleMarker {

        if (!this.pointLayer) throw new Error("Point layer not initialised");

        return L.circleMarker(coordinate, {

            radius: 4,

            fill: true,

            fillColor: "#3388ff",

            fillOpacity: 1,

        })

            .addTo(this.pointLayer)

            .addEventListener("click", () => (this.state = MeasureState.Finishing));

    }

  

    private getContent(measurement: number): string {

        return `${measurement.toFixed(1)} ${this.options?.unit ?? C.map.default.unit}`;

    }

}

  

class CopyControl extends SubControl {

    private previewTooltip: Tooltip | undefined;

    override onAdded(): void {

        if (this.button) {

            this.button.innerHTML = `<iconify-icon icon="lucide:pin" width="19px" height="19px"></iconify-icon>`;

            this.button.ariaLabel = "Copy";

        }

        this.previewTooltip = L.tooltip({ permanent: true, offset: [15, 0] }).setLatLng([0, 0]);

    }

  

    override onSelected(): void {

        this.map.getContainer().style.cursor = "crosshair";

        this.map.on("mousemove", (event: LeafletMouseEvent) => {

            this.renderPreview(event.latlng);

        });

        this.previewTooltip?.addTo(this.map);

    }

  

    override onDeselected(): void {

        this.map.getContainer().style.cursor = "";

        this.map.removeEventListener("mousemove");

        this.previewTooltip?.remove();

    }

  

    override mapClicked(event: LeafletMouseEvent): void {

        void navigator.clipboard.writeText(this.getContent(event.latlng));

    }

  

    private renderPreview(mouseCoordinate: LatLng): void {

        this.previewTooltip

            ?.setContent(this.getContent(mouseCoordinate))

            .setLatLng(mouseCoordinate);

    }

  

    private getContent(coordinate: LatLng): string {

        return `${Math.round(coordinate.lat)}, ${Math.round(coordinate.lng)}`;

    }

}

  

interface ResetControlOptions extends SubControlOptions {

    startCoord: LatLngTuple | null;

    defaultZoom: number;

}

  

class ResetControl extends SubControl {

    private startCoord: LatLngTuple | null;

    private defaultZoom: number;

  

    constructor(options: ResetControlOptions) {

        super(options);

        this.startCoord = options.startCoord;

        this.defaultZoom = options.defaultZoom;

    }

  

    override onAdd(containerEl: HTMLElement): void {

        this.button = L.DomUtil.create("div", "leaflet-control-button", containerEl);

        this.button.addEventListener("click", () => {

            if (!this.startCoord) return;

            if (Number.isFinite(this.defaultZoom)) {

                this.map.flyTo(this.startCoord, this.defaultZoom);

            } else {

                this.map.panTo(this.startCoord);

            }

        });

        L.DomEvent.disableClickPropagation(containerEl);

        this.onAdded();

    }

  

    override onAdded(): void {

        if (this.button) {

            this.button.innerHTML = `<iconify-icon icon="lucide:locate-fixed" width="19px" height="19px"></iconify-icon>`;

            this.button.ariaLabel = "Reset View";

            this.button.title = "Reset View";

        }

    }

  

    override mapClicked(_event: LeafletMouseEvent): void {}

}

  

interface ControlContainerOptions extends ControlOptions {

    enableCopyTool: boolean;

    startCoord: LatLngTuple | null;

    defaultZoom: number;

}

  

const DefaultControlContainerOptions: ControlContainerOptions = {

    enableCopyTool: false,

    startCoord: null,

    defaultZoom: NaN,

};

  

// Lazily define ControlContainer after Leaflet is loaded (L.Control is unavailable at parse time)

type ControlContainerClass = new (options: ControlContainerOptions) => L.Control & {

    updateSettings(options: MapDataSet): void;

};

let _ControlContainer: ControlContainerClass | null = null;

  

function getControlContainerClass(): ControlContainerClass {

    if (_ControlContainer) return _ControlContainer;

  

    class ControlContainer extends L.Control {

        private controls: SubControl[] = [];

        private activeIndex: number = 0;

        private settings: ControlContainerOptions;

  

        constructor(options: ControlContainerOptions) {

            super({ position: "topleft" });

            this.settings = { ...DefaultControlContainerOptions, ...options };

        }

  

        override onAdd(map: Map): HTMLElement {

            this.registerSubControl(PanControl, map);

            this.registerSubControl(MeasureControl, map);

            if (this.settings.enableCopyTool) this.registerSubControl(CopyControl, map);

            if (this.settings.startCoord) {

                this.registerResetControl(map, this.settings.startCoord, this.settings.defaultZoom);

            }

  

            const containerEl = L.DomUtil.create("div", "leaflet-bar leaflet-control");

  

            for (const control of this.controls) {

                control.onAdd(containerEl);

            }

            this.controls[this.activeIndex]?.setSelected(true);

  

            map.on("click", (event: LeafletMouseEvent) => {

                for (const control of this.controls) {

                    if (control.isSelected) control.mapClicked(event);

                }

            });

  

            return containerEl;

        }

  

        override onRemove(map: Map | undefined): void {

            map?.removeEventListener("click");

  

            for (const control of this.controls) {

                control.onRemove();

            }

            this.controls = [];

        }

  

        updateSettings(options: MapDataSet): void {

            for (const control of this.controls) {

                control.updateSettings(options);

            }

        }

  

        private registerSubControl(control: typeof SubControl, map: Map): void {

            const onSelectCallback = (controlIndex: number) => {

                this.controls.at(this.activeIndex)?.setSelected(false);

                this.controls.at(controlIndex)?.setSelected(true);

                this.activeIndex = controlIndex;

            };

            const options = { index: this.controls.length, map, onSelectCallback };

            this.controls.push(new control(options));

        }

  

        private registerResetControl(

            map: Map,

            startCoord: LatLngTuple,

            defaultZoom: number,

        ): void {

            const options: ResetControlOptions = {

                index: this.controls.length,

                map,

                onSelectCallback: () => {},

                startCoord,

                defaultZoom,

            };

            this.controls.push(new ResetControl(options));

        }

    }

  

    _ControlContainer = ControlContainer as unknown as ControlContainerClass;

    return _ControlContainer;

}

  

function isMapDataSet(dataset: unknown): dataset is MapDataSet {

    if (!isNonEmptyObject(dataset)) return false;

    const isOsmMode = dataset["osmMode"] === "true";

    if (isOsmMode) {

        if (!dataset["startCoordinate"]) return false;

    } else {

        if (!dataset["src"]) return false;

    }

    if (

        !dataset["height"] ||

        !dataset["minZoom"] ||

        !dataset["maxZoom"] ||

        !dataset["defaultZoom"] ||

        !dataset["zoomDelta"]

    ) {

        return false;

    }

    return true;

}

  

async function getImageMeta(url: string): Promise<HTMLImageElement> {

    return new Promise((resolve, reject) => {

        const image = new Image();

        image.onload = () => resolve(image);

        image.onerror = (error) => reject(error);

        image.src = url;

    });

}

  

interface MapHandle {

    map: Map;

    themeHandler?: () => void;

}

  

async function initialiseMap(

    mapElement: HTMLElement,

    markers: MarkerDataSet[],

): Promise<MapHandle | undefined> {

    const dataset = mapElement.dataset;

    if (!isMapDataSet(dataset)) {

        return;

    }

  

    mapElement.style.height = `${dataset.height}px`;

  

    const isOsmMode = dataset.osmMode === "true";

    const minZoom = parseFloat(dataset.minZoom);

    const maxZoom = parseFloat(dataset.maxZoom);

    const defaultZoom = parseFloat(dataset.defaultZoom);

    const zoomDelta = parseFloat(dataset.zoomDelta);

  

    let startCoord: LatLngTuple | null = null;

    if (dataset.startCoordinate) {

        try {

            startCoord = parseCoordinates(dataset.startCoordinate);

        } catch {

            startCoord = null;

        }

    }

  

    let mapItem: Map;

    let themeHandler: (() => void) | undefined;

  

    if (isOsmMode) {

        mapItem = L.map(mapElement, {

            crs: L.CRS.EPSG3857,

            center: startCoord ?? [0, 0],

            zoom: Number.isFinite(defaultZoom) ? defaultZoom : minZoom,

            minZoom,

            maxZoom,

            zoomSnap: 0.01,

            zoomDelta,

        });

  

        const tileLayer = L.tileLayer(C.tiles[getCurrentTheme()], {

            attribution: C.tiles.attribution,

            subdomains: C.tiles.subdomains,

            maxZoom: C.tiles.maxZoom,

        }).addTo(mapItem);

  

        themeHandler = () => {

            tileLayer.setUrl(C.tiles[getCurrentTheme()]);

        };

        document.addEventListener("themechange", themeHandler);

    } else {

        const image = await getImageMeta(dataset.src);

        const bounds: LatLngBoundsExpression = [

            [0, 0],

            [image.naturalHeight, image.naturalWidth],

        ];

  

        mapItem = L.map(mapElement, {

            crs: L.CRS.Simple,

            maxBounds: bounds,

            minZoom,

            maxZoom,

            zoomSnap: 0.01,

            zoomDelta,

        });

  

        L.imageOverlay(dataset.src, bounds).addTo(mapItem);

  

        if (startCoord) {

            mapItem.setView(startCoord, Number.isFinite(defaultZoom) ? defaultZoom : minZoom);

        } else {

            mapItem.fitBounds(bounds);

            mapItem.setZoom(Number.isFinite(defaultZoom) ? defaultZoom : minZoom);

        }

    }

  

    const ControlContainer = getControlContainerClass();

    const controls = new ControlContainer({

        enableCopyTool: dataset.enableCopyTool === "true",

        startCoord,

        defaultZoom,

    });

    controls.addTo(mapItem);

    controls.updateSettings(dataset);

  

    markers.map((marker) => addMarker(marker, mapItem, isOsmMode));

  

    /* ===================================== */

    /* 🔥 CUSTOM TILE TRANSFORM (LINEAR) */

    /* ===================================== */

  

    const OFFSET_Y = -88; // 🔥 SATU-SATUNYA VALUE

  

    function getOffsetY(zoom: number): number

    {

        const scale = Math.pow(2, zoom * 0.9); // tweak 0.7–0.9

        return OFFSET_Y / scale;

    }

  

    function adjustTiles(zoom: number) {

        const tiles = mapItem

            .getPanes()

            .tilePane.querySelectorAll(".leaflet-tile-container");

  

        const offset = getOffsetY(zoom);

  

        tiles.forEach((el) => {

            if (!(el instanceof HTMLElement)) return;

  

            let transform = el.style.transform;

            if (!transform) return;

  

            // ❗ remove old translateY (anti stacking)

            transform = transform.replace(/translateY\([^)]+\)/, "").trim();

  

            // ✅ APPLY DI DEPAN (biar tidak kena scale)

            el.style.transform = `translateY(${offset}px) ${transform}`;

        });

    }

  

    /* ===================================== */

    /* 🔥 EVENTS (FIX NO DRIFT) */

    /* ===================================== */

  

    // saat animasi zoom (pakai target zoom, bukan interpolasi)

    mapItem.on("zoomanim", (e: any) => {

        const z = (mapItem as any)._animateToZoom ?? e.zoom;

        requestAnimationFrame(() => adjustTiles(z));

    });

  

    // saat zoom selesai (snap final)

    mapItem.on("zoomend", () => {

        adjustTiles(mapItem.getZoom());

    });

  

    // initial apply (WAJIB)

    adjustTiles(mapItem.getZoom());

  

        return { map: mapItem, themeHandler };

    }

  

function cleanupMap(handle: MapHandle | undefined) {

    if (!handle) return;

    if (handle.themeHandler) {

        document.removeEventListener("themechange", handle.themeHandler);

    }

    handle.map.clearAllEventListeners();

    handle.map.remove();

}

  

async function initializeLeafletMaps() {

    const maps: NodeListOf<HTMLElement> = document.querySelectorAll("div.leaflet-map");

    if (maps.length === 0) return;

  

    try {

        await loadDependencies();

    } catch (err) {

        console.error("[leaflet-map] Failed to load dependencies:", err);

        for (const map of Array.from(maps)) {

            map.textContent =

                "Failed to load map dependencies. Check your browser's content blocking settings.";

        }

        return;

    }

  

    for (const map of Array.from(maps)) {

        const markerData = getMarkerData(map);

        const mapItem = await initialiseMap(map, markerData);

        window.addCleanup(() => cleanupMap(mapItem));

    }

}

  

document.addEventListener("nav", initializeLeafletMaps);

document.addEventListener("render", initializeLeafletMaps);

  

export default "";