CARTO now answers every keyless basemap request with HTTP 200 and a valid
256x256 PNG that is just a dark square watermarked "API KEY REQUIRED".
Leaflet accepts it as a tile and paints it, so the map silently filled with
the warning — no console error, nothing in the network tab to catch it.
Esri's World Dark Gray Canvas is a genuine dark basemap and needs no key.
Its ArcGIS REST service orders the tile path {z}/{y}/{x}, the reverse of
what Leaflet knows how to substitute, so a getTileUrl override is the whole
fix. react-leaflet always instantiates Leaflet's own TileLayer, so the
custom class is added to the map directly and torn down on unmount rather
than passed as a prop.
43 lines
1.9 KiB
TypeScript
43 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import dynamic from "next/dynamic";
|
|
import { Loader2, MapPinned } from "lucide-react";
|
|
|
|
/**
|
|
* Leaflet reads `window` at module scope, so it cannot be evaluated during SSR.
|
|
* `next/dynamic` with `ssr: false` keeps it out of the server bundle entirely —
|
|
* this file is the client boundary that makes that possible (App Router only
|
|
* allows `ssr: false` inside a Client Component).
|
|
*/
|
|
const PlantMap = dynamic(() => import("./PlantMap").then((m) => m.PlantMap), {
|
|
ssr: false,
|
|
loading: () => <MapSkeleton />,
|
|
});
|
|
|
|
function MapSkeleton() {
|
|
return (
|
|
<div className="grid lg:grid-cols-[minmax(0,1fr)_340px] gap-4 items-start">
|
|
<div className="relative rounded-2xl overflow-hidden border border-gray-200 dark:border-white/5 shadow-sm bg-gray-100 dark:bg-surface h-[52vh] min-h-[320px] lg:h-[calc(100vh-15rem)] lg:min-h-[560px] grid place-items-center">
|
|
<div className="text-center">
|
|
<Loader2 className="w-6 h-6 mx-auto text-[#30638E] animate-spin" />
|
|
<p className="mt-2 text-xs text-gray-500 dark:text-gray-400">Loading map…</p>
|
|
</div>
|
|
</div>
|
|
<div className="rounded-2xl border border-gray-200 dark:border-white/5 bg-white dark:bg-surface shadow-sm overflow-hidden">
|
|
<div className="p-4 border-b border-gray-100 dark:border-white/5">
|
|
<div className="h-4 w-20 rounded bg-gray-200 dark:bg-white/10 animate-pulse" />
|
|
<div className="mt-3 h-11 rounded-lg bg-gray-100 dark:bg-white/5 animate-pulse" />
|
|
</div>
|
|
<div className="p-4 space-y-3">
|
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
<div key={i} className="h-9 rounded bg-gray-100 dark:bg-white/5 animate-pulse" />
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function PlantMapLoader(props: React.ComponentProps<typeof import("./PlantMap").PlantMap>) {
|
|
return <PlantMap {...props} />;
|
|
}
|