@goway.to/maps 0.0.0-stage → 0.1.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +676 -0
  3. package/NOTICE +25 -0
  4. package/README.md +59 -2
  5. package/app.plugin.js +19 -0
  6. package/dist/CameraBinding.web.d.ts +24 -0
  7. package/dist/CameraBinding.web.js +46 -0
  8. package/dist/DefaultMapMarker.d.ts +8 -0
  9. package/dist/DefaultMapMarker.js +30 -0
  10. package/dist/GeoJSONSource.d.ts +2 -0
  11. package/dist/GeoJSONSource.js +17 -0
  12. package/dist/GeoJSONSource.web.d.ts +2 -0
  13. package/dist/GeoJSONSource.web.js +68 -0
  14. package/dist/InteractionBinding.web.d.ts +7 -0
  15. package/dist/InteractionBinding.web.js +35 -0
  16. package/dist/Layer.d.ts +2 -0
  17. package/dist/Layer.js +21 -0
  18. package/dist/Layer.web.d.ts +2 -0
  19. package/dist/Layer.web.js +46 -0
  20. package/dist/LayerStyle.web.d.ts +10 -0
  21. package/dist/LayerStyle.web.js +45 -0
  22. package/dist/LightBinding.web.d.ts +5 -0
  23. package/dist/LightBinding.web.js +19 -0
  24. package/dist/MapAttribution.d.ts +27 -0
  25. package/dist/MapAttribution.js +149 -0
  26. package/dist/MapBrand.d.ts +22 -0
  27. package/dist/MapBrand.js +91 -0
  28. package/dist/MapErrorState.d.ts +9 -0
  29. package/dist/MapErrorState.js +58 -0
  30. package/dist/MapPlugin.d.ts +6 -0
  31. package/dist/MapPlugin.js +3 -0
  32. package/dist/MapPlugin.web.d.ts +2 -0
  33. package/dist/MapPlugin.web.js +43 -0
  34. package/dist/MapView.d.ts +2 -0
  35. package/dist/MapView.js +420 -0
  36. package/dist/MapView.web.d.ts +5 -0
  37. package/dist/MapView.web.js +413 -0
  38. package/dist/Marker.d.ts +13 -0
  39. package/dist/Marker.js +11 -0
  40. package/dist/Marker.web.d.ts +15 -0
  41. package/dist/Marker.web.js +51 -0
  42. package/dist/Markers.d.ts +2 -0
  43. package/dist/Markers.js +13 -0
  44. package/dist/Markers.web.d.ts +2 -0
  45. package/dist/Markers.web.js +13 -0
  46. package/dist/PluginProps.web.d.ts +7 -0
  47. package/dist/PluginProps.web.js +19 -0
  48. package/dist/RasterDEMSource.d.ts +2 -0
  49. package/dist/RasterDEMSource.js +7 -0
  50. package/dist/RasterDEMSource.web.d.ts +2 -0
  51. package/dist/RasterDEMSource.web.js +44 -0
  52. package/dist/SourceData.web.d.ts +6 -0
  53. package/dist/SourceData.web.js +14 -0
  54. package/dist/UserLocation.d.ts +2 -0
  55. package/dist/UserLocation.js +19 -0
  56. package/dist/UserLocation.web.d.ts +2 -0
  57. package/dist/UserLocation.web.js +21 -0
  58. package/dist/brand/BrandedChrome.d.ts +47 -0
  59. package/dist/brand/BrandedChrome.js +51 -0
  60. package/dist/brand/GowayLogo.d.ts +28 -0
  61. package/dist/brand/GowayLogo.js +50 -0
  62. package/dist/brand/artwork.d.ts +130 -0
  63. package/dist/brand/artwork.js +176 -0
  64. package/dist/cameraReports.web.d.ts +50 -0
  65. package/dist/cameraReports.web.js +117 -0
  66. package/dist/cameraTarget.d.ts +14 -0
  67. package/dist/cameraTarget.js +8 -0
  68. package/dist/chromeLift.d.ts +15 -0
  69. package/dist/chromeLift.js +15 -0
  70. package/dist/clusters.d.ts +57 -0
  71. package/dist/clusters.js +102 -0
  72. package/dist/commands.web.d.ts +16 -0
  73. package/dist/commands.web.js +158 -0
  74. package/dist/compactCredit.d.ts +52 -0
  75. package/dist/compactCredit.js +40 -0
  76. package/dist/creditHeight.d.ts +3 -0
  77. package/dist/creditHeight.js +12 -0
  78. package/dist/creditLabels.d.ts +30 -0
  79. package/dist/creditLabels.js +30 -0
  80. package/dist/creditRise.d.ts +28 -0
  81. package/dist/creditRise.js +33 -0
  82. package/dist/dragAxes.web.d.ts +65 -0
  83. package/dist/dragAxes.web.js +70 -0
  84. package/dist/engineContext.web.d.ts +13 -0
  85. package/dist/engineContext.web.js +12 -0
  86. package/dist/index.d.ts +12 -0
  87. package/dist/index.js +12 -0
  88. package/dist/index.web.d.ts +13 -0
  89. package/dist/index.web.js +13 -0
  90. package/dist/labels.d.ts +202 -0
  91. package/dist/labels.js +451 -0
  92. package/dist/loadedCamera.d.ts +64 -0
  93. package/dist/loadedCamera.js +56 -0
  94. package/dist/locationStore.d.ts +16 -0
  95. package/dist/locationStore.js +132 -0
  96. package/dist/mapRef.d.ts +4 -0
  97. package/dist/mapRef.js +13 -0
  98. package/dist/moveMarkers.d.ts +27 -0
  99. package/dist/moveMarkers.js +22 -0
  100. package/dist/nativeCameraReports.d.ts +44 -0
  101. package/dist/nativeCameraReports.js +73 -0
  102. package/dist/plugin.d.ts +63 -0
  103. package/dist/plugin.js +2 -0
  104. package/dist/queryLayers.d.ts +19 -0
  105. package/dist/queryLayers.js +54 -0
  106. package/dist/shared-exports.d.ts +17 -0
  107. package/dist/shared-exports.js +13 -0
  108. package/dist/shared.d.ts +170 -0
  109. package/dist/shared.js +337 -0
  110. package/dist/sourceContext.d.ts +2 -0
  111. package/dist/sourceContext.js +9 -0
  112. package/dist/styleUrl.d.ts +19 -0
  113. package/dist/styleUrl.js +22 -0
  114. package/dist/testing.d.ts +41 -0
  115. package/dist/testing.js +80 -0
  116. package/dist/types.d.ts +348 -0
  117. package/dist/types.js +1 -0
  118. package/dist/useMarkerSlots.d.ts +6 -0
  119. package/dist/useMarkerSlots.js +56 -0
  120. package/dist/useUserLocation.d.ts +44 -0
  121. package/dist/useUserLocation.js +247 -0
  122. package/dist/zoom.d.ts +2 -0
  123. package/dist/zoom.js +10 -0
  124. package/metro.cjs +70 -0
  125. package/package.json +115 -4
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Contextual, non-persisted device location.
3
+ *
4
+ * Two statements this hook is the enforcement point for:
5
+ *
6
+ * 1. **Opening the map never asks.** Nothing here runs on mount. The
7
+ * permission is not even READ until the user invokes a location-dependent
8
+ * action, so there is no code path from "app cold-started" to a system
9
+ * prompt. `<UserLocation>` correspondingly draws the dot only against a
10
+ * permission already granted.
11
+ * 2. **The coordinate is transient.** It lives in React state for the life of
12
+ * the screen and is written to no store, no cache, no query key, no
13
+ * AsyncStorage and no backend table. There is deliberately no "last known
14
+ * location" to restore: a location history is exactly the artefact the rule
15
+ * forbids, and the cheapest way not to have one is not to have a writer.
16
+ *
17
+ * ## Failing usefully
18
+ *
19
+ * `locate()` resolves `null` for four DIFFERENT reasons, and the difference is
20
+ * the whole product: "you declined", "your browser will not even ask any more",
21
+ * "this page is not https" and "the device could not get a fix" need four
22
+ * different sentences and three different next steps. The reason is therefore
23
+ * part of the state (`error`), alongside whether asking again could plausibly
24
+ * prompt (`canAskAgain`) — a caller that shows a spinner and then nothing is
25
+ * the bug this hook exists to make impossible to write by accident.
26
+ *
27
+ * ## Web, where `expo-location` is not enough
28
+ *
29
+ * Two web behaviours are corrected here rather than reported as-is:
30
+ *
31
+ * - **A non-secure context.** `navigator.geolocation` EXISTS on an `http://`
32
+ * page; it just fails every call with `PERMISSION_DENIED` without ever
33
+ * prompting. Reported verbatim that is "the user declined", which is a lie
34
+ * about a person who was never asked — and it sends them to look for a
35
+ * permission they never set. `window.isSecureContext` is the reliable
36
+ * signal, and it is checked BEFORE anything touches the permission.
37
+ * - **A durable block.** `expo-location`'s web backend answers `canAskAgain:
38
+ * true` unconditionally, including for an origin the browser has blocked, so
39
+ * "ask again" silently resolves to the same denial forever. The Permissions
40
+ * API knows the truth, so it is consulted directly.
41
+ */
42
+ import { useCallback, useRef, useState } from 'react';
43
+ import { Platform } from 'react-native';
44
+ import * as Location from 'expo-location';
45
+ import { locationPermission } from './locationStore';
46
+ /** How long to wait for a fix before giving the user their UI back. */
47
+ const FIX_TIMEOUT_MS = 12_000;
48
+ const INITIAL = {
49
+ status: 'unknown',
50
+ coordinate: null,
51
+ isLocating: false,
52
+ error: null,
53
+ canAskAgain: true,
54
+ };
55
+ export function useUserLocation() {
56
+ const [state, setState] = useState(INITIAL);
57
+ // Coalesce concurrent taps onto one permission prompt + one fix.
58
+ const inFlight = useRef(null);
59
+ const locate = useCallback(async () => {
60
+ if (inFlight.current)
61
+ return inFlight.current;
62
+ const run = (async () => {
63
+ setState((prev) => ({ ...prev, isLocating: true, error: null }));
64
+ try {
65
+ // Before the permission, not after it: an http:// page never reaches a
66
+ // prompt, so attributing the failure to the user would be wrong AND
67
+ // would point them at a setting that is not the problem.
68
+ if (isInsecureWebContext()) {
69
+ setState({
70
+ status: 'unknown',
71
+ coordinate: null,
72
+ isLocating: false,
73
+ error: 'insecureContext',
74
+ canAskAgain: false,
75
+ });
76
+ return null;
77
+ }
78
+ // The browser's own record of this origin, which `expo-location` does
79
+ // not surface. `denied` here means no prompt will appear, whatever we
80
+ // call next.
81
+ if ((await webPermissionState()) === 'denied') {
82
+ locationPermission.settle('denied');
83
+ setState({
84
+ status: 'denied',
85
+ coordinate: null,
86
+ isLocating: false,
87
+ error: 'denied',
88
+ canAskAgain: false,
89
+ });
90
+ return null;
91
+ }
92
+ // Read first: `getForegroundPermissionsAsync` never prompts, so an
93
+ // already-granted user is not re-asked, and a previously-denied one is
94
+ // not re-prompted on every tap on platforms that would allow it.
95
+ let permission = await Location.getForegroundPermissionsAsync();
96
+ if (!permission.granted && permission.canAskAgain) {
97
+ permission = await Location.requestForegroundPermissionsAsync();
98
+ }
99
+ locationPermission.settle(permission.granted ? 'granted' : 'denied');
100
+ if (!permission.granted) {
101
+ setState({
102
+ status: 'denied',
103
+ coordinate: null,
104
+ isLocating: false,
105
+ error: 'denied',
106
+ canAskAgain: await canAskAgainAfterDenial(permission.canAskAgain),
107
+ });
108
+ return null;
109
+ }
110
+ const position = await withTimeout(Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.Balanced }), FIX_TIMEOUT_MS);
111
+ if (!position) {
112
+ setState((prev) => ({
113
+ ...prev,
114
+ status: 'granted',
115
+ isLocating: false,
116
+ error: 'timeout',
117
+ canAskAgain: true,
118
+ }));
119
+ return null;
120
+ }
121
+ const coordinate = {
122
+ latitude: position.coords.latitude,
123
+ longitude: position.coords.longitude,
124
+ };
125
+ setState({
126
+ status: 'granted',
127
+ coordinate,
128
+ isLocating: false,
129
+ error: null,
130
+ canAskAgain: true,
131
+ });
132
+ return coordinate;
133
+ }
134
+ catch (error) {
135
+ // Web rejects with a `GeolocationPositionError`, which still separates
136
+ // "you declined" from "the device has no position" from "it timed out".
137
+ // Collapsing all three into one sentence is how a user ends up told to
138
+ // check a permission that was never the problem.
139
+ const reason = reasonForThrown(error);
140
+ const canAskAgain = reason === 'denied' ? await canAskAgainAfterDenial(true) : true;
141
+ setState((prev) => ({
142
+ ...prev,
143
+ status: reason === 'denied' ? 'denied' : prev.status,
144
+ isLocating: false,
145
+ error: reason,
146
+ canAskAgain,
147
+ }));
148
+ return null;
149
+ }
150
+ finally {
151
+ inFlight.current = null;
152
+ }
153
+ })();
154
+ inFlight.current = run;
155
+ return run;
156
+ }, []);
157
+ const forget = useCallback(() => {
158
+ setState((prev) => ({ ...prev, coordinate: null, error: null }));
159
+ }, []);
160
+ return { ...state, locate, forget };
161
+ }
162
+ /**
163
+ * `true` on a web page the browser will not give geolocation to at all.
164
+ *
165
+ * Checked rather than inferred: the failure an insecure origin produces is
166
+ * indistinguishable, at the call site, from a user pressing "Block".
167
+ */
168
+ function isInsecureWebContext() {
169
+ if (Platform.OS !== 'web')
170
+ return false;
171
+ if (typeof window === 'undefined')
172
+ return false;
173
+ // `undefined` (an old browser that has no such property) is NOT a failure —
174
+ // only an explicit `false` is.
175
+ return window.isSecureContext === false;
176
+ }
177
+ /**
178
+ * The browser's durable answer for this origin, or `'unknown'` off web and
179
+ * wherever the Permissions API is absent (older Safari, some webviews).
180
+ *
181
+ * Deliberately never PROMPTS: `query()` is a read, which is what makes it safe
182
+ * to call on the way into a user-initiated action.
183
+ */
184
+ async function webPermissionState() {
185
+ if (Platform.OS !== 'web')
186
+ return 'unknown';
187
+ try {
188
+ const permissions = globalThis.navigator?.permissions;
189
+ if (!permissions?.query)
190
+ return 'unknown';
191
+ const status = await permissions.query({ name: 'geolocation' });
192
+ return status.state === 'granted' || status.state === 'denied' || status.state === 'prompt'
193
+ ? status.state
194
+ : 'unknown';
195
+ }
196
+ catch {
197
+ return 'unknown';
198
+ }
199
+ }
200
+ /**
201
+ * After a decline, whether a further tap could still reach a prompt.
202
+ *
203
+ * On native the platform's own `canAskAgain` is the answer. On web it is
204
+ * hard-coded `true` by `expo-location`, so the Permissions API is re-read: a
205
+ * decline the browser has turned into a block for this origin flips to `denied`
206
+ * immediately, and offering "Try again" for that would be offering a button
207
+ * that provably does nothing.
208
+ */
209
+ async function canAskAgainAfterDenial(platformAnswer) {
210
+ if (Platform.OS !== 'web')
211
+ return platformAnswer;
212
+ const state = await webPermissionState();
213
+ // `'unknown'` (no Permissions API) keeps the optimistic answer: a browser
214
+ // that cannot tell us should not have us telling the user it is hopeless.
215
+ return state !== 'denied';
216
+ }
217
+ /** A thrown geolocation failure, mapped onto the reason a user can act on. */
218
+ function reasonForThrown(error) {
219
+ const code = error?.code;
220
+ if (typeof code === 'number') {
221
+ // 1 PERMISSION_DENIED, 2 POSITION_UNAVAILABLE, 3 TIMEOUT — the W3C codes,
222
+ // written out because `GeolocationPositionError` is a web-only global and
223
+ // this module also runs on native.
224
+ if (code === 1)
225
+ return 'denied';
226
+ if (code === 3)
227
+ return 'timeout';
228
+ return 'unavailable';
229
+ }
230
+ return 'unavailable';
231
+ }
232
+ /** Resolve `null` instead of hanging forever on a device that never fixes. */
233
+ async function withTimeout(promise, ms) {
234
+ let timer;
235
+ try {
236
+ return await Promise.race([
237
+ promise,
238
+ new Promise((resolve) => {
239
+ timer = setTimeout(() => resolve(null), ms);
240
+ }),
241
+ ]);
242
+ }
243
+ finally {
244
+ if (timer)
245
+ clearTimeout(timer);
246
+ }
247
+ }
package/dist/zoom.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const ZoomLevelContext: import("react").Context<number>;
2
+ export declare function useZoomLevel(): number;
package/dist/zoom.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The map's whole zoom level, published to its children. `<Markers>` clusters
3
+ * by it; it changes only when the camera crosses a level, so a pan re-renders
4
+ * nothing.
5
+ */
6
+ import { createContext, useContext } from 'react';
7
+ export const ZoomLevelContext = createContext(0);
8
+ export function useZoomLevel() {
9
+ return useContext(ZoomLevelContext);
10
+ }
package/metro.cjs ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * `@goway.to/maps/metro` — what a Metro (Expo) web build needs for the map.
3
+ *
4
+ * const { withGoWayMaps } = require('@goway.to/maps/metro');
5
+ * module.exports = withGoWayMaps(getDefaultConfig(__dirname));
6
+ *
7
+ * maplibre-gl 6 is ESM-only and starts its tile worker BY URL, derived from
8
+ * `import.meta.url` — which inside a Metro bundle is not the package
9
+ * directory, so left alone the worker never starts and every tile request
10
+ * fails silently, with no build error and no failing test. `MapView` on the
11
+ * web points the worker at `/vendor/maplibre-gl/<version>/` on the page's own
12
+ * origin; this copies the INSTALLED maplibre-gl's worker modules there, into
13
+ * the app's `public/`, before Metro serves or exports it. Keyed on the
14
+ * version, so the worker can never be a different release from the main
15
+ * thread it talks to (their message protocol is internal and unversioned).
16
+ *
17
+ * `public/vendor/` is a verbatim copy of an installed dependency: gitignore it.
18
+ * Bundlers that understand `new URL(…, import.meta.url)` (Vite, webpack) do
19
+ * not need this.
20
+ */
21
+ const fs = require('node:fs');
22
+ const path = require('node:path');
23
+
24
+ /** Files the worker needs, relative to `maplibre-gl/dist/`. */
25
+ const WORKER_FILES = ['maplibre-gl-worker.mjs', 'maplibre-gl-shared.mjs'];
26
+
27
+ /**
28
+ * Write the installed maplibre-gl's worker modules to
29
+ * `<projectRoot>/public/vendor/maplibre-gl/<version>/` and return that
30
+ * directory.
31
+ */
32
+ function vendorMaplibreWorker(projectRoot) {
33
+ const packageJsonPath = require.resolve('maplibre-gl/package.json', { paths: [projectRoot] });
34
+ const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
35
+ const distDir = path.join(path.dirname(packageJsonPath), 'dist');
36
+ const vendorRoot = path.join(projectRoot, 'public', 'vendor', 'maplibre-gl');
37
+ const targetDir = path.join(vendorRoot, version);
38
+
39
+ fs.mkdirSync(targetDir, { recursive: true });
40
+ for (const file of WORKER_FILES) {
41
+ const source = path.join(distDir, file);
42
+ const target = path.join(targetDir, file);
43
+ const bytes = fs.readFileSync(source);
44
+ // Only on a real difference: Metro watches `public/`, and rewriting
45
+ // identical bytes on every start would churn the watcher.
46
+ if (!fs.existsSync(target) || !fs.readFileSync(target).equals(bytes)) {
47
+ fs.writeFileSync(target, bytes);
48
+ }
49
+ }
50
+
51
+ // Drop directories left by a previous version, so an old worker is never
52
+ // exported next to the new one.
53
+ for (const entry of fs.readdirSync(vendorRoot)) {
54
+ if (entry !== version)
55
+ fs.rmSync(path.join(vendorRoot, entry), { recursive: true, force: true });
56
+ }
57
+ return targetDir;
58
+ }
59
+
60
+ /**
61
+ * Copy the worker for this project, and return the Metro config unchanged.
62
+ * `projectRoot` defaults to the config's own.
63
+ */
64
+ function withGoWayMaps(config, options = {}) {
65
+ const projectRoot = options.projectRoot ?? config.projectRoot ?? process.cwd();
66
+ vendorMaplibreWorker(projectRoot);
67
+ return config;
68
+ }
69
+
70
+ module.exports = { withGoWayMaps, vendorMaplibreWorker, WORKER_FILES };
package/package.json CHANGED
@@ -1,6 +1,117 @@
1
1
  {
2
2
  "name": "@goway.to/maps",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "GoWay's maps SDK for React and React Native: one declarative map for web and native — GoWay styles that follow your theme, Bloom markers with clustering, a camera framed by value, user location without a prompt on mount.",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "author": "The Oxy Collective, Inc.",
7
+ "homepage": "https://github.com/OxyHQ/GoWay/tree/main/packages/maps#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/OxyHQ/GoWay.git",
11
+ "directory": "packages/maps"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/OxyHQ/GoWay/issues"
15
+ },
16
+ "keywords": [
17
+ "goway",
18
+ "oxy",
19
+ "maps",
20
+ "maplibre",
21
+ "react-native",
22
+ "expo",
23
+ "bloom"
24
+ ],
25
+ "sideEffects": [
26
+ "*.css",
27
+ "./dist/MapView.web.js"
28
+ ],
29
+ "main": "./dist/index.js",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "react-native": "./dist/index.js",
33
+ "browser": "./dist/index.web.js",
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "browser": "./dist/index.web.js",
38
+ "react-native": "./dist/index.js",
39
+ "default": "./dist/index.js"
40
+ },
41
+ "./brand": {
42
+ "types": "./dist/brand/artwork.d.ts",
43
+ "default": "./dist/brand/artwork.js"
44
+ },
45
+ "./plugin": {
46
+ "types": "./dist/plugin.d.ts",
47
+ "default": "./dist/plugin.js"
48
+ },
49
+ "./testing": {
50
+ "types": "./dist/testing.d.ts",
51
+ "default": "./dist/testing.js"
52
+ },
53
+ "./metro": "./metro.cjs",
54
+ "./app.plugin.js": "./app.plugin.js",
55
+ "./package.json": "./package.json"
56
+ },
57
+ "files": [
58
+ "dist",
59
+ "metro.cjs",
60
+ "app.plugin.js",
61
+ "README.md",
62
+ "CHANGELOG.md",
63
+ "LICENSE",
64
+ "NOTICE"
65
+ ],
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "scripts": {
70
+ "build": "node scripts/build.mjs",
71
+ "clean": "rm -rf dist",
72
+ "typecheck": "tsc -p tsconfig.json --noEmit",
73
+ "test": "bun test",
74
+ "prepublishOnly": "bun run typecheck && bun run test && bun run build"
75
+ },
76
+ "dependencies": {
77
+ "supercluster": "^8.0.1"
78
+ },
79
+ "peerDependencies": {
80
+ "@goway.to/sdk": ">=0.6.0",
81
+ "@maplibre/maplibre-react-native": ">=11.4.0",
82
+ "@oxy.so/bloom": ">=10.16.0",
83
+ "expo-location": "*",
84
+ "maplibre-gl": ">=6.10.0",
85
+ "react": ">=19.0.0",
86
+ "react-dom": ">=19.0.0",
87
+ "react-native": ">=0.80.0",
88
+ "react-native-reanimated": ">=4.0.0",
89
+ "react-native-svg": ">=15.0.0"
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "@maplibre/maplibre-react-native": {
93
+ "optional": true
94
+ },
95
+ "maplibre-gl": {
96
+ "optional": true
97
+ },
98
+ "react-dom": {
99
+ "optional": true
100
+ }
101
+ },
102
+ "devDependencies": {
103
+ "@goway.to/sdk": "0.6.0",
104
+ "@maplibre/maplibre-react-native": "^11.4.0",
105
+ "@oxy.so/bloom": "^10.16.1",
106
+ "@types/react": "^19.2.17",
107
+ "@types/supercluster": "^7.1.3",
108
+ "expo-location": "~57.0.19",
109
+ "maplibre-gl": "6.10.0",
110
+ "react": "19.2.3",
111
+ "react-dom": "19.2.3",
112
+ "react-native": "0.86.0",
113
+ "react-native-reanimated": "4.5.0",
114
+ "react-native-svg": "15.15.5",
115
+ "typescript": "^5.9.3"
116
+ }
117
+ }