GeoLeaf Core API - v3.19.0
    Preparing search index...

    Interface GeoLeafPopupActionDetail

    Detail payload for geoleaf:popup:action.

    Dispatched when a user clicks a popup or side-panel action button (type: "action" in popup.fields). Listen via GeoLeaf.events.on("geoleaf:popup:action", …).

    Five fields are plain data; button, setBusy and close are a live DOM node and two closures. The key therefore lives in GeoLeafRawEventMap, not in the sanitising bus, which would have delivered them as {} and undefined without any error.

    ⚠️ Consequence for subscribers, and it is the only breaking part of this change: JSON.stringify(e.detail) now throws (circular DOM reference), and passing the detail to postMessage / a Worker throws DataCloneError. Copy the fields you need instead: const { actionId, layerId, featureId, properties } = e.detail;

    This is a document event: any script on the page can hear it, and therefore any script can now call close() or setBusy() on the popup. That is a real widening — and an acceptable one, because the same script can already do document.querySelector(".gl-poi-popup__action").click(). The confidentiality rule on properties below is what actually guards this channel, and it is unchanged.

    GeoLeaf.Events.on("geoleaf:popup:action", (e) => onPopupAction(e.detail)).

    function onPopupAction(d: GeoLeafPopupActionDetail): void {
    if (d.actionId !== "tickets:create-request") return;
    d.setBusy(true);
    void createRequest(d.featureId)
    .then(() => d.close())
    .finally(() => d.setBusy(false));
    }
    interface GeoLeafPopupActionDetail {
        actionId: string;
        layerId: string;
        featureId: string | number | null;
        properties: Record<string, unknown>;
        lngLat?: { lat: number; lng: number };
        button: HTMLElement;
        setBusy(busy: boolean): void;
        close(): void;
    }
    Index
    actionId: string

    Opaque action identifier from the button config.

    layerId: string

    Layer the feature belongs to.

    featureId: string | number | null

    Feature/POI identifier (null when the source has no stable id).

    properties: Record<string, unknown>

    Whitelisted subset of feature properties, per the payloadFields option of the button.

    ⚠️ Without payloadFields, this is {} — the default goes to confidentiality, not convenience, because this is a document event any script on the page can hear. There is no "send everything" mode, and adding one is not a configuration gap.

    lngLat?: { lat: number; lng: number }

    Geographic position of the popup, when available.

    button: HTMLElement

    The button that was clicked, for host-owned visual state.

    Live node, not a copy: mutating it mutates what the user sees. Prefer setBusy for the pending state — it keeps the busy convention in one place.

    • Toggles the button's pending state: disabled, aria-busy, and the gl-poi-popup__action--busy modifier.

      Safe to call after the surface has closed — it writes to a detached node, which is inert. That is why a .finally(() => d.setBusy(false)) needs no guard.

      Parameters

      • busy: boolean

        true to enter the pending state, false to leave it.

      Returns void

    • Closes the surface the button was rendered in — the popup or the side panel, never both.

      ⚠️ This is deliberately narrower than GeoLeaf.FeatureInfo.close(), which closes both surfaces unconditionally and emits geoleaf:poi:panel:close as it goes. A popup button calling that would have closed an unrelated side panel and announced a panel close nobody performed.

      Idempotent: closing an already-closed surface does nothing.

      Returns void