@symbiote-native/location 0.1.2 → 0.1.3

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 (68) hide show
  1. package/README.md +60 -32
  2. package/build/angular/index.d.ts +1 -0
  3. package/build/angular/index.js +3 -3
  4. package/build/angular/services/location-permissions.service.d.ts +12 -0
  5. package/build/angular/services/location-permissions.service.js +104 -0
  6. package/build/core/geolocation-polyfill.d.ts +2 -0
  7. package/build/core/geolocation-polyfill.js +52 -0
  8. package/build/core/index.d.ts +1 -0
  9. package/build/core/index.js +1 -0
  10. package/build/core/location-permission-api.d.ts +13 -0
  11. package/build/core/location-permission-api.js +15 -0
  12. package/build/core/location.d.ts +0 -3
  13. package/build/core/location.js +1 -13
  14. package/build/core/native-module.d.ts +1 -0
  15. package/build/react/index.d.ts +2 -0
  16. package/build/react/index.js +2 -0
  17. package/build/react/use-location-permissions.d.ts +11 -0
  18. package/build/react/use-location-permissions.js +6 -0
  19. package/build/solid/index.d.ts +2 -0
  20. package/build/solid/index.js +2 -0
  21. package/build/solid/use-location-permissions.d.ts +12 -0
  22. package/build/solid/use-location-permissions.js +6 -0
  23. package/build/svelte/index.d.ts +2 -0
  24. package/build/svelte/index.js +2 -0
  25. package/build/svelte/use-location-permissions.svelte.d.ts +11 -0
  26. package/build/svelte/use-location-permissions.svelte.js +6 -0
  27. package/build/vue/index.d.ts +2 -0
  28. package/build/vue/index.js +2 -0
  29. package/build/vue/use-location-permissions.d.ts +12 -0
  30. package/build/vue/use-location-permissions.js +6 -0
  31. package/build-ngc/angular/index.d.ts +1 -0
  32. package/build-ngc/angular/index.js +3 -3
  33. package/build-ngc/angular/index.js.map +1 -1
  34. package/build-ngc/angular/services/location-permissions.service.d.ts +19 -0
  35. package/build-ngc/angular/services/location-permissions.service.js +39 -0
  36. package/build-ngc/angular/services/location-permissions.service.js.map +1 -0
  37. package/build-ngc/core/geolocation-polyfill.d.ts +2 -0
  38. package/build-ngc/core/geolocation-polyfill.js +53 -0
  39. package/build-ngc/core/geolocation-polyfill.js.map +1 -0
  40. package/build-ngc/core/index.d.ts +1 -0
  41. package/build-ngc/core/index.js +1 -0
  42. package/build-ngc/core/index.js.map +1 -1
  43. package/build-ngc/core/location-permission-api.d.ts +13 -0
  44. package/build-ngc/core/location-permission-api.js +16 -0
  45. package/build-ngc/core/location-permission-api.js.map +1 -0
  46. package/build-ngc/core/location.d.ts +0 -3
  47. package/build-ngc/core/location.js +1 -13
  48. package/build-ngc/core/location.js.map +1 -1
  49. package/build-ngc/core/native-module.d.ts +1 -0
  50. package/build-ngc/core/native-module.js.map +1 -1
  51. package/package.json +23 -23
  52. package/src/angular/index.ts +7 -3
  53. package/src/angular/services/location-permissions.service.ts +40 -0
  54. package/src/core/geolocation-polyfill.ts +82 -0
  55. package/src/core/index.ts +1 -0
  56. package/src/core/location-permission-api.ts +26 -0
  57. package/src/core/location.ts +1 -16
  58. package/src/core/native-module.ts +1 -0
  59. package/src/react/index.ts +6 -0
  60. package/src/react/use-location-permissions.ts +25 -0
  61. package/src/solid/index.ts +6 -0
  62. package/src/solid/use-location-permissions.ts +26 -0
  63. package/src/svelte/index.ts +6 -0
  64. package/src/svelte/svelte-ambient.d.ts +3 -0
  65. package/src/svelte/svelte-compile.test-helper.ts +7 -0
  66. package/src/svelte/use-location-permissions.svelte.ts +25 -0
  67. package/src/vue/index.ts +6 -0
  68. package/src/vue/use-location-permissions.ts +26 -0
package/README.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # @symbiote-native/location
2
2
 
