{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "leaflet-property-boundary-map",
  "title": "Leaflet Property Boundary Map",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-react/blocks/leaflet-property-boundary-map/LeafletPropertyBoundaryMap.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport { LeafletMap, LeafletMarker, LeafletPolygon, type LeafletMapRef } from '@/components/ui/leaflet-map'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\n\nexport interface Parcel {\n  apn: string\n  address: string\n  zoning: string\n  /** Plain-hex zone fill — Leaflet renders paths to SVG/canvas, so CSS vars do not resolve there. */\n  color: string\n  lotSqFt: string\n  acres: number\n  assessedValue: string\n  taxYear: number\n  coords: [number, number]\n  polygon: [number, number][]\n}\n\nexport interface LeafletPropertyBoundaryMapProps extends React.HTMLAttributes<HTMLDivElement> {\n  parcels?: Parcel[]\n}\n\nconst DEFAULT_PARCELS: Parcel[] = [\n  {\n    apn: '093-142-018',\n    address: '418 Kingsley Ave, Palo Alto, CA',\n    zoning: 'R-1 (Single Family)',\n    color: '#facc15',\n    lotSqFt: '8,712 sq ft',\n    acres: 0.2,\n    assessedValue: '$3,940,000',\n    taxYear: 2025,\n    coords: [-122.1709, 37.4281],\n    polygon: [\n      [-122.1715, 37.4285],\n      [-122.1703, 37.4285],\n      [-122.1703, 37.4277],\n      [-122.1715, 37.4277],\n      [-122.1715, 37.4285],\n    ],\n  },\n  {\n    apn: '093-142-019',\n    address: '424 Kingsley Ave, Palo Alto, CA',\n    zoning: 'R-1 (Single Family)',\n    color: '#facc15',\n    lotSqFt: '9,580 sq ft',\n    acres: 0.22,\n    assessedValue: '$4,120,000',\n    taxYear: 2025,\n    coords: [-122.1693, 37.4281],\n    polygon: [\n      [-122.1699, 37.4285],\n      [-122.1687, 37.4285],\n      [-122.1687, 37.4277],\n      [-122.1699, 37.4277],\n      [-122.1699, 37.4285],\n    ],\n  },\n  {\n    apn: '093-142-021',\n    address: '510 Lytton Ave, Palo Alto, CA',\n    zoning: 'CS (Service Commercial)',\n    color: '#c084fc',\n    lotSqFt: '21,780 sq ft',\n    acres: 0.5,\n    assessedValue: '$6,850,000',\n    taxYear: 2025,\n    coords: [-122.1699, 37.4268],\n    polygon: [\n      [-122.1708, 37.4273],\n      [-122.169, 37.4273],\n      [-122.169, 37.4263],\n      [-122.1708, 37.4263],\n      [-122.1708, 37.4273],\n    ],\n  },\n  {\n    apn: '093-142-024',\n    address: '777 Bryant Ct, Palo Alto, CA',\n    zoning: 'RM-20 (Multi-Family)',\n    color: '#38bdf8',\n    lotSqFt: '13,068 sq ft',\n    acres: 0.3,\n    assessedValue: '$5,230,000',\n    taxYear: 2025,\n    coords: [-122.1723, 37.4268],\n    polygon: [\n      [-122.173, 37.4273],\n      [-122.1716, 37.4273],\n      [-122.1716, 37.4263],\n      [-122.173, 37.4263],\n      [-122.173, 37.4273],\n    ],\n  },\n  {\n    apn: '093-142-030',\n    address: '250 Hamilton Ave, Palo Alto, CA',\n    zoning: 'PF (Public Facility)',\n    color: '#34d399',\n    lotSqFt: '30,492 sq ft',\n    acres: 0.7,\n    assessedValue: '$8,900,000',\n    taxYear: 2025,\n    coords: [-122.1679, 37.4261],\n    polygon: [\n      [-122.1687, 37.4265],\n      [-122.1671, 37.4265],\n      [-122.1671, 37.4256],\n      [-122.1687, 37.4256],\n      [-122.1687, 37.4265],\n    ],\n  },\n]\n\n// Downtown Palo Alto — stable reference so the map's center effect never re-fires.\nconst MAP_CENTER: [number, number] = [-122.1697, 37.4275]\n\nexport function LeafletPropertyBoundaryMap({\n  className,\n  parcels = DEFAULT_PARCELS,\n  ...props\n}: LeafletPropertyBoundaryMapProps) {\n  const mapRef = React.useRef<LeafletMapRef>(null)\n  const [activeApn, setActiveApn] = React.useState(parcels[0]?.apn ?? '')\n  const activeParcel = parcels.find((p) => p.apn === activeApn) ?? parcels[0]\n\n  const selectParcel = (p: Parcel) => {\n    setActiveApn(p.apn)\n    mapRef.current?.flyTo({ center: p.coords, zoom: 17 })\n  }\n\n  return (\n    <div\n      data-slot=\"leaflet-property-boundary-map\"\n      className={cn('grid gap-4 lg:grid-cols-[1fr_320px]', className)}\n      {...props}\n    >\n      <div className=\"border-border bg-card relative h-[480px] overflow-hidden rounded-xl border\">\n        <LeafletMap ref={mapRef} variant=\"satellite-streets\" center={MAP_CENTER} zoom={16} className=\"h-full w-full\">\n          {/* Cadastral lot polygons, filled by zoning class */}\n          {parcels.map((p) => (\n            <LeafletPolygon\n              key={`lot-${p.apn}`}\n              lngLatPath={p.polygon}\n              color={p.color}\n              weight={activeParcel?.apn === p.apn ? 3 : 1.5}\n              opacity={0.95}\n              fill\n              fillColor={p.color}\n              fillOpacity={activeParcel?.apn === p.apn ? 0.35 : 0.15}\n              onClick={() => selectParcel(p)}\n            />\n          ))}\n\n          {parcels.map((p) => (\n            <LeafletMarker key={p.apn} lngLat={p.coords} anchor=\"center\" onClick={() => selectParcel(p)}>\n              <div className=\"group flex cursor-pointer flex-col items-center\">\n                <span\n                  className={`border-border bg-background/90 rounded border px-1.5 py-0.5 font-mono text-xs font-bold shadow-md ${\n                    activeParcel?.apn === p.apn ? 'text-foreground' : 'text-muted-foreground'\n                  }`}\n                  style={activeParcel?.apn === p.apn ? { color: p.color, borderColor: p.color } : undefined}\n                >\n                  {p.apn}\n                </span>\n              </div>\n            </LeafletMarker>\n          ))}\n        </LeafletMap>\n      </div>\n\n      {/* Cadastral Parcel Valuation Card */}\n      {activeParcel && (\n        <Card className=\"flex flex-col justify-between\">\n          <CardHeader>\n            <div className=\"flex items-center justify-between\">\n              <Badge variant=\"outline\" className=\"font-mono text-xs\">\n                APN {activeParcel.apn}\n              </Badge>\n              <Badge variant=\"secondary\" className=\"gap-1.5 text-xs\">\n                <span className=\"size-2 rounded-full\" style={{ backgroundColor: activeParcel.color }} />\n                {activeParcel.zoning}\n              </Badge>\n            </div>\n            <CardTitle className=\"mt-2 text-base font-medium\">{activeParcel.address}</CardTitle>\n            <CardDescription className=\"font-mono text-xs\">\n              {activeParcel.lotSqFt} • {activeParcel.acres} Acres\n            </CardDescription>\n          </CardHeader>\n          <CardContent className=\"space-y-4\">\n            <div className=\"border-border space-y-2 border-t pt-3 font-mono text-xs\">\n              <div className=\"flex items-center justify-between\">\n                <span className=\"text-muted-foreground\">Assessed Valuation</span>\n                <span className=\"text-foreground text-base font-bold\">{activeParcel.assessedValue}</span>\n              </div>\n              <div className=\"flex items-center justify-between\">\n                <span className=\"text-muted-foreground\">Zoning Code</span>\n                <span className=\"text-foreground\">{activeParcel.zoning}</span>\n              </div>\n              <div className=\"flex items-center justify-between\">\n                <span className=\"text-muted-foreground\">Assessment Roll Year</span>\n                <span className=\"text-foreground\">{activeParcel.taxYear}</span>\n              </div>\n            </div>\n\n            <div className=\"border-border space-y-1 border-t pt-3\">\n              <div className=\"text-muted-foreground mb-1 font-mono text-xs tracking-wider uppercase\">\n                Adjacent Cadastral Lots\n              </div>\n              {parcels.map((p) => (\n                <button\n                  key={p.apn}\n                  type=\"button\"\n                  className={`flex w-full items-center justify-between rounded-md px-2 py-1 text-xs transition-colors ${\n                    activeParcel.apn === p.apn\n                      ? 'bg-accent text-accent-foreground font-semibold'\n                      : 'hover:bg-muted text-muted-foreground'\n                  }`}\n                  onClick={() => selectParcel(p)}\n                >\n                  <span className=\"font-mono\">{p.apn}</span>\n                  <span className=\"font-mono text-xs opacity-75\">{p.lotSqFt}</span>\n                </button>\n              ))}\n            </div>\n\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              className=\"w-full font-mono text-xs\"\n              onClick={() => selectParcel(activeParcel)}\n            >\n              Center Cadastral Lot\n            </Button>\n          </CardContent>\n        </Card>\n      )}\n    </div>\n  )\n}\n\nexport default LeafletPropertyBoundaryMap\n",
      "type": "registry:block",
      "target": "~/components/blocks/LeafletPropertyBoundaryMap.tsx"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/badge.json",
    "https://uipkge.dev/r/react/button.json",
    "https://uipkge.dev/r/react/card.json",
    "https://uipkge.dev/r/react/leaflet-map.json"
  ],
  "description": "Cadastral parcel boundary polygons with zoning classes, lot acreage, and assessed valuation on free Esri satellite tiles — no API key.",
  "categories": [
    "real-estate",
    "places",
    "map"
  ]
}