Skip to content

MSI Controls API

Promise-based direct control API for precise map operations.

Controls vs Handles

Controls provide granular, promise-based operations for precise control over individual map functions. Use controls when you need:

  • Single, discrete operations
  • Direct control over map state
  • Promise-based async/await patterns
  • Fine-grained customization

Handles provide stream-based workflows for common patterns. Learn about Handles →

Getting Controls

typescript
import De from '@de./sdk'

const msi = new De.MSI({
  element: 'map',
  accessToken: 'your-token'
})

const { controls, handles } = await msi.load()

// Now use controls for direct operations
await controls.getCurrentLocation()

Location Services

getCurrentLocation()

Get the user's current GPS location.

1

Get Current Location

Request user's current position

typescript
const location = await controls.getCurrentLocation()

console.log('Location:', location)
// {
//   lng: -74.0060,
//   lat: 40.7128,
//   accuracy: 10,
//   heading: 45,
//   speed: 0
// }

Returns: Promise<Location>

Throws:

  • PERMISSION_DENIED - User denied location access
  • POSITION_UNAVAILABLE - Location unavailable
  • TIMEOUT - Request timed out

pinCurrentLocation()

Get current location and add a pin marker on the map.

2

Pin Current Location

Show user location with marker

typescript
const location = await controls.pinCurrentLocation({
  label: 'You are here',
  draggable: false,
  color: 'blue'
})

console.log('Pinned at:', location)

Parameters:

typescript
{
  label?: string           // Marker label
  sublabel?: string        // Secondary text
  draggable?: boolean      // Allow marker drag
  color?: string           // Marker color
  icon?: string            // Custom icon
}

Returns: Promise<Location>

trackLiveLocation()

Continuously track user's location with updates.

3

Track Live Location

Monitor position changes

typescript
const unsubscribe = await controls.trackLiveLocation({
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0
}, (location) => {
  console.log('Location updated:', location)
  updateMap(location)
})

// Stop tracking when done
unsubscribe()

Parameters:

typescript
// Options
{
  enableHighAccuracy?: boolean  // High accuracy mode
  timeout?: number              // Timeout in ms
  maximumAge?: number           // Max cache age in ms
}

// Callback
(location: Location) => void

Returns: Promise<() => void> - Unsubscribe function

setLiveLocationOptions()

Configure live location tracking behavior.

typescript
await controls.setLiveLocationOptions({
  updateInterval: 1000,        // Update every 1 second
  distanceFilter: 10,          // Minimum 10m movement
  showTrail: true,             // Show location trail
  trailColor: '#0ea5e9',       // Trail color
  smoothing: true              // Smooth position updates
})

Map Styling

setMapStyle()

Change the map's visual style.

1

Set Map Style

Apply different map themes

typescript
// Predefined styles
await controls.setMapStyle('streets')
await controls.setMapStyle('satellite')
await controls.setMapStyle('dark')
await controls.setMapStyle('light')

// Custom style URL
await controls.setMapStyle('mapbox://styles/username/style-id')

Available Styles:

  • streets - Standard street map
  • satellite - Satellite imagery
  • hybrid - Satellite with labels
  • dark - Dark theme
  • light - Light theme
  • outdoors - Terrain and trails
  • navigation-day - Optimized for daytime navigation
  • navigation-night - Optimized for nighttime navigation

Layer Controls

Control map layer visibility.

typescript
// Toggle traffic layer
await controls.setLayerVisibility('traffic', true)

// Toggle transit layer
await controls.setLayerVisibility('transit', true)

// Toggle 3D buildings
await controls.setLayerVisibility('buildings-3d', true)

// Custom layers
await controls.addLayer({
  id: 'custom-markers',
  type: 'symbol',
  source: 'markers-data',
  layout: {
    'icon-image': 'marker-icon',
    'icon-size': 1.5
  }
})

Map Controls

Show/hide map UI controls.

typescript
// Navigation controls (zoom, rotate)
await controls.showControl('navigation', true)

// Geolocate button
await controls.showControl('geolocate', true)

// Scale bar
await controls.showControl('scale', true)

// Fullscreen button
await controls.showControl('fullscreen', true)

Search & Geocoding

searchQuery()

Search for places by text query.

1

Search Places

Find locations by name or address

typescript
const results = await controls.searchQuery('Central Park, New York', {
  limit: 5,
  types: ['poi', 'address'],
  proximity: { lng: -74.0060, lat: 40.7128 },
  bbox: [-74.1, 40.6, -73.9, 40.8]
})

console.log('Search results:', results)
// [
//   {
//     id: 'poi.123',
//     name: 'Central Park',
//     address: 'New York, NY 10024',
//     coordinates: { lng: -73.9654, lat: 40.7829 },
//     relevance: 0.95
//   },
//   ...
// ]

