{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "map-heatmap-01",
  "title": "Weighted heatmap example",
  "description": "A heatmap of 60 illustrative points in Toronto, counted or weighted, composed from the Unmap map, the heatmap-layer item and your ToggleGroup.",
  "registryDependencies": [
    "https://registry.unmap.dev/r/map.json",
    "https://registry.unmap.dev/r/heatmap-layer.json",
    "toggle-group"
  ],
  "files": [
    {
      "path": "registry/blocks/map-heatmap-01.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Map } from \"@/components/ui/map\";\nimport { HeatmapLayer } from \"@/components/ui/heatmap-layer\";\nimport { ToggleGroup, ToggleGroupItem } from \"@/components/ui/toggle-group\";\nimport { cn } from \"@/lib/utils\";\n\nconst COPY = {\n  en: {\n    noKey: \"Add your unmap key to load the map.\",\n    title: \"Point density\",\n    hint: \"Switch weighting to see where the heaviest points gather.\",\n    group: \"How points count\",\n    even: \"Each point once\",\n    weighted: \"By weight\",\n    data: \"60 illustrative points across Toronto, weighted 1 to 5.\",\n  },\n  fr: {\n    noKey: \"Ajoutez votre clé unmap pour charger la carte.\",\n    title: \"Densité des points\",\n    hint: \"Activez la pondération pour voir où se concentrent les points les plus lourds.\",\n    group: \"Comment les points comptent\",\n    even: \"Chaque point une fois\",\n    weighted: \"Selon le poids\",\n    data: \"60 points illustratifs répartis dans Toronto, pondérés de 1 à 5.\",\n  },\n} as const;\n\n/** Deterministic sample points around a centre: the same 60 points on every load. */\nfunction samplePoints(center: [number, number], count: number, spread: number) {\n  let seed = 7;\n  const next = () => ((seed = (seed * 16807) % 2147483647) - 1) / 2147483646;\n  return {\n    type: \"FeatureCollection\" as const,\n    features: Array.from({ length: count }, (_, i) => ({\n      type: \"Feature\" as const,\n      id: i,\n      properties: { weight: 1 + Math.round(next() * 4) },\n      geometry: { type: \"Point\" as const, coordinates: [center[0] + (next() - 0.5) * spread, center[1] + (next() - 0.5) * spread * 0.7] },\n    })),\n  };\n}\n\n/** Illustrative data: 60 points north of downtown Toronto, clear of the lake, with a `weight` from 1 to 5, not real places. */\nconst POINTS = samplePoints([-79.4, 43.71], 60, 0.16);\n\ntype Weighting = \"even\" | \"weighted\";\n\n/**\n * A minimal example: a heatmap of 60 illustrative points around Toronto, in your --primary. Switch\n * between counting each point once and weighing it by its `weight`, and the hot spots move to where\n * the heaviest points are. The heatmap is drawn in the browser: the only requests are the map's own.\n */\nexport function MapHeatmap({\n  apiKey,\n  lang = \"en\",\n  className,\n}: {\n  /** Your Unmap browser key. */\n  apiKey: string;\n  /** Language of the copy and the map labels: \"en\" (default) or \"fr\". */\n  lang?: \"en\" | \"fr\";\n  className?: string;\n}) {\n  const copy = COPY[lang];\n  const [weighting, setWeighting] = useState<Weighting>(\"even\");\n\n  return (\n    <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n      <div role=\"region\" aria-label={copy.title} className=\"relative h-96\">\n        <Map apiKey={apiKey} center={[-79.4, 43.71]} zoom={10.75} lang={lang}>\n          {/* One radius in both states; weighted, the intensity is divided by the mean weight (about 3),\n              so the switch moves the hot spots rather than just heating the whole map up. */}\n          <HeatmapLayer\n            data={POINTS}\n            weight={weighting === \"weighted\" ? \"weight\" : 1}\n            intensity={weighting === \"weighted\" ? 1 / 3 : 1}\n            radius={44}\n          />\n        </Map>\n      </div>\n      {/* No key, no map: one line says what to add. */}\n      {apiKey.trim() === \"\" ? <p className=\"text-xs text-muted-foreground\">{copy.noKey}</p> : null}\n      <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n        <ToggleGroup\n          aria-label={copy.group}\n          variant=\"outline\"\n          size=\"sm\"\n          value={[weighting]}\n          onValueChange={(next: unknown[]) => {\n            // One option is always on: pressing the pressed one keeps it.\n            if (next[0] === \"even\" || next[0] === \"weighted\") setWeighting(next[0]);\n          }}\n        >\n          <ToggleGroupItem value=\"even\">{copy.even}</ToggleGroupItem>\n          <ToggleGroupItem value=\"weighted\">{copy.weighted}</ToggleGroupItem>\n        </ToggleGroup>\n        <p className=\"text-sm text-muted-foreground\">{copy.hint}</p>\n      </div>\n      <p className=\"text-xs text-muted-foreground\">{copy.data}</p>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/unmap-map-heatmap.tsx"
    }
  ],
  "docs": "Import MapHeatmap from your components/unmap-map-heatmap file and pass apiKey (your Unmap browser key). Use lang=\"fr\" for French. Allow your site origin on the key. Preview: https://unmap.dev/templates/map-heatmap",
  "categories": [
    "examples",
    "maps"
  ],
  "type": "registry:block"
}