import { Controller } from "stimulus" ; import { reactive } from "../utilities/reactive" ; import { useMixin } from "./create_mixin" ; export interface GeolocationOptions extends Partial < PositionOptions > { } export interface GeolocationData { locatedAt : number | null ; error : GeolocationPositionError | null ; coords : { accuracy : number ; latitude : number ; longitude : number ; altitude : number | null ; altitudeAccuracy : number | null ; heading : number | null ; speed : number | null ; } ; teardown : ( ) => void ; } export function useGeolocation ( controller , options = { } , update ? , error ? ) { if ( update ) { update = update . bind ( controller ) ; } if ( error ) { error = error . bind ( controller ) ; } const { enableHighAccuracy = true , maximumAge = 30000 , timeout = 27000 , } = options ; const isSupported = navigator && 'geolocation' in navigator ; const values = reactive ( { locatedAt : null , error : null , coords : { accuracy : 0 , latitude : Infinity , longitude : Infinity , altitude : null , altitudeAccuracy : null , heading : null , speed : null , } , teardown : ( ) => { if ( watcher ) { navigator . geolocation . clearWatch ( watcher ) ; watcher = null ; } } , } as GeolocationData ) ; let setup = ( ) => { if ( isSupported ) { watcher = navigator . geolocation . watchPosition ( ( position ) => { values . locatedAt = position . timestamp ; values . coords = position . coords ; values . error = null ; if ( update ) { update ( position ) ; } } , ( err ) => { values . error = err ; if ( error ) { error ( err ) ; } } , { enableHighAccuracy , maximumAge , timeout , } ) ; } } ; let watcher = null ; useMixin ( controller , setup , values . teardown ) ; return values ; }