react-native-map-link 2.11.4 → 3.0.0
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/lib/components/popup/Popup.d.ts +39 -0
- package/lib/components/popup/Popup.js +110 -0
- package/lib/components/popup/PopupBody.d.ts +16 -0
- package/lib/components/popup/PopupBody.js +31 -0
- package/lib/components/popup/PopupFlatList.d.ts +10 -0
- package/lib/components/popup/PopupFlatList.js +11 -0
- package/lib/components/popup/PopupFooter.d.ts +15 -0
- package/lib/components/popup/PopupFooter.js +18 -0
- package/lib/components/popup/PopupHeader.d.ts +17 -0
- package/lib/components/popup/PopupHeader.js +48 -0
- package/lib/components/popup/PopupItem.d.ts +13 -0
- package/lib/components/popup/PopupItem.js +38 -0
- package/lib/components/popup/PopupSeparator.d.ts +8 -0
- package/lib/components/popup/PopupSeparator.js +19 -0
- package/lib/constants.d.ts +15 -0
- package/lib/constants.js +97 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +116 -0
- package/lib/type.d.ts +92 -0
- package/lib/type.js +2 -0
- package/lib/utils.d.ts +44 -0
- package/lib/utils.js +307 -0
- package/package.json +52 -20
- package/index.d.ts +0 -128
- package/index.js +0 -8
- package/src/components/Popup.js +0 -298
- package/src/constants.js +0 -95
- package/src/images/apple-maps.png +0 -0
- package/src/images/citymapper.png +0 -0
- package/src/images/dgis.png +0 -0
- package/src/images/gett.png +0 -0
- package/src/images/google-maps.png +0 -0
- package/src/images/kakao-map.png +0 -0
- package/src/images/liftago.png +0 -0
- package/src/images/lyft.png +0 -0
- package/src/images/maps-me.png +0 -0
- package/src/images/mapycz.png +0 -0
- package/src/images/moovit.png +0 -0
- package/src/images/naver-map.png +0 -0
- package/src/images/osmand.png +0 -0
- package/src/images/petalmaps.png +0 -0
- package/src/images/tmap.png +0 -0
- package/src/images/transit.png +0 -0
- package/src/images/truckmap.png +0 -0
- package/src/images/uber.png +0 -0
- package/src/images/waze.png +0 -0
- package/src/images/yandex-maps.png +0 -0
- package/src/images/yandex-taxi.png +0 -0
- package/src/images/yandex.png +0 -0
- package/src/index.js +0 -345
- package/src/utils.js +0 -252
package/lib/type.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ViewStyle, StyleProp, ImageStyle, TextStyle, ImageSourcePropType } from 'react-native';
|
|
3
|
+
/** id for map application. this is the id that is passed to the `app` option */
|
|
4
|
+
export type MapId = 'apple-maps' | 'google-maps' | 'citymapper' | 'uber' | 'lyft' | 'transit' | 'truckmap' | 'waze' | 'yandex' | 'moovit' | 'yandex-maps' | 'yandex-taxi' | 'kakaomap' | 'tmap' | 'mapycz' | 'maps-me' | 'osmand' | 'gett' | 'navermap' | 'dgis' | 'liftago' | 'petalmaps';
|
|
5
|
+
export type DirectionMode = 'car' | 'walk' | 'public-transport' | 'bike';
|
|
6
|
+
/** options shared across different types */
|
|
7
|
+
export interface SharedOptions {
|
|
8
|
+
/** optionally you can set which apps to show (default: will show all supported apps installed on device) */
|
|
9
|
+
appsWhiteList?: MapId[];
|
|
10
|
+
/** custom titles to display for each app instead of using default titles. */
|
|
11
|
+
appTitles?: Partial<Record<MapId, string>>;
|
|
12
|
+
}
|
|
13
|
+
export interface MapLinkOptions extends SharedOptions {
|
|
14
|
+
latitude: number | string;
|
|
15
|
+
longitude: number | string;
|
|
16
|
+
/** optionally specify starting location for directions */
|
|
17
|
+
sourceLatitude?: number;
|
|
18
|
+
/** not optional if `sourceLatitude` is specified */
|
|
19
|
+
sourceLongitude?: number;
|
|
20
|
+
/** optional, true will always add Google Maps to iOS and open in Safari, even if app is not installed (default: false) */
|
|
21
|
+
alwaysIncludeGoogle?: boolean;
|
|
22
|
+
googleForceLatLon?: boolean;
|
|
23
|
+
appleIgnoreLatLon?: boolean;
|
|
24
|
+
googlePlaceId?: string;
|
|
25
|
+
title?: string;
|
|
26
|
+
/** optionally specify specific app to use */
|
|
27
|
+
app?: MapId;
|
|
28
|
+
/** optional (default: 'Open in Maps') */
|
|
29
|
+
dialogTitle?: string;
|
|
30
|
+
/** optional (default: 'What app would you like to use?') */
|
|
31
|
+
dialogMessage?: string;
|
|
32
|
+
cancelText?: string;
|
|
33
|
+
/** to link into Naver Map You should provide your appname which is the bundle ID in iOS and applicationId in android. */
|
|
34
|
+
naverCallerName?: string;
|
|
35
|
+
directionsMode?: DirectionMode;
|
|
36
|
+
}
|
|
37
|
+
export interface PopupStyleProp {
|
|
38
|
+
container?: StyleProp<ViewStyle>;
|
|
39
|
+
itemContainer?: StyleProp<ViewStyle>;
|
|
40
|
+
image?: StyleProp<ImageStyle>;
|
|
41
|
+
itemText?: StyleProp<TextStyle>;
|
|
42
|
+
headerContainer?: StyleProp<ViewStyle>;
|
|
43
|
+
titleText?: StyleProp<TextStyle>;
|
|
44
|
+
subtitleText?: StyleProp<TextStyle>;
|
|
45
|
+
cancelButtonContainer?: StyleProp<ViewStyle>;
|
|
46
|
+
cancelButtonText?: StyleProp<TextStyle>;
|
|
47
|
+
separatorStyle?: StyleProp<ViewStyle>;
|
|
48
|
+
activityIndicatorContainer?: StyleProp<ViewStyle>;
|
|
49
|
+
}
|
|
50
|
+
export interface PopupProps extends SharedOptions {
|
|
51
|
+
isVisible: boolean;
|
|
52
|
+
showHeader?: boolean;
|
|
53
|
+
customHeader?: React.ReactNode;
|
|
54
|
+
customFooter?: React.ReactNode;
|
|
55
|
+
onCancelPressed: () => void;
|
|
56
|
+
onBackButtonPressed: () => void;
|
|
57
|
+
onAppPressed: (appName: MapId) => void;
|
|
58
|
+
style?: PopupStyleProp;
|
|
59
|
+
modalProps?: object;
|
|
60
|
+
options: MapLinkOptions;
|
|
61
|
+
}
|
|
62
|
+
export type GetAppsResponse = {
|
|
63
|
+
id: MapId;
|
|
64
|
+
name: string;
|
|
65
|
+
icon: ImageSourcePropType;
|
|
66
|
+
/** function to link user to map app */
|
|
67
|
+
open: () => Promise<string | null | undefined>;
|
|
68
|
+
};
|
|
69
|
+
export interface ShowLocationProps {
|
|
70
|
+
latitude: number | string;
|
|
71
|
+
longitude: number | string;
|
|
72
|
+
sourceLatitude?: number | null;
|
|
73
|
+
sourceLongitude?: number | null;
|
|
74
|
+
appleIgnoreLatLon?: boolean;
|
|
75
|
+
alwaysIncludeGoogle?: boolean;
|
|
76
|
+
googleForceLatLon?: boolean;
|
|
77
|
+
googlePlaceId?: number | string;
|
|
78
|
+
title?: string | null;
|
|
79
|
+
app?: string | null;
|
|
80
|
+
dialogTitle?: string | null;
|
|
81
|
+
dialogMessage?: string | null;
|
|
82
|
+
cancelText?: string | null;
|
|
83
|
+
appsWhiteList?: string[] | null;
|
|
84
|
+
appTitles?: Record<string, string>;
|
|
85
|
+
naverCallerName?: string;
|
|
86
|
+
directionsMode?: 'car' | 'walk' | 'public-transport' | 'bike' | undefined;
|
|
87
|
+
}
|
|
88
|
+
export interface GetAppsProps extends ShowLocationProps {
|
|
89
|
+
alwaysIncludeGoogle?: boolean;
|
|
90
|
+
appsWhiteList?: string[] | null;
|
|
91
|
+
naverCallerName?: string;
|
|
92
|
+
}
|
package/lib/type.js
ADDED
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const getAvailableApps: (prefixes: Record<string, string>) => Promise<string[]>;
|
|
2
|
+
export declare const isAppInstalled: (app: string, prefixes: Record<string, string>) => Promise<boolean>;
|
|
3
|
+
export declare const isSupportedApp: (app: string) => boolean;
|
|
4
|
+
export declare const getNotSupportedApps: (apps: string[]) => string[];
|
|
5
|
+
export declare const checkNotSupportedApps: (apps: string[]) => void;
|
|
6
|
+
export declare const askAppChoice: ({ dialogTitle, dialogMessage, cancelText, appsWhiteList, prefixes, appTitles, }: {
|
|
7
|
+
dialogTitle: string | null | undefined;
|
|
8
|
+
dialogMessage: string | null | undefined;
|
|
9
|
+
cancelText: string | null | undefined;
|
|
10
|
+
appsWhiteList: string[] | null | undefined;
|
|
11
|
+
prefixes: Record<string, string>;
|
|
12
|
+
appTitles: Record<string, string> | null | undefined;
|
|
13
|
+
}) => Promise<string | null>;
|
|
14
|
+
export declare const getDirectionsModeAppleMaps: (directionsMode: 'car' | 'walk' | 'public-transport' | 'bike' | undefined) => string | undefined;
|
|
15
|
+
export declare const getDirectionsModeGoogleMaps: (directionsMode: 'car' | 'walk' | 'public-transport' | 'bike' | undefined) => string | undefined;
|
|
16
|
+
export declare const checkOptions: ({ latitude, longitude, googleForceLatLon, googlePlaceId, title, app, prefixes, appTitles, appsWhiteList, }: {
|
|
17
|
+
latitude: number | string;
|
|
18
|
+
longitude: number | string;
|
|
19
|
+
googleForceLatLon?: boolean | null | undefined;
|
|
20
|
+
googlePlaceId?: number | string | null | undefined;
|
|
21
|
+
title?: string | null | undefined;
|
|
22
|
+
app?: string | null | undefined;
|
|
23
|
+
appTitles: Record<string, string> | null | undefined;
|
|
24
|
+
prefixes: Record<string, string>;
|
|
25
|
+
appsWhiteList: string[] | null | undefined;
|
|
26
|
+
}) => void;
|
|
27
|
+
export declare const generateMapUrl: ({ app, directionsMode, appleIgnoreLatLon, googleForceLatLon, googlePlaceId, naverCallerName, lat, lng, latlng, sourceLat, sourceLng, sourceLatLng, title, encodedTitle, prefixes, useSourceDestiny, }: {
|
|
28
|
+
app: string | null;
|
|
29
|
+
directionsMode: 'car' | 'walk' | 'public-transport' | 'bike' | undefined;
|
|
30
|
+
appleIgnoreLatLon?: boolean | undefined;
|
|
31
|
+
googleForceLatLon?: boolean | undefined;
|
|
32
|
+
googlePlaceId: string | number | null | undefined;
|
|
33
|
+
naverCallerName: string | null | undefined;
|
|
34
|
+
lat: number;
|
|
35
|
+
lng: number;
|
|
36
|
+
latlng: string;
|
|
37
|
+
sourceLat?: number | undefined;
|
|
38
|
+
sourceLng?: number | undefined;
|
|
39
|
+
sourceLatLng?: string | undefined;
|
|
40
|
+
title?: string | null | undefined;
|
|
41
|
+
encodedTitle?: string | undefined;
|
|
42
|
+
prefixes: Record<string, string>;
|
|
43
|
+
useSourceDestiny: boolean;
|
|
44
|
+
}) => string;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMapUrl = exports.checkOptions = exports.getDirectionsModeGoogleMaps = exports.getDirectionsModeAppleMaps = exports.askAppChoice = exports.checkNotSupportedApps = exports.getNotSupportedApps = exports.isSupportedApp = exports.isAppInstalled = exports.getAvailableApps = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
const getAvailableApps = async (prefixes) => {
|
|
7
|
+
const availableApps = [];
|
|
8
|
+
await Promise.all(Object.entries(prefixes).map(async ([app, _]) => {
|
|
9
|
+
try {
|
|
10
|
+
const isInstalled = await (0, exports.isAppInstalled)(app, prefixes);
|
|
11
|
+
if (isInstalled) {
|
|
12
|
+
availableApps.push(app);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
console.error(`Error checking if ${app} is installed:`, error);
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
19
|
+
return availableApps;
|
|
20
|
+
};
|
|
21
|
+
exports.getAvailableApps = getAvailableApps;
|
|
22
|
+
const isAppInstalled = (app, prefixes) => {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
if (!(app in prefixes)) {
|
|
25
|
+
return resolve(false);
|
|
26
|
+
}
|
|
27
|
+
react_native_1.Linking.canOpenURL(prefixes[app])
|
|
28
|
+
.then((result) => {
|
|
29
|
+
resolve(!!result);
|
|
30
|
+
})
|
|
31
|
+
.catch(() => resolve(false));
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
exports.isAppInstalled = isAppInstalled;
|
|
35
|
+
const isSupportedApp = (app) => {
|
|
36
|
+
return constants_1.appKeys.includes(app);
|
|
37
|
+
};
|
|
38
|
+
exports.isSupportedApp = isSupportedApp;
|
|
39
|
+
const getNotSupportedApps = (apps) => {
|
|
40
|
+
return apps.filter((app) => !(0, exports.isSupportedApp)(app));
|
|
41
|
+
};
|
|
42
|
+
exports.getNotSupportedApps = getNotSupportedApps;
|
|
43
|
+
const checkNotSupportedApps = (apps) => {
|
|
44
|
+
const notSupportedApps = (0, exports.getNotSupportedApps)(apps);
|
|
45
|
+
if (notSupportedApps.length) {
|
|
46
|
+
throw new MapsException(`appsWhiteList [${notSupportedApps}] are not supported apps, please provide some of the supported apps [${constants_1.appKeys}]`);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.checkNotSupportedApps = checkNotSupportedApps;
|
|
50
|
+
const askAppChoice = ({ dialogTitle, dialogMessage, cancelText, appsWhiteList, prefixes, appTitles, }) => {
|
|
51
|
+
return new Promise(async (resolve) => {
|
|
52
|
+
let availableApps = await (0, exports.getAvailableApps)(prefixes);
|
|
53
|
+
if (appsWhiteList && appsWhiteList.length) {
|
|
54
|
+
availableApps = availableApps.filter((appName) => appsWhiteList.includes(appName));
|
|
55
|
+
}
|
|
56
|
+
if (availableApps.length < 2) {
|
|
57
|
+
return resolve(availableApps[0] || null);
|
|
58
|
+
}
|
|
59
|
+
if (constants_1.isIOS) {
|
|
60
|
+
const options = availableApps.map((app) => appTitles?.[app]);
|
|
61
|
+
options?.push(cancelText || '');
|
|
62
|
+
react_native_1.ActionSheetIOS.showActionSheetWithOptions({
|
|
63
|
+
title: dialogTitle || '',
|
|
64
|
+
message: dialogMessage || '',
|
|
65
|
+
options: options || [],
|
|
66
|
+
cancelButtonIndex: options ? options.length - 1 : 0,
|
|
67
|
+
}, (buttonIndex) => {
|
|
68
|
+
if (buttonIndex === options.length - 1) {
|
|
69
|
+
return resolve(null);
|
|
70
|
+
}
|
|
71
|
+
return resolve(availableApps[buttonIndex]);
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const options = availableApps.map((app) => ({
|
|
76
|
+
text: appTitles?.[app] || '',
|
|
77
|
+
onPress: () => resolve(app),
|
|
78
|
+
}));
|
|
79
|
+
options.unshift({
|
|
80
|
+
text: cancelText || '',
|
|
81
|
+
onPress: () => resolve(null),
|
|
82
|
+
});
|
|
83
|
+
return react_native_1.Alert.alert(dialogTitle || '', dialogMessage || '', options, {
|
|
84
|
+
cancelable: true,
|
|
85
|
+
onDismiss: () => resolve(null),
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
exports.askAppChoice = askAppChoice;
|
|
90
|
+
const getDirectionsModeAppleMaps = (directionsMode) => {
|
|
91
|
+
const modeMap = {
|
|
92
|
+
car: 'd',
|
|
93
|
+
bike: 'b',
|
|
94
|
+
walk: 'w',
|
|
95
|
+
'public-transport': 'r',
|
|
96
|
+
};
|
|
97
|
+
return modeMap[directionsMode || ''] || undefined;
|
|
98
|
+
};
|
|
99
|
+
exports.getDirectionsModeAppleMaps = getDirectionsModeAppleMaps;
|
|
100
|
+
const getDirectionsModeGoogleMaps = (directionsMode) => {
|
|
101
|
+
const modeMap = {
|
|
102
|
+
car: 'driving',
|
|
103
|
+
walk: 'walking',
|
|
104
|
+
'public-transport': 'transit',
|
|
105
|
+
bike: 'bicycling',
|
|
106
|
+
};
|
|
107
|
+
return modeMap[directionsMode || ''] || undefined;
|
|
108
|
+
};
|
|
109
|
+
exports.getDirectionsModeGoogleMaps = getDirectionsModeGoogleMaps;
|
|
110
|
+
const checkOptions = ({ latitude, longitude, googleForceLatLon, googlePlaceId, title, app, prefixes, appTitles, appsWhiteList, }) => {
|
|
111
|
+
if (!latitude || !longitude) {
|
|
112
|
+
throw new MapsException('`showLocation` should contain keys `latitude` and `longitude`.');
|
|
113
|
+
}
|
|
114
|
+
if (title && typeof title !== 'string') {
|
|
115
|
+
throw new MapsException('`title` should be of type `string`.');
|
|
116
|
+
}
|
|
117
|
+
if (googleForceLatLon && typeof googleForceLatLon !== 'boolean') {
|
|
118
|
+
throw new MapsException('Option `googleForceLatLon` should be of type `boolean`.');
|
|
119
|
+
}
|
|
120
|
+
if (googlePlaceId && typeof googlePlaceId !== 'string') {
|
|
121
|
+
throw new MapsException('Option `googlePlaceId` should be of type `string`.');
|
|
122
|
+
}
|
|
123
|
+
if (app && !(app in prefixes)) {
|
|
124
|
+
throw new MapsException('Option `app` should be undefined, null, or one of the following: "' +
|
|
125
|
+
Object.keys(prefixes).join('", "') +
|
|
126
|
+
'".');
|
|
127
|
+
}
|
|
128
|
+
if (appsWhiteList && appsWhiteList.length) {
|
|
129
|
+
(0, exports.checkNotSupportedApps)(appsWhiteList);
|
|
130
|
+
}
|
|
131
|
+
if (appTitles && typeof appTitles !== 'object') {
|
|
132
|
+
throw new MapsException('Option `appTitles` should be of type `object`.');
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
exports.checkOptions = checkOptions;
|
|
136
|
+
const generateMapUrl = ({ app, directionsMode, appleIgnoreLatLon, googleForceLatLon, googlePlaceId, naverCallerName, lat, lng, latlng, sourceLat, sourceLng, sourceLatLng, title, encodedTitle, prefixes, useSourceDestiny, }) => {
|
|
137
|
+
let url = '';
|
|
138
|
+
switch (app) {
|
|
139
|
+
case 'apple-maps':
|
|
140
|
+
const appleDirectionMode = (0, exports.getDirectionsModeAppleMaps)(directionsMode);
|
|
141
|
+
url = prefixes['apple-maps'];
|
|
142
|
+
if (useSourceDestiny || directionsMode) {
|
|
143
|
+
url = `${url}?daddr=${latlng}`;
|
|
144
|
+
url += sourceLatLng ? `&saddr=${sourceLatLng}` : '';
|
|
145
|
+
}
|
|
146
|
+
else if (!appleIgnoreLatLon) {
|
|
147
|
+
url = `${url}?ll=${latlng}`;
|
|
148
|
+
}
|
|
149
|
+
url +=
|
|
150
|
+
useSourceDestiny || directionsMode || !appleIgnoreLatLon ? '&' : '?';
|
|
151
|
+
url += `q=${title ? encodedTitle : 'Location'}`;
|
|
152
|
+
url += appleDirectionMode ? `&dirflg=${appleDirectionMode}` : '';
|
|
153
|
+
break;
|
|
154
|
+
case 'google-maps':
|
|
155
|
+
const googleDirectionMode = (0, exports.getDirectionsModeGoogleMaps)(directionsMode);
|
|
156
|
+
// Always using universal URL instead of URI scheme since the latter doesn't support all parameters (#155)
|
|
157
|
+
if (useSourceDestiny || directionsMode) {
|
|
158
|
+
// Use "dir" as this will open up directions
|
|
159
|
+
url = 'https://www.google.com/maps/dir/?api=1';
|
|
160
|
+
url += sourceLatLng ? `&origin=${sourceLatLng}` : '';
|
|
161
|
+
if (!googleForceLatLon && title) {
|
|
162
|
+
url += `&destination=${encodedTitle}`;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
url += `&destination=${latlng}`;
|
|
166
|
+
}
|
|
167
|
+
url += googlePlaceId ? `&destination_place_id=${googlePlaceId}` : '';
|
|
168
|
+
url += googleDirectionMode ? `&travelmode=${googleDirectionMode}` : '';
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Use "search" as this will open up a single marker
|
|
172
|
+
url = 'https://www.google.com/maps/search/?api=1';
|
|
173
|
+
if (!googleForceLatLon && title) {
|
|
174
|
+
url += `&query=${encodedTitle}`;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
url += `&query=${latlng}`;
|
|
178
|
+
}
|
|
179
|
+
url += googlePlaceId ? `&query_place_id=${googlePlaceId}` : '';
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
case 'citymapper':
|
|
183
|
+
url = `${prefixes.citymapper}directions?endcoord=${latlng}`;
|
|
184
|
+
if (title) {
|
|
185
|
+
url += `&endname=${encodedTitle}`;
|
|
186
|
+
}
|
|
187
|
+
if (useSourceDestiny) {
|
|
188
|
+
url += `&startcoord=${sourceLatLng}`;
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case 'uber':
|
|
192
|
+
url = `${prefixes.uber}?action=setPickup&dropoff[latitude]=${lat}&dropoff[longitude]=${lng}`;
|
|
193
|
+
if (title) {
|
|
194
|
+
url += `&dropoff[nickname]=${encodedTitle}`;
|
|
195
|
+
}
|
|
196
|
+
url += useSourceDestiny
|
|
197
|
+
? `&pickup[latitude]=${sourceLat}&pickup[longitude]=${sourceLng}`
|
|
198
|
+
: '&pickup=my_location';
|
|
199
|
+
break;
|
|
200
|
+
case 'lyft':
|
|
201
|
+
url = `${prefixes.lyft}ridetype?id=lyft&destination[latitude]=${lat}&destination[longitude]=${lng}`;
|
|
202
|
+
if (useSourceDestiny) {
|
|
203
|
+
url += `&pickup[latitude]=${sourceLat}&pickup[longitude]=${sourceLng}`;
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
case 'transit':
|
|
207
|
+
url = `${prefixes.transit}directions?to=${latlng}`;
|
|
208
|
+
if (useSourceDestiny) {
|
|
209
|
+
url += `&from=${sourceLatLng}`;
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
case 'truckmap':
|
|
213
|
+
url = `https://truckmap.com/place/${lat},${lng}`;
|
|
214
|
+
if (useSourceDestiny) {
|
|
215
|
+
url = `https://truckmap.com/route/${sourceLat},${sourceLng}/${lat},${lng}`;
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
case 'waze':
|
|
219
|
+
url = `${prefixes.waze}?ll=${latlng}&navigate=yes`;
|
|
220
|
+
if (title) {
|
|
221
|
+
url += `&q=${encodedTitle}`;
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
case 'yandex':
|
|
225
|
+
url = `${prefixes.yandex}build_route_on_map?lat_to=${lat}&lon_to=${lng}`;
|
|
226
|
+
if (useSourceDestiny) {
|
|
227
|
+
url += `&lat_from=${sourceLat}&lon_from=${sourceLng}`;
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
230
|
+
case 'moovit':
|
|
231
|
+
url = `${prefixes.moovit}?dest_lat=${lat}&dest_lon=${lng}`;
|
|
232
|
+
if (title) {
|
|
233
|
+
url += `&dest_name=${encodedTitle}`;
|
|
234
|
+
}
|
|
235
|
+
if (useSourceDestiny) {
|
|
236
|
+
url += `&orig_lat=${sourceLat}&orig_lon=${sourceLng}`;
|
|
237
|
+
}
|
|
238
|
+
break;
|
|
239
|
+
case 'yandex-taxi':
|
|
240
|
+
url = `${prefixes['yandex-taxi']}route?end-lat=${lat}&end-lon=${lng}&appmetrica_tracking_id=1178268795219780156`;
|
|
241
|
+
break;
|
|
242
|
+
case 'yandex-maps':
|
|
243
|
+
url = `${prefixes['yandex-maps']}?pt=${lng},${lat}`;
|
|
244
|
+
break;
|
|
245
|
+
case 'kakaomap':
|
|
246
|
+
url = `${prefixes.kakaomap}look?p=${latlng}`;
|
|
247
|
+
if (useSourceDestiny) {
|
|
248
|
+
url = `${prefixes.kakaomap}route?sp=${sourceLat},${sourceLng}&ep=${latlng}&by=CAR`;
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
case 'tmap':
|
|
252
|
+
url = `${prefixes.tmap}viewmap?x=${lng}&y=${lat}`;
|
|
253
|
+
if (useSourceDestiny) {
|
|
254
|
+
url = `${prefixes.tmap}route?startx=${sourceLng}&starty=${sourceLat}&goalx=${lng}&goaly=${lat}`;
|
|
255
|
+
}
|
|
256
|
+
break;
|
|
257
|
+
case 'mapycz':
|
|
258
|
+
url = `${prefixes.mapycz}www.mapy.cz/zakladni?x=${lng}&y=${lat}&source=coor&id=${lng},${lat}`;
|
|
259
|
+
break;
|
|
260
|
+
case 'maps-me':
|
|
261
|
+
url = `${prefixes['maps-me']}route?sll=${sourceLat},${sourceLng}&saddr= &dll=${lat},${lng}&daddr=${title}&type=vehicle`;
|
|
262
|
+
break;
|
|
263
|
+
case 'osmand':
|
|
264
|
+
url = constants_1.isIOS
|
|
265
|
+
? `${prefixes.osmand}?lat=${lat}&lon=${lng}`
|
|
266
|
+
: `${prefixes.osmand}?q=${lat},${lng}`;
|
|
267
|
+
break;
|
|
268
|
+
case 'gett':
|
|
269
|
+
url = `${prefixes.gett}order?pickup=my_location&dropoff_latitude=${lat}&dropoff_longitude=${lng}`;
|
|
270
|
+
break;
|
|
271
|
+
case 'navermap':
|
|
272
|
+
url = `${prefixes.navermap}map?lat=${lat}&lng=${lng}&appname=${naverCallerName}`;
|
|
273
|
+
if (useSourceDestiny) {
|
|
274
|
+
url = `${prefixes.navermap}route?slat=${sourceLat}&slng=${sourceLng}&dlat=${lat}&dlng=${lng}&appname=${naverCallerName}`;
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
case 'dgis':
|
|
278
|
+
url = `${prefixes.dgis}routeSearch/to/${lng},${lat}/go`;
|
|
279
|
+
if (useSourceDestiny) {
|
|
280
|
+
url = `${prefixes.dgis}routeSearch/to/${lng},${lat}/from/${sourceLng},${sourceLat}/go`;
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
case 'liftago':
|
|
284
|
+
url = `${prefixes.liftago}order?destinationLat=${lat}&destinationLon=${lng}`;
|
|
285
|
+
if (title) {
|
|
286
|
+
url += `&destinationName=${encodedTitle}`;
|
|
287
|
+
}
|
|
288
|
+
if (useSourceDestiny) {
|
|
289
|
+
url += `&pickupLat=${sourceLat}&pickupLon=${sourceLng}`;
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
case 'petalmaps':
|
|
293
|
+
url = `${prefixes.petalmaps}navigation?daddr=${lat},${lng}`;
|
|
294
|
+
if (useSourceDestiny) {
|
|
295
|
+
url += `&saddr=${sourceLat},${sourceLng}`;
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
return url;
|
|
300
|
+
};
|
|
301
|
+
exports.generateMapUrl = generateMapUrl;
|
|
302
|
+
class MapsException extends Error {
|
|
303
|
+
constructor(message) {
|
|
304
|
+
super(message);
|
|
305
|
+
this.name = 'MapsException';
|
|
306
|
+
}
|
|
307
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-map-link",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Open the map app of the user's choice with a specific location",
|
|
5
|
-
"
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Open the map app of the user's choice with a specific location.",
|
|
5
|
+
"source": "src/index",
|
|
6
|
+
"main": "lib/index.js",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
8
9
|
"url": "git+https://github.com/includable/react-native-map-link.git"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
12
|
+
"build": "tsc --project tsconfig.build.json",
|
|
11
13
|
"lint": "eslint src --max-warnings=0 && eslint tests --max-warnings=0",
|
|
12
|
-
"
|
|
14
|
+
"release": "semantic-release",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"tscheck": "tsc --noEmit"
|
|
13
17
|
},
|
|
14
18
|
"keywords": [
|
|
15
19
|
"react-native",
|
|
@@ -27,31 +31,59 @@
|
|
|
27
31
|
"url": "https://github.com/includable/react-native-map-link/issues"
|
|
28
32
|
},
|
|
29
33
|
"homepage": "https://github.com/includable/react-native-map-link#readme",
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"prop-types": "^15.8.1",
|
|
32
|
-
"react-native-modal": "^13.0.1"
|
|
33
|
-
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": ">=16.8.0",
|
|
36
36
|
"react-native": ">=0.40.0"
|
|
37
37
|
},
|
|
38
|
+
"files": [
|
|
39
|
+
"lib"
|
|
40
|
+
],
|
|
38
41
|
"devDependencies": {
|
|
39
|
-
"@babel/core": "^7.
|
|
40
|
-
"@babel/eslint-parser": "^7.
|
|
41
|
-
"@babel/eslint-plugin": "^7.
|
|
42
|
-
"@babel/runtime": "^7.
|
|
43
|
-
"@react-native-community/eslint-config": "^3.0
|
|
44
|
-
"
|
|
45
|
-
"
|
|
42
|
+
"@babel/core": "^7.23.9",
|
|
43
|
+
"@babel/eslint-parser": "^7.23.10",
|
|
44
|
+
"@babel/eslint-plugin": "^7.23.5",
|
|
45
|
+
"@babel/runtime": "^7.23.9",
|
|
46
|
+
"@react-native-community/eslint-config": "^3.2.0",
|
|
47
|
+
"@types/jest": "^29.5.12",
|
|
48
|
+
"@types/react": "^18.2.55",
|
|
49
|
+
"@types/react-native": "^0.73.0",
|
|
50
|
+
"@types/react-test-renderer": "^18.0.7",
|
|
51
|
+
"@typescript-eslint/eslint-plugin": "^7.0.1",
|
|
52
|
+
"@typescript-eslint/parser": "^7.0.1",
|
|
53
|
+
"babel-jest": "^29.7.0",
|
|
54
|
+
"clsx": "^2.1.0",
|
|
55
|
+
"eslint": "^8.56.0",
|
|
46
56
|
"eslint-plugin-flowtype": "^8.0.3",
|
|
47
|
-
"jest": "^27.
|
|
48
|
-
"
|
|
49
|
-
"
|
|
57
|
+
"eslint-plugin-jest": "^27.6.3",
|
|
58
|
+
"eslint-plugin-prettier": "5.0.0",
|
|
59
|
+
"jest": "^29.7.0",
|
|
60
|
+
"metro-react-native-babel-preset": "^0.77.0",
|
|
61
|
+
"prettier": "^3.2.5",
|
|
62
|
+
"react-native": "^0.73.4",
|
|
63
|
+
"react-native-typescript-transformer": "^1.2.13",
|
|
64
|
+
"semantic-release": "^23.0.2",
|
|
65
|
+
"ts-jest": "^29.1.2",
|
|
66
|
+
"typescript": "^5.3.3"
|
|
50
67
|
},
|
|
51
68
|
"jest": {
|
|
52
69
|
"preset": "react-native",
|
|
70
|
+
"moduleFileExtensions": [
|
|
71
|
+
"ts",
|
|
72
|
+
"tsx",
|
|
73
|
+
"js"
|
|
74
|
+
],
|
|
75
|
+
"transform": {
|
|
76
|
+
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
|
|
77
|
+
"\\.(ts|tsx)$": "ts-jest"
|
|
78
|
+
},
|
|
53
79
|
"setupFiles": [
|
|
54
|
-
"./tests/setup.
|
|
55
|
-
]
|
|
80
|
+
"./tests/setup.ts"
|
|
81
|
+
],
|
|
82
|
+
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
|
|
83
|
+
"testPathIgnorePatterns": [
|
|
84
|
+
"\\.snap$",
|
|
85
|
+
"<rootDir>/node_modules/"
|
|
86
|
+
],
|
|
87
|
+
"cacheDirectory": ".jest/cache"
|
|
56
88
|
}
|
|
57
89
|
}
|
package/index.d.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
ViewStyle,
|
|
4
|
-
StyleProp,
|
|
5
|
-
ImageStyle,
|
|
6
|
-
TextStyle,
|
|
7
|
-
ImageSourcePropType,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
|
|
10
|
-
/** id for map application. this is the id that is passed to the `app` option */
|
|
11
|
-
export type MapId =
|
|
12
|
-
| 'apple-maps'
|
|
13
|
-
| 'google-maps'
|
|
14
|
-
| 'citymapper'
|
|
15
|
-
| 'uber'
|
|
16
|
-
| 'lyft'
|
|
17
|
-
| 'transit'
|
|
18
|
-
| 'truckmap'
|
|
19
|
-
| 'waze'
|
|
20
|
-
| 'yandex'
|
|
21
|
-
| 'moovit'
|
|
22
|
-
| 'yandex-maps'
|
|
23
|
-
| 'yandex-taxi'
|
|
24
|
-
| 'kakaomap'
|
|
25
|
-
| 'tmap'
|
|
26
|
-
| 'mapycz'
|
|
27
|
-
| 'maps-me'
|
|
28
|
-
| 'osmand'
|
|
29
|
-
| 'gett'
|
|
30
|
-
| 'navermap'
|
|
31
|
-
| 'dgis'
|
|
32
|
-
| 'liftago'
|
|
33
|
-
| 'petalmaps';
|
|
34
|
-
|
|
35
|
-
/** options shared across different types */
|
|
36
|
-
interface SharedOptions {
|
|
37
|
-
/** optionally you can set which apps to show (default: will show all supported apps installed on device) */
|
|
38
|
-
appsWhiteList?: MapId[];
|
|
39
|
-
/** custom titles to display for each app instead of using default titles. */
|
|
40
|
-
appTitles?: Partial<Record<MapId, string>>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface Options extends SharedOptions {
|
|
44
|
-
latitude: number | string;
|
|
45
|
-
longitude: number | string;
|
|
46
|
-
/** optionally specify starting location for directions */
|
|
47
|
-
sourceLatitude?: number;
|
|
48
|
-
/** not optional if `sourceLatitude` is specified */
|
|
49
|
-
sourceLongitude?: number;
|
|
50
|
-
/** optional, true will always add Google Maps to iOS and open in Safari, even if app is not installed (default: false) */
|
|
51
|
-
alwaysIncludeGoogle?: boolean;
|
|
52
|
-
googleForceLatLon?: boolean;
|
|
53
|
-
appleIgnoreLatLon?: boolean;
|
|
54
|
-
googlePlaceId?: string;
|
|
55
|
-
title?: string;
|
|
56
|
-
/** optionally specify specific app to use */
|
|
57
|
-
app?: MapId;
|
|
58
|
-
/** optional (default: 'Open in Maps') */
|
|
59
|
-
dialogTitle?: string;
|
|
60
|
-
/** optional (default: 'What app would you like to use?') */
|
|
61
|
-
dialogMessage?: string;
|
|
62
|
-
cancelText?: string;
|
|
63
|
-
/** to link into Naver Map You should provide your appname which is the bundle ID in iOS and applicationId in android. */
|
|
64
|
-
naverCallerName?: string;
|
|
65
|
-
directionsMode?: 'car' | 'walk' | 'public-transport' | 'bike';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
interface PopupStyleProp {
|
|
69
|
-
container?: StyleProp<ViewStyle>;
|
|
70
|
-
itemContainer?: StyleProp<ViewStyle>;
|
|
71
|
-
image?: StyleProp<ImageStyle>;
|
|
72
|
-
itemText?: StyleProp<TextStyle>;
|
|
73
|
-
headerContainer?: StyleProp<ViewStyle>;
|
|
74
|
-
titleText?: StyleProp<TextStyle>;
|
|
75
|
-
subtitleText?: StyleProp<TextStyle>;
|
|
76
|
-
cancelButtonContainer?: StyleProp<ViewStyle>;
|
|
77
|
-
cancelButtonText?: StyleProp<TextStyle>;
|
|
78
|
-
separatorStyle?: StyleProp<ViewStyle>;
|
|
79
|
-
activityIndicatorContainer?: StyleProp<ViewStyle>;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
interface PopupProps extends SharedOptions {
|
|
83
|
-
isVisible: boolean;
|
|
84
|
-
showHeader?: boolean;
|
|
85
|
-
customHeader?: React.ReactNode;
|
|
86
|
-
customFooter?: React.ReactNode;
|
|
87
|
-
onCancelPressed: () => void;
|
|
88
|
-
onBackButtonPressed: () => void;
|
|
89
|
-
onAppPressed: (appName: MapId) => void;
|
|
90
|
-
style?: PopupStyleProp;
|
|
91
|
-
modalProps?: object;
|
|
92
|
-
options: Options;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Link users to their desired map app.
|
|
97
|
-
*
|
|
98
|
-
* If an `app` option is passed, it will directly link to that map app,
|
|
99
|
-
* else it will prompt user to select map app.
|
|
100
|
-
*
|
|
101
|
-
* Prompts via `ActionSheetIOS` on iOS & `Alert.alert` on Android.
|
|
102
|
-
*
|
|
103
|
-
* If these prompts don't meet your UI use case, checkout the `Popup` component,
|
|
104
|
-
* or use the `getApps` function to build a custom UI.
|
|
105
|
-
*/
|
|
106
|
-
export function showLocation(
|
|
107
|
-
options: Options,
|
|
108
|
-
): Promise<string | undefined | null>;
|
|
109
|
-
|
|
110
|
-
export type GetAppResult = {
|
|
111
|
-
id: MapId;
|
|
112
|
-
name: string;
|
|
113
|
-
icon: ImageSourcePropType;
|
|
114
|
-
/** function to link user to map app */
|
|
115
|
-
open: () => Promise<void>;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Get array of map apps on users device.
|
|
120
|
-
*
|
|
121
|
-
* Useful for building custom UIs.
|
|
122
|
-
*/
|
|
123
|
-
export function getApps(options: Options): Promise<GetAppResult[]>;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* A styled popup component that displays icons in the app list
|
|
127
|
-
*/
|
|
128
|
-
export class Popup extends React.Component<PopupProps> {}
|