Parameters:

typescript
{
  query: string              // Search query
  limit?: number             // Max results (default: 10)
  types?: string[]           // Filter by type
  proximity?: Location       // Bias near location
  bbox?: [number, number, number, number]  // Bounding box
  language?: string          // Result language
  country?: string[]         // Filter by country codes
}

Returns: Promise<SearchResult[]>

searchSelect()

Select a search result and display on map.

2

Select Search Result

Show selected place on map

typescript
const results = await controls.searchQuery('Times Square')

// Select first result
const selected = await controls.searchSelect(results[0], {
  zoom: 15,
  addMarker: true,
  markerOptions: {
    label: results[0].name,
    color: 'red'
  }
})

console.log('Selected:', selected)

Parameters:

typescript
{
  result: SearchResult       // Result to select
  zoom?: number             // Zoom level
  addMarker?: boolean       // Add marker
  markerOptions?: MarkerOptions  // Marker styling
}

resolvePlace()

Forward geocoding - convert address to coordinates.

3

Forward Geocoding

Address to coordinates

typescript
const location = await controls.resolvePlace(
  '1600 Amphitheatre Parkway, Mountain View, CA'
)

console.log('Coordinates:', location)
// {
//   lng: -122.0840,
//   lat: 37.4220,
//   address: '1600 Amphitheatre Parkway, Mountain View, CA 94043',
//   formatted: 'Google Headquarters'
// }

Parameters: address: string

Returns: Promise<ResolvedLocation>

resolveCoordinates()

Reverse geocoding - convert coordinates to address.

4

Reverse Geocoding

Coordinates to address

typescript
const address = await controls.resolveCoordinates({
  lng: -73.9855,
  lat: 40.7580
})

console.log('Address:', address)
// {
  place: 'Times Square',
  street: 'Broadway',
  city: 'New York',
  state: 'NY',
  country: 'United States',
  postalCode: '10036',
  formatted: 'Times Square, Broadway, New York, NY 10036, USA'
}

Parameters: coordinates: Location

Returns: Promise<Address>

Drag & Pick Location

Interactive location picker for user selection.

enableDragPickLocation()

Enable drag-to-pick mode.

1

Enable Location Picker

Let users pick a location by dragging

typescript
const pickedLocation = await controls.enableDragPickLocation({
  initialPosition: { lng: -74.0060, lat: 40.7128 },
  onDrag: (location) => {
    console.log('Dragging:', location)
  },
  content: {
    title: 'Select Location',
    subtitle: 'Drag the map to select',
    confirmText: 'Confirm',
    cancelText: 'Cancel'
  }
})

if (pickedLocation) {
  console.log('User picked:', pickedLocation)
} else {
  console.log('User cancelled')
}

Parameters:

typescript
{
  initialPosition?: Location    // Starting position
  onDrag?: (location: Location) => void  // Drag callback
  content?: {
    title?: string              // Picker title
    subtitle?: string           // Instructions
    confirmText?: string        // Confirm button
    cancelText?: string         // Cancel button
  }
}

Returns: Promise<Location | null>

disableDragPickLocation()

Disable picker mode and return to normal map.

typescript
await controls.disableDragPickLocation()

setDragPickContent()

Customize picker UI during active session.

typescript
await controls.setDragPickContent({
  title: 'Delivery Address',
  subtitle: 'Move the pin to your exact location',
  confirmText: 'Use This Location'
})

Advanced Location Features

Get Precise Location

Enhanced location with multiple attempts for better accuracy.

typescript
async function getPreciseLocation() {
  const locations = []
  
  for (let i = 0; i < 3; i++) {
    const loc = await controls.getCurrentLocation()
    locations.push(loc)
    await new Promise(resolve => setTimeout(resolve, 1000))
  }
  
  // Return most accurate
  return locations.reduce((best, current) => 
    current.accuracy < best.accuracy ? current : best
  )
}

const preciseLocation = await getPreciseLocation()

Location Distance Calculation

typescript
import { utils } from '@de./sdk'

const loc1 = await controls.getCurrentLocation()
const loc2 = { lng: -73.9855, lat: 40.7580 }

const distance = utils.calculateDistance(loc1, loc2)
console.log(`Distance: ${distance.toFixed(2)} meters`)

Continuous Address Updates

typescript
const unsubscribe = await controls.trackLiveLocation({
  enableHighAccuracy: true
}, async (location) => {
  // Get address for current location
  const address = await controls.resolveCoordinates(location)
  console.log('Current address:', address.formatted)
  
  updateUI({
    location,
    address: address.formatted
  })
})

Search with Autocomplete

Build a search UI with autocomplete.

