diff options
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox.tsx')
-rw-r--r-- | src/client/views/nodes/MapBox/MapBox.tsx | 527 |
1 files changed, 458 insertions, 69 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 9b75ca7e3..2b563faf2 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,7 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import BingMapsReact from 'bingmaps-react'; +// import 'mapbox-gl/dist/mapbox-gl.css'; + import { Button, EditableText, IconButton, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, flow, toJS} from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; @@ -26,7 +28,36 @@ import { FieldView, FieldViewProps } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../trails'; import { MapAnchorMenu } from './MapAnchorMenu'; +import { + Map as MapboxMap, + MapRef, + Marker, + ControlPosition, + FullscreenControl, + MapProvider, + MarkerProps, + NavigationControl, + ScaleControl, + ViewState, + ViewStateChangeEvent, + useControl, + GeolocateControl, + Popup, + MapEvent, + Source, + Layer} from 'react-map-gl'; +import MapboxGeocoder, {GeocoderOptions} from '@mapbox/mapbox-gl-geocoder'; +import debounce from 'debounce'; import './MapBox.scss'; +import { NumberLiteralType } from 'typescript'; +// import { GeocoderControl } from './GeocoderControl'; +import mapboxgl, { LngLat, MapLayerMouseEvent } from 'mapbox-gl'; +import { Feature, FeatureCollection } from 'geojson'; +import { MarkerEvent } from 'react-map-gl/dist/esm/types'; +import { MapboxApiUtility, TransportationType} from './MapboxApiUtility'; +import { Autocomplete, TextField } from '@mui/material'; +import { List } from '../../../../fields/List'; + // amongus /** * MapBox architecture: @@ -42,6 +73,30 @@ import './MapBox.scss'; */ const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/ and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS=<your apikey> +const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNscHgwNDd1MDA3MXIydm92ODdianp6cGYifQ.WFAqbhwxtMHOWSPtu0l2uQ'; +const MAPBOX_FORWARD_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/'; + +const MAPBOX_REVERSE_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/'; + +type PopupInfo = { + longitude: number, + latitude: number, + title: string, + description: string +} + +export type GeocoderControlProps = Omit<GeocoderOptions, 'accessToken' | 'mapboxgl' | 'marker'> & { + mapboxAccessToken: string, + marker?: Omit<MarkerProps, 'longitude' | 'latitude'>; + position: ControlPosition; + + onResult: (...args: any[]) => void; +} + +type MapMarker = { + longitude: number, + latitude: number +} /** * Consider integrating later: allows for drawing, circling, making shapes on map @@ -67,6 +122,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps private _dragRef = React.createRef<HTMLDivElement>(); private _sidebarRef = React.createRef<SidebarAnnos>(); private _ref: React.RefObject<HTMLDivElement> = React.createRef(); + private _mapRef: React.RefObject<MapRef> = React.createRef(); private _disposers: { [key: string]: IReactionDisposer } = {}; private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void); @@ -81,6 +137,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @computed get allPushpins() { return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN); } + @computed get allRoutes() { + return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE); + } + @computed get allRoutesGeoJson() { + const features = this.allRoutes.map(route => { + return { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: route.coordinates + } + }; + }); + + return { + type: 'FeatureCollection', + features: features + }; + } @computed get SidebarShown() { return this.layoutDoc._layout_showSidebar ? true : false; } @@ -97,8 +173,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps componentDidMount() { this._unmounting = false; this.props.setContentView?.(this); + } + _unmounting = false; componentWillUnmount(): void { this._unmounting = true; @@ -327,49 +405,29 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps entityType: 'PopulatedPlace', }; - // incrementer: number = 0; - /* - * Creates Pushpin doc and adds it to the list of annotations - */ - @action - createPushpin = undoable((latitude: number, longitude: number, map?: string) => { - // Stores the pushpin as a MapMarkerDocument - const pushpin = Docs.Create.PushpinDocument( - NumCast(latitude), - NumCast(longitude), - false, - [], - { title: map ?? `lat=${latitude},lng=${longitude}`, map: map } - // ,'pushpinIDamongus'+ this.incrementer++ - ); - this.addDocument(pushpin, this.annotationKey); - return pushpin; - // mapMarker.infoWindowOpen = true; - }, 'createpin'); - // The pin that is selected @observable selectedPin: Doc | undefined; @action deselectPin = () => { if (this.selectedPin) { - // Removes filter - Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove'); - Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove'); - Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); + // // Removes filter + // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove'); + // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove'); + // Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); - const temp = this.selectedPin; - if (!this._unmounting) { - this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp)); - } - const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(temp.latitude, temp.longitude)); - this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(temp as Doc)); - if (!this._unmounting) { - this._bingMap.current.entities.push(newpin); - } - this.map_docToPinMap.set(temp, newpin); - this.selectedPin = undefined; - this.bingSearchBarContents = this.rootDoc.map; + // const temp = this.selectedPin; + // if (!this._unmounting) { + // this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp)); + // } + // const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(temp.latitude, temp.longitude)); + // this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(temp as Doc)); + // if (!this._unmounting) { + // this._bingMap.current.entities.push(newpin); + // } + // this.map_docToPinMap.set(temp, newpin); + // this.selectedPin = undefined; + // this.bingSearchBarContents = this.rootDoc.map; } }; @@ -534,6 +592,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps tryHideMapAnchorMenu = (e: PointerEvent) => { let target = document.elementFromPoint(e.x, e.y); while (target) { + if (target.id === 'route-destination-searcher-listbox') return; if (target === MapAnchorMenu.top.current) return; target = target.parentElement; } @@ -546,11 +605,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @action centerOnSelectedPin = () => { if (this.selectedPin) { - this.dataDoc.latitude = this.selectedPin.latitude; - this.dataDoc.longitude = this.selectedPin.longitude; - this.dataDoc.map = this.selectedPin.map ?? ''; - this.bingSearchBarContents = this.selectedPin.map; + this._mapRef.current?.flyTo({ + center: [NumCast(this.selectedPin.longitude), NumCast(this.selectedPin.latitude)] + }) } + // if (this.selectedPin) { + // this.dataDoc.latitude = this.selectedPin.latitude; + // this.dataDoc.longitude = this.selectedPin.longitude; + // this.dataDoc.map = this.selectedPin.map ?? ''; + // this.bingSearchBarContents = this.selectedPin.map; + // } MapAnchorMenu.Instance.fadeOut(true); document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu); }; @@ -564,6 +628,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps mapTypeId: 'grayscale', }; + /** * Map options */ @@ -582,16 +647,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }, }; - @action - searchbarOnEdit = (newText: string) => (this.bingSearchBarContents = newText); + recolorPin = (pin: Doc, color?: string) => { - this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin)); - this.map_docToPinMap.delete(pin); - const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(pin.latitude, pin.longitude), color ? { color } : {}); - this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(pin)); - this._bingMap.current.entities.push(newpin); - this.map_docToPinMap.set(pin, newpin); + // this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin)); + // this.map_docToPinMap.delete(pin); + // const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(pin.latitude, pin.longitude), color ? { color } : {}); + // this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(pin)); + // this._bingMap.current.entities.push(newpin); + // this.map_docToPinMap.set(pin, newpin); }; /* @@ -660,25 +724,25 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps setupMoveUpEvents( e, e, - e => { + e => { // move event if (!dragClone) { - dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement; + dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement; // copy draggable pin dragClone.style.position = 'absolute'; dragClone.style.zIndex = '10000'; - DragManager.Root().appendChild(dragClone); + DragManager.Root().appendChild(dragClone); // add clone to root } dragClone.style.transform = `translate(${e.clientX - 15}px, ${e.clientY - 15}px)`; return false; }, - e => { + e => { // up event if (!dragClone) return; DragManager.Root().removeChild(dragClone); - let target = document.elementFromPoint(e.x, e.y); + let target = document.elementFromPoint(e.x, e.y); // element for specified x and y coordinates while (target) { - if (target === this._ref.current) { + if (target === this._ref.current) { const cpt = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); const x = cpt[0] - (this.props.PanelWidth() - this.sidebarWidth()) / 2; - const y = cpt[1] - 32 /* height of search bar */ - this.props.PanelHeight() / 2; + const y = cpt[1] - 20 /* height of search bar */ - this.props.PanelHeight() / 2; const location = this._bingMap.current.tryPixelToLocation(new this.MicrosoftMaps.Point(x, y)); this.createPushpin(location.latitude, location.longitude); break; @@ -695,8 +759,236 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps ); }; + // incrementer: number = 0; + /* + * Creates Pushpin doc and adds it to the list of annotations + */ + @action + createPushpin = undoable((latitude: number, longitude: number, location?: string, wikiData?: string) => { + // Stores the pushpin as a MapMarkerDocument + const pushpin = Docs.Create.PushpinDocument( + NumCast(latitude), + NumCast(longitude), + false, + [], + {title: location ?? `lat=${latitude},lng=${longitude}`, map: location, description: "", wikiData: wikiData}, + // { title: map ?? `lat=${latitude},lng=${longitude}`, map: map }, + // ,'pushpinIDamongus'+ this.incrementer++ + ); + this.addDocument(pushpin, this.annotationKey); + console.log(pushpin); + return pushpin; + + // mapMarker.infoWindowOpen = true; + }, 'createpin'); + + @action + createMapRoute = undoable((coordinates: List<any>, origin: string, destination: string) => { + const mapRoute = Docs.Create.MapRouteDocument( + false, + [], + {title: `${origin} -> ${destination}`, routeCoordinates: coordinates}, + ); + this.addDocument(mapRoute, this.annotationKey); + return mapRoute; + + // mapMarker.infoWindowOpen = true; + }, 'createmaproute'); + searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch(); + + + + @observable + mapboxMapViewState: ViewState = { + zoom: 9, + longitude: -71.41, + latitude: 41.82, + pitch: 0, + bearing: 0, + padding: { + top: 0, + bottom: 0, + left: 0, + right: 0 + } + } + + @observable + featuresFromGeocodeResults: any[] = []; + + @action + onMapMove = (e: ViewStateChangeEvent) => { + this.mapboxMapViewState = e.viewState; + } + + + @action + addMarkerForFeature = (feature: any) => { + const location = feature.place_name; + if (feature.center){ + const longitude = feature.center[0]; + const latitude = feature.center[1]; + const wikiData = feature.properties?.wikiData; + + this.createPushpin( + latitude, + longitude, + location, + wikiData + ) + this.featuresFromGeocodeResults = []; + + } else { + // TODO: handle error + } + } + + + + /** + * Makes a forward geocoding API call to Mapbox to retrieve locations based on the search input + * @param searchText the search input (presumably a location) + */ + handleSearchChange = async (searchText: string) => { + const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText); + if (features){ + runInAction(() => { + this.featuresFromGeocodeResults = features; + }) + } + // try { + // const url = MAPBOX_FORWARD_GEOCODE_BASE_URL + encodeURI(searchText) +'.json' +`?access_token=${MAPBOX_ACCESS_TOKEN}`; + // const response = await fetch(url); + // const data = await response.json(); + // runInAction(() => { + // this.featuresFromGeocodeResults = data.features; + // }) + // } catch (error: any){ + // // TODO: handle error in better way + // console.log(error); + // } + } + // @action + // debouncedCall = React.useCallback(debounce(this.debouncedOnSearchBarChange, 300), []); + + /** + * Makes a reverse geocoding API call to retrieve features corresponding to a map click (based on longitude + * and latitude). Sets the search results accordingly. + * @param e + */ + handleMapClick = async (e: MapLayerMouseEvent) => { + e.preventDefault(); + const lngLat: LngLat = e.lngLat; + const longitude: number = lngLat.lng; + const latitude: number = lngLat.lat; + + const features = await MapboxApiUtility.reverseGeocodeForFeatures(longitude, latitude); + if (features){ + runInAction(() => { + this.featuresFromGeocodeResults = features; + }) + } + + // // REVERSE GEOCODE TO GET LOCATION DETAILS + // try { + // const url = MAPBOX_REVERSE_GEOCODE_BASE_URL + encodeURI(longitude.toString() + "," + latitude.toString()) + '.json' + + // `?access_token=${MAPBOX_ACCESS_TOKEN}`; + // const response = await fetch(url); + // const data = await response.json(); + // console.log("REV GEOCODE DATA: ", data); + // runInAction(() => { + // this.featuresFromGeocodeResults = data.features; + // }) + // } catch (error: any){ + // // TODO: handle error in better way + // console.log(error); + // } + } + + @observable + currentPopup: PopupInfo | undefined = undefined; + + @action + handleMarkerClick = (e: MarkerEvent<mapboxgl.Marker, MouseEvent>, pinDoc: Doc) => { + this.featuresFromGeocodeResults = []; + this.deselectPin(); // TODO: check this method + this.selectedPin = pinDoc; + // this.bingSearchBarContents = pinDoc.map; + + // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match'); + // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match'); + Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPin)}`, 'check'); + + this.recolorPin(this.selectedPin, 'green'); // TODO: check this method + + + MapAnchorMenu.Instance.Delete = this.deleteSelectedPin; + MapAnchorMenu.Instance.Center = this.centerOnSelectedPin; + MapAnchorMenu.Instance.OnClick = this.createNoteAnnotation; + MapAnchorMenu.Instance.StartDrag = this.startAnchorDrag; + + // pass in the pinDoc + MapAnchorMenu.Instance.setPinDoc(pinDoc); + MapAnchorMenu.Instance.setAllMapboxPins( + this.allAnnotations.filter(anno => !anno.layout_unrendered) + ) + + MapAnchorMenu.Instance.DisplayRoute = this.displayRoute; + MapAnchorMenu.Instance.HideRoute = this.hideRoute; + MapAnchorMenu.Instance.AddNewRouteToMap = this.createMapRoute; + MapAnchorMenu.Instance.CreatePin = this.addMarkerForFeature; + + // const longitude = NumCast(pinDoc.longitude); + // const latitude = NumCast(pinDoc.longitude); + // const x = longitude + (this.props.PanelWidth() - this.sidebarWidth()) / 2; + // const y = latitude + this.props.PanelHeight() / 2 + 20; + // const cpt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y); + MapAnchorMenu.Instance.jumpTo(e.originalEvent.clientX, e.originalEvent.clientY, true); + + document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true); + }; + + @observable + temporaryRouteSource: FeatureCollection = { + type: 'FeatureCollection', + features: [] + } + + @action + displayRoute = (routeInfoMap: Record<TransportationType, any> | undefined, type: TransportationType) => { + if (routeInfoMap){ + const newTempRouteSource: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + properties: {}, + geometry: { + type: 'LineString', + coordinates: routeInfoMap[type].coordinates + } + } + ] + } + // TODO: Create pin for destination + // TODO: Fly to point where full route will be shown + this.temporaryRouteSource = newTempRouteSource; + } + } + + @action + hideRoute = () => { + this.temporaryRouteSource = { + type: 'FeatureCollection', + features: [] + } + } + + + + static _firstRender = true; static _rerenderDelay = 500; _rerenderTimeout: any; @@ -732,14 +1024,42 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps {SnappingManager.GetIsDragging() ? null : renderAnnotations()} <div className="mapBox-searchbar"> - <EditableText - // editing - setVal={(newText: string | number) => typeof newText === 'string' && this.searchbarOnEdit(newText)} - onEnter={e => this.bingSearch()} - placeholder={this.bingSearchBarContents || 'enter city/zip/...'} - textAlign="center" + <TextField + fullWidth + placeholder='Enter a location' + onChange={(e) => this.handleSearchChange(e.target.value)} /> - <IconButton + {/* <Autocomplete + fullWidth + id="map-location-searcher" + freeSolo + onInputChange={(e, searchText) => this.handleSearchChange(searchText)} + onChange={(e, selectedOption) => { + this.handleSearchChange(""); // clear input + this.addMarkerForFeature(selectedOption); + }} + options={this.featuresFromGeocodeResults + .filter(feature => feature.place_name) + .map(feature => feature)} + getOptionLabel={(feature) => feature.place_name} + renderInput={(params) => ( + <TextField + {...params} + placeholder='Enter a location' + /> + )} + /> */} + {/* <EditableText + // editing + setVal={(newText: string | number) => typeof newText === 'string' && this.handleSearchChange(newText)} + // onEnter={e => this.bingSearch()} + onEnter={e => {}} + height={32} + // placeholder={this.bingSearchBarContents || 'Enter a location'} + placeholder='Enter a location' + textAlign="center" + /> */} + {/* <IconButton icon={ <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="magnifying-glass" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" color="#DFDFDF"> <path @@ -752,18 +1072,87 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps /> <div style={{ width: 30, height: 30 }} ref={this._dragRef} onPointerDown={this.dragToggle}> <Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size={'lg'} icon={'bullseye'} />} /> - </div> - </div> + </div> */} + </div> + <div className='mapbox-geocoding-search-results'> + {this.featuresFromGeocodeResults.length > 0 && ( + <React.Fragment> + <h4>Choose a location for your pin: </h4> + {this.featuresFromGeocodeResults + .filter(feature => feature.place_name) + .map((feature, idx) => ( + <div + key={idx} + className='search-result-container' + onClick={() => { + this.handleSearchChange(""); + this.addMarkerForFeature(feature); + }} + > + <div className='search-result-place-name'> + {feature.place_name} + </div> + </div> + ))} + </React.Fragment> + )} + </div> + <MapProvider> + <MapboxMap + ref={this._mapRef} + initialViewState={{ + longitude: -100, + latitude: 40, + zoom: 3.5 + }} + mapboxAccessToken={MAPBOX_ACCESS_TOKEN} + id="mapbox-map" + mapStyle="mapbox://styles/mapbox/streets-v9" + style={{height: '100%', width: '100%'}} + {...this.mapboxMapViewState} + onMove={this.onMapMove} + onDblClick={this.handleMapClick} + + + > + <Source id='temporary-route' type='geojson' data={this.temporaryRouteSource}/> + <Layer + id='temporary-route-layer' + type='line' + source='temporary-route' + layout={{"line-join": "round", "line-cap": "round"}} + paint={{"line-color": "#36454F", "line-width": 4, "line-dasharray": [1,1]}} + /> + <> + {this.allPushpins + // .filter(anno => !anno.layout_unrendered) + .map((pushpin, idx) => ( + <Marker + key={idx} + longitude={NumCast(pushpin.longitude)} + latitude={NumCast(pushpin.latitude)} + anchor='bottom' + onClick={(e: MarkerEvent<mapboxgl.Marker, MouseEvent>) => this.handleMarkerClick(e, pushpin)} + /> + ))} + </> + + {/* {this.mapMarkers.length > 0 && this.mapMarkers.map((marker, idx) => ( + <Marker key={idx} longitude={marker.longitude} latitude={marker.latitude}/> + ))} */} - <BingMapsReact + </MapboxMap> + </MapProvider> + + {/* <BingMapsReact onMapReady={this.bingMapReady} // bingMapsKey={bingApiKey} height="100%" mapOptions={this.bingMapOptions} width="100%" viewOptions={this.bingViewOptions} - /> - <div> + /> */} + {/* <div> {!this._mapReady ? null : this.allAnnotations @@ -793,7 +1182,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps focus={returnOne} /> ))} - </div> + </div> */} {/* <MapBoxInfoWindow key={Docs.Create.MapMarkerDocument(NumCast(40), NumCast(40), false, [], {})[Id]} {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit} |