Overlay components
These items work with the catalog overlays a map composes: the energy set through profile="energy" and the treaties through overlays={["treaties"]}. The overlays themselves are documented under Overlays.
npx shadcn@latest registry add @unmap=https://registry.unmap.dev/r/{name}.json
npx shadcn@latest add @unmap/energy-mapnpx shadcn-vue@latest add https://registry.unmap.dev/r/vue/energy-map.jsonThe React line registers the registry once per project, so later items can be named @unmap/<item>; shadcn-vue has no registry add and takes the item URL directly. Files land in components/ui/ beside your own; nothing is overwritten without asking.
Browse every item on registry.unmap.dev| Item | What it is |
|---|---|
energy-layer-control | The energy overlay set as a layer-legend preset, for a map that already used profile="energy". |
energy-map | <Map> already composed with profile="energy" (muted by default). Map composition only, not a style. |
well-search | Search box labelled for UWIs. Sends the query string only; the gateway detects UWI vs civic. |
legal-land-search | Search box labelled for LSD. Same rule: query string only. |
energy-popup | Identify wells, pipelines, and facilities on click. onLookup(at) fires as a click starts a lookup, then one of onIdentify(hit, at), onMiss(at) or onError(error, at) (Vue: @lookup, @identify, @miss, @error). Only the latest click answers: a lookup overtaken by a newer click gets none of the three. |
treaty-context | Historic and modern treaty switches, a coordinate lookup, and a details panel that lists every treaty record at a point, in English and French. Pair with overlays={["treaties"]}. onSelect (Vue: @select) receives each answer: the context, the record ids drawn under the point, and the hidden categories. onError (Vue: @error) receives a failed lookup and the point it was for. |
Energy
energy-map is a map already composed with profile="energy" on muted cartography, and the
other energy items work inside it: well-search finds a well by its UWI, energy-layer-control
switches the overlays on and off, and energy-popup identifies what is under a click. A key without
the energy add-on still gets the basemap; the overlay tiles and UWI search answer
403 addon_required. Every search and every click that identifies is one request. The layer
control renders a bare fieldset, so the example floats it in your Card. See
Energy profile.
"use client";
import { Card, CardContent } from "@/components/ui/card";
import { EnergyMap } from "@/components/ui/energy-map";
import { EnergyLayerControl } from "@/components/ui/energy-layer-control";
import { WellSearch } from "@/components/ui/well-search";
import { EnergyPopup } from "@/components/ui/energy-popup";
export function WellsMap() {
const apiKey = process.env.NEXT_PUBLIC_UNMAP_KEY!;
return (
<div className="h-[560px]">
<EnergyMap apiKey={apiKey} center={[-114.07, 51.05]} zoom={7}>
<div className="absolute top-3 left-3 z-10 w-72">
<WellSearch apiKey={apiKey} />
</div>
<Card className="absolute right-3 bottom-10 z-10 w-60">
<CardContent>
<EnergyLayerControl />
</CardContent>
</Card>
<EnergyPopup apiKey={apiKey} onIdentify={(hit) => console.log(hit.uwi ?? hit.name)} />
</EnergyMap>
</div>
);
}<script setup lang="ts">
import type { IdentifyResult } from "@unmap/geocoding";
import { Card, CardContent } from "@/components/ui/card";
import { UnmapEnergyMap } from "@/components/ui/energy-map";
import { UnmapEnergyLayerControl } from "@/components/ui/energy-layer-control";
import { UnmapWellSearch } from "@/components/ui/well-search";
import { UnmapEnergyPopup } from "@/components/ui/energy-popup";
const apiKey = import.meta.env.VITE_UNMAP_KEY!;
function onIdentify(hit: IdentifyResult) {
console.log(hit.uwi ?? hit.name);
}
</script>
<template>
<div class="h-[560px]">
<UnmapEnergyMap :api-key="apiKey" :center="[-114.07, 51.05]" :zoom="7">
<div class="absolute top-3 left-3 z-10 w-72">
<UnmapWellSearch :api-key="apiKey" />
</div>
<Card class="absolute right-3 bottom-10 z-10 w-60">
<CardContent>
<UnmapEnergyLayerControl />
</CardContent>
</Card>
<UnmapEnergyPopup :api-key="apiKey" @identify="onIdentify" />
</UnmapEnergyMap>
</div>
</template>legal-land-search is the LSD twin of well-search: the same search box, labelled for legal land
descriptions such as NW-25-24-1-W5, and it sends the query string only. It works on any map; the
search needs an add-on that includes legal land (Legal Land, Energy or Agriculture). See
Legal land.
"use client";
import { Map } from "@/components/ui/map";
import { LegalLandSearch } from "@/components/ui/legal-land-search";
export function LandFinder() {
const apiKey = process.env.NEXT_PUBLIC_UNMAP_KEY!;
return (
<div className="h-[480px]">
<Map apiKey={apiKey} style="muted" center={[-113.49, 53.55]} zoom={8}>
<div className="absolute top-3 left-3 z-10 w-72">
<LegalLandSearch apiKey={apiKey} onSelect={(result) => console.log(result.name)} />
</div>
</Map>
</div>
);
}<script setup lang="ts">
import type { GeocodeResult } from "@unmap/geocoding";
import { UnmapMap } from "@/components/ui/map";
import { UnmapLegalLandSearch } from "@/components/ui/legal-land-search";
const apiKey = import.meta.env.VITE_UNMAP_KEY!;
function onSelect(result: GeocodeResult) {
console.log(result.name);
}
</script>
<template>
<div class="h-[480px]">
<UnmapMap :api-key="apiKey" map-style="muted" :center="[-113.49, 53.55]" :zoom="8">
<div class="absolute top-3 left-3 z-10 w-72">
<UnmapLegalLandSearch :api-key="apiKey" @select="onSelect" />
</div>
</UnmapMap>
</div>
</template>Treaties
treaty-context pairs with overlays={["treaties"]}: switches for historic and modern treaties,
a coordinate lookup, and a panel that lists every treaty record at a point, in English and French.
Each lookup, from a click on the map, typed coordinates or the point prop, is one request. The
treaties overlay is core, with no add-on. See Treaty overlay.
"use client";
import { Card, CardContent } from "@/components/ui/card";
import { Map } from "@/components/ui/map";
import { TreatyContext } from "@/components/ui/treaty-context";
export function TreatyMap() {
const apiKey = process.env.NEXT_PUBLIC_UNMAP_KEY!;
return (
<div className="h-[560px]">
<Map apiKey={apiKey} style="muted" center={[-106.67, 52.13]} zoom={5} overlays={["treaties"]}>
<Card className="absolute top-3 left-3 z-10 max-h-[calc(100%-1.5rem)] w-80 overflow-y-auto">
<CardContent>
<TreatyContext apiKey={apiKey} onSelect={({ context }) => console.log(context.matches.map((match) => match.name))} />
</CardContent>
</Card>
</Map>
</div>
);
}<script setup lang="ts">
import type { TreatySelection } from "@unmap/geocoding";
import { Card, CardContent } from "@/components/ui/card";
import { UnmapMap } from "@/components/ui/map";
import { UnmapTreatyContext } from "@/components/ui/treaty-context";
const apiKey = import.meta.env.VITE_UNMAP_KEY!;
function onSelect({ context }: TreatySelection) {
console.log(context.matches.map((match) => match.name));
}
</script>
<template>
<div class="h-[560px]">
<UnmapMap :api-key="apiKey" map-style="muted" :center="[-106.67, 52.13]" :zoom="5" :overlays="['treaties']">
<Card class="absolute top-3 left-3 z-10 max-h-[calc(100%-1.5rem)] w-80 overflow-y-auto">
<CardContent>
<UnmapTreatyContext :api-key="apiKey" @select="onSelect" />
</CardContent>
</Card>
</UnmapMap>
</div>
</template>