typescript
let searchTimeout: any

async function handleSearchInput(query: string) {
  // Debounce search
  clearTimeout(searchTimeout)
  
  searchTimeout = setTimeout(async () => {
    if (query.length < 3) return
    
    const results = await controls.searchQuery(query, {
      limit: 5,
      types: ['address', 'poi']
    })
    
    displaySearchResults(results)
  }, 300)
}

async function selectResult(result: SearchResult) {
  await controls.searchSelect(result, {
    zoom: 16,
    addMarker: true,
    markerOptions: {
      label: result.name
    }
  })
}

Map Bounds & Viewport

fitBounds()

Adjust map to show specific bounds.

typescript
await controls.fitBounds({
  southwest: { lng: -74.1, lat: 40.6 },
  northeast: { lng: -73.9, lat: 40.8 }
}, {
  padding: 50,           // Padding in pixels
  maxZoom: 15,          // Maximum zoom level
  animate: true,        // Smooth animation
  duration: 1000        // Animation duration (ms)
})

getBounds()

Get current map viewport bounds.

typescript
const bounds = await controls.getBounds()

console.log('Visible area:', bounds)
// {
//   southwest: { lng: -74.05, lat: 40.70 },
//   northeast: { lng: -74.00, lat: 40.75 }
// }

setCenter()

Move map to specific coordinates.

typescript
await controls.setCenter(
  { lng: -73.9855, lat: 40.7580 },
  {
    zoom: 14,
    animate: true,
    duration: 2000
  }
)

setZoom()

Set map zoom level.

typescript
await controls.setZoom(15, {
  animate: true,
  duration: 1000
})

Error Handling

typescript
try {
  const location = await controls.getCurrentLocation()
} catch (error) {
  switch (error.code) {
    case 'PERMISSION_DENIED':
      alert('Please enable location access')
      break
      
    case 'POSITION_UNAVAILABLE':
      alert('Location unavailable. Check GPS/network.')
      break
      
    case 'TIMEOUT':
      alert('Location request timed out. Try again.')
      break
      
    default:
      console.error('Location error:', error)
  }
}

Performance Tips

Best Practices

  • Cache search results to avoid duplicate requests
  • Debounce search input (300-500ms)
  • Use appropriate accuracy for use case
  • Clean up location tracking when not needed
  • Limit search result count

Avoid

  • Tracking location continuously if not needed
  • Requesting high accuracy unnecessarily
  • Creating new markers for every location update
  • Searching on every keystroke
  • Ignoring error states

Complete Examples

typescript
import De from '@de./sdk'

const msi = new De.MSI({
  element: 'map',
  accessToken: token
})

const { controls } = await msi.load()

// Get user location
const userLocation = await controls.getCurrentLocation()

// Search nearby restaurants
const restaurants = await controls.searchQuery('restaurants', {
  proximity: userLocation,
  types: ['poi'],
  limit: 10
})

// Display results
restaurants.forEach(async (restaurant, index) => {
  await controls.addMarker({
    position: restaurant.coordinates,
    label: restaurant.name,
    onClick: () => {
      showRestaurantDetails(restaurant)
    }
  })
})

// Fit map to show all results
const bounds = calculateBounds([
  userLocation,
  ...restaurants.map(r => r.coordinates)
])
await controls.fitBounds(bounds)

Address Autocomplete Component

typescript
class AddressAutocomplete {
  private controls: MSIControls
  private timeout: any
  
  constructor(controls: MSIControls) {
    this.controls = controls
  }
  
  async search(query: string): Promise<SearchResult[]> {
    clearTimeout(this.timeout)
    
    return new Promise((resolve) => {
      this.timeout = setTimeout(async () => {
        if (query.length < 3) {
          resolve([])
          return
        }
        
        const results = await this.controls.searchQuery(query, {
          types: ['address'],
          limit: 5
        })
        
        resolve(results)
      }, 300)
    })
  }
  
  async select(result: SearchResult) {
    await this.controls.searchSelect(result, {
      zoom: 16,
      addMarker: true
    })
    
    return result
  }
}

// Usage
const autocomplete = new AddressAutocomplete(controls)
const results = await autocomplete.search('123 Main')
await autocomplete.select(results[0])

Type Definitions

typescript
interface Location {
  lng: number
  lat: number
  accuracy?: number
  heading?: number
  speed?: number
  altitude?: number
}

interface SearchResult {
  id: string
  name: string
  address: string
  coordinates: Location
  type: string
  relevance: number
  bbox?: [number, number, number, number]
}

interface Address {
  place?: string
  street?: string
  city: string
  state: string
  country: string
  postalCode?: string
  formatted: string
}

interface Bounds {
  southwest: Location
  northeast: Location
}

Next Steps