@lugg/maps 0.2.0-alpha.0 → 0.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/android/src/main/java/com/luggmaps/{LuggMapsGoogleMapView.kt → LuggGoogleMapView.kt} +111 -36
- package/android/src/main/java/com/luggmaps/{LuggMapsGoogleMapViewManager.kt → LuggGoogleMapViewManager.kt} +66 -39
- package/android/src/main/java/com/luggmaps/{LuggMapsWrapperView.kt → LuggMapWrapperView.kt} +1 -1
- package/android/src/main/java/com/luggmaps/LuggMapWrapperViewManager.kt +25 -0
- package/android/src/main/java/com/luggmaps/{LuggMapsMarkerView.kt → LuggMarkerView.kt} +13 -7
- package/android/src/main/java/com/luggmaps/{LuggMapsMarkerViewManager.kt → LuggMarkerViewManager.kt} +23 -17
- package/android/src/main/java/com/luggmaps/{LuggMapsPackage.kt → LuggPackage.kt} +2 -2
- package/android/src/main/java/com/luggmaps/{LuggMapsPolylineView.kt → LuggPolylineView.kt} +11 -4
- package/android/src/main/java/com/luggmaps/{LuggMapsPolylineViewManager.kt → LuggPolylineViewManager.kt} +22 -16
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +89 -43
- package/android/src/main/java/com/luggmaps/events/CameraIdleEvent.kt +10 -2
- package/android/src/main/java/com/luggmaps/events/CameraMoveEvent.kt +6 -5
- package/android/src/main/java/com/luggmaps/events/ReadyEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +14 -0
- package/ios/{LuggMapsAppleMapView.h → LuggAppleMapView.h} +2 -2
- package/ios/{LuggMapsAppleMapView.mm → LuggAppleMapView.mm} +140 -71
- package/ios/{LuggMapsGoogleMapView.h → LuggGoogleMapView.h} +1 -1
- package/ios/{LuggMapsGoogleMapView.mm → LuggGoogleMapView.mm} +82 -64
- package/ios/{LuggMapsWrapperView.h → LuggMapWrapperView.h} +1 -1
- package/ios/{LuggMapsWrapperView.mm → LuggMapWrapperView.mm} +7 -7
- package/ios/{LuggMapsMarkerView.h → LuggMarkerView.h} +8 -6
- package/ios/{LuggMapsMarkerView.mm → LuggMarkerView.mm} +21 -8
- package/ios/{LuggMapsPolylineView.h → LuggPolylineView.h} +6 -5
- package/ios/{LuggMapsPolylineView.mm → LuggPolylineView.mm} +14 -9
- package/ios/core/GMSPolylineAnimator.m +85 -36
- package/ios/core/MKPolylineAnimator.m +63 -32
- package/ios/events/CameraIdleEvent.h +6 -1
- package/ios/events/CameraMoveEvent.h +6 -3
- package/ios/events/ReadyEvent.h +20 -0
- package/lib/module/MapProvider.js +13 -0
- package/lib/module/MapProvider.js.map +1 -0
- package/lib/module/MapProvider.types.js +4 -0
- package/lib/module/MapProvider.types.js.map +1 -0
- package/lib/module/MapProvider.web.js +14 -0
- package/lib/module/MapProvider.web.js.map +1 -0
- package/lib/module/MapView.js +21 -7
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +266 -0
- package/lib/module/MapView.web.js.map +1 -0
- package/lib/module/{Marker.js → components/Marker.js} +6 -3
- package/lib/module/components/Marker.js.map +1 -0
- package/lib/module/components/Marker.web.js +34 -0
- package/lib/module/components/Marker.web.js.map +1 -0
- package/lib/module/{Polyline.js → components/Polyline.js} +7 -4
- package/lib/module/components/Polyline.js.map +1 -0
- package/lib/module/components/Polyline.web.js +177 -0
- package/lib/module/components/Polyline.web.js.map +1 -0
- package/lib/module/components/index.js +5 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/components/index.web.js +5 -0
- package/lib/module/components/index.web.js.map +1 -0
- package/{src/fabric/LuggMapsAppleMapViewNativeComponent.ts → lib/module/fabric/LuggAppleMapViewNativeComponent.ts} +13 -3
- package/lib/module/fabric/{LuggMapsGoogleMapViewNativeComponent.ts → LuggGoogleMapViewNativeComponent.ts} +13 -3
- package/{src/fabric/LuggMapsWrapperViewNativeComponent.ts → lib/module/fabric/LuggMapWrapperViewNativeComponent.ts} +1 -1
- package/lib/module/fabric/{LuggMapsMarkerViewNativeComponent.ts → LuggMarkerViewNativeComponent.ts} +1 -1
- package/{src/fabric/LuggMapsPolylineViewNativeComponent.ts → lib/module/fabric/LuggPolylineViewNativeComponent.ts} +1 -1
- package/lib/module/index.js +3 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +6 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/typescript/plugin/src/withLuggMapsAndroid.d.ts +6 -0
- package/lib/typescript/plugin/src/withLuggMapsAndroid.d.ts.map +1 -0
- package/lib/typescript/plugin/src/withLuggMapsIOS.d.ts +6 -0
- package/lib/typescript/plugin/src/withLuggMapsIOS.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.d.ts +8 -0
- package/lib/typescript/src/MapProvider.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.types.d.ts +16 -0
- package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.web.d.ts +3 -0
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +24 -14
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts +12 -0
- package/lib/typescript/src/MapView.web.d.ts.map +1 -0
- package/lib/typescript/src/{Marker.types.d.ts → components/Marker.d.ts} +10 -5
- package/lib/typescript/src/components/Marker.d.ts.map +1 -0
- package/lib/typescript/src/{Marker.d.ts → components/Marker.web.d.ts} +2 -2
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
- package/lib/typescript/src/{Polyline.types.d.ts → components/Polyline.d.ts} +10 -5
- package/lib/typescript/src/components/Polyline.d.ts.map +1 -0
- package/lib/typescript/src/components/Polyline.web.d.ts +6 -0
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +3 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -0
- package/lib/typescript/src/components/index.web.d.ts +5 -0
- package/lib/typescript/src/components/index.web.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggMapsAppleMapViewNativeComponent.d.ts → LuggAppleMapViewNativeComponent.d.ts} +10 -3
- package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggMapsGoogleMapViewNativeComponent.d.ts → LuggGoogleMapViewNativeComponent.d.ts} +10 -3
- package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggMapsWrapperViewNativeComponent.d.ts → LuggMapWrapperViewNativeComponent.d.ts} +1 -1
- package/lib/typescript/src/fabric/LuggMapWrapperViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggMapsMarkerViewNativeComponent.d.ts → LuggMarkerViewNativeComponent.d.ts} +1 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/{LuggMapsPolylineViewNativeComponent.d.ts → LuggPolylineViewNativeComponent.d.ts} +1 -1
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -6
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +7 -0
- package/lib/typescript/src/index.web.d.ts.map +1 -0
- package/package.json +20 -7
- package/plugin/build/index.js +4 -4
- package/{lib/typescript/plugin/src/withMapsAndroid.d.ts → plugin/build/withLuggMapsAndroid.d.ts} +0 -1
- package/plugin/build/withLuggMapsAndroid.js +15 -0
- package/{lib/typescript/plugin/src/withMapsIOS.d.ts → plugin/build/withLuggMapsIOS.d.ts} +0 -1
- package/plugin/build/withLuggMapsIOS.js +27 -0
- package/plugin/build/withMapsAndroid.d.ts +1 -1
- package/plugin/build/withMapsIOS.d.ts +1 -1
- package/src/MapProvider.tsx +10 -0
- package/src/MapProvider.types.ts +16 -0
- package/src/MapProvider.web.tsx +6 -0
- package/src/MapView.tsx +27 -10
- package/src/MapView.types.ts +24 -15
- package/src/MapView.web.tsx +319 -0
- package/src/components/Marker.tsx +63 -0
- package/src/components/Marker.web.tsx +32 -0
- package/src/components/Polyline.tsx +57 -0
- package/src/components/Polyline.web.tsx +222 -0
- package/src/components/index.ts +2 -0
- package/src/components/index.web.ts +4 -0
- package/{lib/module/fabric/LuggMapsAppleMapViewNativeComponent.ts → src/fabric/LuggAppleMapViewNativeComponent.ts} +13 -3
- package/src/fabric/{LuggMapsGoogleMapViewNativeComponent.ts → LuggGoogleMapViewNativeComponent.ts} +13 -3
- package/{lib/module/fabric/LuggMapsWrapperViewNativeComponent.ts → src/fabric/LuggMapWrapperViewNativeComponent.ts} +1 -1
- package/src/fabric/{LuggMapsMarkerViewNativeComponent.ts → LuggMarkerViewNativeComponent.ts} +1 -1
- package/{lib/module/fabric/LuggMapsPolylineViewNativeComponent.ts → src/fabric/LuggPolylineViewNativeComponent.ts} +1 -1
- package/src/index.ts +11 -7
- package/src/index.web.ts +17 -0
- package/android/src/main/java/com/luggmaps/LuggMapsWrapperViewManager.kt +0 -25
- package/lib/module/Marker.js.map +0 -1
- package/lib/module/Marker.types.js +0 -4
- package/lib/module/Marker.types.js.map +0 -1
- package/lib/module/Polyline.js.map +0 -1
- package/lib/module/Polyline.types.js +0 -4
- package/lib/module/Polyline.types.js.map +0 -1
- package/lib/typescript/plugin/src/withMapsAndroid.d.ts.map +0 -1
- package/lib/typescript/plugin/src/withMapsIOS.d.ts.map +0 -1
- package/lib/typescript/src/Marker.d.ts.map +0 -1
- package/lib/typescript/src/Marker.types.d.ts.map +0 -1
- package/lib/typescript/src/Polyline.d.ts +0 -6
- package/lib/typescript/src/Polyline.d.ts.map +0 -1
- package/lib/typescript/src/Polyline.types.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggMapsAppleMapViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggMapsGoogleMapViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggMapsMarkerViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggMapsPolylineViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/fabric/LuggMapsWrapperViewNativeComponent.d.ts.map +0 -1
- package/src/Marker.tsx +0 -31
- package/src/Marker.types.ts +0 -32
- package/src/Polyline.tsx +0 -32
- package/src/Polyline.types.ts +0 -24
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lugg/maps",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.10",
|
|
4
4
|
"description": "Universal maps for React Native.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
9
|
"source": "./src/index.ts",
|
|
10
|
+
"react-native": "./lib/module/index.js",
|
|
11
|
+
"web": {
|
|
12
|
+
"types": "./lib/typescript/src/index.web.d.ts",
|
|
13
|
+
"default": "./lib/module/index.web.js"
|
|
14
|
+
},
|
|
10
15
|
"types": "./lib/typescript/src/index.d.ts",
|
|
11
16
|
"default": "./lib/module/index.js"
|
|
12
17
|
},
|
|
13
|
-
"./package.json": "./package.json"
|
|
18
|
+
"./package.json": "./package.json",
|
|
19
|
+
"./app.plugin.js": "./app.plugin.js"
|
|
14
20
|
},
|
|
15
21
|
"files": [
|
|
16
22
|
"src",
|
|
@@ -74,6 +80,7 @@
|
|
|
74
80
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
75
81
|
"@types/jest": "^29.5.14",
|
|
76
82
|
"@types/react": "^19.2.0",
|
|
83
|
+
"@vis.gl/react-google-maps": "^1.7.1",
|
|
77
84
|
"commitlint": "^19.8.1",
|
|
78
85
|
"del-cli": "^6.0.0",
|
|
79
86
|
"eslint": "^9.35.0",
|
|
@@ -90,9 +97,15 @@
|
|
|
90
97
|
"typescript": "^5.9.2"
|
|
91
98
|
},
|
|
92
99
|
"peerDependencies": {
|
|
100
|
+
"@vis.gl/react-google-maps": ">=1.0.0",
|
|
93
101
|
"react": "*",
|
|
94
102
|
"react-native": "*"
|
|
95
103
|
},
|
|
104
|
+
"peerDependenciesMeta": {
|
|
105
|
+
"@vis.gl/react-google-maps": {
|
|
106
|
+
"optional": true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
96
109
|
"dependencies": {
|
|
97
110
|
"@expo/config-plugins": "^9.0.0"
|
|
98
111
|
},
|
|
@@ -129,11 +142,11 @@
|
|
|
129
142
|
},
|
|
130
143
|
"ios": {
|
|
131
144
|
"componentProvider": {
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
145
|
+
"LuggGoogleMapView": "LuggGoogleMapView",
|
|
146
|
+
"LuggAppleMapView": "LuggAppleMapView",
|
|
147
|
+
"LuggMarkerView": "LuggMarkerView",
|
|
148
|
+
"LuggMapWrapperView": "LuggMapWrapperView",
|
|
149
|
+
"LuggPolylineView": "LuggPolylineView"
|
|
137
150
|
}
|
|
138
151
|
}
|
|
139
152
|
},
|
package/plugin/build/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const withLuggMapsAndroid_1 = require("./withLuggMapsAndroid");
|
|
5
|
+
const withLuggMapsIOS_1 = require("./withLuggMapsIOS");
|
|
6
6
|
const pkg = require('../../package.json');
|
|
7
7
|
const withMaps = (config, props = {}) => {
|
|
8
8
|
const { iosGoogleMapsApiKey, androidGoogleMapsApiKey } = props ?? {};
|
|
9
|
-
config = (0,
|
|
10
|
-
config = (0,
|
|
9
|
+
config = (0, withLuggMapsIOS_1.withLuggMapsIOS)(config, { apiKey: iosGoogleMapsApiKey });
|
|
10
|
+
config = (0, withLuggMapsAndroid_1.withLuggMapsAndroid)(config, { apiKey: androidGoogleMapsApiKey });
|
|
11
11
|
return config;
|
|
12
12
|
};
|
|
13
13
|
exports.default = (0, config_plugins_1.createRunOncePlugin)(withMaps, pkg.name, pkg.version);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withLuggMapsAndroid = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const withLuggMapsAndroid = (config, { apiKey }) => {
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
return config;
|
|
8
|
+
}
|
|
9
|
+
return (0, config_plugins_1.withAndroidManifest)(config, (c) => {
|
|
10
|
+
const mainApplication = config_plugins_1.AndroidConfig.Manifest.getMainApplicationOrThrow(c.modResults);
|
|
11
|
+
config_plugins_1.AndroidConfig.Manifest.addMetaDataItemToMainApplication(mainApplication, 'com.google.android.geo.API_KEY', apiKey);
|
|
12
|
+
return c;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
exports.withLuggMapsAndroid = withLuggMapsAndroid;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withLuggMapsIOS = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const withLuggMapsIOS = (config, { apiKey }) => {
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
return config;
|
|
8
|
+
}
|
|
9
|
+
config = (0, config_plugins_1.withInfoPlist)(config, (c) => {
|
|
10
|
+
c.modResults.GMSApiKey = apiKey;
|
|
11
|
+
return c;
|
|
12
|
+
});
|
|
13
|
+
config = (0, config_plugins_1.withAppDelegate)(config, (c) => {
|
|
14
|
+
const contents = c.modResults.contents;
|
|
15
|
+
// Add import for GoogleMaps
|
|
16
|
+
if (!contents.includes('import GoogleMaps')) {
|
|
17
|
+
c.modResults.contents = contents.replace(/(import (?:UIKit|Expo))/, '$1\nimport GoogleMaps');
|
|
18
|
+
}
|
|
19
|
+
// Add GMSServices.provideAPIKey call
|
|
20
|
+
if (!c.modResults.contents.includes('GMSServices.provideAPIKey')) {
|
|
21
|
+
c.modResults.contents = c.modResults.contents.replace(/(func application\([^)]+\)[^{]*\{)/, `$1\n GMSServices.provideAPIKey("${apiKey}")\n`);
|
|
22
|
+
}
|
|
23
|
+
return c;
|
|
24
|
+
});
|
|
25
|
+
return config;
|
|
26
|
+
};
|
|
27
|
+
exports.withLuggMapsIOS = withLuggMapsIOS;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MapProviderProps } from './MapProvider.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provider component for map configuration.
|
|
5
|
+
* On web, wraps children with Google Maps APIProvider.
|
|
6
|
+
* On native, passes children through.
|
|
7
|
+
*/
|
|
8
|
+
export function MapProvider({ children }: MapProviderProps) {
|
|
9
|
+
return children;
|
|
10
|
+
}
|
package/src/MapView.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Platform, StyleSheet } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import LuggGoogleMapViewNativeComponent, {
|
|
4
4
|
Commands as GoogleMapCommands,
|
|
5
|
-
} from './fabric/
|
|
6
|
-
import
|
|
5
|
+
} from './fabric/LuggGoogleMapViewNativeComponent';
|
|
6
|
+
import LuggAppleMapViewNativeComponent, {
|
|
7
7
|
Commands as AppleMapCommands,
|
|
8
|
-
} from './fabric/
|
|
9
|
-
import
|
|
8
|
+
} from './fabric/LuggAppleMapViewNativeComponent';
|
|
9
|
+
import LuggMapWrapperViewNativeComponent from './fabric/LuggMapWrapperViewNativeComponent';
|
|
10
10
|
import type {
|
|
11
11
|
MapViewProps,
|
|
12
12
|
MapViewRef,
|
|
@@ -55,7 +55,8 @@ export class MapView
|
|
|
55
55
|
const first = coordinates[0];
|
|
56
56
|
if (!ref || !first) return;
|
|
57
57
|
|
|
58
|
-
const { padding
|
|
58
|
+
const { padding, duration = -1 } = options ?? {};
|
|
59
|
+
const { top = 0, left = 0, bottom = 0, right = 0 } = padding ?? {};
|
|
59
60
|
|
|
60
61
|
if (coordinates.length === 1) {
|
|
61
62
|
const zoom = this.props.initialZoom ?? 10;
|
|
@@ -63,7 +64,15 @@ export class MapView
|
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
this.nativeCommands.fitCoordinates(
|
|
67
|
+
this.nativeCommands.fitCoordinates(
|
|
68
|
+
ref,
|
|
69
|
+
coordinates,
|
|
70
|
+
top,
|
|
71
|
+
left,
|
|
72
|
+
bottom,
|
|
73
|
+
right,
|
|
74
|
+
duration
|
|
75
|
+
);
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
render() {
|
|
@@ -72,21 +81,25 @@ export class MapView
|
|
|
72
81
|
mapId,
|
|
73
82
|
initialCoordinate,
|
|
74
83
|
initialZoom,
|
|
84
|
+
minZoom,
|
|
85
|
+
maxZoom,
|
|
75
86
|
zoomEnabled,
|
|
76
87
|
scrollEnabled,
|
|
77
88
|
rotateEnabled,
|
|
78
89
|
pitchEnabled,
|
|
79
90
|
padding,
|
|
91
|
+
userLocationEnabled,
|
|
80
92
|
onCameraMove,
|
|
81
93
|
onCameraIdle,
|
|
94
|
+
onReady,
|
|
82
95
|
children,
|
|
83
96
|
...rest
|
|
84
97
|
} = this.props;
|
|
85
98
|
|
|
86
99
|
const NativeMapView =
|
|
87
100
|
Platform.OS === 'ios' && provider === 'apple'
|
|
88
|
-
?
|
|
89
|
-
:
|
|
101
|
+
? LuggAppleMapViewNativeComponent
|
|
102
|
+
: LuggGoogleMapViewNativeComponent;
|
|
90
103
|
|
|
91
104
|
return (
|
|
92
105
|
<NativeMapView
|
|
@@ -95,15 +108,19 @@ export class MapView
|
|
|
95
108
|
mapId={mapId}
|
|
96
109
|
initialCoordinate={initialCoordinate}
|
|
97
110
|
initialZoom={initialZoom}
|
|
111
|
+
minZoom={minZoom}
|
|
112
|
+
maxZoom={maxZoom}
|
|
98
113
|
zoomEnabled={zoomEnabled}
|
|
99
114
|
scrollEnabled={scrollEnabled}
|
|
100
115
|
rotateEnabled={rotateEnabled}
|
|
101
116
|
pitchEnabled={pitchEnabled}
|
|
102
117
|
padding={padding}
|
|
118
|
+
userLocationEnabled={userLocationEnabled}
|
|
103
119
|
onCameraMove={onCameraMove}
|
|
104
120
|
onCameraIdle={onCameraIdle}
|
|
121
|
+
onReady={onReady}
|
|
105
122
|
>
|
|
106
|
-
<
|
|
123
|
+
<LuggMapWrapperViewNativeComponent style={StyleSheet.absoluteFill} />
|
|
107
124
|
{children}
|
|
108
125
|
</NativeMapView>
|
|
109
126
|
);
|
package/src/MapView.types.ts
CHANGED
|
@@ -13,11 +13,10 @@ export interface MoveCameraOptions {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Options for fitting coordinates in view
|
|
16
|
-
* @default padding 0
|
|
17
16
|
* @default duration -1
|
|
18
17
|
*/
|
|
19
18
|
export interface FitCoordinatesOptions {
|
|
20
|
-
padding?:
|
|
19
|
+
padding?: EdgeInsets;
|
|
21
20
|
duration?: number;
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -33,20 +32,12 @@ export interface MapViewRef {
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/**
|
|
36
|
-
* Camera
|
|
37
|
-
*/
|
|
38
|
-
export interface CameraMoveEvent {
|
|
39
|
-
coordinate: Coordinate;
|
|
40
|
-
zoom: number;
|
|
41
|
-
dragging: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Camera idle event data
|
|
35
|
+
* Camera event payload
|
|
46
36
|
*/
|
|
47
|
-
export interface
|
|
37
|
+
export interface CameraEventPayload {
|
|
48
38
|
coordinate: Coordinate;
|
|
49
39
|
zoom: number;
|
|
40
|
+
gesture: boolean;
|
|
50
41
|
}
|
|
51
42
|
|
|
52
43
|
/**
|
|
@@ -71,6 +62,14 @@ export interface MapViewProps extends ViewProps {
|
|
|
71
62
|
* @default 10
|
|
72
63
|
*/
|
|
73
64
|
initialZoom?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Minimum zoom level
|
|
67
|
+
*/
|
|
68
|
+
minZoom?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Maximum zoom level
|
|
71
|
+
*/
|
|
72
|
+
maxZoom?: number;
|
|
74
73
|
/**
|
|
75
74
|
* Enable zoom gestures
|
|
76
75
|
* @default true
|
|
@@ -95,14 +94,24 @@ export interface MapViewProps extends ViewProps {
|
|
|
95
94
|
* Map content padding
|
|
96
95
|
*/
|
|
97
96
|
padding?: EdgeInsets;
|
|
97
|
+
/**
|
|
98
|
+
* Show current user location on the map.
|
|
99
|
+
* Requires location permission to be granted, otherwise silently ignored.
|
|
100
|
+
* @default false
|
|
101
|
+
*/
|
|
102
|
+
userLocationEnabled?: boolean;
|
|
98
103
|
/**
|
|
99
104
|
* Called when camera moves
|
|
100
105
|
*/
|
|
101
|
-
onCameraMove?: (event: NativeSyntheticEvent<
|
|
106
|
+
onCameraMove?: (event: NativeSyntheticEvent<CameraEventPayload>) => void;
|
|
102
107
|
/**
|
|
103
108
|
* Called when camera stops moving
|
|
104
109
|
*/
|
|
105
|
-
onCameraIdle?: (event: NativeSyntheticEvent<
|
|
110
|
+
onCameraIdle?: (event: NativeSyntheticEvent<CameraEventPayload>) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Called when map is loaded and ready
|
|
113
|
+
*/
|
|
114
|
+
onReady?: () => void;
|
|
106
115
|
/**
|
|
107
116
|
* Map children (markers, polylines, etc.)
|
|
108
117
|
*/
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
Component,
|
|
4
|
+
isValidElement,
|
|
5
|
+
useEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type CSSProperties,
|
|
9
|
+
type ReactElement,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import type { NativeSyntheticEvent, ViewStyle } from 'react-native';
|
|
13
|
+
import { View } from 'react-native';
|
|
14
|
+
import { Map, useMap } from '@vis.gl/react-google-maps';
|
|
15
|
+
import { Marker } from './components/Marker.web';
|
|
16
|
+
import { Polyline } from './components/Polyline.web';
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
MapViewProps,
|
|
20
|
+
MapViewRef,
|
|
21
|
+
MoveCameraOptions,
|
|
22
|
+
FitCoordinatesOptions,
|
|
23
|
+
CameraEventPayload,
|
|
24
|
+
} from './MapView.types';
|
|
25
|
+
import type { Coordinate } from './types';
|
|
26
|
+
|
|
27
|
+
// Map-specific component types that render inside the Google Map
|
|
28
|
+
const MAP_COMPONENT_TYPES = new Set([Marker, Polyline]);
|
|
29
|
+
|
|
30
|
+
const isMapComponent = (child: ReactElement): boolean =>
|
|
31
|
+
MAP_COMPONENT_TYPES.has(child.type as typeof Marker | typeof Polyline);
|
|
32
|
+
|
|
33
|
+
const createSyntheticEvent = <T,>(nativeEvent: T): NativeSyntheticEvent<T> =>
|
|
34
|
+
({
|
|
35
|
+
nativeEvent,
|
|
36
|
+
currentTarget: null,
|
|
37
|
+
target: null,
|
|
38
|
+
bubbles: false,
|
|
39
|
+
cancelable: false,
|
|
40
|
+
defaultPrevented: false,
|
|
41
|
+
eventPhase: 0,
|
|
42
|
+
isTrusted: true,
|
|
43
|
+
preventDefault: () => {},
|
|
44
|
+
stopPropagation: () => {},
|
|
45
|
+
isDefaultPrevented: () => false,
|
|
46
|
+
isPropagationStopped: () => false,
|
|
47
|
+
persist: () => {},
|
|
48
|
+
timeStamp: Date.now(),
|
|
49
|
+
type: '',
|
|
50
|
+
} as unknown as NativeSyntheticEvent<T>);
|
|
51
|
+
|
|
52
|
+
interface MapControllerProps {
|
|
53
|
+
onMapReady: (map: google.maps.Map) => void;
|
|
54
|
+
onCameraMove?: (event: NativeSyntheticEvent<CameraEventPayload>) => void;
|
|
55
|
+
onCameraIdle?: (event: NativeSyntheticEvent<CameraEventPayload>) => void;
|
|
56
|
+
onReady?: () => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface UserLocationMarkerProps {
|
|
60
|
+
enabled?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const userLocationDotStyle: CSSProperties = {
|
|
64
|
+
width: 16,
|
|
65
|
+
height: 16,
|
|
66
|
+
backgroundColor: '#4285F4',
|
|
67
|
+
border: '2px solid white',
|
|
68
|
+
borderRadius: '50%',
|
|
69
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.3)',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function UserLocationMarker({ enabled }: UserLocationMarkerProps) {
|
|
73
|
+
const [coordinate, setCoordinate] = useState<Coordinate | null>(null);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!enabled) {
|
|
77
|
+
setCoordinate(null);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let watchId: number | null = null;
|
|
82
|
+
|
|
83
|
+
const updateLocation = (position: GeolocationPosition) => {
|
|
84
|
+
setCoordinate({
|
|
85
|
+
latitude: position.coords.latitude,
|
|
86
|
+
longitude: position.coords.longitude,
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
navigator.geolocation.getCurrentPosition(updateLocation, () => {});
|
|
91
|
+
watchId = navigator.geolocation.watchPosition(updateLocation, () => {});
|
|
92
|
+
|
|
93
|
+
return () => {
|
|
94
|
+
if (watchId !== null) {
|
|
95
|
+
navigator.geolocation.clearWatch(watchId);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}, [enabled]);
|
|
99
|
+
|
|
100
|
+
if (!coordinate) return null;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Marker coordinate={coordinate} anchor={{ x: 0.5, y: 0.5 }}>
|
|
104
|
+
<div style={userLocationDotStyle} />
|
|
105
|
+
</Marker>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function MapController({
|
|
110
|
+
onMapReady,
|
|
111
|
+
onCameraMove,
|
|
112
|
+
onCameraIdle,
|
|
113
|
+
onReady,
|
|
114
|
+
}: MapControllerProps) {
|
|
115
|
+
const map = useMap();
|
|
116
|
+
const readyFired = useRef(false);
|
|
117
|
+
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!map) return;
|
|
120
|
+
onMapReady(map);
|
|
121
|
+
|
|
122
|
+
if (!readyFired.current) {
|
|
123
|
+
readyFired.current = true;
|
|
124
|
+
onReady?.();
|
|
125
|
+
}
|
|
126
|
+
}, [map, onMapReady, onReady]);
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!map) return;
|
|
130
|
+
|
|
131
|
+
const createPayload = (gesture: boolean): CameraEventPayload => {
|
|
132
|
+
const center = map.getCenter();
|
|
133
|
+
return {
|
|
134
|
+
coordinate: {
|
|
135
|
+
latitude: center?.lat() ?? 0,
|
|
136
|
+
longitude: center?.lng() ?? 0,
|
|
137
|
+
},
|
|
138
|
+
zoom: map.getZoom() ?? 0,
|
|
139
|
+
gesture,
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let isDragging = false;
|
|
144
|
+
|
|
145
|
+
const dragStartListener = map.addListener('dragstart', () => {
|
|
146
|
+
isDragging = true;
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const dragEndListener = map.addListener('dragend', () => {
|
|
150
|
+
isDragging = false;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const centerListener = map.addListener('center_changed', () => {
|
|
154
|
+
onCameraMove?.(createSyntheticEvent(createPayload(isDragging)));
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const idleListener = map.addListener('idle', () => {
|
|
158
|
+
onCameraIdle?.(createSyntheticEvent(createPayload(false)));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return () => {
|
|
162
|
+
google.maps.event.removeListener(dragStartListener);
|
|
163
|
+
google.maps.event.removeListener(dragEndListener);
|
|
164
|
+
google.maps.event.removeListener(centerListener);
|
|
165
|
+
google.maps.event.removeListener(idleListener);
|
|
166
|
+
};
|
|
167
|
+
}, [map, onCameraMove, onCameraIdle]);
|
|
168
|
+
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export class MapView extends Component<MapViewProps> implements MapViewRef {
|
|
173
|
+
static defaultProps: Partial<MapViewProps> = {
|
|
174
|
+
provider: 'google',
|
|
175
|
+
mapId: 'DEMO_MAP_ID',
|
|
176
|
+
initialZoom: 10,
|
|
177
|
+
zoomEnabled: true,
|
|
178
|
+
scrollEnabled: true,
|
|
179
|
+
rotateEnabled: true,
|
|
180
|
+
pitchEnabled: true,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
private mapInstance: google.maps.Map | null = null;
|
|
184
|
+
|
|
185
|
+
private handleMapReady = (map: google.maps.Map) => {
|
|
186
|
+
this.mapInstance = map;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
moveCamera(coordinate: Coordinate, options: MoveCameraOptions) {
|
|
190
|
+
const map = this.mapInstance;
|
|
191
|
+
if (!map) return;
|
|
192
|
+
|
|
193
|
+
const { zoom, duration = -1 } = options;
|
|
194
|
+
const center = { lat: coordinate.latitude, lng: coordinate.longitude };
|
|
195
|
+
|
|
196
|
+
if (duration === 0) {
|
|
197
|
+
map.moveCamera({ center, zoom });
|
|
198
|
+
} else {
|
|
199
|
+
const currentZoom = map.getZoom();
|
|
200
|
+
const zoomChanged = zoom !== undefined && zoom !== currentZoom;
|
|
201
|
+
|
|
202
|
+
if (zoomChanged) {
|
|
203
|
+
map.setZoom(zoom);
|
|
204
|
+
}
|
|
205
|
+
map.panTo(center);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
fitCoordinates(coordinates: Coordinate[], options?: FitCoordinatesOptions) {
|
|
210
|
+
const map = this.mapInstance;
|
|
211
|
+
const first = coordinates[0];
|
|
212
|
+
if (!map || !first) return;
|
|
213
|
+
|
|
214
|
+
const { padding, duration = -1 } = options ?? {};
|
|
215
|
+
|
|
216
|
+
if (coordinates.length === 1) {
|
|
217
|
+
const zoom = this.props.initialZoom ?? 10;
|
|
218
|
+
this.moveCamera(first, { zoom, duration });
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const bounds = new google.maps.LatLngBounds();
|
|
223
|
+
coordinates.forEach((coord) => {
|
|
224
|
+
bounds.extend({ lat: coord.latitude, lng: coord.longitude });
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
map.fitBounds(bounds, {
|
|
228
|
+
top: padding?.top ?? 0,
|
|
229
|
+
left: padding?.left ?? 0,
|
|
230
|
+
bottom: padding?.bottom ?? 0,
|
|
231
|
+
right: padding?.right ?? 0,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
render() {
|
|
236
|
+
const {
|
|
237
|
+
mapId,
|
|
238
|
+
initialCoordinate,
|
|
239
|
+
initialZoom,
|
|
240
|
+
minZoom,
|
|
241
|
+
maxZoom,
|
|
242
|
+
zoomEnabled,
|
|
243
|
+
scrollEnabled,
|
|
244
|
+
pitchEnabled,
|
|
245
|
+
padding,
|
|
246
|
+
userLocationEnabled,
|
|
247
|
+
onCameraMove,
|
|
248
|
+
onCameraIdle,
|
|
249
|
+
onReady,
|
|
250
|
+
children,
|
|
251
|
+
style,
|
|
252
|
+
} = this.props;
|
|
253
|
+
|
|
254
|
+
const gestureHandling =
|
|
255
|
+
scrollEnabled === false && zoomEnabled === false
|
|
256
|
+
? 'none'
|
|
257
|
+
: scrollEnabled === false
|
|
258
|
+
? 'none'
|
|
259
|
+
: 'auto';
|
|
260
|
+
|
|
261
|
+
const defaultCenter = initialCoordinate
|
|
262
|
+
? { lat: initialCoordinate.latitude, lng: initialCoordinate.longitude }
|
|
263
|
+
: undefined;
|
|
264
|
+
|
|
265
|
+
// Separate map children (Marker, Polyline) from overlay children (regular Views)
|
|
266
|
+
const mapChildren: ReactNode[] = [];
|
|
267
|
+
const overlayChildren: ReactNode[] = [];
|
|
268
|
+
|
|
269
|
+
Children.forEach(children, (child) => {
|
|
270
|
+
if (!isValidElement(child)) return;
|
|
271
|
+
if (isMapComponent(child)) {
|
|
272
|
+
mapChildren.push(child);
|
|
273
|
+
} else {
|
|
274
|
+
overlayChildren.push(child);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const mapContainerStyle: ViewStyle = {
|
|
279
|
+
position: 'absolute',
|
|
280
|
+
top: padding?.top ?? 0,
|
|
281
|
+
left: padding?.left ?? 0,
|
|
282
|
+
right: padding?.right ?? 0,
|
|
283
|
+
bottom: padding?.bottom ?? 0,
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const mapStyle: CSSProperties = {
|
|
287
|
+
width: '100%',
|
|
288
|
+
height: '100%',
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<View style={style}>
|
|
293
|
+
<View style={mapContainerStyle}>
|
|
294
|
+
<Map
|
|
295
|
+
mapId={mapId}
|
|
296
|
+
defaultCenter={defaultCenter}
|
|
297
|
+
defaultZoom={initialZoom}
|
|
298
|
+
minZoom={minZoom}
|
|
299
|
+
maxZoom={maxZoom}
|
|
300
|
+
gestureHandling={gestureHandling}
|
|
301
|
+
disableDefaultUI
|
|
302
|
+
tilt={pitchEnabled === false ? 0 : undefined}
|
|
303
|
+
style={mapStyle}
|
|
304
|
+
>
|
|
305
|
+
<MapController
|
|
306
|
+
onMapReady={this.handleMapReady}
|
|
307
|
+
onCameraMove={onCameraMove}
|
|
308
|
+
onCameraIdle={onCameraIdle}
|
|
309
|
+
onReady={onReady}
|
|
310
|
+
/>
|
|
311
|
+
<UserLocationMarker enabled={userLocationEnabled} />
|
|
312
|
+
{mapChildren}
|
|
313
|
+
</Map>
|
|
314
|
+
</View>
|
|
315
|
+
{overlayChildren}
|
|
316
|
+
</View>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
}
|