@symbiote-native/sensors 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 (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +138 -0
  3. package/build/angular/index.d.ts +16 -0
  4. package/build/angular/index.js +12 -0
  5. package/build/angular/services/accelerometer.service/index.d.ts +6 -0
  6. package/build/angular/services/accelerometer.service/index.js +81 -0
  7. package/build/angular/services/barometer.service/index.d.ts +6 -0
  8. package/build/angular/services/barometer.service/index.js +81 -0
  9. package/build/angular/services/device-motion.service/index.d.ts +6 -0
  10. package/build/angular/services/device-motion.service/index.js +81 -0
  11. package/build/angular/services/gyroscope.service/index.d.ts +6 -0
  12. package/build/angular/services/gyroscope.service/index.js +81 -0
  13. package/build/angular/services/light-sensor.service/index.d.ts +6 -0
  14. package/build/angular/services/light-sensor.service/index.js +81 -0
  15. package/build/angular/services/magnetometer-uncalibrated.service/index.d.ts +6 -0
  16. package/build/angular/services/magnetometer-uncalibrated.service/index.js +81 -0
  17. package/build/angular/services/magnetometer.service/index.d.ts +6 -0
  18. package/build/angular/services/magnetometer.service/index.js +81 -0
  19. package/build/angular/services/pedometer.service/index.d.ts +6 -0
  20. package/build/angular/services/pedometer.service/index.js +76 -0
  21. package/build/core/accelerometer.d.ts +10 -0
  22. package/build/core/accelerometer.js +6 -0
  23. package/build/core/barometer.d.ts +9 -0
  24. package/build/core/barometer.js +6 -0
  25. package/build/core/device-motion.d.ts +40 -0
  26. package/build/core/device-motion.js +21 -0
  27. package/build/core/device-sensor.d.ts +27 -0
  28. package/build/core/device-sensor.js +61 -0
  29. package/build/core/gyroscope.d.ts +10 -0
  30. package/build/core/gyroscope.js +6 -0
  31. package/build/core/index.d.ts +11 -0
  32. package/build/core/index.js +10 -0
  33. package/build/core/light-sensor.d.ts +8 -0
  34. package/build/core/light-sensor.js +6 -0
  35. package/build/core/magnetometer-uncalibrated.d.ts +10 -0
  36. package/build/core/magnetometer-uncalibrated.js +6 -0
  37. package/build/core/magnetometer.d.ts +10 -0
  38. package/build/core/magnetometer.js +6 -0
  39. package/build/core/native/exponent-accelerometer.d.ts +3 -0
  40. package/build/core/native/exponent-accelerometer.js +3 -0
  41. package/build/core/native/exponent-barometer.d.ts +3 -0
  42. package/build/core/native/exponent-barometer.js +3 -0
  43. package/build/core/native/exponent-device-motion.d.ts +7 -0
  44. package/build/core/native/exponent-device-motion.js +3 -0
  45. package/build/core/native/exponent-gyroscope.d.ts +3 -0
  46. package/build/core/native/exponent-gyroscope.js +3 -0
  47. package/build/core/native/exponent-light-sensor/index.android.d.ts +3 -0
  48. package/build/core/native/exponent-light-sensor/index.android.js +3 -0
  49. package/build/core/native/exponent-light-sensor/index.d.ts +1 -0
  50. package/build/core/native/exponent-light-sensor/index.ios.d.ts +3 -0
  51. package/build/core/native/exponent-light-sensor/index.ios.js +6 -0
  52. package/build/core/native/exponent-light-sensor/index.js +5 -0
  53. package/build/core/native/exponent-magnetometer-uncalibrated.d.ts +3 -0
  54. package/build/core/native/exponent-magnetometer-uncalibrated.js +3 -0
  55. package/build/core/native/exponent-magnetometer.d.ts +3 -0
  56. package/build/core/native/exponent-magnetometer.js +3 -0
  57. package/build/core/native/exponent-pedometer.d.ts +10 -0
  58. package/build/core/native/exponent-pedometer.js +3 -0
  59. package/build/core/pedometer.d.ts +10 -0
  60. package/build/core/pedometer.js +44 -0
  61. package/build/react/hooks/use-accelerometer/index.d.ts +2 -0
  62. package/build/react/hooks/use-accelerometer/index.js +17 -0
  63. package/build/react/hooks/use-barometer/index.d.ts +2 -0
  64. package/build/react/hooks/use-barometer/index.js +17 -0
  65. package/build/react/hooks/use-device-motion/index.d.ts +2 -0
  66. package/build/react/hooks/use-device-motion/index.js +17 -0
  67. package/build/react/hooks/use-gyroscope/index.d.ts +2 -0
  68. package/build/react/hooks/use-gyroscope/index.js +17 -0
  69. package/build/react/hooks/use-light-sensor/index.d.ts +2 -0
  70. package/build/react/hooks/use-light-sensor/index.js +17 -0
  71. package/build/react/hooks/use-magnetometer/index.d.ts +2 -0
  72. package/build/react/hooks/use-magnetometer/index.js +17 -0
  73. package/build/react/hooks/use-magnetometer-uncalibrated/index.d.ts +2 -0
  74. package/build/react/hooks/use-magnetometer-uncalibrated/index.js +17 -0
  75. package/build/react/hooks/use-pedometer/index.d.ts +2 -0
  76. package/build/react/hooks/use-pedometer/index.js +14 -0
  77. package/build/react/index.d.ts +16 -0
  78. package/build/react/index.js +14 -0
  79. package/build/vue/composables/use-accelerometer/index.d.ts +3 -0
  80. package/build/vue/composables/use-accelerometer/index.js +25 -0
  81. package/build/vue/composables/use-barometer/index.d.ts +3 -0
  82. package/build/vue/composables/use-barometer/index.js +25 -0
  83. package/build/vue/composables/use-device-motion/index.d.ts +3 -0
  84. package/build/vue/composables/use-device-motion/index.js +25 -0
  85. package/build/vue/composables/use-gyroscope/index.d.ts +3 -0
  86. package/build/vue/composables/use-gyroscope/index.js +25 -0
  87. package/build/vue/composables/use-light-sensor/index.d.ts +3 -0
  88. package/build/vue/composables/use-light-sensor/index.js +25 -0
  89. package/build/vue/composables/use-magnetometer/index.d.ts +3 -0
  90. package/build/vue/composables/use-magnetometer/index.js +25 -0
  91. package/build/vue/composables/use-magnetometer-uncalibrated/index.d.ts +3 -0
  92. package/build/vue/composables/use-magnetometer-uncalibrated/index.js +25 -0
  93. package/build/vue/composables/use-pedometer/index.d.ts +3 -0
  94. package/build/vue/composables/use-pedometer/index.js +20 -0
  95. package/build/vue/index.d.ts +16 -0
  96. package/build/vue/index.js +14 -0
  97. package/build-ngc/angular/index.d.ts +16 -0
  98. package/build-ngc/angular/index.js +13 -0
  99. package/build-ngc/angular/index.js.map +1 -0
  100. package/build-ngc/angular/services/accelerometer.service/index.d.ts +9 -0
  101. package/build-ngc/angular/services/accelerometer.service/index.js +40 -0
  102. package/build-ngc/angular/services/accelerometer.service/index.js.map +1 -0
  103. package/build-ngc/angular/services/barometer.service/index.d.ts +9 -0
  104. package/build-ngc/angular/services/barometer.service/index.js +40 -0
  105. package/build-ngc/angular/services/barometer.service/index.js.map +1 -0
  106. package/build-ngc/angular/services/device-motion.service/index.d.ts +9 -0
  107. package/build-ngc/angular/services/device-motion.service/index.js +40 -0
  108. package/build-ngc/angular/services/device-motion.service/index.js.map +1 -0
  109. package/build-ngc/angular/services/gyroscope.service/index.d.ts +9 -0
  110. package/build-ngc/angular/services/gyroscope.service/index.js +40 -0
  111. package/build-ngc/angular/services/gyroscope.service/index.js.map +1 -0
  112. package/build-ngc/angular/services/light-sensor.service/index.d.ts +9 -0
  113. package/build-ngc/angular/services/light-sensor.service/index.js +40 -0
  114. package/build-ngc/angular/services/light-sensor.service/index.js.map +1 -0
  115. package/build-ngc/angular/services/magnetometer-uncalibrated.service/index.d.ts +9 -0
  116. package/build-ngc/angular/services/magnetometer-uncalibrated.service/index.js +40 -0
  117. package/build-ngc/angular/services/magnetometer-uncalibrated.service/index.js.map +1 -0
  118. package/build-ngc/angular/services/magnetometer.service/index.d.ts +9 -0
  119. package/build-ngc/angular/services/magnetometer.service/index.js +40 -0
  120. package/build-ngc/angular/services/magnetometer.service/index.js.map +1 -0
  121. package/build-ngc/angular/services/pedometer.service/index.d.ts +9 -0
  122. package/build-ngc/angular/services/pedometer.service/index.js +35 -0
  123. package/build-ngc/angular/services/pedometer.service/index.js.map +1 -0
  124. package/build-ngc/core/accelerometer.d.ts +10 -0
  125. package/build-ngc/core/accelerometer.js +7 -0
  126. package/build-ngc/core/accelerometer.js.map +1 -0
  127. package/build-ngc/core/barometer.d.ts +9 -0
  128. package/build-ngc/core/barometer.js +7 -0
  129. package/build-ngc/core/barometer.js.map +1 -0
  130. package/build-ngc/core/device-motion.d.ts +40 -0
  131. package/build-ngc/core/device-motion.js +22 -0
  132. package/build-ngc/core/device-motion.js.map +1 -0
  133. package/build-ngc/core/device-sensor.d.ts +27 -0
  134. package/build-ngc/core/device-sensor.js +62 -0
  135. package/build-ngc/core/device-sensor.js.map +1 -0
  136. package/build-ngc/core/gyroscope.d.ts +10 -0
  137. package/build-ngc/core/gyroscope.js +7 -0
  138. package/build-ngc/core/gyroscope.js.map +1 -0
  139. package/build-ngc/core/index.d.ts +11 -0
  140. package/build-ngc/core/index.js +11 -0
  141. package/build-ngc/core/index.js.map +1 -0
  142. package/build-ngc/core/light-sensor.d.ts +8 -0
  143. package/build-ngc/core/light-sensor.js +7 -0
  144. package/build-ngc/core/light-sensor.js.map +1 -0
  145. package/build-ngc/core/magnetometer-uncalibrated.d.ts +10 -0
  146. package/build-ngc/core/magnetometer-uncalibrated.js +7 -0
  147. package/build-ngc/core/magnetometer-uncalibrated.js.map +1 -0
  148. package/build-ngc/core/magnetometer.d.ts +10 -0
  149. package/build-ngc/core/magnetometer.js +7 -0
  150. package/build-ngc/core/magnetometer.js.map +1 -0
  151. package/build-ngc/core/native/exponent-accelerometer.d.ts +3 -0
  152. package/build-ngc/core/native/exponent-accelerometer.js +4 -0
  153. package/build-ngc/core/native/exponent-accelerometer.js.map +1 -0
  154. package/build-ngc/core/native/exponent-barometer.d.ts +3 -0
  155. package/build-ngc/core/native/exponent-barometer.js +4 -0
  156. package/build-ngc/core/native/exponent-barometer.js.map +1 -0
  157. package/build-ngc/core/native/exponent-device-motion.d.ts +7 -0
  158. package/build-ngc/core/native/exponent-device-motion.js +4 -0
  159. package/build-ngc/core/native/exponent-device-motion.js.map +1 -0
  160. package/build-ngc/core/native/exponent-gyroscope.d.ts +3 -0
  161. package/build-ngc/core/native/exponent-gyroscope.js +4 -0
  162. package/build-ngc/core/native/exponent-gyroscope.js.map +1 -0
  163. package/build-ngc/core/native/exponent-light-sensor/index.android.d.ts +3 -0
  164. package/build-ngc/core/native/exponent-light-sensor/index.android.js +4 -0
  165. package/build-ngc/core/native/exponent-light-sensor/index.android.js.map +1 -0
  166. package/build-ngc/core/native/exponent-light-sensor/index.d.ts +1 -0
  167. package/build-ngc/core/native/exponent-light-sensor/index.ios.d.ts +3 -0
  168. package/build-ngc/core/native/exponent-light-sensor/index.ios.js +7 -0
  169. package/build-ngc/core/native/exponent-light-sensor/index.ios.js.map +1 -0
  170. package/build-ngc/core/native/exponent-light-sensor/index.js +6 -0
  171. package/build-ngc/core/native/exponent-light-sensor/index.js.map +1 -0
  172. package/build-ngc/core/native/exponent-magnetometer-uncalibrated.d.ts +3 -0
  173. package/build-ngc/core/native/exponent-magnetometer-uncalibrated.js +4 -0
  174. package/build-ngc/core/native/exponent-magnetometer-uncalibrated.js.map +1 -0
  175. package/build-ngc/core/native/exponent-magnetometer.d.ts +3 -0
  176. package/build-ngc/core/native/exponent-magnetometer.js +4 -0
  177. package/build-ngc/core/native/exponent-magnetometer.js.map +1 -0
  178. package/build-ngc/core/native/exponent-pedometer.d.ts +10 -0
  179. package/build-ngc/core/native/exponent-pedometer.js +4 -0
  180. package/build-ngc/core/native/exponent-pedometer.js.map +1 -0
  181. package/build-ngc/core/pedometer.d.ts +10 -0
  182. package/build-ngc/core/pedometer.js +45 -0
  183. package/build-ngc/core/pedometer.js.map +1 -0
  184. package/package.json +106 -0
  185. package/src/angular/index.ts +26 -0
  186. package/src/angular/services/accelerometer.service/accelerometer.service.test.ts +118 -0
  187. package/src/angular/services/accelerometer.service/index.ts +39 -0
  188. package/src/angular/services/barometer.service/barometer.service.test.ts +122 -0
  189. package/src/angular/services/barometer.service/index.ts +39 -0
  190. package/src/angular/services/device-motion.service/device-motion.service.test.ts +125 -0
  191. package/src/angular/services/device-motion.service/index.ts +39 -0
  192. package/src/angular/services/gyroscope.service/gyroscope.service.test.ts +118 -0
  193. package/src/angular/services/gyroscope.service/index.ts +39 -0
  194. package/src/angular/services/light-sensor.service/index.ts +39 -0
  195. package/src/angular/services/light-sensor.service/light-sensor.service.test.ts +118 -0
  196. package/src/angular/services/magnetometer-uncalibrated.service/index.ts +39 -0
  197. package/src/angular/services/magnetometer-uncalibrated.service/magnetometer-uncalibrated.service.test.ts +123 -0
  198. package/src/angular/services/magnetometer.service/index.ts +39 -0
  199. package/src/angular/services/magnetometer.service/magnetometer.service.test.ts +118 -0
  200. package/src/angular/services/pedometer.service/index.ts +34 -0
  201. package/src/angular/services/pedometer.service/pedometer.service.test.ts +86 -0
  202. package/src/core/accelerometer.test.ts +49 -0
  203. package/src/core/accelerometer.ts +19 -0
  204. package/src/core/barometer.test.ts +46 -0
  205. package/src/core/barometer.ts +15 -0
  206. package/src/core/device-motion.test.ts +60 -0
  207. package/src/core/device-motion.ts +41 -0
  208. package/src/core/device-sensor.test.ts +76 -0
  209. package/src/core/device-sensor.ts +95 -0
  210. package/src/core/gyroscope.test.ts +46 -0
  211. package/src/core/gyroscope.ts +16 -0
  212. package/src/core/index.ts +37 -0
  213. package/src/core/light-sensor.test.ts +49 -0
  214. package/src/core/light-sensor.ts +18 -0
  215. package/src/core/magnetometer-uncalibrated.test.ts +49 -0
  216. package/src/core/magnetometer-uncalibrated.ts +20 -0
  217. package/src/core/magnetometer.test.ts +49 -0
  218. package/src/core/magnetometer.ts +19 -0
  219. package/src/core/native/exponent-accelerometer.ts +9 -0
  220. package/src/core/native/exponent-barometer.ts +9 -0
  221. package/src/core/native/exponent-device-motion.ts +15 -0
  222. package/src/core/native/exponent-gyroscope.ts +9 -0
  223. package/src/core/native/exponent-light-sensor/index.android.ts +9 -0
  224. package/src/core/native/exponent-light-sensor/index.ios.ts +12 -0
  225. package/src/core/native/exponent-light-sensor/index.ts +5 -0
  226. package/src/core/native/exponent-magnetometer-uncalibrated.ts +9 -0
  227. package/src/core/native/exponent-magnetometer.ts +9 -0
  228. package/src/core/native/exponent-pedometer.ts +17 -0
  229. package/src/core/pedometer.test.ts +118 -0
  230. package/src/core/pedometer.ts +62 -0
  231. package/src/react/hooks/use-accelerometer/index.ts +21 -0
  232. package/src/react/hooks/use-accelerometer/use-accelerometer.test.tsx +81 -0
  233. package/src/react/hooks/use-barometer/index.ts +21 -0
  234. package/src/react/hooks/use-barometer/use-barometer.test.tsx +83 -0
  235. package/src/react/hooks/use-device-motion/index.ts +21 -0
  236. package/src/react/hooks/use-device-motion/use-device-motion.test.tsx +88 -0
  237. package/src/react/hooks/use-gyroscope/index.ts +21 -0
  238. package/src/react/hooks/use-gyroscope/use-gyroscope.test.tsx +79 -0
  239. package/src/react/hooks/use-light-sensor/index.ts +21 -0
  240. package/src/react/hooks/use-light-sensor/use-light-sensor.test.tsx +79 -0
  241. package/src/react/hooks/use-magnetometer/index.ts +21 -0
  242. package/src/react/hooks/use-magnetometer/use-magnetometer.test.tsx +81 -0
  243. package/src/react/hooks/use-magnetometer-uncalibrated/index.ts +23 -0
  244. package/src/react/hooks/use-magnetometer-uncalibrated/use-magnetometer-uncalibrated.test.tsx +88 -0
  245. package/src/react/hooks/use-pedometer/index.ts +17 -0
  246. package/src/react/hooks/use-pedometer/use-pedometer.test.tsx +69 -0
  247. package/src/react/index.ts +29 -0
  248. package/src/vue/composables/use-accelerometer/index.ts +34 -0
  249. package/src/vue/composables/use-accelerometer/use-accelerometer.test.ts +96 -0
  250. package/src/vue/composables/use-barometer/index.ts +30 -0
  251. package/src/vue/composables/use-barometer/use-barometer.test.ts +100 -0
  252. package/src/vue/composables/use-device-motion/index.ts +30 -0
  253. package/src/vue/composables/use-device-motion/use-device-motion.test.ts +104 -0
  254. package/src/vue/composables/use-gyroscope/index.ts +30 -0
  255. package/src/vue/composables/use-gyroscope/use-gyroscope.test.ts +96 -0
  256. package/src/vue/composables/use-light-sensor/index.ts +30 -0
  257. package/src/vue/composables/use-light-sensor/use-light-sensor.test.ts +96 -0
  258. package/src/vue/composables/use-magnetometer/index.ts +30 -0
  259. package/src/vue/composables/use-magnetometer/use-magnetometer.test.ts +96 -0
  260. package/src/vue/composables/use-magnetometer-uncalibrated/index.ts +36 -0
  261. package/src/vue/composables/use-magnetometer-uncalibrated/use-magnetometer-uncalibrated.test.ts +103 -0
  262. package/src/vue/composables/use-pedometer/index.ts +25 -0
  263. package/src/vue/composables/use-pedometer/use-pedometer.test.ts +77 -0
  264. package/src/vue/index.ts +29 -0
@@ -0,0 +1,15 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentBarometer } from './native/exponent-barometer';
3
+
4
+ // Pressure is in hectopascals (hPa); relativeAltitude (meters) is iOS-only; timestamp is in seconds.
5
+ export type IBarometerMeasurement = {
6
+ pressure: number;
7
+ relativeAltitude?: number;
8
+ timestamp: number;
9
+ };
10
+
11
+ export class BarometerSensor extends DeviceSensor<IBarometerMeasurement> {}
12
+
13
+ const BAROMETER_DID_UPDATE_EVENT_NAME = 'barometerDidUpdate';
14
+
15
+ export const Barometer = new BarometerSensor(exponentBarometer, BAROMETER_DID_UPDATE_EVENT_NAME);
@@ -0,0 +1,60 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const FAKE_GRAVITY = 9.80665;
4
+
5
+ const FAKE_NATIVE_DEVICE_MOTION = {
6
+ addListener: vi.fn(() => ({ remove: vi.fn() })),
7
+ listenerCount: vi.fn(() => 0),
8
+ removeAllListeners: vi.fn(),
9
+ setUpdateInterval: vi.fn(),
10
+ Gravity: FAKE_GRAVITY,
11
+ };
12
+
13
+ // The real ExponentDeviceMotion native module only exists on device — resolving it via
14
+ // requireNativeModule() at import time would throw in this headless test run, so the
15
+ // module-lookup file is faked in place of `expo-modules-core`'s runtime resolution.
16
+ vi.mock('./native/exponent-device-motion', () => ({
17
+ exponentDeviceMotion: FAKE_NATIVE_DEVICE_MOTION,
18
+ }));
19
+
20
+ // device-sensor.ts (imported transitively through ./device-motion) pulls Platform/PermissionStatus
21
+ // from expo-modules-core, whose real entry drags in the Flow-typed 'react-native' source that
22
+ // Vitest's Oxc transform can't parse — same fake as device-sensor.test.ts.
23
+ vi.mock('expo-modules-core', () => ({
24
+ Platform: { OS: 'ios' },
25
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
26
+ }));
27
+
28
+ const { DeviceMotion, gravity } = await import('./device-motion');
29
+
30
+ afterEach(() => {
31
+ DeviceMotion.removeAllListeners();
32
+ vi.clearAllMocks();
33
+ });
34
+
35
+ describe('DeviceMotion', () => {
36
+ it('sets the update interval', () => {
37
+ DeviceMotion.setUpdateInterval(1234);
38
+
39
+ expect(FAKE_NATIVE_DEVICE_MOTION.setUpdateInterval).toHaveBeenCalledTimes(1);
40
+ expect(FAKE_NATIVE_DEVICE_MOTION.setUpdateInterval).toHaveBeenCalledWith(1234);
41
+ });
42
+
43
+ it('subscribes through the shared deviceMotionDidUpdate event name', () => {
44
+ const listener = vi.fn();
45
+ DeviceMotion.addListener(listener);
46
+
47
+ expect(FAKE_NATIVE_DEVICE_MOTION.addListener).toHaveBeenCalledWith(
48
+ 'deviceMotionDidUpdate',
49
+ listener,
50
+ );
51
+ });
52
+
53
+ it('exposes the native Gravity constant as a standalone export', () => {
54
+ expect(gravity).toBe(FAKE_GRAVITY);
55
+ });
56
+
57
+ it('exposes the native Gravity constant as an instance property', () => {
58
+ expect(DeviceMotion.gravity).toBe(FAKE_GRAVITY);
59
+ });
60
+ });
@@ -0,0 +1,41 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentDeviceMotion } from './native/exponent-device-motion';
3
+
4
+ // Acceleration figures are in meters per second squared (m/s^2); rotation is in degrees and
5
+ // rotationRate in degrees per second (deg/s); interval is in milliseconds; timestamps are in
6
+ // seconds. `acceleration` and `rotationRate` are null on devices that can't isolate gravity
7
+ // from raw acceleration.
8
+ export type IDeviceMotionMeasurement = {
9
+ acceleration: null | { x: number; y: number; z: number; timestamp: number };
10
+ accelerationIncludingGravity: { x: number; y: number; z: number; timestamp: number };
11
+ rotation: { alpha: number; beta: number; gamma: number; timestamp: number };
12
+ rotationRate: null | { alpha: number; beta: number; gamma: number; timestamp: number };
13
+ interval: number;
14
+ orientation: DeviceMotionOrientation;
15
+ };
16
+
17
+ // Device orientation based on screen rotation.
18
+ export enum DeviceMotionOrientation {
19
+ Portrait = 0,
20
+ RightLandscape = 90,
21
+ UpsideDown = 180,
22
+ LeftLandscape = -90,
23
+ }
24
+
25
+ export class DeviceMotionSensor extends DeviceSensor<IDeviceMotionMeasurement> {
26
+ // Standard gravitational acceleration for Earth (m/s^2), read off the native module rather
27
+ // than hardcoded — mirrors upstream's dual exposure as both an instance property and the
28
+ // standalone `gravity` export below.
29
+ readonly gravity: number = exponentDeviceMotion.Gravity;
30
+ }
31
+
32
+ const DEVICE_MOTION_DID_UPDATE_EVENT_NAME = 'deviceMotionDidUpdate';
33
+
34
+ export const DeviceMotion = new DeviceMotionSensor(
35
+ exponentDeviceMotion,
36
+ DEVICE_MOTION_DID_UPDATE_EVENT_NAME,
37
+ );
38
+
39
+ // Standalone export mirroring the instance property above, for callers that only need the
40
+ // constant and not the full sensor singleton.
41
+ export const gravity: number = exponentDeviceMotion.Gravity;
@@ -0,0 +1,76 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import type { INativeSensorModule } from './device-sensor';
3
+
4
+ // expo-modules-core's real entry transitively imports the 'react-native' package for
5
+ // Platform/TurboModuleRegistry, whose Flow-typed source Vitest's Oxc transform cannot parse
6
+ // (Metro strips Flow on-device, Vitest has no such pipeline) — faked here the same way
7
+ // react-native-bootsplash is faked in the splash-screen package's own composable tests.
8
+ vi.mock('expo-modules-core', () => ({
9
+ Platform: { OS: 'ios' },
10
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
11
+ }));
12
+
13
+ const { DeviceSensor } = await import('./device-sensor');
14
+
15
+ // DeviceSensor only ever calls addListener/listenerCount/removeAllListeners on its native
16
+ // module — a plain fake satisfying INativeSensorModule is enough, no need to extend
17
+ // expo-modules-core's real NativeModule (which requires a live native JSI runtime to construct).
18
+ function createFakeNativeModule(): INativeSensorModule<unknown> {
19
+ const listeners = new Set<(measurement: unknown) => void>();
20
+ return {
21
+ addListener: vi.fn((_eventName: string, listener: (measurement: unknown) => void) => {
22
+ listeners.add(listener);
23
+ return { remove: () => listeners.delete(listener) };
24
+ }),
25
+ listenerCount: vi.fn(() => listeners.size),
26
+ removeAllListeners: vi.fn(() => listeners.clear()),
27
+ setUpdateInterval: vi.fn(),
28
+ };
29
+ }
30
+
31
+ describe('DeviceSensor', () => {
32
+ it('counts the number of listeners', () => {
33
+ const nativeModule = createFakeNativeModule();
34
+ const sensor = new DeviceSensor(nativeModule, 'mockDidUpdate');
35
+
36
+ const subscription1 = sensor.addListener(() => {});
37
+ expect(sensor.hasListeners()).toBe(true);
38
+ expect(sensor.getListenerCount()).toBe(1);
39
+
40
+ const subscription2 = sensor.addListener(() => {});
41
+ sensor.addListener(() => {});
42
+ expect(sensor.getListenerCount()).toBe(3);
43
+
44
+ subscription2.remove();
45
+ expect(sensor.getListenerCount()).toBe(2);
46
+
47
+ sensor.removeSubscription(subscription1);
48
+ expect(sensor.getListenerCount()).toBe(1);
49
+
50
+ sensor.removeAllListeners();
51
+ expect(sensor.getListenerCount()).toBe(0);
52
+ });
53
+
54
+ it('forwards setUpdateInterval to the native module', () => {
55
+ const nativeModule = createFakeNativeModule();
56
+ const sensor = new DeviceSensor(nativeModule, 'mockDidUpdate');
57
+
58
+ sensor.setUpdateInterval(1234);
59
+
60
+ expect(nativeModule.setUpdateInterval).toHaveBeenCalledTimes(1);
61
+ expect(nativeModule.setUpdateInterval).toHaveBeenCalledWith(1234);
62
+ });
63
+
64
+ it('falls back to a granted default permission response when the native module has none', async () => {
65
+ const nativeModule = createFakeNativeModule();
66
+ const sensor = new DeviceSensor(nativeModule, 'mockDidUpdate');
67
+
68
+ await expect(sensor.getPermissionsAsync()).resolves.toEqual({
69
+ granted: true,
70
+ expires: 'never',
71
+ canAskAgain: true,
72
+ status: 'granted',
73
+ });
74
+ await expect(sensor.isAvailableAsync()).resolves.toBe(false);
75
+ });
76
+ });
@@ -0,0 +1,95 @@
1
+ // expo-sensors' own DeviceSensor imports PermissionResponse/PermissionExpiration/PermissionStatus
2
+ // from the `expo` meta-package. We never depend on `expo` itself (it drags in a second
3
+ // Metro/babel pipeline — see the symbiote-expo-native-module skill) so this pulls the same
4
+ // three exports straight from expo-modules-core, which is where `expo` re-exports them from.
5
+ import {
6
+ Platform,
7
+ PermissionStatus,
8
+ type EventSubscription,
9
+ type PermissionExpiration,
10
+ type PermissionResponse,
11
+ } from 'expo-modules-core';
12
+
13
+ export type IListener<Measurement> = (measurement: Measurement) => void;
14
+
15
+ export type INativeSensorModule<Measurement> = {
16
+ addListener(eventName: string, listener: IListener<Measurement>): EventSubscription;
17
+ listenerCount(eventName: string): number;
18
+ removeAllListeners(eventName: string): void;
19
+ setUpdateInterval?(intervalMs: number): void;
20
+ isAvailableAsync?(): Promise<boolean>;
21
+ getPermissionsAsync?(): Promise<PermissionResponse>;
22
+ requestPermissionsAsync?(): Promise<PermissionResponse>;
23
+ };
24
+
25
+ const DEFAULT_PERMISSION_RESPONSE: PermissionResponse = {
26
+ granted: true,
27
+ expires: 'never',
28
+ canAskAgain: true,
29
+ status: PermissionStatus.GRANTED,
30
+ };
31
+
32
+ export class DeviceSensor<Measurement> {
33
+ readonly nativeModule: INativeSensorModule<Measurement>;
34
+ readonly nativeEventName: string;
35
+
36
+ constructor(nativeModule: INativeSensorModule<Measurement>, nativeEventName: string) {
37
+ this.nativeModule = nativeModule;
38
+ this.nativeEventName = nativeEventName;
39
+ }
40
+
41
+ addListener(listener: IListener<Measurement>): EventSubscription {
42
+ return this.nativeModule.addListener(this.nativeEventName, listener);
43
+ }
44
+
45
+ hasListeners(): boolean {
46
+ return this.getListenerCount() > 0;
47
+ }
48
+
49
+ getListenerCount(): number {
50
+ return this.nativeModule.listenerCount(this.nativeEventName);
51
+ }
52
+
53
+ removeAllListeners(): void {
54
+ this.nativeModule.removeAllListeners(this.nativeEventName);
55
+ }
56
+
57
+ // upstream keeps this only for callers still holding a pre-subscription-object reference.
58
+ removeSubscription(subscription: EventSubscription): void {
59
+ subscription.remove();
60
+ }
61
+
62
+ setUpdateInterval(intervalMs: number): void {
63
+ if (!this.nativeModule.setUpdateInterval) {
64
+ console.warn(
65
+ `@symbiote-native/sensors: setUpdateInterval() is not supported on ${Platform.OS}`,
66
+ );
67
+ return;
68
+ }
69
+ this.nativeModule.setUpdateInterval(intervalMs);
70
+ }
71
+
72
+ async isAvailableAsync(): Promise<boolean> {
73
+ if (!this.nativeModule.isAvailableAsync) {
74
+ return false;
75
+ }
76
+ return this.nativeModule.isAvailableAsync();
77
+ }
78
+
79
+ async getPermissionsAsync(): Promise<PermissionResponse> {
80
+ if (!this.nativeModule.getPermissionsAsync) {
81
+ return DEFAULT_PERMISSION_RESPONSE;
82
+ }
83
+ return this.nativeModule.getPermissionsAsync();
84
+ }
85
+
86
+ async requestPermissionsAsync(): Promise<PermissionResponse> {
87
+ if (!this.nativeModule.requestPermissionsAsync) {
88
+ return DEFAULT_PERMISSION_RESPONSE;
89
+ }
90
+ return this.nativeModule.requestPermissionsAsync();
91
+ }
92
+ }
93
+
94
+ export { PermissionStatus };
95
+ export type { EventSubscription, PermissionExpiration, PermissionResponse };
@@ -0,0 +1,46 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const FAKE_NATIVE_GYROSCOPE = {
4
+ addListener: vi.fn(() => ({ remove: vi.fn() })),
5
+ listenerCount: vi.fn(() => 0),
6
+ removeAllListeners: vi.fn(),
7
+ setUpdateInterval: vi.fn(),
8
+ };
9
+
10
+ // The real ExponentGyroscope native module only exists on device — resolving it via
11
+ // requireNativeModule() at import time would throw in this headless test run, so the
12
+ // module-lookup file is faked in place of `expo-modules-core`'s runtime resolution.
13
+ vi.mock('./native/exponent-gyroscope', () => ({
14
+ exponentGyroscope: FAKE_NATIVE_GYROSCOPE,
15
+ }));
16
+
17
+ // device-sensor.ts (imported transitively through ./gyroscope) pulls Platform/PermissionStatus
18
+ // from expo-modules-core, whose real entry drags in the Flow-typed 'react-native' source that
19
+ // Vitest's Oxc transform can't parse — same fake as device-sensor.test.ts.
20
+ vi.mock('expo-modules-core', () => ({
21
+ Platform: { OS: 'ios' },
22
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
23
+ }));
24
+
25
+ const { Gyroscope } = await import('./gyroscope');
26
+
27
+ afterEach(() => {
28
+ Gyroscope.removeAllListeners();
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ describe('Gyroscope', () => {
33
+ it('sets the update interval', () => {
34
+ Gyroscope.setUpdateInterval(1234);
35
+
36
+ expect(FAKE_NATIVE_GYROSCOPE.setUpdateInterval).toHaveBeenCalledTimes(1);
37
+ expect(FAKE_NATIVE_GYROSCOPE.setUpdateInterval).toHaveBeenCalledWith(1234);
38
+ });
39
+
40
+ it('subscribes through the shared gyroscopeDidUpdate event name', () => {
41
+ const listener = vi.fn();
42
+ Gyroscope.addListener(listener);
43
+
44
+ expect(FAKE_NATIVE_GYROSCOPE.addListener).toHaveBeenCalledWith('gyroscopeDidUpdate', listener);
45
+ });
46
+ });
@@ -0,0 +1,16 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentGyroscope } from './native/exponent-gyroscope';
3
+
4
+ // Values are rotation rate in radians/second reported along each axis; timestamp is in seconds.
5
+ export type IGyroscopeMeasurement = {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ timestamp: number;
10
+ };
11
+
12
+ export class GyroscopeSensor extends DeviceSensor<IGyroscopeMeasurement> {}
13
+
14
+ const GYROSCOPE_DID_UPDATE_EVENT_NAME = 'gyroscopeDidUpdate';
15
+
16
+ export const Gyroscope = new GyroscopeSensor(exponentGyroscope, GYROSCOPE_DID_UPDATE_EVENT_NAME);
@@ -0,0 +1,37 @@
1
+ export {
2
+ Accelerometer,
3
+ AccelerometerSensor,
4
+ type IAccelerometerMeasurement,
5
+ } from './accelerometer';
6
+ export { Barometer, BarometerSensor, type IBarometerMeasurement } from './barometer';
7
+ export {
8
+ DeviceMotion,
9
+ DeviceMotionSensor,
10
+ DeviceMotionOrientation,
11
+ gravity,
12
+ type IDeviceMotionMeasurement,
13
+ } from './device-motion';
14
+ export { Gyroscope, GyroscopeSensor, type IGyroscopeMeasurement } from './gyroscope';
15
+ export { LightSensor, LightSensorSensor, type ILightSensorMeasurement } from './light-sensor';
16
+ export { Magnetometer, MagnetometerSensor, type IMagnetometerMeasurement } from './magnetometer';
17
+ export {
18
+ MagnetometerUncalibrated,
19
+ MagnetometerUncalibratedSensor,
20
+ type IMagnetometerUncalibratedMeasurement,
21
+ } from './magnetometer-uncalibrated';
22
+ export {
23
+ watchStepCount,
24
+ getStepCountAsync,
25
+ isAvailableAsync,
26
+ getPermissionsAsync,
27
+ requestPermissionsAsync,
28
+ type IPedometerResult,
29
+ type IPedometerUpdateCallback,
30
+ } from './pedometer';
31
+ export { DeviceSensor, type IListener, type INativeSensorModule } from './device-sensor';
32
+ export type {
33
+ EventSubscription,
34
+ PermissionExpiration,
35
+ PermissionResponse,
36
+ } from 'expo-modules-core';
37
+ export { PermissionStatus } from 'expo-modules-core';
@@ -0,0 +1,49 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const FAKE_NATIVE_LIGHT_SENSOR = {
4
+ addListener: vi.fn(() => ({ remove: vi.fn() })),
5
+ listenerCount: vi.fn(() => 0),
6
+ removeAllListeners: vi.fn(),
7
+ setUpdateInterval: vi.fn(),
8
+ };
9
+
10
+ // The real ExpoLightSensor native module only exists on device — resolving it via
11
+ // requireNativeModule() at import time would throw in this headless test run, so the
12
+ // module-lookup file is faked in place of `expo-modules-core`'s runtime resolution.
13
+ vi.mock('./native/exponent-light-sensor', () => ({
14
+ exponentLightSensor: FAKE_NATIVE_LIGHT_SENSOR,
15
+ }));
16
+
17
+ // device-sensor.ts (imported transitively through ./light-sensor) pulls Platform/PermissionStatus
18
+ // from expo-modules-core, whose real entry drags in the Flow-typed 'react-native' source that
19
+ // Vitest's Oxc transform can't parse — same fake as device-sensor.test.ts.
20
+ vi.mock('expo-modules-core', () => ({
21
+ Platform: { OS: 'ios' },
22
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
23
+ }));
24
+
25
+ const { LightSensor } = await import('./light-sensor');
26
+
27
+ afterEach(() => {
28
+ LightSensor.removeAllListeners();
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ describe('LightSensor', () => {
33
+ it('sets the update interval', () => {
34
+ LightSensor.setUpdateInterval(1234);
35
+
36
+ expect(FAKE_NATIVE_LIGHT_SENSOR.setUpdateInterval).toHaveBeenCalledTimes(1);
37
+ expect(FAKE_NATIVE_LIGHT_SENSOR.setUpdateInterval).toHaveBeenCalledWith(1234);
38
+ });
39
+
40
+ it('subscribes through the shared lightSensorDidUpdate event name', () => {
41
+ const listener = vi.fn();
42
+ LightSensor.addListener(listener);
43
+
44
+ expect(FAKE_NATIVE_LIGHT_SENSOR.addListener).toHaveBeenCalledWith(
45
+ 'lightSensorDidUpdate',
46
+ listener,
47
+ );
48
+ });
49
+ });
@@ -0,0 +1,18 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentLightSensor } from './native/exponent-light-sensor';
3
+
4
+ // Ambient light level in lux (lx); timestamp is in seconds. Android-only — see
5
+ // core/native/exponent-light-sensor/index.ios.ts for the iOS stub.
6
+ export type ILightSensorMeasurement = {
7
+ illuminance: number;
8
+ timestamp: number;
9
+ };
10
+
11
+ export class LightSensorSensor extends DeviceSensor<ILightSensorMeasurement> {}
12
+
13
+ const LIGHT_SENSOR_DID_UPDATE_EVENT_NAME = 'lightSensorDidUpdate';
14
+
15
+ export const LightSensor = new LightSensorSensor(
16
+ exponentLightSensor,
17
+ LIGHT_SENSOR_DID_UPDATE_EVENT_NAME,
18
+ );
@@ -0,0 +1,49 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const FAKE_NATIVE_MAGNETOMETER_UNCALIBRATED = {
4
+ addListener: vi.fn(() => ({ remove: vi.fn() })),
5
+ listenerCount: vi.fn(() => 0),
6
+ removeAllListeners: vi.fn(),
7
+ setUpdateInterval: vi.fn(),
8
+ };
9
+
10
+ // The real ExponentMagnetometerUncalibrated native module only exists on device — resolving it
11
+ // via requireNativeModule() at import time would throw in this headless test run, so the
12
+ // module-lookup file is faked in place of `expo-modules-core`'s runtime resolution.
13
+ vi.mock('./native/exponent-magnetometer-uncalibrated', () => ({
14
+ exponentMagnetometerUncalibrated: FAKE_NATIVE_MAGNETOMETER_UNCALIBRATED,
15
+ }));
16
+
17
+ // device-sensor.ts (imported transitively through ./magnetometer-uncalibrated) pulls
18
+ // Platform/PermissionStatus from expo-modules-core, whose real entry drags in the Flow-typed
19
+ // 'react-native' source that Vitest's Oxc transform can't parse — same fake as device-sensor.test.ts.
20
+ vi.mock('expo-modules-core', () => ({
21
+ Platform: { OS: 'ios' },
22
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
23
+ }));
24
+
25
+ const { MagnetometerUncalibrated } = await import('./magnetometer-uncalibrated');
26
+
27
+ afterEach(() => {
28
+ MagnetometerUncalibrated.removeAllListeners();
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ describe('MagnetometerUncalibrated', () => {
33
+ it('sets the update interval', () => {
34
+ MagnetometerUncalibrated.setUpdateInterval(1234);
35
+
36
+ expect(FAKE_NATIVE_MAGNETOMETER_UNCALIBRATED.setUpdateInterval).toHaveBeenCalledTimes(1);
37
+ expect(FAKE_NATIVE_MAGNETOMETER_UNCALIBRATED.setUpdateInterval).toHaveBeenCalledWith(1234);
38
+ });
39
+
40
+ it('subscribes through the shared magnetometerUncalibratedDidUpdate event name', () => {
41
+ const listener = vi.fn();
42
+ MagnetometerUncalibrated.addListener(listener);
43
+
44
+ expect(FAKE_NATIVE_MAGNETOMETER_UNCALIBRATED.addListener).toHaveBeenCalledWith(
45
+ 'magnetometerUncalibratedDidUpdate',
46
+ listener,
47
+ );
48
+ });
49
+ });
@@ -0,0 +1,20 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentMagnetometerUncalibrated } from './native/exponent-magnetometer-uncalibrated';
3
+
4
+ // Values are the uncalibrated strength of the magnetic field along each axis, in microteslas
5
+ // (`μT`); timestamp is in seconds.
6
+ export type IMagnetometerUncalibratedMeasurement = {
7
+ x: number;
8
+ y: number;
9
+ z: number;
10
+ timestamp: number;
11
+ };
12
+
13
+ export class MagnetometerUncalibratedSensor extends DeviceSensor<IMagnetometerUncalibratedMeasurement> {}
14
+
15
+ const MAGNETOMETER_UNCALIBRATED_DID_UPDATE_EVENT_NAME = 'magnetometerUncalibratedDidUpdate';
16
+
17
+ export const MagnetometerUncalibrated = new MagnetometerUncalibratedSensor(
18
+ exponentMagnetometerUncalibrated,
19
+ MAGNETOMETER_UNCALIBRATED_DID_UPDATE_EVENT_NAME,
20
+ );
@@ -0,0 +1,49 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ const FAKE_NATIVE_MAGNETOMETER = {
4
+ addListener: vi.fn(() => ({ remove: vi.fn() })),
5
+ listenerCount: vi.fn(() => 0),
6
+ removeAllListeners: vi.fn(),
7
+ setUpdateInterval: vi.fn(),
8
+ };
9
+
10
+ // The real ExponentMagnetometer native module only exists on device — resolving it via
11
+ // requireNativeModule() at import time would throw in this headless test run, so the
12
+ // module-lookup file is faked in place of `expo-modules-core`'s runtime resolution.
13
+ vi.mock('./native/exponent-magnetometer', () => ({
14
+ exponentMagnetometer: FAKE_NATIVE_MAGNETOMETER,
15
+ }));
16
+
17
+ // device-sensor.ts (imported transitively through ./magnetometer) pulls Platform/PermissionStatus
18
+ // from expo-modules-core, whose real entry drags in the Flow-typed 'react-native' source that
19
+ // Vitest's Oxc transform can't parse — same fake as device-sensor.test.ts.
20
+ vi.mock('expo-modules-core', () => ({
21
+ Platform: { OS: 'ios' },
22
+ PermissionStatus: { GRANTED: 'granted', UNDETERMINED: 'undetermined', DENIED: 'denied' },
23
+ }));
24
+
25
+ const { Magnetometer } = await import('./magnetometer');
26
+
27
+ afterEach(() => {
28
+ Magnetometer.removeAllListeners();
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ describe('Magnetometer', () => {
33
+ it('sets the update interval', () => {
34
+ Magnetometer.setUpdateInterval(1234);
35
+
36
+ expect(FAKE_NATIVE_MAGNETOMETER.setUpdateInterval).toHaveBeenCalledTimes(1);
37
+ expect(FAKE_NATIVE_MAGNETOMETER.setUpdateInterval).toHaveBeenCalledWith(1234);
38
+ });
39
+
40
+ it('subscribes through the shared magnetometerDidUpdate event name', () => {
41
+ const listener = vi.fn();
42
+ Magnetometer.addListener(listener);
43
+
44
+ expect(FAKE_NATIVE_MAGNETOMETER.addListener).toHaveBeenCalledWith(
45
+ 'magnetometerDidUpdate',
46
+ listener,
47
+ );
48
+ });
49
+ });
@@ -0,0 +1,19 @@
1
+ import { DeviceSensor } from './device-sensor';
2
+ import { exponentMagnetometer } from './native/exponent-magnetometer';
3
+
4
+ // Values are the strength of the magnetic field along each axis, measured in microteslas (μT); timestamp is in seconds.
5
+ export type IMagnetometerMeasurement = {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ timestamp: number;
10
+ };
11
+
12
+ export class MagnetometerSensor extends DeviceSensor<IMagnetometerMeasurement> {}
13
+
14
+ const MAGNETOMETER_DID_UPDATE_EVENT_NAME = 'magnetometerDidUpdate';
15
+
16
+ export const Magnetometer = new MagnetometerSensor(
17
+ exponentMagnetometer,
18
+ MAGNETOMETER_DID_UPDATE_EVENT_NAME,
19
+ );
@@ -0,0 +1,9 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { INativeSensorModule } from '../device-sensor';
3
+ import type { IAccelerometerMeasurement } from '../accelerometer';
4
+
5
+ const EXPONENT_ACCELEROMETER_MODULE_NAME = 'ExponentAccelerometer';
6
+
7
+ export const exponentAccelerometer = requireNativeModule<
8
+ INativeSensorModule<IAccelerometerMeasurement>
9
+ >(EXPONENT_ACCELEROMETER_MODULE_NAME);
@@ -0,0 +1,9 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { INativeSensorModule } from '../device-sensor';
3
+ import type { IBarometerMeasurement } from '../barometer';
4
+
5
+ const EXPO_BAROMETER_MODULE_NAME = 'ExpoBarometer';
6
+
7
+ export const exponentBarometer = requireNativeModule<INativeSensorModule<IBarometerMeasurement>>(
8
+ EXPO_BAROMETER_MODULE_NAME,
9
+ );
@@ -0,0 +1,15 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { INativeSensorModule } from '../device-sensor';
3
+ import type { IDeviceMotionMeasurement } from '../device-motion';
4
+
5
+ const EXPONENT_DEVICE_MOTION_MODULE_NAME = 'ExponentDeviceMotion';
6
+
7
+ // The native module also exposes a `Gravity` numeric constant (standard gravitational
8
+ // acceleration, 9.80665 m/s^2) alongside the shared sensor surface.
9
+ type IExponentDeviceMotionModule = INativeSensorModule<IDeviceMotionMeasurement> & {
10
+ Gravity: number;
11
+ };
12
+
13
+ export const exponentDeviceMotion = requireNativeModule<IExponentDeviceMotionModule>(
14
+ EXPONENT_DEVICE_MOTION_MODULE_NAME,
15
+ );
@@ -0,0 +1,9 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { INativeSensorModule } from '../device-sensor';
3
+ import type { IGyroscopeMeasurement } from '../gyroscope';
4
+
5
+ const EXPONENT_GYROSCOPE_MODULE_NAME = 'ExponentGyroscope';
6
+
7
+ export const exponentGyroscope = requireNativeModule<INativeSensorModule<IGyroscopeMeasurement>>(
8
+ EXPONENT_GYROSCOPE_MODULE_NAME,
9
+ );
@@ -0,0 +1,9 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { INativeSensorModule } from '../../device-sensor';
3
+ import type { ILightSensorMeasurement } from '../../light-sensor';
4
+
5
+ const EXPONENT_LIGHT_SENSOR_MODULE_NAME = 'ExpoLightSensor';
6
+
7
+ export const exponentLightSensor = requireNativeModule<
8
+ INativeSensorModule<ILightSensorMeasurement>
9
+ >(EXPONENT_LIGHT_SENSOR_MODULE_NAME);