3
- A wrapper package for [SymbioteNative](../../README.md) that makes
4
- [`expo-location`](https://github.com/expo/expo/tree/main/packages/expo-location) usable from
5
- **every** adapter — React, Vue, Svelte, Solid, and Angular. Every export is a plain async
6
- function or a `usePermissions`-style hook built by `expo-modules-core`'s `createPermissionHook`,
7
- so there is no adapter-specific state to wrap: the React, Vue, Svelte, Solid, and Angular entry
8
- points are plain re-exports of the same `core`.
3
+ Find out where the user is, which way they face and whether they are walking, turn an address into
4
+ coordinates and back, and keep tracking in the background or watch for entering a region. One API
5
+ for every [SymbioteNative](../../README.md) adapter (React, Vue, Svelte, Solid and Angular).
9
6
 
10
- Foreground position, heading, geocoding, and motion activity, plus background location updates
11
- and geofencing — registered as tasks through [`@symbiote-native/task-manager`](../task-manager).
7
+ It wraps [`expo-location`](https://github.com/expo/expo/tree/main/packages/expo-location).
8
+ Functions and streams live in a shared `core`; the three permission hooks
9
+ (`useForegroundPermissions`, `useBackgroundPermissions`, `useMotionActivityPermissions`) are
10
+ per-adapter over the shared `createPermissionHook` factory, and Angular gets one
11
+ `*PermissionsService` each. Background updates and geofencing register as tasks through
12
+ [`@symbiote-native/task-manager`](../task-manager).
12
13
 
13
14
  ## Install
14
15
 
@@ -24,36 +25,36 @@ npx @symbiote-native/cli new my-app --location
24
25
  npx @symbiote-native/cli add --location
25
26
  ```
26
27
 
27
- Either way: installs `@symbiote-native/location`, wires the native autolinking automatically, and — since
28
- this package has an optional, policy-sensitive Android bundle — asks at the end whether to grant
28
+ Either way: installs `@symbiote-native/location`, wires the native autolinking automatically, and - since
29
+ this package has an optional, policy-sensitive Android bundle - asks at the end whether to grant
29
30
  background location too (see the note below the manual-install block). See
30
31
  [`@symbiote-native/cli`](../cli).
31
32
 
32
33
  <details>
33
- <summary>Manual install (no CLI — installing and wiring native autolinking by hand)</summary>
34
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
34
35
 
35
36
  ```bash
36
37
  npm install @symbiote-native/location
37
38
  ```
38
39
 
39
40
  `expo-location` and `expo-modules-core` come along as regular dependencies, pinned to exact
40
- versions — never install them yourself, and never add the `expo` meta-package to your project.
41
+ versions - never install them yourself, and never add the `expo` meta-package to your project.
41
42
 
42
43
  ## Required one-time step: native autolinking wiring
43
44
 
44
- Same one-time step as every other `expo-modules-core` package this project ships — see
45
+ Same one-time step as every other `expo-modules-core` package this project ships - see
45
46
  [`@symbiote-native/local-auth`'s README](../local-auth/README.md#required-one-time-step-native-autolinking-wiring)
46
47
  and the `symbiote-expo-native-module` project skill.
47
48
 
48
49
  `native-link.json` declares four iOS `Info.plist` usage-description keys
49
50
  (`NSLocationAlwaysAndWhenInUseUsageDescription`, `NSLocationAlwaysUsageDescription`,
50
- `NSLocationWhenInUseUsageDescription`, `NSMotionUsageDescription`) with generic default text —
51
+ `NSLocationWhenInUseUsageDescription`, `NSMotionUsageDescription`) with generic default text -
51
52
  override any of them by setting the same key yourself before or after install
52
53
  (`@symbiote-native/expo-modules-link`'s patcher is additive-only). Android's two base permissions
53
54
  (`ACCESS_COARSE_LOCATION`/`ACCESS_FINE_LOCATION`) already ship in `expo-location`'s own
54
55
  `AndroidManifest.xml` and merge automatically.
55
56
 
56
- `native-link.json` also declares `ios.infoPlistArrayKeys.UIBackgroundModes: ["location"]` —
57
+ `native-link.json` also declares `ios.infoPlistArrayKeys.UIBackgroundModes: ["location"]` -
57
58
  upstream's own `withLocation.ts` config plugin always adds it, since without it iOS silently
58
59
  stops delivering `startLocationUpdatesAsync` updates once the app backgrounds. Wired
59
60
  automatically by the same postinstall step (see `@symbiote-native/expo-modules-link`), merged
@@ -61,9 +62,9 @@ into the same array `@symbiote-native/audio`/`@symbiote-native/task-manager` may
61
62
 
62
63
  </details>
63
64
 
64
- **Background location — opt-in, asked for you.** `ACCESS_BACKGROUND_LOCATION`,
65
+ **Background location - opt-in, asked for you.** `ACCESS_BACKGROUND_LOCATION`,
65
66
  `FOREGROUND_SERVICE`, `FOREGROUND_SERVICE_LOCATION`, and `ACTIVITY_RECOGNITION` (+ its Play
66
- Services counterpart) are Android permissions opt-in by default, matching upstream — requesting
67
+ Services counterpart) are Android permissions opt-in by default, matching upstream - requesting
67
68
  background location triggers Play Console policy review, so it's a deliberate choice, never a
68
69
  package side effect. `new --location`/`add --location` above already ask, interactively, whether
69
70
  to grant them; say yes and the trio (minus `ACTIVITY_RECOGNITION`, still a hand-edit) lands in
@@ -74,19 +75,20 @@ option reminder. Said no, or ran non-interactively (CI, piped stdin)? Run it any
74
75
  npx @symbiote-native/cli grant location
75
76
  ```
76
77
 
77
- Idempotent — safe to run again even if already granted.
78
+ Idempotent - safe to run again even if already granted.
78
79
 
79
80
  ## Shape
80
81
 
81
82
  ```
82
- src/core/ location.ts (every function + the two useXPermissions hooks), subscribers.ts (the
83
- watchId-keyed event-subscriber machinery shared by position/heading/motion-activity
84
- watches), native-module.ts (requireNativeModule resolution), types.ts.
85
- src/angular/ @symbiote-native/location/angular — export * from '../core'
83
+ src/core/ location.ts (every function), subscribers.ts (the watchId-keyed event-subscriber
84
+ machinery shared by position/heading/motion-activity watches),
85
+ geolocation-polyfill.ts, location-permission-api.ts (get/request pairs the hooks
86
+ bind to), native-module.ts (requireNativeModule resolution), types.ts.
87
+ src/react|vue|solid|svelte/ use-location-permissions: the three permission hooks
88
+ src/angular/ location-permissions.service: Foreground/Background/MotionActivityPermissionsService
86
89
  ```
87
90
 
88
- `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto
89
- `src/core/`. `./angular` stays a physical file/subpath since Angular ships through a separate
91
+ Each adapter subpath re-exports `core` plus its own hooks. `./angular` ships through a separate
90
92
  `ngc`/AOT build (`build-ngc/`).
91
93
 
92
94
  ## Use it
@@ -112,7 +114,7 @@ if (granted) {
112
114
  ```
113
115
 
114
116
  Background updates and geofencing register a task defined with
115
- [`@symbiote-native/task-manager`](../task-manager)'s `defineTask` — the task itself must be
117
+ [`@symbiote-native/task-manager`](../task-manager)'s `defineTask` - the task itself must be
116
118
  defined at module scope, since native can relaunch the JS bundle headlessly to run it:
117
119
 
118
120
  ```ts
@@ -140,8 +142,10 @@ if (granted) {
140
142
  }
141
143
  ```
142
144
 
143
- Identical import surface on every adapter — `@symbiote-native/location/react`, `/vue`, `/svelte`,
144
- `/solid`, `/angular` all re-export the same functions.
145
+ Identical function surface on every adapter: `@symbiote-native/location/react`, `/vue`, `/svelte`,
146
+ `/solid`, `/angular`. The permission hooks return the adapter's own reactive box (React tuple,
147
+ Vue `Ref`, Solid `Accessor`, Svelte rune object); on Angular inject the matching service and call
148
+ `connect()` for a signal, `get()` / `request()` to refresh.
145
149
 
146
150
  ## API
147
151
 
@@ -156,12 +160,13 @@ watchHeadingAsync(callback, errorHandler?): Promise<ILocationSubscription>
156
160
  geocodeAsync(address: string): Promise<ILocationGeocodedLocation[]>
157
161
  reverseGeocodeAsync(location): Promise<ILocationGeocodedAddress[]>
158
162
  getForegroundPermissionsAsync() / requestForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>
159
- useForegroundPermissions(options?)
163
+ useForegroundPermissions(options?) // Angular: ForegroundPermissionsService
160
164
  getBackgroundPermissionsAsync() / requestBackgroundPermissionsAsync(): Promise<PermissionResponse>
161
165
  useBackgroundPermissions(options?)
162
166
  hasServicesEnabledAsync(): Promise<boolean>
163
167
  getMotionActivityPermissionsAsync() / requestMotionActivityPermissionsAsync(): Promise<PermissionResponse>
164
168
  useMotionActivityPermissions(options?)
169
+ installWebGeolocationPolyfill(): void // navigator.geolocation
165
170
  getMotionActivityAsync(): Promise<IMotionActivityObject>
166
171
  watchMotionActivityAsync(callback, errorHandler?): Promise<ILocationSubscription> // foreground only
167
172
  isBackgroundLocationAvailableAsync(): Promise<boolean>
@@ -175,19 +180,42 @@ with this repo's `I`-prefix convention for exported types (`ts-js-best-practices
175
180
 
176
181
  ## Notes
177
182
 
178
- - **Motion activity needs no location permission at all** — it reads Play Services activity
183
+ - **Motion activity needs no location permission at all** - it reads Play Services activity
179
184
  recognition / the iOS motion coprocessor directly, gated only by its own
180
185
  `getMotionActivityPermissionsAsync`/`requestMotionActivityPermissionsAsync`.
181
- - **`watchMotionActivityAsync` is foreground-only** — updates pause while the app is backgrounded
186
+ - **`watchMotionActivityAsync` is foreground-only** - updates pause while the app is backgrounded
182
187
  and resume when it returns, per upstream's own contract.
188
+ - **Ask foreground first, then background.** Background permission is a separate, stricter prompt.
189
+ - **Background tracking has hard limits.** It stops if the user terminates the app. On Android a
190
+ terminated app does not restart on a location or geofence event; on iOS the system relaunches it
191
+ for a new geofence event.
192
+ - **Emulators need a location set.** Android Emulator: Settings > Location > Use location (and turn
193
+ off Improve Location Accuracy). iOS Simulator: Features > Location, anything but None.
183
194
  - **No Expo Go warning.** Upstream logs a one-time console warning about background-location
184
195
  limits when running inside Expo Go; this project never runs under Expo Go
185
196
  (`<examples_vs_dot_examples>` in root CLAUDE.md), so the check and the warning are dropped
186
197
  rather than ported.
187
198
 
199
+ ## Common questions
200
+
201
+ - **`getCurrentPositionAsync` hangs on some Android devices.** Race it against your own timer, fall
202
+ back to `getLastKnownPositionAsync()`, and prefer `watchPositionAsync` for updates.
203
+ - **Stops updating in the background after minutes on Android.** Pass `foregroundService` to
204
+ `startLocationUpdatesAsync`.
205
+ - **Background permission denied right away.** Ask foreground first; after Allow Once, a background
206
+ request in the same session silently fails.
207
+ - **Accuracy and battery.** `Accuracy.Balanced` for most uses.
208
+ - **Killed app.** Background tracking stops when the user terminates the app.
209
+
210
+ Sources: [Expo docs: Location](https://docs.expo.dev/versions/latest/sdk/location/),
211
+ [expo/expo#33981](https://github.com/expo/expo/issues/33981),
212
+ [expo/expo#39851](https://github.com/expo/expo/issues/39851),
213
+ [expo/expo#26825](https://github.com/expo/expo/issues/26825),
214
+ [expo/expo#14076](https://github.com/expo/expo/issues/14076).
215
+
188
216
  ## Test it
189
217
 
190
- No Fabric/Descriptor angle at all — every function here is a pure async-function surface plus a
218
+ No Fabric/Descriptor angle at all - every function here is a pure async-function surface plus a
191
219
  handful of `watchId`-keyed event subscriptions, never a view or per-instance state. Tests inject a
192
220
  fake native-module object in place of the real `requireNativeModule` resolution and fire the wired
193
- listeners directly (`src/core/location.test.ts`) — no `installFabric()`, no ViewConfig.
221
+ listeners directly (`src/core/location.test.ts`) - no `installFabric()`, no ViewConfig.
@@ -1 +1,2 @@
1
1
  export * from '../core';
2
+ export { ForegroundPermissionsService, BackgroundPermissionsService, MotionActivityPermissionsService, } from './services/location-permissions.service';
@@ -1,4 +1,4 @@
1
- // @symbiote-native/location/angular: the Angular entry over the framework-agnostic core. Same
2
- // reasoning as the React/Vue entries — no per-instance state or event stream to wrap in a
3
- // service, so this is a plain re-export.
1
+ // @symbiote-native/location/angular: the core plus the permission services, the location
2
+ // streams need no service wrapper
4
3
  export * from '../core/index.js';
4
+ export { ForegroundPermissionsService, BackgroundPermissionsService, MotionActivityPermissionsService, } from './services/location-permissions.service.js';
@@ -0,0 +1,12 @@
1
+ import { PermissionsServiceBase } from '@symbiote-native/angular';
2
+ import type { ILocationPermissionResponse } from '../../core';
3
+ import type { PermissionResponse } from 'expo-modules-core';
4
+ export declare class ForegroundPermissionsService extends PermissionsServiceBase<ILocationPermissionResponse> {
5
+ constructor();
6
+ }
7
+ export declare class BackgroundPermissionsService extends PermissionsServiceBase<PermissionResponse> {
8
+ constructor();
9
+ }
10
+ export declare class MotionActivityPermissionsService extends PermissionsServiceBase<PermissionResponse> {
11
+ constructor();
12
+ }
@@ -0,0 +1,104 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { Injectable } from '@angular/core';
36
+ import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../../core/location-permission-api.js';
37
+ import { PermissionsServiceBase } from '@symbiote-native/angular';
38
+ // Angular twin of `../../react`'s location permission hooks
39
+ let ForegroundPermissionsService = (() => {
40
+ let _classDecorators = [Injectable({ providedIn: 'root' })];
41
+ let _classDescriptor;
42
+ let _classExtraInitializers = [];
43
+ let _classThis;
44
+ let _classSuper = PermissionsServiceBase;
45
+ var ForegroundPermissionsService = class extends _classSuper {
46
+ static { _classThis = this; }
47
+ static {
48
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
49
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
50
+ ForegroundPermissionsService = _classThis = _classDescriptor.value;
51
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
52
+ __runInitializers(_classThis, _classExtraInitializers);
53
+ }
54
+ constructor() {
55
+ super(foregroundPermissionMethods.getMethod, foregroundPermissionMethods.requestMethod);
56
+ }
57
+ };
58
+ return ForegroundPermissionsService = _classThis;
59
+ })();
60
+ export { ForegroundPermissionsService };
61
+ let BackgroundPermissionsService = (() => {
62
+ let _classDecorators = [Injectable({ providedIn: 'root' })];
63
+ let _classDescriptor;
64
+ let _classExtraInitializers = [];
65
+ let _classThis;
66
+ let _classSuper = PermissionsServiceBase;
67
+ var BackgroundPermissionsService = class extends _classSuper {
68
+ static { _classThis = this; }
69
+ static {
70
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
71
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
72
+ BackgroundPermissionsService = _classThis = _classDescriptor.value;
73
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
74
+ __runInitializers(_classThis, _classExtraInitializers);
75
+ }
76
+ constructor() {
77
+ super(backgroundPermissionMethods.getMethod, backgroundPermissionMethods.requestMethod);
78
+ }
79
+ };
80
+ return BackgroundPermissionsService = _classThis;
81
+ })();
82
+ export { BackgroundPermissionsService };
83
+ let MotionActivityPermissionsService = (() => {
84
+ let _classDecorators = [Injectable({ providedIn: 'root' })];
85
+ let _classDescriptor;
86
+ let _classExtraInitializers = [];
87
+ let _classThis;
88
+ let _classSuper = PermissionsServiceBase;
89
+ var MotionActivityPermissionsService = class extends _classSuper {
90
+ static { _classThis = this; }
91
+ static {
92
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
93
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
94
+ MotionActivityPermissionsService = _classThis = _classDescriptor.value;
95
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
96
+ __runInitializers(_classThis, _classExtraInitializers);
97
+ }
98
+ constructor() {
99
+ super(motionActivityPermissionMethods.getMethod, motionActivityPermissionMethods.requestMethod);
100
+ }
101
+ };
102
+ return MotionActivityPermissionsService = _classThis;
103
+ })();
104
+ export { MotionActivityPermissionsService };
@@ -0,0 +1,2 @@
1
+ /** Polyfills `navigator.geolocation` for interop with the React Native and Web geolocation API. */
2
+ export declare function installWebGeolocationPolyfill(): void;
@@ -0,0 +1,52 @@
1
+ import { Platform } from 'expo-modules-core';
2
+ import { expoLocation } from './native-module.js';
3
+ import { locationSubscriber } from './subscribers.js';
4
+ import { LocationAccuracy } from './types.js';
5
+ function convertGeolocationOptions(options) {
6
+ return {
7
+ accuracy: options.enableHighAccuracy
8
+ ? LocationAccuracy.High
9
+ : LocationAccuracy.Balanced,
10
+ };
11
+ }
12
+ async function requestCurrentPosition(success, error, options) {
13
+ try {
14
+ await expoLocation.requestPermissionsAsync();
15
+ success(await expoLocation.getCurrentPositionAsync(convertGeolocationOptions(options)));
16
+ }
17
+ catch (cause) {
18
+ error(cause);
19
+ }
20
+ }
21
+ // Returns undefined like the web API, the async work runs detached and reports through `error`
22
+ function getCurrentPosition(success, error = () => { }, options = {}) {
23
+ void requestCurrentPosition(success, error, options);
24
+ }
25
+ function watchPosition(success, error = () => { }, options = {}) {
26
+ const watchId = locationSubscriber.registerCallback(success);
27
+ expoLocation
28
+ .watchPositionImplAsync(watchId, convertGeolocationOptions(options))
29
+ .catch((cause) => {
30
+ locationSubscriber.unregisterCallback(watchId);
31
+ error({ watchId, message: cause.message, code: cause.code });
32
+ });
33
+ return watchId;
34
+ }
35
+ function clearWatch(watchId) {
36
+ locationSubscriber.unregisterCallback(watchId);
37
+ }
38
+ /** Polyfills `navigator.geolocation` for interop with the React Native and Web geolocation API. */
39
+ export function installWebGeolocationPolyfill() {
40
+ if (Platform.OS === 'web')
41
+ return;
42
+ if (!Reflect.has(globalThis, 'window'))
43
+ Reflect.set(globalThis, 'window', globalThis);
44
+ const windowObject = Reflect.get(globalThis, 'window');
45
+ if (!Reflect.has(windowObject, 'navigator'))
46
+ Reflect.set(windowObject, 'navigator', {});
47
+ Reflect.set(Reflect.get(windowObject, 'navigator'), 'geolocation', {
48
+ getCurrentPosition,
49
+ watchPosition,
50
+ clearWatch,
51
+ });
52
+ }
@@ -1,5 +1,6 @@
1
1
  export { PermissionStatus, type PermissionHookOptions, type PermissionExpiration, } from 'expo-modules-core';
2
2
  export { getCurrentWatchId } from './subscribers';
3
+ export { installWebGeolocationPolyfill } from './geolocation-polyfill';
3
4
  export * from './location';
4
5
  export * from './types';
5
6
  export { LocationAccuracy as Accuracy, LocationActivityType as ActivityType, LocationGeofencingEventType as GeofencingEventType, LocationGeofencingRegionState as GeofencingRegionState, } from './types';
@@ -1,5 +1,6 @@
1
1
  export { PermissionStatus, } from 'expo-modules-core';
2
2
  export { getCurrentWatchId } from './subscribers.js';
3
+ export { installWebGeolocationPolyfill } from './geolocation-polyfill.js';
3
4
  export * from './location.js';
4
5
  export * from './types.js';
5
6
  export { LocationAccuracy as Accuracy, LocationActivityType as ActivityType, LocationGeofencingEventType as GeofencingEventType, LocationGeofencingRegionState as GeofencingRegionState, } from './types.js';
@@ -0,0 +1,13 @@
1
+ import { getBackgroundPermissionsAsync, getForegroundPermissionsAsync, getMotionActivityPermissionsAsync, requestBackgroundPermissionsAsync, requestForegroundPermissionsAsync, requestMotionActivityPermissionsAsync } from './location';
2
+ export declare const foregroundPermissionMethods: {
3
+ getMethod: typeof getForegroundPermissionsAsync;
4
+ requestMethod: typeof requestForegroundPermissionsAsync;
5
+ };
6
+ export declare const backgroundPermissionMethods: {
7
+ getMethod: typeof getBackgroundPermissionsAsync;
8
+ requestMethod: typeof requestBackgroundPermissionsAsync;
9
+ };
10
+ export declare const motionActivityPermissionMethods: {
11
+ getMethod: typeof getMotionActivityPermissionsAsync;
12
+ requestMethod: typeof requestMotionActivityPermissionsAsync;
13
+ };
@@ -0,0 +1,15 @@
1
+ // `methods` every adapter's location permission hooks bind to the shared
2
+ // `@symbiote-native/{react,vue,solid,svelte}` `createPermissionHook` factory
3
+ import { getBackgroundPermissionsAsync, getForegroundPermissionsAsync, getMotionActivityPermissionsAsync, requestBackgroundPermissionsAsync, requestForegroundPermissionsAsync, requestMotionActivityPermissionsAsync, } from './location.js';
4
+ export const foregroundPermissionMethods = {
5
+ getMethod: getForegroundPermissionsAsync,
6
+ requestMethod: requestForegroundPermissionsAsync,
7
+ };
8
+ export const backgroundPermissionMethods = {
9
+ getMethod: getBackgroundPermissionsAsync,
10
+ requestMethod: requestBackgroundPermissionsAsync,
11
+ };
12
+ export const motionActivityPermissionMethods = {
13
+ getMethod: getMotionActivityPermissionsAsync,
14
+ requestMethod: requestMotionActivityPermissionsAsync,
15
+ };
@@ -12,14 +12,11 @@ export declare function geocodeAsync(address: string): Promise<ILocationGeocoded
12
12
  export declare function reverseGeocodeAsync(location: Pick<ILocationGeocodedLocation, 'latitude' | 'longitude'>): Promise<ILocationGeocodedAddress[]>;
13
13
  export declare function getForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>;
14
14
  export declare function requestForegroundPermissionsAsync(): Promise<ILocationPermissionResponse>;
15
- export declare const useForegroundPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [ILocationPermissionResponse | null, () => Promise<ILocationPermissionResponse>, () => Promise<ILocationPermissionResponse>];
16
15
  export declare function getBackgroundPermissionsAsync(): Promise<PermissionResponse>;
17
16
  export declare function requestBackgroundPermissionsAsync(): Promise<PermissionResponse>;
18
- export declare const useBackgroundPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [PermissionResponse | null, () => Promise<PermissionResponse>, () => Promise<PermissionResponse>];
19
17
  export declare function hasServicesEnabledAsync(): Promise<boolean>;
20
18
  export declare function getMotionActivityPermissionsAsync(): Promise<PermissionResponse>;
21
19
  export declare function requestMotionActivityPermissionsAsync(): Promise<PermissionResponse>;
22
- export declare const useMotionActivityPermissions: (options?: import("expo-modules-core").PermissionHookOptions<object> | undefined) => [PermissionResponse | null, () => Promise<PermissionResponse>, () => Promise<PermissionResponse>];
23
20
  /** No location permission required — uses Play Services activity recognition / the iOS motion
24
21
  * coprocessor directly. */
25
22
  export declare function getMotionActivityAsync(): Promise<IMotionActivityObject>;
@@ -1,4 +1,4 @@
1
- import { createPermissionHook, Platform } from 'expo-modules-core';
1
+ import { Platform } from 'expo-modules-core';
2
2
  import { expoLocation } from './native-module.js';
3
3
  import { headingSubscriber, locationErrorSubscriber, locationSubscriber, motionActivitySubscriber, } from './subscribers.js';
4
4
  import { LocationAccuracy } from './types.js';
@@ -85,20 +85,12 @@ export async function getForegroundPermissionsAsync() {
85
85
  export async function requestForegroundPermissionsAsync() {
86
86
  return expoLocation.requestForegroundPermissionsAsync();
87
87
  }
88
- export const useForegroundPermissions = createPermissionHook({
89
- getMethod: getForegroundPermissionsAsync,
90
- requestMethod: requestForegroundPermissionsAsync,
91
- });
92
88
  export async function getBackgroundPermissionsAsync() {
93
89
  return expoLocation.getBackgroundPermissionsAsync();
94
90
  }
95
91
  export async function requestBackgroundPermissionsAsync() {
96
92
  return expoLocation.requestBackgroundPermissionsAsync();
97
93
  }
98
- export const useBackgroundPermissions = createPermissionHook({
99
- getMethod: getBackgroundPermissionsAsync,
100
- requestMethod: requestBackgroundPermissionsAsync,
101
- });
102
94
  export async function hasServicesEnabledAsync() {
103
95
  return expoLocation.hasServicesEnabledAsync();
104
96
  }
@@ -108,10 +100,6 @@ export async function getMotionActivityPermissionsAsync() {
108
100
  export async function requestMotionActivityPermissionsAsync() {
109
101
  return expoLocation.requestMotionActivityPermissionsAsync();
110
102
  }
111
- export const useMotionActivityPermissions = createPermissionHook({
112
- getMethod: getMotionActivityPermissionsAsync,
113
- requestMethod: requestMotionActivityPermissionsAsync,
114
- });
115
103
  /** No location permission required — uses Play Services activity recognition / the iOS motion
116
104
  * coprocessor directly. */
117
105
  export async function getMotionActivityAsync() {
@@ -4,6 +4,7 @@ export type INativeLocationModule = {
4
4
  addListener(eventName: string, listener: (event: unknown) => void): EventSubscription;
5
5
  getProviderStatusAsync(): Promise<ILocationProviderStatus>;
6
6
  enableNetworkProviderAsync(): Promise<void>;
7
+ requestPermissionsAsync(): Promise<void>;
7
8
  getCurrentPositionAsync(options: ILocationOptions): Promise<ILocationObject>;
8
9
  getLastKnownPositionAsync(options: ILocationLastKnownOptions): Promise<ILocationObject | null>;
9
10
  watchPositionImplAsync(watchId: number, options: ILocationOptions): Promise<void>;
@@ -0,0 +1,2 @@
1
+ export * from '../core';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions';
@@ -0,0 +1,2 @@
1
+ export * from '../core/index.js';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions.js';
@@ -0,0 +1,11 @@
1
+ import type { ILocationPermissionResponse } from '../core';
2
+ import type { IPermissionHookBehavior } from '@symbiote-native/engine';
3
+ import type { PermissionResponse } from 'expo-modules-core';
4
+ export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
5
+ TPermission | null,
6
+ () => Promise<TPermission>,
7
+ () => Promise<TPermission>
8
+ ];
9
+ export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
10
+ export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
11
+ export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
@@ -0,0 +1,6 @@
1
+ import { createPermissionHook } from '@symbiote-native/react';
2
+ import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
3
+ // React twin of `expo-location`'s permission hooks
4
+ export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
5
+ export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
6
+ export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
@@ -0,0 +1,2 @@
1
+ export * from '../core';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions';
@@ -0,0 +1,2 @@
1
+ export * from '../core/index.js';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions.js';
@@ -0,0 +1,12 @@
1
+ import type { ILocationPermissionResponse } from '../core';
2
+ import type { IPermissionHookBehavior } from '@symbiote-native/engine';
3
+ import type { PermissionResponse } from 'expo-modules-core';
4
+ import type { Accessor } from 'solid-js';
5
+ export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
6
+ Accessor<TPermission | null>,
7
+ () => Promise<TPermission>,
8
+ () => Promise<TPermission>
9
+ ];
10
+ export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
11
+ export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
12
+ export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
@@ -0,0 +1,6 @@
1
+ import { createPermissionHook } from '@symbiote-native/solid';
2
+ import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
3
+ // Solid twin of `../react`'s location permission hooks
4
+ export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
5
+ export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
6
+ export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
@@ -0,0 +1,2 @@
1
+ export * from '../core';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions.svelte';
@@ -0,0 +1,2 @@
1
+ export * from '../core/index.js';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions.svelte';
@@ -0,0 +1,11 @@
1
+ import type { ILocationPermissionResponse } from '../core';
2
+ import type { IPermissionHookBehavior } from '@symbiote-native/engine';
3
+ import type { PermissionResponse } from 'expo-modules-core';
4
+ export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => {
5
+ readonly status: TPermission | null;
6
+ requestPermission: () => Promise<TPermission>;
7
+ getPermission: () => Promise<TPermission>;
8
+ };
9
+ export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
10
+ export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
11
+ export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
@@ -0,0 +1,6 @@
1
+ import { createPermissionHook } from '@symbiote-native/svelte/runes/create-permission-hook';
2
+ import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
3
+ // Svelte twin of `../react`'s location permission hooks
4
+ export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
5
+ export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
6
+ export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
@@ -0,0 +1,2 @@
1
+ export * from '../core';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions';
@@ -0,0 +1,2 @@
1
+ export * from '../core/index.js';
2
+ export { useForegroundPermissions, useBackgroundPermissions, useMotionActivityPermissions, } from './use-location-permissions.js';
@@ -0,0 +1,12 @@
1
+ import type { ILocationPermissionResponse } from '../core';
2
+ import type { IPermissionHookBehavior } from '@symbiote-native/engine';
3
+ import type { PermissionResponse } from 'expo-modules-core';
4
+ import type { Ref } from '@vue/runtime-core';
5
+ export type IUseLocationPermissionsHook<TPermission> = (options?: IPermissionHookBehavior) => [
6
+ Ref<TPermission | null>,
7
+ () => Promise<TPermission>,
8
+ () => Promise<TPermission>
9
+ ];
10
+ export declare const useForegroundPermissions: IUseLocationPermissionsHook<ILocationPermissionResponse>;
11
+ export declare const useBackgroundPermissions: IUseLocationPermissionsHook<PermissionResponse>;
12
+ export declare const useMotionActivityPermissions: IUseLocationPermissionsHook<PermissionResponse>;
@@ -0,0 +1,6 @@
1
+ import { createPermissionHook } from '@symbiote-native/vue';
2
+ import { backgroundPermissionMethods, foregroundPermissionMethods, motionActivityPermissionMethods, } from '../core/location-permission-api.js';
3
+ // Vue twin of `../react`'s location permission hooks
4
+ export const useForegroundPermissions = createPermissionHook(foregroundPermissionMethods);
5
+ export const useBackgroundPermissions = createPermissionHook(backgroundPermissionMethods);
6
+ export const useMotionActivityPermissions = createPermissionHook(motionActivityPermissionMethods);
@@ -1 +1,2 @@
1
1
  export * from '../core';
2
+ export { ForegroundPermissionsService, BackgroundPermissionsService, MotionActivityPermissionsService, } from './services/location-permissions.service';