Map Sync
terrae/syncFreeComponent
Synchronized multi-map component with bidirectional movement sync.
Install it
npx shadcn@latest add https://www.terrae.dev/sync.jsonSource
1"use client"23import { createContext, useContext, useEffect, useRef, useState, type ReactNode } from "react"4import { useTheme } from "next-themes"5import type mapboxgl from "mapbox-gl"6import { mapgl, detectedLibrary } from "./map-library"7import { Globe } from "lucide-react"8import { cn } from "@/lib/utils"9import {10 defaultMapStyles,11 defaultMapLibreStyles,12 type MapProjection,13 type MapCoordinates,14 type MapThemeStyles,15 type MapSyncLayout,16} from "./types"1718type MapConfig = {19 style?: string20 styles?: MapThemeStyles21 label?: string22}2324type MapSyncProps = {25 accessToken?: string26 maps: [MapConfig, MapConfig] | [MapConfig, MapConfig, MapConfig, MapConfig]27 center?: MapCoordinates28 zoom?: number29 bearing?: number30 pitch?: number31 projection?: MapProjection32 layout?: MapSyncLayout33 showLabels?: boolean34 loader?: ReactNode35}3637type MapSyncContextValue = {38 registerMap: (index: number, map: mapboxgl.Map) => void39 unregisterMap: (index: number) => void40 accessToken?: string41 initialCenter: MapCoordinates42 initialZoom: number43 initialBearing: number44 initialPitch: number45 projection?: MapProjection46}4748type MapSyncProviderProps = {49 children: ReactNode50 accessToken?: string51 initialCenter: MapCoordinates52 initialZoom: number53 initialBearing: number54 initialPitch: number55 projection?: MapProjection56}5758type SyncedMapPanelProps = {59 index: number60 style: { width: string; height: string }61 label: string62 showLabel: boolean63 mapStyle?: string64 mapStyles?: MapThemeStyles65 loader?: ReactNode66}6768const DEFAULT_CENTER: MapCoordinates = [0, 0]69const DEFAULT_ZOOM = 270const DEFAULT_BEARING = 071const DEFAULT_PITCH = 07273const LABEL_BASE_STYLES = "absolute z-10 bg-background/95 backdrop-blur-sm border rounded px-2 py-1 text-xs font-medium"7475const MapSyncContext = createContext<MapSyncContextValue | null>(null)7677const useMapSync = () => {78 const context = useContext(MapSyncContext)79 if (!context) {80 throw new Error("useMapSync must be used within MapSyncProvider")81 }82 return context83}8485export const MapSync = ({86 accessToken,87 maps,88 center = DEFAULT_CENTER,89 zoom = DEFAULT_ZOOM,90 bearing = DEFAULT_BEARING,91 pitch = DEFAULT_PITCH,92 projection,93 layout = "horizontal",94 showLabels = false,95 loader,96}: MapSyncProps) => {97 const mapCount = maps.length98 const isGrid = layout === "grid" && mapCount === 499100 const getLayoutClasses = () => {101 if (isGrid) {102 return "grid grid-cols-2 grid-rows-2"103 }104// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from terrae
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Map Animated Circleanimated-circle | terrae | Components | Free | 1 dep | |
| Map Animated Footprintanimated-footprint | terrae | Components | Free | 2 deps | |
| Map Animated Polygonanimated-polygon | terrae | Components | Free | 1 dep | |
| Map Animated Pulseanimated-pulse | terrae | Components | Free | 1 dep | |
| Map Arc Animatedarc-animated | terrae | Components | Free | 1 dep | |
| Map Blur Areablur-area | terrae | Components | Free | 1 dep | |
| Map Camera Followcamera-follow | terrae | Components | Free | 1 dep | |
| Map Choroplethchoropleth | terrae | Components | Free | 1 dep |
