@symbiote-native/sensors 0.2.0 → 0.3.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 (100) hide show
  1. package/README.md +5 -5
  2. package/build/angular/services/accelerometer.service/index.js +7 -12
  3. package/build/angular/services/barometer.service/index.js +7 -12
  4. package/build/angular/services/device-motion.service/index.js +7 -12
  5. package/build/angular/services/gyroscope.service/index.js +7 -12
  6. package/build/angular/services/light-sensor.service/index.js +7 -12
  7. package/build/angular/services/magnetometer-uncalibrated.service/index.js +8 -12
  8. package/build/angular/services/magnetometer.service/index.js +7 -12
  9. package/build/angular/services/pedometer.service/index.js +6 -10
  10. package/build/core/device-motion.js +3 -4
  11. package/build/svelte/index.d.ts +16 -0
  12. package/build/svelte/index.js +14 -0
  13. package/build/svelte/runes/use-accelerometer.svelte.d.ts +4 -0
  14. package/build/svelte/runes/use-accelerometer.svelte.js +31 -0
  15. package/build/svelte/runes/use-barometer.svelte.d.ts +4 -0
  16. package/build/svelte/runes/use-barometer.svelte.js +22 -0
  17. package/build/svelte/runes/use-device-motion.svelte.d.ts +4 -0
  18. package/build/svelte/runes/use-device-motion.svelte.js +22 -0
  19. package/build/svelte/runes/use-gyroscope.svelte.d.ts +4 -0
  20. package/build/svelte/runes/use-gyroscope.svelte.js +22 -0
  21. package/build/svelte/runes/use-light-sensor.svelte.d.ts +4 -0
  22. package/build/svelte/runes/use-light-sensor.svelte.js +22 -0
  23. package/build/svelte/runes/use-magnetometer-uncalibrated.svelte.d.ts +4 -0
  24. package/build/svelte/runes/use-magnetometer-uncalibrated.svelte.js +22 -0
  25. package/build/svelte/runes/use-magnetometer.svelte.d.ts +4 -0
  26. package/build/svelte/runes/use-magnetometer.svelte.js +22 -0
  27. package/build/svelte/runes/use-pedometer.svelte.d.ts +4 -0
  28. package/build/svelte/runes/use-pedometer.svelte.js +20 -0
  29. package/build-ngc/angular/services/accelerometer.service/index.js +10 -15
  30. package/build-ngc/angular/services/accelerometer.service/index.js.map +1 -1
  31. package/build-ngc/angular/services/barometer.service/index.js +10 -15
  32. package/build-ngc/angular/services/barometer.service/index.js.map +1 -1
  33. package/build-ngc/angular/services/device-motion.service/index.js +10 -15
  34. package/build-ngc/angular/services/device-motion.service/index.js.map +1 -1
  35. package/build-ngc/angular/services/gyroscope.service/index.js +10 -15
  36. package/build-ngc/angular/services/gyroscope.service/index.js.map +1 -1
  37. package/build-ngc/angular/services/light-sensor.service/index.js +10 -15
  38. package/build-ngc/angular/services/light-sensor.service/index.js.map +1 -1
  39. package/build-ngc/angular/services/magnetometer-uncalibrated.service/index.js +11 -15
  40. package/build-ngc/angular/services/magnetometer-uncalibrated.service/index.js.map +1 -1
  41. package/build-ngc/angular/services/magnetometer.service/index.js +10 -15
  42. package/build-ngc/angular/services/magnetometer.service/index.js.map +1 -1
  43. package/build-ngc/angular/services/pedometer.service/index.js +9 -13
  44. package/build-ngc/angular/services/pedometer.service/index.js.map +1 -1
  45. package/build-ngc/core/device-motion.js +3 -4
  46. package/build-ngc/core/device-motion.js.map +1 -1
  47. package/native-link.json +52 -0
  48. package/package.json +31 -13
  49. package/src/angular/services/accelerometer.service/index.ts +7 -12
  50. package/src/angular/services/barometer.service/index.ts +7 -12
  51. package/src/angular/services/device-motion.service/index.ts +7 -12
  52. package/src/angular/services/gyroscope.service/index.ts +7 -12
  53. package/src/angular/services/light-sensor.service/index.ts +7 -12
  54. package/src/angular/services/magnetometer-uncalibrated.service/index.ts +8 -12
  55. package/src/angular/services/magnetometer.service/index.ts +7 -12
  56. package/src/angular/services/pedometer.service/index.ts +6 -10
  57. package/src/core/device-motion.ts +3 -4
  58. package/src/svelte/index.ts +29 -0
  59. package/src/svelte/runes/use-accelerometer.svelte.ts +36 -0
  60. package/src/svelte/runes/use-barometer.svelte.ts +27 -0
  61. package/src/svelte/runes/use-device-motion.svelte.ts +27 -0
  62. package/src/svelte/runes/use-gyroscope.svelte.ts +27 -0
  63. package/src/svelte/runes/use-light-sensor.svelte.ts +27 -0
  64. package/src/svelte/runes/use-magnetometer-uncalibrated.svelte.ts +31 -0
  65. package/src/svelte/runes/use-magnetometer.svelte.ts +27 -0
  66. package/src/svelte/runes/use-pedometer.svelte.ts +23 -0
  67. package/src/svelte/svelte-ambient.d.ts +6 -0
  68. package/src/angular/services/accelerometer.service/accelerometer.service.test.ts +0 -118
  69. package/src/angular/services/barometer.service/barometer.service.test.ts +0 -122
  70. package/src/angular/services/device-motion.service/device-motion.service.test.ts +0 -125
  71. package/src/angular/services/gyroscope.service/gyroscope.service.test.ts +0 -118
  72. package/src/angular/services/light-sensor.service/light-sensor.service.test.ts +0 -118
  73. package/src/angular/services/magnetometer-uncalibrated.service/magnetometer-uncalibrated.service.test.ts +0 -123
  74. package/src/angular/services/magnetometer.service/magnetometer.service.test.ts +0 -118
  75. package/src/angular/services/pedometer.service/pedometer.service.test.ts +0 -86
  76. package/src/core/accelerometer.test.ts +0 -49
  77. package/src/core/barometer.test.ts +0 -46
  78. package/src/core/device-motion.test.ts +0 -60
  79. package/src/core/device-sensor.test.ts +0 -76
  80. package/src/core/gyroscope.test.ts +0 -46
  81. package/src/core/light-sensor.test.ts +0 -49
  82. package/src/core/magnetometer-uncalibrated.test.ts +0 -49
  83. package/src/core/magnetometer.test.ts +0 -49
  84. package/src/core/pedometer.test.ts +0 -118
  85. package/src/react/hooks/use-accelerometer/use-accelerometer.test.tsx +0 -81
  86. package/src/react/hooks/use-barometer/use-barometer.test.tsx +0 -83
  87. package/src/react/hooks/use-device-motion/use-device-motion.test.tsx +0 -88
  88. package/src/react/hooks/use-gyroscope/use-gyroscope.test.tsx +0 -79
  89. package/src/react/hooks/use-light-sensor/use-light-sensor.test.tsx +0 -79
  90. package/src/react/hooks/use-magnetometer/use-magnetometer.test.tsx +0 -81
  91. package/src/react/hooks/use-magnetometer-uncalibrated/use-magnetometer-uncalibrated.test.tsx +0 -88
  92. package/src/react/hooks/use-pedometer/use-pedometer.test.tsx +0 -69
  93. package/src/vue/composables/use-accelerometer/use-accelerometer.test.ts +0 -96
  94. package/src/vue/composables/use-barometer/use-barometer.test.ts +0 -100
  95. package/src/vue/composables/use-device-motion/use-device-motion.test.ts +0 -104
  96. package/src/vue/composables/use-gyroscope/use-gyroscope.test.ts +0 -96
  97. package/src/vue/composables/use-light-sensor/use-light-sensor.test.ts +0 -96
  98. package/src/vue/composables/use-magnetometer/use-magnetometer.test.ts +0 -96
  99. package/src/vue/composables/use-magnetometer-uncalibrated/use-magnetometer-uncalibrated.test.ts +0 -103
  100. package/src/vue/composables/use-pedometer/use-pedometer.test.ts +0 -77
