{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "map-geojson-01",
  "title": "Service zones example",
  "description": "Three illustrative service zones over Calgary; click one for its name and hours, composed from the Unmap map and the geojson-layer item.",
  "registryDependencies": [
    "https://registry.unmap.dev/r/map.json",
    "https://registry.unmap.dev/r/geojson-layer.json"
  ],
  "files": [
    {
      "path": "registry/blocks/map-geojson-01.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Map } from \"@/components/ui/map\";\nimport { GeoJSONLayer } from \"@/components/ui/geojson-layer\";\nimport { useMap } from \"@/lib/map-context\";\nimport { cn } from \"@/lib/utils\";\n\nconst COPY = {\n  en: {\n    noKey: \"Add your unmap key to load the map.\",\n    title: \"Service zones\",\n    hint: \"Click a zone to read its properties.\",\n    data: \"Three illustrative zones; the hours are made up.\",\n  },\n  fr: {\n    noKey: \"Ajoutez votre clé unmap pour charger la carte.\",\n    title: \"Zones de service\",\n    hint: \"Cliquez sur une zone pour lire ses propriétés.\",\n    data: \"Trois zones illustratives ; les heures sont inventées.\",\n  },\n} as const;\n\ntype Zone = { name: string; name_fr: string; hours: string; hours_fr: string; ring: [number, number][] };\n\n/**\n * Illustrative data, not a real service: three delivery zones drawn over Calgary's inner city, each\n * with the hours a courier would cover it. The neighbourhoods are real; the zones and hours are not.\n */\nconst ZONES: Zone[] = [\n  {\n    name: \"Downtown\",\n    name_fr: \"Centre-ville\",\n    hours: \"every day, 7:00 to 22:00\",\n    hours_fr: \"tous les jours, de 7 h à 22 h\",\n    ring: [[-114.098, 51.054], [-114.07, 51.056], [-114.035, 51.053], [-114.037, 51.036], [-114.072, 51.035], [-114.098, 51.037], [-114.098, 51.054]],\n  },\n  {\n    name: \"North Hill\",\n    name_fr: \"North Hill\",\n    hours: \"Monday to Saturday, 8:00 to 20:00\",\n    hours_fr: \"du lundi au samedi, de 8 h à 20 h\",\n    ring: [[-114.112, 51.081], [-114.072, 51.085], [-114.032, 51.079], [-114.035, 51.06], [-114.075, 51.059], [-114.11, 51.061], [-114.112, 51.081]],\n  },\n  {\n    name: \"Beltline South\",\n    name_fr: \"Beltline Sud\",\n    hours: \"weekdays, 9:00 to 18:00\",\n    hours_fr: \"en semaine, de 9 h à 18 h\",\n    ring: [[-114.103, 51.032], [-114.07, 51.033], [-114.042, 51.031], [-114.045, 51.013], [-114.075, 51.011], [-114.1, 51.015], [-114.103, 51.032]],\n  },\n];\n\nconst DATA = {\n  type: \"FeatureCollection\" as const,\n  features: ZONES.map(({ ring, ...properties }, index) => ({\n    type: \"Feature\" as const,\n    id: index,\n    properties,\n    geometry: { type: \"Polygon\" as const, coordinates: [ring] },\n  })),\n};\n\n/** Frames the three zones once the map exists, at every width. */\nfunction FitZones() {\n  const map = useMap();\n  useEffect(() => {\n    map?.fitBounds([[-114.112, 51.011], [-114.032, 51.085]], { padding: 24, animate: false });\n  }, [map]);\n  return null;\n}\n\n/**\n * A minimal example: three illustrative service zones over Calgary, drawn in your --primary. Hover\n * a zone to highlight it and click it to read its name and hours. The zones are drawn in the\n * browser: the only requests are the map's own.\n */\nexport function MapGeojson({\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 [zone, setZone] = useState<Record<string, unknown> | null>(null);\n  const field = (name: string) => String(zone?.[lang === \"fr\" ? `${name}_fr` : name] ?? \"\");\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={[-114.072, 51.048]} zoom={11} lang={lang}>\n          <FitZones />\n          <GeoJSONLayer data={DATA} onClick={(event) => setZone(event.feature.properties)} />\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      <p aria-live=\"polite\" className=\"text-sm text-muted-foreground\">\n        {zone ? (\n          <>\n            <span className=\"font-medium text-foreground\">{field(\"name\")}</span>\n            {lang === \"fr\" ? \" : \" : \": \"}\n            {field(\"hours\")}\n          </>\n        ) : (\n          copy.hint\n        )}\n      </p>\n      <p className=\"text-xs text-muted-foreground\">{copy.data}</p>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/unmap-map-geojson.tsx"
    }
  ],
  "docs": "Import MapGeojson from your components/unmap-map-geojson 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-geojson",
  "categories": [
    "examples",
    "maps"
  ],
  "type": "registry:block"
}