{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "hub-locator-map",
  "title": "Hub Locator Map",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/hub-locator-map/HubLocatorMap.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '@/lib/utils'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Map, MapMarker } from '@/components/ui/map'\n\nexport interface HubLocation {\n  id: string\n  code: string\n  city: string\n  country: string\n  lat: number\n  lng: number\n  latencyMs: number\n}\n\nexport interface HubLocatorMapProps {\n  class?: HTMLAttributes['class']\n  accessToken?: string\n  hubs?: HubLocation[]\n}\n\nconst DEFAULT_HUBS: HubLocation[] = [\n  {\n    id: 'iad-01',\n    code: 'IAD-01',\n    city: 'Ashburn',\n    country: 'United States',\n    lat: 39.0438,\n    lng: -77.4874,\n    latencyMs: 11,\n  },\n  {\n    id: 'lhr-01',\n    code: 'LHR-01',\n    city: 'London',\n    country: 'United Kingdom',\n    lat: 51.5074,\n    lng: -0.1278,\n    latencyMs: 14,\n  },\n  { id: 'fra-01', code: 'FRA-01', city: 'Frankfurt', country: 'Germany', lat: 50.1109, lng: 8.6821, latencyMs: 13 },\n  { id: 'nrt-01', code: 'NRT-01', city: 'Tokyo', country: 'Japan', lat: 35.6762, lng: 139.6503, latencyMs: 19 },\n  { id: 'sin-01', code: 'SIN-01', city: 'Singapore', country: 'Singapore', lat: 1.3521, lng: 103.8198, latencyMs: 22 },\n  { id: 'gru-01', code: 'GRU-01', city: 'São Paulo', country: 'Brazil', lat: -23.5505, lng: -46.6333, latencyMs: 42 },\n]\n\nconst props = withDefaults(defineProps<HubLocatorMapProps>(), {\n  accessToken: '',\n})\n\nconst hubs = computed(() => props.hubs ?? DEFAULT_HUBS)\nconst selectedId = ref(DEFAULT_HUBS[0]?.id ?? '')\n\nlet mapboxInstance: any = null\nfunction onMapCreated(map: any) {\n  mapboxInstance = map\n}\n\nfunction selectHub(hub: HubLocation) {\n  selectedId.value = hub.id\n  mapboxInstance?.flyTo?.({\n    center: [hub.lng, hub.lat],\n    zoom: 5.5,\n    essential: true,\n    duration: 900,\n  })\n}\n</script>\n\n<template>\n  <div data-slot=\"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\">Hubs</h2>\n      <p class=\"text-muted-foreground text-xs\">{{ hubs.length }} locations</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          <Map\n            :access-token=\"accessToken\"\n            variant=\"dark\"\n            :center=\"[10, 25]\"\n            :zoom=\"1.6\"\n            class=\"absolute inset-0 size-full\"\n            @created=\"onMapCreated\"\n          >\n            <MapMarker 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            </MapMarker>\n          </Map>\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.code }}</p>\n              <p class=\"text-muted-foreground truncate text-xs\">{{ hub.city }}, {{ hub.country }}</p>\n            </div>\n            <span class=\"text-muted-foreground font-mono text-xs tabular-nums\">{{ hub.latencyMs }}ms</span>\n          </button>\n        </CardContent>\n      </Card>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/HubLocatorMap.vue"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/map.json"
  ],
  "description": "Global hub locator. Pins on a Mapbox map with a short location list and fly-to on select.",
  "categories": [
    "dashboard",
    "app",
    "logistics"
  ]
}