package/README.md CHANGED
@@ -38,8 +38,8 @@ package with zero further changes:
38
38
 
39
39
  Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
40
40
  peer-dependency exclusion list, per-sensor permission strings — live in the
41
- `symbiote-expo-native-module` skill. Reference implementation: `.examples/react/ios/Podfile` and
42
- `.examples/react/android/app/src/main/java/com/canary/MainApplication.kt`.
41
+ `symbiote-expo-native-module` skill. Reference implementation: `examples/expo-react/ios/Podfile`
42
+ and `examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt`.
43
43
 
44
44
  Permissions ship with the native module itself — nothing to reimplement, just the platform
45
45
  permission string each sensor needs (e.g. DeviceMotion/Pedometer need `NSMotionUsageDescription`
@@ -99,9 +99,9 @@ export class SensorsScreen {
99
99
  }
100
100
  ```
101
101
 
102
- The React example above mirrors the real demo screen, `.examples/react/screens/SensorsScreen.tsx`
103
- — the Vue and Angular snippets are illustrative; those adapters' own demo screens aren't wired up
104
- yet (React is this repo's "prove the pattern first" adapter for this package).
102
+ All three examples above mirror the real canary demo screens —
103
+ `examples/expo-react/screens/SensorsScreen.tsx`, `examples/expo-vue-sfc/screens/SensorsScreen.vue`,
104
+ `examples/expo-vue-tsx/screens/SensorsScreen.tsx`, `examples/expo-angular/src/screens/SensorsScreen.ts`.
105
105
 
106
106
  Every hook/composable/`connect()` takes an optional `updateIntervalMs` and returns `null` until the
107
107
  first native reading arrives — check `isAvailableAsync()` separately if you need to distinguish
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { Accelerometer } from '../../../core/index.js';
37
- // Angular twin of React's `useAccelerometer` hook and Vue's `useAccelerometer` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useAccelerometer` hook / Vue's `useAccelerometer` composable.
38
+ // Angular has no per-instance hook, so `connect()` stands in: call it ONCE, inside an injection
39
+ // context (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(AccelerometerService).connect();
43
42
  // // template: {{ measurement()?.x }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let AccelerometerService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let AccelerometerService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  Accelerometer.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { Barometer } from '../../../core/index.js';
37
- // Angular twin of React's `useBarometer` hook and Vue's `useBarometer` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useBarometer` hook / Vue's `useBarometer` composable. Angular has no
38
+ // per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(BarometerService).connect();
43
42
  // // template: {{ measurement()?.pressure }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let BarometerService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let BarometerService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  Barometer.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { DeviceMotion } from '../../../core/index.js';
37
- // Angular twin of React's `useDeviceMotion` hook and Vue's `useDeviceMotion` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useDeviceMotion` hook / Vue's `useDeviceMotion` composable. Angular
38
+ // has no per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(DeviceMotionService).connect();
43
42
  // // template: {{ measurement()?.rotation?.alpha }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let DeviceMotionService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let DeviceMotionService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  DeviceMotion.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { Gyroscope } from '../../../core/index.js';
37
- // Angular twin of React's `useGyroscope` hook and Vue's `useGyroscope` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useGyroscope` hook / Vue's `useGyroscope` composable. Angular has no
38
+ // per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(GyroscopeService).connect();
43
42
  // // template: {{ measurement()?.x }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let GyroscopeService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let GyroscopeService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  Gyroscope.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { LightSensor } from '../../../core/index.js';
37
- // Angular twin of React's `useLightSensor` hook and Vue's `useLightSensor` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useLightSensor` hook / Vue's `useLightSensor` composable. Angular
38
+ // has no per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(LightSensorService).connect();
43
42
  // // template: {{ measurement()?.illuminance }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let LightSensorService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let LightSensorService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  LightSensor.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,18 +34,13 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { MagnetometerUncalibrated } from '../../../core/index.js';
37
- // Angular twin of React's `useMagnetometerUncalibrated` hook and Vue's
38
- // `useMagnetometerUncalibrated` composable. Angular has no per-instance hook — state and
39
- // lifecycle live in DI instead, so `connect()` stands in for the hook's role: call it ONCE
40
- // (typically from a component's field initializer, inside an injection context).
37
+ // Angular twin of React's `useMagnetometerUncalibrated` hook / Vue's
38
+ // `useMagnetometerUncalibrated` composable. Angular has no per-instance hook, so `connect()`
39
+ // stands in: call it ONCE, inside an injection context (typically a component's field
40
+ // initializer).
41
41
  //
42
42
  // readonly measurement = inject(MagnetometerUncalibratedService).connect();
43
43
  // // template: {{ measurement()?.x }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
44
  let MagnetometerUncalibratedService = (() => {
50
45
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
46
  let _classDescriptor;
@@ -60,13 +55,14 @@ let MagnetometerUncalibratedService = (() => {
60
55
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
56
  __runInitializers(_classThis, _classExtraInitializers);
62
57
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
58
+ // Captured in the constructor (always an injection context) so `connect()` can build an
59
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
60
  injector = inject(Injector);
67
61
  connect(updateIntervalMs) {
68
62
  const measurement = signal(null);
69
63
  effect(onCleanup => {
64
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
65
+ // re-run on, so a later change is not picked up.
70
66
  if (updateIntervalMs !== undefined) {
71
67
  MagnetometerUncalibrated.setUpdateInterval(updateIntervalMs);
72
68
  }
@@ -34,18 +34,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { Magnetometer } from '../../../core/index.js';
37
- // Angular twin of React's `useMagnetometer` hook and Vue's `useMagnetometer` composable.
38
- // Angular has no per-instance hook — state and lifecycle live in DI instead, so `connect()`
39
- // stands in for the hook's role: call it ONCE (typically from a component's field initializer,
40
- // inside an injection context).
37
+ // Angular twin of React's `useMagnetometer` hook / Vue's `useMagnetometer` composable. Angular
38
+ // has no per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer).
41
40
  //
42
41
  // readonly measurement = inject(MagnetometerService).connect();
43
42
  // // template: {{ measurement()?.x }}
44
- //
45
- // Unlike HideAnimationService.connect(), there is no per-render config to re-sync — the
46
- // subscription doesn't depend on anything the caller's own signals could change between
47
- // renders — so a single effect() that subscribes once and cleans up once is enough; no
48
- // `updateConfig`-style effect that re-runs on every read is needed here.
49
43
  let MagnetometerService = (() => {
50
44
  let _classDecorators = [Injectable({ providedIn: 'root' })];
51
45
  let _classDescriptor;
@@ -60,13 +54,14 @@ let MagnetometerService = (() => {
60
54
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
61
55
  __runInitializers(_classThis, _classExtraInitializers);
62
56
  }
63
- // Captured in the constructor (itself always run inside an injection context by Angular's
64
- // own DI) so `connect()` can create an `effect()` even when called from plain field-initializer
65
- // code that is not, on its own, an active injection context — mirrors HideAnimationService.
57
+ // Captured in the constructor (always an injection context) so `connect()` can build an
58
+ // `effect()` even when called from a field initializer that isn't one on its own.
66
59
  injector = inject(Injector);
67
60
  connect(updateIntervalMs) {
68
61
  const measurement = signal(null);
69
62
  effect(onCleanup => {
63
+ // updateIntervalMs applies once, at connect time — the effect has no reactive read to
64
+ // re-run on, so a later change is not picked up.
70
65
  if (updateIntervalMs !== undefined) {
71
66
  Magnetometer.setUpdateInterval(updateIntervalMs);
72
67
  }
@@ -34,16 +34,13 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import { effect, inject, Injectable, Injector, signal } from '@angular/core';
36
36
  import { watchStepCount } from '../../../core/index.js';
37
- // Angular twin of React's `usePedometer` hook and Vue's `usePedometer` composable. Angular has
38
- // no per-instance hook — state and lifecycle live in DI instead, so `connect()` stands in for
39
- // the hook's role: call it ONCE (typically from a component's field initializer, inside an
40
- // injection context).
37
+ // Angular twin of React's `usePedometer` hook / Vue's `usePedometer` composable. Angular has no
38
+ // per-instance hook, so `connect()` stands in: call it ONCE, inside an injection context
39
+ // (typically a component's field initializer). Pedometer has no setUpdateInterval, unlike the
40
+ // other sensor services, so there is no interval param here.
41
41
  //
42
42
  // readonly result = inject(PedometerService).connect();
43
43
  // // template: {{ result()?.steps }}
44
- //
45
- // Unlike AccelerometerService.connect(), there is no updateIntervalMs to apply — Pedometer has
46
- // no setUpdateInterval — so a single effect() that subscribes once and cleans up once is enough.
47
44
  let PedometerService = (() => {
48
45
  let _classDecorators = [Injectable({ providedIn: 'root' })];
49
46
  let _classDescriptor;
@@ -58,9 +55,8 @@ let PedometerService = (() => {
58
55
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
59
56
  __runInitializers(_classThis, _classExtraInitializers);
60
57
  }
61
- // Captured in the constructor (itself always run inside an injection context by Angular's own
62
- // DI) so `connect()` can create an `effect()` even when called from plain field-initializer
63
- // code that is not, on its own, an active injection context — mirrors AccelerometerService.
58
+ // Captured in the constructor (always an injection context) so `connect()` can build an
59
+ // `effect()` even when called from a field initializer that isn't one on its own.
64
60
  injector = inject(Injector);
65
61
  connect() {
66
62
  const result = signal(null);
@@ -10,12 +10,11 @@ export var DeviceMotionOrientation;
10
10
  })(DeviceMotionOrientation || (DeviceMotionOrientation = {}));
11
11
  export class DeviceMotionSensor extends DeviceSensor {
12
12
  // Standard gravitational acceleration for Earth (m/s^2), read off the native module rather
13
- // than hardcoded — mirrors upstream's dual exposure as both an instance property and the
14
- // standalone `gravity` export below.
13
+ // than hardcoded — mirrors upstream's dual exposure as an instance property and this
14
+ // standalone export.
15
15
  gravity = exponentDeviceMotion.Gravity;
16
16
  }
17
17
  const DEVICE_MOTION_DID_UPDATE_EVENT_NAME = 'deviceMotionDidUpdate';
18
18
  export const DeviceMotion = new DeviceMotionSensor(exponentDeviceMotion, DEVICE_MOTION_DID_UPDATE_EVENT_NAME);
19
- // Standalone export mirroring the instance property above, for callers that only need the
20
- // constant and not the full sensor singleton.
19
+ // Same value as `DeviceMotion.gravity`, for callers that only need the constant.
21
20
  export const gravity = exponentDeviceMotion.Gravity;
@@ -0,0 +1,16 @@
1
+ export { useAccelerometer } from './runes/use-accelerometer.svelte';
2
+ export type { IAccelerometerMeasurement } from '../core';
3
+ export { useBarometer } from './runes/use-barometer.svelte';
4
+ export type { IBarometerMeasurement } from '../core';
5
+ export { useDeviceMotion } from './runes/use-device-motion.svelte';
6
+ export { DeviceMotionOrientation, gravity, type IDeviceMotionMeasurement } from '../core';
7
+ export { useGyroscope } from './runes/use-gyroscope.svelte';
8
+ export type { IGyroscopeMeasurement } from '../core';
9
+ export { useLightSensor } from './runes/use-light-sensor.svelte';
10
+ export type { ILightSensorMeasurement } from '../core';
11
+ export { useMagnetometer } from './runes/use-magnetometer.svelte';
12
+ export type { IMagnetometerMeasurement } from '../core';
13
+ export { useMagnetometerUncalibrated } from './runes/use-magnetometer-uncalibrated.svelte';
14
+ export type { IMagnetometerUncalibratedMeasurement } from '../core';
15
+ export { usePedometer } from './runes/use-pedometer.svelte';
16
+ export { watchStepCount, getStepCountAsync, isAvailableAsync, getPermissionsAsync, requestPermissionsAsync, type IPedometerResult, type IPedometerUpdateCallback, } from '../core';
@@ -0,0 +1,14 @@
1
+ // @symbiote-native/sensors/svelte: the Svelte entry over the framework-agnostic core.
2
+ // useAccelerometer wires the Accelerometer singleton's addListener lifecycle onto Svelte's own
3
+ // `$effect` (runes/use-accelerometer.svelte.ts) — mirrors the lifecycle-bucket naming convention
4
+ // of adapters/svelte/src/runes (never `hooks/`/`composables/`, those are React's and Vue's terms).
5
+ export { useAccelerometer } from './runes/use-accelerometer.svelte';
6
+ export { useBarometer } from './runes/use-barometer.svelte';
7
+ export { useDeviceMotion } from './runes/use-device-motion.svelte';
8
+ export { DeviceMotionOrientation, gravity } from '../core/index.js';
9
+ export { useGyroscope } from './runes/use-gyroscope.svelte';
10
+ export { useLightSensor } from './runes/use-light-sensor.svelte';
11
+ export { useMagnetometer } from './runes/use-magnetometer.svelte';
12
+ export { useMagnetometerUncalibrated } from './runes/use-magnetometer-uncalibrated.svelte';
13
+ export { usePedometer } from './runes/use-pedometer.svelte';
14
+ export { watchStepCount, getStepCountAsync, isAvailableAsync, getPermissionsAsync, requestPermissionsAsync, } from '../core/index.js';
@@ -0,0 +1,4 @@
1
+ import { type IAccelerometerMeasurement } from '../../core';
2
+ export declare function useAccelerometer(updateIntervalMs?: number): {
3
+ readonly current: IAccelerometerMeasurement | null;
4
+ };
@@ -0,0 +1,31 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic Accelerometer singleton (core/).
2
+ // `.svelte.ts` (not `.ts`): runes ($state/$effect) only work in files with this extension
3
+ // outside an actual `.svelte` component; `runes/` is the framework's own lifecycle-bucket term
4
+ // (CLAUDE.md's <adapter_src_follows_framework_idioms>).
5
+ //
6
+ // Returns a boxed getter, not a bare `$state`: Svelte 5 reactivity is lexically scoped to the
7
+ // declaring module and doesn't survive being returned as a raw value, so callers read `.current`
8
+ // like unwrapping Vue's `Ref.value`.
9
+ //
10
+ // `updateIntervalMs` is a plain number, not a getter: it applies once at subscribe time and
11
+ // never reacts to a later change, matching the Vue/React twins.
12
+ import { Accelerometer } from '../../core/index.js';
13
+ export function useAccelerometer(updateIntervalMs) {
14
+ let measurement = $state(null);
15
+ $effect(() => {
16
+ if (updateIntervalMs !== undefined) {
17
+ Accelerometer.setUpdateInterval(updateIntervalMs);
18
+ }
19
+ // `measurement` is only ever written here, never read, so the effect has an empty dependency
20
+ // set and runs exactly once on mount, cleaning up exactly once on unmount.
21
+ const subscription = Accelerometer.addListener(next => {
22
+ measurement = next;
23
+ });
24
+ return () => subscription.remove();
25
+ });
26
+ return {
27
+ get current() {
28
+ return measurement;
29
+ },
30
+ };
31
+ }
@@ -0,0 +1,4 @@
1
+ import { type IBarometerMeasurement } from '../../core';
2
+ export declare function useBarometer(updateIntervalMs?: number): {
3
+ readonly current: IBarometerMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic Barometer singleton (core/) — mirrors
2
+ // use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in `runes/` with
3
+ // a `.svelte.ts` extension, returns a boxed getter object, and takes a plain `updateIntervalMs`
4
+ // rather than a getter.
5
+ import { Barometer } from '../../core/index.js';
6
+ export function useBarometer(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ Barometer.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = Barometer.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type IDeviceMotionMeasurement } from '../../core';
2
+ export declare function useDeviceMotion(updateIntervalMs?: number): {
3
+ readonly current: IDeviceMotionMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic DeviceMotion singleton (core/) — mirrors
2
+ // use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in `runes/` with
3
+ // a `.svelte.ts` extension, returns a boxed getter object, and takes a plain `updateIntervalMs`
4
+ // rather than a getter.
5
+ import { DeviceMotion } from '../../core/index.js';
6
+ export function useDeviceMotion(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ DeviceMotion.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = DeviceMotion.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type IGyroscopeMeasurement } from '../../core';
2
+ export declare function useGyroscope(updateIntervalMs?: number): {
3
+ readonly current: IGyroscopeMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic Gyroscope singleton (core/) — mirrors
2
+ // use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in `runes/` with
3
+ // a `.svelte.ts` extension, returns a boxed getter object, and takes a plain `updateIntervalMs`
4
+ // rather than a getter.
5
+ import { Gyroscope } from '../../core/index.js';
6
+ export function useGyroscope(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ Gyroscope.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = Gyroscope.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type ILightSensorMeasurement } from '../../core';
2
+ export declare function useLightSensor(updateIntervalMs?: number): {
3
+ readonly current: ILightSensorMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic LightSensor singleton (core/) — mirrors
2
+ // use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in `runes/` with
3
+ // a `.svelte.ts` extension, returns a boxed getter object, and takes a plain `updateIntervalMs`
4
+ // rather than a getter.
5
+ import { LightSensor } from '../../core/index.js';
6
+ export function useLightSensor(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ LightSensor.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = LightSensor.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type IMagnetometerUncalibratedMeasurement } from '../../core';
2
+ export declare function useMagnetometerUncalibrated(updateIntervalMs?: number): {
3
+ readonly current: IMagnetometerUncalibratedMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic MagnetometerUncalibrated singleton (core/) —
2
+ // mirrors use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in
3
+ // `runes/` with a `.svelte.ts` extension, returns a boxed getter object, and takes a plain
4
+ // `updateIntervalMs` rather than a getter.
5
+ import { MagnetometerUncalibrated, } from '../../core/index.js';
6
+ export function useMagnetometerUncalibrated(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ MagnetometerUncalibrated.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = MagnetometerUncalibrated.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type IMagnetometerMeasurement } from '../../core';
2
+ export declare function useMagnetometer(updateIntervalMs?: number): {
3
+ readonly current: IMagnetometerMeasurement | null;
4
+ };
@@ -0,0 +1,22 @@
1
+ // Svelte lifecycle wiring over the framework-agnostic Magnetometer singleton (core/) — mirrors
2
+ // use-accelerometer.svelte.ts's shape exactly. See its header for why this lives in `runes/` with
3
+ // a `.svelte.ts` extension, returns a boxed getter object, and takes a plain `updateIntervalMs`
4
+ // rather than a getter.
5
+ import { Magnetometer } from '../../core/index.js';
6
+ export function useMagnetometer(updateIntervalMs) {
7
+ let measurement = $state(null);
8
+ $effect(() => {
9
+ if (updateIntervalMs !== undefined) {
10
+ Magnetometer.setUpdateInterval(updateIntervalMs);
11
+ }
12
+ const subscription = Magnetometer.addListener(next => {
13
+ measurement = next;
14
+ });
15
+ return () => subscription.remove();
16
+ });
17
+ return {
18
+ get current() {
19
+ return measurement;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,4 @@
1
+ import { type IPedometerResult } from '../../core';
2
+ export declare function usePedometer(): {
3
+ readonly current: IPedometerResult | null;
4
+ };