{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "leaflet-hub-locator-map",
  "title": "Leaflet Hub Locator Map",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/leaflet-hub-locator-map/LeafletHubLocatorMap.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { LeafletCircle, LeafletMap, LeafletMarker, type LeafletMapRef } from '@/components/ui/leaflet-map'\n\nexport interface DistributionHub {\n  id: string\n  code: string\n  name: string\n  city: string\n  state: string\n  lat: number\n  lng: number\n  capacityPct: number\n  bays: number\n  /** Delivery coverage radius in miles. */\n  coverageMiles: number\n}\n\nexport interface LeafletHubLocatorMapProps {\n  class?: HTMLAttributes['class']\n  hubs?: DistributionHub[]\n}\n\nconst DEFAULT_HUBS: DistributionHub[] = [\n  {\n    id: 'atl-01',\n    code: 'ATL-01',\n    name: 'South Atlanta DC',\n    city: 'Atlanta',\n    state: 'GA',\n    lat: 33.629,\n    lng: -84.402,\n    capacityPct: 82,\n    bays: 36,\n    coverageMiles: 18,\n  },\n  {\n    id: 'atl-02',\n    code: 'ATL-02',\n    name: 'Marietta Cross-Dock',\n    city: 'Marietta',\n    state: 'GA',\n    lat: 33.953,\n    lng: -84.55,\n    capacityPct: 64,\n    bays: 22,\n    coverageMiles: 14,\n  },\n  {\n    id: 'atl-03',\n    code: 'ATL-03',\n    name: 'McDonough Fulfillment',\n    city: 'McDonough',\n    state: 'GA',\n    lat: 33.447,\n    lng: -84.147,\n    capacityPct: 91,\n    bays: 48,\n    coverageMiles: 22,\n  },\n  {\n    id: 'atl-04',\n    code: 'ATL-04',\n    name: 'Peachtree City Hub',\n    city: 'Peachtree City',\n    state: 'GA',\n    lat: 33.397,\n    lng: -84.596,\n    capacityPct: 57,\n    bays: 18,\n    coverageMiles: 15,\n  },\n  {\n    id: 'atl-05',\n    code: 'ATL-05',\n    name: 'Douglasville Depot',\n    city: 'Douglasville',\n    state: 'GA',\n    lat: 33.751,\n    lng: -84.747,\n    capacityPct: 73,\n    bays: 26,\n    coverageMiles: 16,\n  },\n  {\n    id: 'atl-06',\n    code: 'ATL-06',\n    name: 'Conyers Annex',\n    city: 'Conyers',\n    state: 'GA',\n    lat: 33.667,\n    lng: -84.018,\n    capacityPct: 88,\n    bays: 30,\n    coverageMiles: 20,\n  },\n]\n\nconst METERS_PER_MILE = 1609.34\n\nconst props = defineProps<LeafletHubLocatorMapProps>()\n\nconst hubs = computed(() => props.hubs ?? DEFAULT_HUBS)\nconst selectedId = ref(DEFAULT_HUBS[0]?.id ?? '')\n\nconst mapRef = ref<LeafletMapRef | null>(null)\n\nfunction selectHub(hub: DistributionHub) {\n  selectedId.value = hub.id\n  mapRef.value?.flyTo?.({\n    center: [hub.lng, hub.lat],\n    zoom: 11.5,\n    duration: 900,\n  })\n}\n\nfunction capacityVariant(capacityPct: number) {\n  return capacityPct >= 85 ? 'warning' : 'info'\n}\n</script>\n\n<template>\n  <div data-slot=\"leaflet-hub-locator-map\" :class=\"cn('flex h-full min-h-0 flex-col gap-4', props.class)\">\n    <div class=\"flex flex-wrap items-center justify-between gap-3\">\n      <h2 class=\"text-foreground text-lg font-semibold tracking-tight\">Distribution hubs</h2>\n      <p class=\"text-muted-foreground text-xs\">{{ hubs.length }} centers</p>\n    </div>\n\n    <div class=\"grid min-h-0 flex-1 grid-cols-1 gap-4 lg:grid-cols-12\">\n      <Card class=\"border-border flex min-h-0 flex-col overflow-hidden shadow-xs lg:col-span-8\">\n        <div class=\"relative min-h-[360px] flex-1 overflow-hidden\">\n          <LeafletMap\n            ref=\"mapRef\"\n            variant=\"streets\"\n            :center=\"[-84.388, 33.749]\"\n            :zoom=\"10.5\"\n            class=\"absolute inset-0 size-full\"\n          >\n            <LeafletCircle\n              v-for=\"hub in hubs\"\n              :key=\"`${hub.id}-coverage`\"\n              :center=\"[hub.lng, hub.lat]\"\n              :radius=\"hub.coverageMiles * METERS_PER_MILE\"\n              color=\"#3b82f6\"\n              :weight=\"selectedId === hub.id ? 2 : 1.5\"\n              :fill=\"true\"\n              fill-color=\"#3b82f6\"\n              :fill-opacity=\"selectedId === hub.id ? 0.16 : 0.07\"\n            />\n            <LeafletMarker v-for=\"hub in hubs\" :key=\"hub.id\" :lng-lat=\"[hub.lng, hub.lat]\" anchor=\"center\">\n              <button\n                type=\"button\"\n                class=\"rounded-full border px-2 py-0.5 font-mono text-xs font-semibold shadow-xs\"\n                :class=\"\n                  selectedId === hub.id\n                    ? 'border-primary bg-primary text-primary-foreground'\n                    : 'border-border bg-card text-foreground'\n                \"\n                @click.stop=\"selectHub(hub)\"\n              >\n                {{ hub.code }}\n              </button>\n            </LeafletMarker>\n          </LeafletMap>\n        </div>\n      </Card>\n\n      <Card class=\"border-border flex min-h-0 flex-col overflow-hidden shadow-xs lg:col-span-4\">\n        <CardHeader class=\"border-border border-b p-4\">\n          <CardTitle class=\"text-sm font-semibold\">Locations</CardTitle>\n        </CardHeader>\n        <CardContent class=\"divide-border min-h-0 flex-1 divide-y overflow-auto p-0\">\n          <button\n            v-for=\"hub in hubs\"\n            :key=\"hub.id\"\n            type=\"button\"\n            :class=\"\n              cn(\n                'hover:bg-accent/50 flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors',\n                selectedId === hub.id && 'bg-accent/60',\n              )\n            \"\n            @click=\"selectHub(hub)\"\n          >\n            <div class=\"min-w-0\">\n              <p class=\"text-foreground truncate text-sm font-medium\">{{ hub.name }}</p>\n              <p class=\"text-muted-foreground truncate text-xs\">\n                {{ hub.city }}, {{ hub.state }} · {{ hub.bays }} bays · {{ hub.coverageMiles }} mi\n              </p>\n            </div>\n            <Badge :variant=\"capacityVariant(hub.capacityPct)\" class=\"shrink-0 font-mono text-xs tabular-nums\">\n              {{ hub.capacityPct }}%\n            </Badge>\n          </button>\n        </CardContent>\n      </Card>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/LeafletHubLocatorMap.vue"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/leaflet-map.json"
  ],
  "description": "Distribution hub locator on free OpenStreetMap tiles — no API key. Coverage rings, capacity badges, and fly-to on select.",
  "categories": [
    "dashboard",
    "app",
    "logistics"
  ]
}