{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "isochrone-reachability-map",
  "title": "Isochrone Reachability Map",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/isochrone-reachability-map/IsochroneReachabilityMap.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { Map, MapMarker, MapSource, MapLayer, type MapRef } from '@/components/ui/map'\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\n\ndefineProps<{ accessToken?: string }>()\n\nconst mapRef = ref<MapRef | null>(null)\nconst selectedTime = ref<10 | 20 | 30>(20)\n\nconst hubLocation: [number, number] = [-87.6298, 41.8781] // Chicago Loop\n\n// Approximated polygon coordinates for 10m, 20m, 30m isochrones\nfunction createIsochroneCoords(radiusMiles: number) {\n  const points: [number, number][] = []\n  const steps = 36\n  const latDelta = radiusMiles / 69\n  const lngDelta = radiusMiles / (69 * Math.cos((41.8781 * Math.PI) / 180))\n  for (let i = 0; i <= steps; i++) {\n    const angle = (i / steps) * 2 * Math.PI\n    // Add small organic jitter\n    const jitter = 1 + Math.sin(angle * 3) * 0.12\n    const lng = hubLocation[0] + lngDelta * Math.cos(angle) * jitter\n    const lat = hubLocation[1] + latDelta * Math.sin(angle) * jitter\n    points.push([lng, lat])\n  }\n  return points\n}\n\nconst isochrones = {\n  10: { coords: createIsochroneCoords(2.8), pop: '340K', jobs: '520K', color: '#10b981', label: '10 Min Commute' },\n  20: { coords: createIsochroneCoords(6.2), pop: '1.24M', jobs: '890K', color: '#3b82f6', label: '20 Min Commute' },\n  30: { coords: createIsochroneCoords(11.5), pop: '2.85M', jobs: '1.45M', color: '#f59e0b', label: '30 Min Commute' },\n}\n</script>\n\n<template>\n  <div class=\"grid gap-4 lg:grid-cols-[1fr_320px]\">\n    <div class=\"border-border bg-card relative h-[480px] overflow-hidden rounded-xl border\">\n      <Map\n        ref=\"mapRef\"\n        :access-token=\"accessToken\"\n        variant=\"light\"\n        :center=\"hubLocation\"\n        :zoom=\"10.8\"\n        class=\"h-full w-full\"\n      >\n        <!-- 30m Isochrone Fill & Line -->\n        <MapSource\n          id=\"iso-30\"\n          :options=\"{\n            type: 'geojson',\n            data: {\n              type: 'Feature',\n              properties: {},\n              geometry: { type: 'Polygon', coordinates: [isochrones[30].coords] },\n            },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-30-fill\"\n          :options=\"{\n            type: 'fill',\n            source: 'iso-30',\n            paint: { 'fill-color': '#f59e0b', 'fill-opacity': selectedTime >= 30 ? 0.15 : 0.04 },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-30-line\"\n          :options=\"{\n            type: 'line',\n            source: 'iso-30',\n            paint: { 'line-color': '#f59e0b', 'line-width': 1.5, 'line-dasharray': [2, 2] },\n          }\"\n        />\n\n        <!-- 20m Isochrone Fill & Line -->\n        <MapSource\n          id=\"iso-20\"\n          :options=\"{\n            type: 'geojson',\n            data: {\n              type: 'Feature',\n              properties: {},\n              geometry: { type: 'Polygon', coordinates: [isochrones[20].coords] },\n            },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-20-fill\"\n          :options=\"{\n            type: 'fill',\n            source: 'iso-20',\n            paint: { 'fill-color': '#3b82f6', 'fill-opacity': selectedTime >= 20 ? 0.22 : 0.06 },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-20-line\"\n          :options=\"{\n            type: 'line',\n            source: 'iso-20',\n            paint: { 'line-color': '#3b82f6', 'line-width': 2 },\n          }\"\n        />\n\n        <!-- 10m Isochrone Fill & Line -->\n        <MapSource\n          id=\"iso-10\"\n          :options=\"{\n            type: 'geojson',\n            data: {\n              type: 'Feature',\n              properties: {},\n              geometry: { type: 'Polygon', coordinates: [isochrones[10].coords] },\n            },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-10-fill\"\n          :options=\"{\n            type: 'fill',\n            source: 'iso-10',\n            paint: { 'fill-color': '#10b981', 'fill-opacity': 0.3 },\n          }\"\n        />\n        <MapLayer\n          id=\"iso-10-line\"\n          :options=\"{\n            type: 'line',\n            source: 'iso-10',\n            paint: { 'line-color': '#10b981', 'line-width': 2.5 },\n          }\"\n        />\n\n        <!-- Central Hub Marker -->\n        <MapMarker :lng-lat=\"hubLocation\" anchor=\"center\">\n          <div class=\"relative flex items-center justify-center\">\n            <span class=\"bg-primary/30 absolute size-6 animate-ping rounded-full\" />\n            <div\n              class=\"bg-primary text-primary-foreground ring-background flex size-6 items-center justify-center rounded-full font-mono text-xs font-bold shadow-md ring-2\"\n            >\n              ★\n            </div>\n          </div>\n        </MapMarker>\n      </Map>\n    </div>\n\n    <!-- Isochrone Analytics Card -->\n    <Card class=\"flex flex-col justify-between\">\n      <CardHeader>\n        <div class=\"flex items-center justify-between\">\n          <Badge variant=\"outline\" class=\"font-mono text-xs\">COMMUTE ANALYSIS</Badge>\n          <Badge class=\"border-info/20 bg-info/10 text-info\">Drive-Time</Badge>\n        </div>\n        <CardTitle class=\"mt-2 text-lg\">Reachability Zones</CardTitle>\n        <CardDescription>Transit reachability from Downtown Distribution Hub.</CardDescription>\n      </CardHeader>\n      <CardContent class=\"space-y-4\">\n        <!-- Range Selector Tabs -->\n        <div class=\"border-border bg-muted grid grid-cols-3 gap-1 rounded-lg border p-1 text-xs\">\n          <button\n            v-for=\"t in [10, 20, 30] as const\"\n            :key=\"t\"\n            type=\"button\"\n            class=\"rounded-md py-1.5 font-medium transition-colors\"\n            :class=\"\n              selectedTime === t\n                ? 'bg-background text-foreground shadow-xs'\n                : 'text-muted-foreground hover:text-foreground'\n            \"\n            @click=\"selectedTime = t\"\n          >\n            {{ t }} mins\n          </button>\n        </div>\n\n        <div class=\"border-border space-y-3 border-t pt-3\">\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs\">Population Reach</span>\n            <span class=\"text-foreground font-mono text-base font-bold\">{{ isochrones[selectedTime].pop }}</span>\n          </div>\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs\">Workforce / Labor Pool</span>\n            <span class=\"text-foreground font-mono text-base font-bold\">{{ isochrones[selectedTime].jobs }}</span>\n          </div>\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs\">Service Band</span>\n            <span class=\"font-mono text-xs font-semibold\" :style=\"{ color: isochrones[selectedTime].color }\">\n              {{ isochrones[selectedTime].label }}\n            </span>\n          </div>\n        </div>\n\n        <div class=\"border-border text-muted-foreground space-y-2 border-t pt-3 text-xs\">\n          <div class=\"flex items-center gap-2\">\n            <span class=\"bg-success size-2 rounded-full\" />\n            <span>Green ring: 10-minute urban core</span>\n          </div>\n          <div class=\"flex items-center gap-2\">\n            <span class=\"bg-info size-2 rounded-full\" />\n            <span>Blue ring: 20-minute metropolitan belt</span>\n          </div>\n          <div class=\"flex items-center gap-2\">\n            <span class=\"bg-warning size-2 rounded-full\" />\n            <span>Amber ring: 30-minute outer ring</span>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/IsochroneReachabilityMap.vue"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/map.json"
  ],
  "description": "Drive-time reachability zones showing 10m, 20m, and 30m commute polygons with workforce population metrics.",
  "categories": [
    "logistics",
    "geo",
    "map"
  ]
}