gps-plus-slam-app-framework 1.3.0 → 1.7.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 (247) hide show
  1. package/dist/absolute-orientation-CAEh840t.d.ts +54 -0
  2. package/dist/{app-selectors-B8VQoMDY.d.ts → app-selectors-ikTUQZpe.d.ts} +1 -1
  3. package/dist/ar/bresenham3d.d.ts +1 -1
  4. package/dist/ar/camera-blit-capture.d.ts +2 -2
  5. package/dist/ar/camera-blit-capture.js +74 -9
  6. package/dist/ar/capability-checker.d.ts +1 -1
  7. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  8. package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
  9. package/dist/ar/depth-grid-lookup.d.ts +2 -0
  10. package/dist/ar/depth-grid-lookup.js +43 -0
  11. package/dist/ar/depth-sampler.d.ts +2 -2
  12. package/dist/ar/depth-sampler.js +2 -4
  13. package/dist/ar/depth-unprojection.d.ts +1 -1
  14. package/dist/ar/enable-gps-ar.d.ts +1 -1
  15. package/dist/ar/enable-gps-ar.js +26 -1
  16. package/dist/ar/frame-loop.d.ts +1 -1
  17. package/dist/ar/image-capture.d.ts +2 -2
  18. package/dist/ar/image-capture.js +1 -154
  19. package/dist/ar/image-quality.d.ts +2 -0
  20. package/dist/ar/image-quality.js +168 -0
  21. package/dist/ar/index.d.ts +31 -19
  22. package/dist/ar/index.js +17 -5
  23. package/dist/ar/occupancy-grid.d.ts +1 -1
  24. package/dist/ar/occupancy-grid.js +29 -2
  25. package/dist/ar/planar-pnp.d.ts +2 -0
  26. package/dist/ar/planar-pnp.js +425 -0
  27. package/dist/ar/qr-debug-view.d.ts +2 -0
  28. package/dist/ar/qr-debug-view.js +89 -0
  29. package/dist/ar/qr-derived-pose.d.ts +2 -0
  30. package/dist/ar/qr-derived-pose.js +114 -0
  31. package/dist/ar/qr-detection-controller.d.ts +2 -0
  32. package/dist/ar/qr-detection-controller.js +2 -0
  33. package/dist/ar/qr-frontend.d.ts +2 -0
  34. package/dist/ar/qr-frontend.js +60 -0
  35. package/dist/ar/qr-pose.d.ts +2 -0
  36. package/dist/ar/qr-pose.js +267 -0
  37. package/dist/ar/qr-size-depth-context.d.ts +3 -0
  38. package/dist/ar/qr-size-depth-context.js +42 -0
  39. package/dist/ar/qr-size-measurer.d.ts +2 -0
  40. package/dist/ar/qr-size-measurer.js +2 -0
  41. package/dist/ar/replay-scene.d.ts +1 -1
  42. package/dist/ar/replay-scene.js +1 -1
  43. package/dist/ar/scene-node-names.d.ts +1 -1
  44. package/dist/ar/webxr-nue-basis.d.ts +1 -1
  45. package/dist/ar/webxr-session.d.ts +4 -4
  46. package/dist/ar/webxr-session.js +2 -2
  47. package/dist/ar/xr-camera-texture.d.ts +1 -1
  48. package/dist/ar/xr-error-handler.d.ts +1 -1
  49. package/dist/ar/xr-frame-loop.d.ts +1 -1
  50. package/dist/ar-MFpFlV7j.js +382 -0
  51. package/dist/{ar-world-group-alignment-C9lwwIyI.d.ts → ar-world-group-alignment-69fgnB39.d.ts} +1 -1
  52. package/dist/{camera-blit-capture-CnxUDbKx.d.ts → camera-blit-capture-NKT9H5-e.d.ts} +57 -4
  53. package/dist/capture-motion-gate-0Yl2NpQG.d.ts +24 -0
  54. package/dist/capture-motion-gate-4EscNZCw.js +94 -0
  55. package/dist/concurrency-By0oOTZt.d.ts +50 -0
  56. package/dist/core/index.d.ts +2 -2
  57. package/dist/core/index.js +2 -2
  58. package/dist/create-slam-app-store-DkCHOpvb.js +149 -0
  59. package/dist/{create-slam-app-store-BljusOua.d.ts → create-slam-app-store-n_VF63D5.d.ts} +50 -40
  60. package/dist/depth-grid-lookup-DQ-IYhO3.d.ts +21 -0
  61. package/dist/{depth-sampler-Bhanfwla.d.ts → depth-sampler-asc8exHt.d.ts} +1 -1
  62. package/dist/{depth-unprojection-Y6i_mJuT.d.ts → depth-unprojection-DjsbJW9L.d.ts} +1 -1
  63. package/dist/{enable-gps-ar-BfUJOgpW.d.ts → enable-gps-ar-DkNhFv4Y.d.ts} +4 -4
  64. package/dist/{frame-conversions-BfsafGWR.d.ts → frame-conversions-DObhj8Wf.d.ts} +1 -1
  65. package/dist/{fused-path-DJoVu98b.d.ts → fused-path-v6eOmLl3.d.ts} +1 -1
  66. package/dist/geo/h3-proximity.d.ts +2 -2
  67. package/dist/geo/h3-proximity.js +61 -2
  68. package/dist/geo/index.d.ts +2 -2
  69. package/dist/geo/index.js +2 -2
  70. package/dist/geodesic-angle-BTldfFgs.js +39 -0
  71. package/dist/{gps-anchor-dYeCvvp5.d.ts → gps-anchor-BeFO2RYa.d.ts} +1 -1
  72. package/dist/{gps-ar-pose-sampler-DVb96iOy.d.ts → gps-ar-pose-sampler-DHMZmYAc.d.ts} +1 -1
  73. package/dist/{gps-event-coordinator-CWIDOk4U.d.ts → gps-event-coordinator-CjWW636x.d.ts} +21 -11
  74. package/dist/{gps-event-markers-Dc9FT-q1.d.ts → gps-event-markers-Cz9RMA2k.d.ts} +18 -0
  75. package/dist/{h3-proximity-I1msGPgE.d.ts → h3-proximity-C-j0pw1j.d.ts} +39 -1
  76. package/dist/image-capture-B2-b6tKK.js +374 -0
  77. package/dist/{image-capture-qAZ5Fh5X.d.ts → image-capture-CNZDrQXG.d.ts} +103 -3
  78. package/dist/image-quality-smCBoFj1.d.ts +158 -0
  79. package/dist/index-BAPokxMb.d.ts +22 -0
  80. package/dist/{index-BYYUdf9v.d.ts → index-BODDUTvD.d.ts} +1 -1
  81. package/dist/index-BneSj4_5.d.ts +399 -0
  82. package/dist/index-_Rhgoqkh.d.ts +2 -0
  83. package/dist/index.d.ts +80 -67
  84. package/dist/index.js +24 -12
  85. package/dist/{leaflet-map-overlay-6CJC-E1l.d.ts → leaflet-map-overlay-CmIyiE8n.d.ts} +1 -1
  86. package/dist/{map-data-CkloBxIl.d.ts → map-data-B4oEehUh.d.ts} +1 -1
  87. package/dist/{map-overlay-draw-krOKwDAq.d.ts → map-overlay-draw-ymz1s7fG.d.ts} +1 -1
  88. package/dist/{null-storage-backend-uKQE8tl7.d.ts → null-storage-backend-B9rtyDfG.d.ts} +2 -2
  89. package/dist/{occupancy-grid-BRNRaPyT.d.ts → occupancy-grid-DnOc-6PU.d.ts} +12 -2
  90. package/dist/{opfs-storage-D5zAn_lx.d.ts → opfs-storage-3VZh-qH6.d.ts} +23 -4
  91. package/dist/{opfs-storage-backend-6aYMUZlJ.d.ts → opfs-storage-backend-JJiUJo-3.d.ts} +3 -3
  92. package/dist/{persistence-middleware-B9ei4Nhx.d.ts → persistence-middleware-DAPTTwB2.d.ts} +1 -1
  93. package/dist/planar-pnp-my9bqULS.d.ts +67 -0
  94. package/dist/qr-debug-view-Brl73HGO.d.ts +29 -0
  95. package/dist/qr-derived-pose-CmxTP2m4.d.ts +122 -0
  96. package/dist/qr-detected-slice-VQssZmQJ.d.ts +166 -0
  97. package/dist/qr-detection-controller-B-tLVd-S.js +119 -0
  98. package/dist/qr-detection-controller-CDurHv8E.d.ts +48 -0
  99. package/dist/qr-frontend--fFX25mV.d.ts +58 -0
  100. package/dist/qr-pose-D2rfu5DA.d.ts +138 -0
  101. package/dist/qr-pose-aggregation-B7tWJq7j.d.ts +90 -0
  102. package/dist/qr-pose-aggregation-DBiaLW0O.js +191 -0
  103. package/dist/qr-size-depth-context-CeAG53fy.d.ts +13 -0
  104. package/dist/qr-size-measurer-DLb33geH.js +596 -0
  105. package/dist/qr-size-measurer-DQdAsid1.d.ts +165 -0
  106. package/dist/recording-options-BPCpMHLK.d.ts +514 -0
  107. package/dist/{recording-replayer-r0DZ9ALp.d.ts → recording-replayer-DQKpAGyQ.d.ts} +2 -2
  108. package/dist/recording-slice-DaxHZvNu.d.ts +55 -0
  109. package/dist/{replay-engine-XpDa0dy1.d.ts → replay-engine-CmKh_4wf.d.ts} +7 -4
  110. package/dist/{replay-scene-Bw58VL6p.d.ts → replay-scene-DBlDrV_x.d.ts} +3 -3
  111. package/dist/sensors/absolute-orientation.d.ts +2 -0
  112. package/dist/sensors/absolute-orientation.js +145 -0
  113. package/dist/sensors/gps-error-handler.d.ts +1 -1
  114. package/dist/sensors/gps.d.ts +1 -1
  115. package/dist/sensors/index.d.ts +5 -4
  116. package/dist/sensors/index.js +2 -1
  117. package/dist/sensors/permission-checker.d.ts +1 -1
  118. package/dist/sensors/permission-checker.js +1 -1
  119. package/dist/state/app-selectors.d.ts +1 -1
  120. package/dist/state/combined-root-state.d.ts +1 -1
  121. package/dist/state/create-slam-app-store.d.ts +1 -1
  122. package/dist/state/create-slam-app-store.js +1 -74
  123. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  124. package/dist/state/gps-event-coordinator.d.ts +2 -2
  125. package/dist/state/gps-event-coordinator.js +27 -17
  126. package/dist/state/index.d.ts +20 -17
  127. package/dist/state/index.js +5 -4
  128. package/dist/state/persistence-middleware.d.ts +1 -1
  129. package/dist/state/persistence-middleware.js +30 -19
  130. package/dist/state/qr-detected-slice.d.ts +4 -0
  131. package/dist/state/qr-detected-slice.js +311 -0
  132. package/dist/state/recording-options.d.ts +2 -2
  133. package/dist/state/recording-options.js +273 -7
  134. package/dist/state/recording-replayer.d.ts +2 -2
  135. package/dist/state/recording-replayer.js +1 -1
  136. package/dist/state/recording-slice.d.ts +1 -1
  137. package/dist/state/recording-slice.js +5 -1
  138. package/dist/state/replay-engine.d.ts +1 -1
  139. package/dist/state/replay-engine.js +7 -3
  140. package/dist/state/store-subscribers.d.ts +2 -2
  141. package/dist/state/subscribe-to-selector.d.ts +1 -1
  142. package/dist/state/tracking-quality.d.ts +2 -2
  143. package/dist/state/tracking-quality.js +40 -128
  144. package/dist/state/tracking-slice.d.ts +1 -1
  145. package/dist/{state-BkIfpiyA.js → state-E51QT_-j.js} +2 -1
  146. package/dist/storage/file-system-utils.d.ts +1 -1
  147. package/dist/storage/index.d.ts +9 -9
  148. package/dist/storage/index.js +4 -4
  149. package/dist/storage/null-storage-backend.d.ts +1 -1
  150. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  151. package/dist/storage/opfs-storage-backend.js +3 -3
  152. package/dist/storage/opfs-storage.d.ts +1 -1
  153. package/dist/storage/opfs-storage.js +5 -4
  154. package/dist/storage/storage-backend.d.ts +1 -1
  155. package/dist/storage/zip-coverage-embed.d.ts +2 -0
  156. package/dist/storage/zip-coverage-embed.js +88 -0
  157. package/dist/storage/zip-export.d.ts +2 -2
  158. package/dist/storage/zip-export.js +37 -59
  159. package/dist/storage/zip-reader.d.ts +1 -1
  160. package/dist/{storage-backend-Do6YDpNo.d.ts → storage-backend-BdVLD0dU.d.ts} +1 -1
  161. package/dist/{store-subscribers-0YWyOLvV.d.ts → store-subscribers-CA6AJH_8.d.ts} +2 -2
  162. package/dist/{subscribe-to-selector-CZ6k1NFP.d.ts → subscribe-to-selector-B6EUmQ3I.d.ts} +1 -1
  163. package/dist/test-utils/browser-mocks.d.ts +7 -1
  164. package/dist/test-utils/browser-mocks.js +6 -0
  165. package/dist/test-utils/zip-round-trip-helpers.d.ts +9 -1
  166. package/dist/test-utils/zip-round-trip-helpers.js +5 -1
  167. package/dist/{tracking-slice-CdK8c-8P.d.ts → tracking-slice-BuAZxXZ5.d.ts} +1 -1
  168. package/dist/types/ar-types.d.ts +1 -1
  169. package/dist/types/geo-types.d.ts +1 -1
  170. package/dist/types/index.d.ts +2 -2
  171. package/dist/utils/concurrency.d.ts +2 -2
  172. package/dist/utils/concurrency.js +66 -2
  173. package/dist/utils/failure-tracker.d.ts +1 -1
  174. package/dist/utils/format-file-size.d.ts +1 -1
  175. package/dist/utils/fused-path.d.ts +1 -1
  176. package/dist/utils/index.d.ts +8 -7
  177. package/dist/utils/index.js +2 -1
  178. package/dist/utils/list-formatter.d.ts +1 -1
  179. package/dist/utils/logger.d.ts +1 -1
  180. package/dist/visualization/accuracy-circles.d.ts +1 -1
  181. package/dist/visualization/alignment-lerper.d.ts +1 -1
  182. package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
  183. package/dist/visualization/ar-world-group-alignment.js +1 -1
  184. package/dist/visualization/camera-follower.d.ts +1 -1
  185. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  186. package/dist/visualization/frame-conversions.d.ts +1 -1
  187. package/dist/visualization/frustum-visibility.d.ts +1 -1
  188. package/dist/visualization/gps-anchor.d.ts +1 -1
  189. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  190. package/dist/visualization/gps-event-markers.d.ts +1 -1
  191. package/dist/visualization/gps-event-markers.js +40 -5
  192. package/dist/visualization/hit-test-reticle.d.ts +1 -1
  193. package/dist/visualization/hit-test-reticle.js +1 -0
  194. package/dist/visualization/index.d.ts +18 -18
  195. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  196. package/dist/visualization/leaflet-map-overlay.js +15 -3
  197. package/dist/visualization/lerp-utils.d.ts +1 -1
  198. package/dist/visualization/map-data.d.ts +1 -1
  199. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  200. package/dist/visualization/map-overlay.d.ts +1 -1
  201. package/dist/visualization/three-dispose.d.ts +1 -1
  202. package/dist/visualization/vis-colors.d.ts +1 -1
  203. package/dist/{webxr-session-TIaD883f.js → webxr-session-DG-eNfny.js} +244 -11
  204. package/dist/{webxr-session-GjZ2BIpS.d.ts → webxr-session-Do5L6G3B.d.ts} +86 -8
  205. package/dist/zip-coverage-embed-DCAREVmw.d.ts +41 -0
  206. package/dist/{zip-export-G14hkSPG.d.ts → zip-export-ol0S_Ofd.d.ts} +27 -23
  207. package/package.json +2 -2
  208. package/dist/concurrency-CO1FQvs3.d.ts +0 -24
  209. package/dist/file-system-CwXTNHmB.d.ts +0 -114
  210. package/dist/index-CF05QV2m.d.ts +0 -2
  211. package/dist/recording-options-DJBXuMxV.d.ts +0 -182
  212. package/dist/recording-slice-89O07ebs.d.ts +0 -36
  213. package/dist/storage/file-system.d.ts +0 -2
  214. package/dist/storage/file-system.js +0 -289
  215. /package/dist/{accuracy-circles-BpwWAs8G.d.ts → accuracy-circles-BtqOP_v1.d.ts} +0 -0
  216. /package/dist/{alignment-lerper-Dm9G7JJO.d.ts → alignment-lerper-Bil6vbVw.d.ts} +0 -0
  217. /package/dist/{ar-types-Dan1MVTi.d.ts → ar-types-BFX2r1wk.d.ts} +0 -0
  218. /package/dist/{bresenham3d-CFfd7n6B.d.ts → bresenham3d-CU1Gv2W4.d.ts} +0 -0
  219. /package/dist/{camera-follower-C2mwEn7c.d.ts → camera-follower-CqJJ7zRj.d.ts} +0 -0
  220. /package/dist/{capability-checker-CQXJHxXg.d.ts → capability-checker-DUQLg6gq.d.ts} +0 -0
  221. /package/dist/{capture-failure-tracker-CUeU3L_M.d.ts → capture-failure-tracker-gsm8q7yi.d.ts} +0 -0
  222. /package/dist/{chromium-camera-access-workaround-Jqbn0apH.d.ts → chromium-camera-access-workaround-D4K2uwwQ.d.ts} +0 -0
  223. /package/dist/{css3d-renderer-manager-ptu_t3B3.d.ts → css3d-renderer-manager-B3kGNtcn.d.ts} +0 -0
  224. /package/dist/{failure-tracker-Cn8Fo9D4.d.ts → failure-tracker-BO7M7jF_.d.ts} +0 -0
  225. /package/dist/{file-system-utils-CXIoL-DM.d.ts → file-system-utils-DOajnMm-.d.ts} +0 -0
  226. /package/dist/{format-file-size-CLCZz3lC.d.ts → format-file-size-Dc98ulzB.d.ts} +0 -0
  227. /package/dist/{frame-loop-CMewS8cY.d.ts → frame-loop-CpVjQ1dH.d.ts} +0 -0
  228. /package/dist/{frustum-visibility-CmI96ESS.d.ts → frustum-visibility-CeoCZchO.d.ts} +0 -0
  229. /package/dist/{geo-types-SaPnIEUM.d.ts → geo-types-3Ip1NzVR.d.ts} +0 -0
  230. /package/dist/{gps-VuezJWK3.d.ts → gps-BBO3hKfT.d.ts} +0 -0
  231. /package/dist/{gps-compass-cubes-BM1uGiYV.d.ts → gps-compass-cubes-DSN87L8p.d.ts} +0 -0
  232. /package/dist/{gps-error-handler-CJl_2MVm.d.ts → gps-error-handler-BbPsfw-_.d.ts} +0 -0
  233. /package/dist/{hit-test-reticle-BEzEybxZ.d.ts → hit-test-reticle-DV-2TpB9.d.ts} +0 -0
  234. /package/dist/{lerp-utils-BpV-0Dtk.d.ts → lerp-utils-BLmHhkVe.d.ts} +0 -0
  235. /package/dist/{list-formatter-RRcBe8Vg.d.ts → list-formatter-KNMS0ay2.d.ts} +0 -0
  236. /package/dist/{logger-BEHXsnnq.d.ts → logger-CLnPrHiD.d.ts} +0 -0
  237. /package/dist/{map-overlay-bcogY5fK.d.ts → map-overlay-Dh2B97MP.d.ts} +0 -0
  238. /package/dist/{permission-checker-GpAiSCwd.d.ts → permission-checker-CDuI8BwC.d.ts} +0 -0
  239. /package/dist/{scene-node-names-Bu0S66H1.d.ts → scene-node-names-BiShOQDB.d.ts} +0 -0
  240. /package/dist/{session-disposers-M-oashRH.js → session-disposers-zv9OGXPB.js} +0 -0
  241. /package/dist/{three-dispose-D950t71B.d.ts → three-dispose-Bt1k7WKh.d.ts} +0 -0
  242. /package/dist/{vis-colors-D6omC64K.d.ts → vis-colors-Obw2pLqT.d.ts} +0 -0
  243. /package/dist/{webxr-nue-basis-CqKQmZzT.d.ts → webxr-nue-basis-3nfjDJJp.d.ts} +0 -0
  244. /package/dist/{xr-camera-texture-DBwCaKTd.d.ts → xr-camera-texture-Cva1q3Qj.d.ts} +0 -0
  245. /package/dist/{xr-error-handler-C0AQRmxs.d.ts → xr-error-handler-CtvHpjfm.d.ts} +0 -0
  246. /package/dist/{xr-frame-loop-BtYytZJg.d.ts → xr-frame-loop-DIYtRcUa.d.ts} +0 -0
  247. /package/dist/{zip-reader-DSEXt7K6.d.ts → zip-reader-D9iPQwdQ.d.ts} +0 -0
@@ -0,0 +1,54 @@
1
+ //#region ../src/sensors/absolute-orientation.d.ts
2
+ /**
3
+ * AbsoluteOrientationSensor capture (Generic Sensor API).
4
+ *
5
+ * Phase 1 of the AbsoluteOrientationSensor plan
6
+ * (GpsPlusSlamJs_Docs/docs/2026-06-25-absolute-orientation-sensor-plan.md §5.1):
7
+ * passive instrumentation that fuses accelerometer + gyroscope + magnetometer
8
+ * into an Earth-referenced (ENU) quaternion, captured per GPS event as an
9
+ * independent north reference. No production behaviour change.
10
+ *
11
+ * Platform: Chrome Android only. Safari / Firefox / desktop / iOS lack the
12
+ * sensor → this module degrades to a clean, reported no-op.
13
+ *
14
+ * The raw `'device'` reference frame is recorded together with the screen angle
15
+ * so either the device- or screen-compensated form can be reconstructed offline
16
+ * (plan §8 Q1).
17
+ */
18
+ /** A single absolute-orientation reading, snapshotted into the GPS event payload. */
19
+ interface AbsoluteOrientationReading {
20
+ /** [x,y,z,w] quaternion mapping device-frame → Earth ENU (+X East, +Y North, +Z Up). */
21
+ quaternion: [number, number, number, number];
22
+ /** Reference frame the quaternion is expressed in. We record raw 'device'. */
23
+ referenceFrame: 'device' | 'screen';
24
+ /** screen.orientation.angle at sample time — needed to reconstruct the 'device' frame. */
25
+ screenAngleDeg: number;
26
+ /** Capture time (epoch ms) — pairs with the GPS event; lets warm-up be detected offline. */
27
+ timestamp: number;
28
+ }
29
+ /** Lifecycle status surfaced to the caller (HUD/observability). */
30
+ type AbsoluteOrientationStatus = {
31
+ state: 'active';
32
+ } | {
33
+ state: 'unavailable';
34
+ reason: string;
35
+ } | {
36
+ state: 'error';
37
+ reason: string;
38
+ };
39
+ /** True when the sensor can plausibly run here (secure context + API present). */
40
+ declare function isAbsoluteOrientationAvailable(): boolean;
41
+ /**
42
+ * Start capturing absolute orientation. Idempotent (stops any prior watch first).
43
+ *
44
+ * On platforms without the sensor — or when permissions are denied — it reports
45
+ * `unavailable`/`error` via `onStatus` and stays a no-op; the recorder keeps
46
+ * working unchanged. Never throws.
47
+ */
48
+ declare function startAbsoluteOrientationWatch(onStatus?: (status: AbsoluteOrientationStatus) => void): Promise<void>;
49
+ /** Latest reading, or null when unavailable/not-yet-warmed-up. Mirrors getLastDeviceOrientation. */
50
+ declare function getLatestAbsoluteOrientation(): AbsoluteOrientationReading | null;
51
+ /** Stop the watch and clear cached state. Idempotent. */
52
+ declare function stopAbsoluteOrientationWatch(): void;
53
+ //#endregion
54
+ export { startAbsoluteOrientationWatch as a, isAbsoluteOrientationAvailable as i, AbsoluteOrientationStatus as n, stopAbsoluteOrientationWatch as o, getLatestAbsoluteOrientation as r, AbsoluteOrientationReading as t };
@@ -1,4 +1,4 @@
1
- import { L as CombinedRootState, r as SlamAppRootState } from "./create-slam-app-store-BljusOua.js";
1
+ import { N as CombinedRootState, r as SlamAppRootState } from "./create-slam-app-store-n_VF63D5.js";
2
2
  import * as _$gps_plus_slam_js0 from "gps-plus-slam-js";
3
3
  import { ArImageCapture, GpsPoint, LatLong, Matrix4, Quaternion, Vector3 } from "gps-plus-slam-js";
4
4
  import * as _$_reduxjs_toolkit0 from "@reduxjs/toolkit";
@@ -1,2 +1,2 @@
1
- import { n as MAX_TRACE_STEPS, r as bresenham3d, t as GridCell } from "../bresenham3d-CFfd7n6B.js";
1
+ import { n as MAX_TRACE_STEPS, r as bresenham3d, t as GridCell } from "../bresenham3d-CU1Gv2W4.js";
2
2
  export { GridCell, MAX_TRACE_STEPS, bresenham3d };
@@ -1,2 +1,2 @@
1
- import { i as computeCaptureSize, n as CameraBlitCaptureConfig, r as DEFAULT_BLIT_CONFIG, t as CameraBlitCapture } from "../camera-blit-capture-CnxUDbKx.js";
2
- export { CameraBlitCapture, CameraBlitCaptureConfig, DEFAULT_BLIT_CONFIG, computeCaptureSize };
1
+ import { a as computeCaptureSize, i as computeAspectFitSize, n as CameraBlitCaptureConfig, r as DEFAULT_BLIT_CONFIG, t as CameraBlitCapture } from "../camera-blit-capture-NKT9H5-e.js";
2
+ export { CameraBlitCapture, CameraBlitCaptureConfig, DEFAULT_BLIT_CONFIG, computeAspectFitSize, computeCaptureSize };
@@ -51,6 +51,36 @@ function computeCaptureSize(cameraWidth, cameraHeight, divisor) {
51
51
  };
52
52
  }
53
53
  /**
54
+ * Compute blit dimensions that PRESERVE the camera aspect ratio with the
55
+ * **longer edge fixed at `maxEdge`**. Unlike {@link computeCaptureSize} (which
56
+ * divides the native resolution by a user divisor), this fits the frame into a
57
+ * fixed pixel budget, so a 4:3 camera becomes e.g. 512×384 — NOT a stretched
58
+ * 512×512. Used by the QR-detection blit (B2) so the detector sees an
59
+ * undistorted code while the readback cost stays bounded by `maxEdge²`.
60
+ *
61
+ * @param cameraWidth - Native camera width in pixels (from XRCamera)
62
+ * @param cameraHeight - Native camera height in pixels (from XRCamera)
63
+ * @param maxEdge - Target length (px) of the longer output edge.
64
+ * @returns Integer dimensions, longer edge == `maxEdge`, aspect preserved
65
+ * (within rounding), each clamped to ≥ 1. When `maxEdge` itself is invalid
66
+ * (< 1 / NaN / Infinity) the longer edge falls back to
67
+ * `DEFAULT_BLIT_CONFIG.width` (still aspect-preserving). When the camera
68
+ * dimensions are invalid (≤ 0 / NaN / Infinity) the aspect is unknown, so it
69
+ * returns a square at the (possibly defaulted) edge.
70
+ */
71
+ function computeAspectFitSize(cameraWidth, cameraHeight, maxEdge) {
72
+ const safeEdge = maxEdge >= 1 && Number.isFinite(maxEdge) ? Math.floor(maxEdge) : DEFAULT_BLIT_CONFIG.width;
73
+ if (!(cameraWidth > 0) || !Number.isFinite(cameraWidth) || !(cameraHeight > 0) || !Number.isFinite(cameraHeight)) return {
74
+ width: safeEdge,
75
+ height: safeEdge
76
+ };
77
+ const scale = safeEdge / Math.max(cameraWidth, cameraHeight);
78
+ return {
79
+ width: Math.max(1, Math.round(cameraWidth * scale)),
80
+ height: Math.max(1, Math.round(cameraHeight * scale))
81
+ };
82
+ }
83
+ /**
54
84
  * Number of sampled pixels to check in isBlackFrame.
55
85
  * We sample a subset rather than checking every pixel for speed.
56
86
  */
@@ -168,6 +198,32 @@ var CameraBlitCapture = class {
168
198
  }
169
199
  }
170
200
  /**
201
+ * Capture the camera texture as **top-left-origin** RGBA — the orientation
202
+ * QR detection (and `BarcodeDetector`) expects — returning a FRESH copy that
203
+ * is safe to retain beyond the next capture.
204
+ *
205
+ * This is the efficient replacement for the demo's old JPEG round-trip: blit
206
+ * + readback (shared with {@link captureToBlob} / {@link captureToPixels}),
207
+ * then the same vertical flip the JPEG encoder applies, but with no encode →
208
+ * decode. Unlike {@link captureToPixels} (which returns the reusable internal
209
+ * buffer in WebGL bottom-row-first order), this returns an owned,
210
+ * correctly-oriented `Uint8ClampedArray`.
211
+ *
212
+ * IMPORTANT: Must be called within the XR animation frame callback, while the
213
+ * camera texture is valid.
214
+ *
215
+ * @returns `{ data, width, height }` (top-left RGBA), or null on
216
+ * failure/dispose.
217
+ */
218
+ captureToRgba(renderer, cameraTexture) {
219
+ if (!this.captureToPixels(renderer, cameraTexture)) return null;
220
+ return {
221
+ data: this.flippedPixelCopy(),
222
+ width: this.width,
223
+ height: this.height
224
+ };
225
+ }
226
+ /**
171
227
  * Check if a pixel buffer is entirely black (all zeros).
172
228
  * Uses sampling for performance (checks BLACK_CHECK_SAMPLE_COUNT evenly-spaced pixels).
173
229
  *
@@ -197,10 +253,19 @@ var CameraBlitCapture = class {
197
253
  return this.pixelsToJpegViaCanvas(quality);
198
254
  }
199
255
  getFlippedImageData() {
200
- const clampedBuffer = new Uint8ClampedArray(this.pixelBuffer);
201
- const imageData = new ImageData(clampedBuffer, this.width, this.height);
202
- this.flipImageDataVertically(imageData);
203
- return imageData;
256
+ return new ImageData(this.flippedPixelCopy(), this.width, this.height);
257
+ }
258
+ /**
259
+ * Produce a FRESH, top-left-origin RGBA copy of the internal readback buffer.
260
+ * WebGL `readPixels` returns bottom-row-first; this copies (so the internal
261
+ * buffer stays y-flipped for a subsequent capture) and swaps rows. Shared by
262
+ * the JPEG encode path ({@link getFlippedImageData}) and {@link captureToRgba}.
263
+ */
264
+ flippedPixelCopy() {
265
+ const copy = new Uint8ClampedArray(this.pixelBuffer.length);
266
+ copy.set(this.pixelBuffer);
267
+ this.flipRowsVertically(copy, this.width, this.height);
268
+ return copy;
204
269
  }
205
270
  async pixelsToJpegViaOffscreenCanvas(quality) {
206
271
  const offscreen = new OffscreenCanvas(this.width, this.height);
@@ -229,11 +294,11 @@ var CameraBlitCapture = class {
229
294
  });
230
295
  }
231
296
  /**
232
- * Flip ImageData vertically in-place.
233
- * WebGL readPixels returns bottom-row-first; canvas expects top-row-first.
297
+ * Flip an RGBA buffer vertically in-place (row swap).
298
+ * WebGL readPixels returns bottom-row-first; canvas / detectors expect
299
+ * top-row-first.
234
300
  */
235
- flipImageDataVertically(imageData) {
236
- const { data, width, height } = imageData;
301
+ flipRowsVertically(data, width, height) {
237
302
  const rowSize = width * 4;
238
303
  const tempRow = new Uint8ClampedArray(rowSize);
239
304
  for (let y = 0; y < Math.floor(height / 2); y++) {
@@ -291,4 +356,4 @@ var CameraBlitCapture = class {
291
356
  }
292
357
  };
293
358
  //#endregion
294
- export { CameraBlitCapture, DEFAULT_BLIT_CONFIG, computeCaptureSize };
359
+ export { CameraBlitCapture, DEFAULT_BLIT_CONFIG, computeAspectFitSize, computeCaptureSize };
@@ -1,2 +1,2 @@
1
- import { i as isFullySupported, n as CapabilitySupport, r as capabilityMessage, t as CapabilityMessageOptions } from "../capability-checker-CQXJHxXg.js";
1
+ import { i as isFullySupported, n as CapabilitySupport, r as capabilityMessage, t as CapabilityMessageOptions } from "../capability-checker-DUQLg6gq.js";
2
2
  export { CapabilityMessageOptions, CapabilitySupport, capabilityMessage, isFullySupported };
@@ -1,2 +1,2 @@
1
- import { a as createCaptureFailureTracker, i as DEFAULT_CAPTURE_TRACKER_CONFIG, n as CaptureFailureTracker, r as CaptureFailureTrackerConfig, t as CAPTURE_FAILURE_WARNING } from "../capture-failure-tracker-CUeU3L_M.js";
1
+ import { a as createCaptureFailureTracker, i as DEFAULT_CAPTURE_TRACKER_CONFIG, n as CaptureFailureTracker, r as CaptureFailureTrackerConfig, t as CAPTURE_FAILURE_WARNING } from "../capture-failure-tracker-gsm8q7yi.js";
2
2
  export { CAPTURE_FAILURE_WARNING, CaptureFailureTracker, CaptureFailureTrackerConfig, DEFAULT_CAPTURE_TRACKER_CONFIG, createCaptureFailureTracker };
@@ -1,2 +1,2 @@
1
- import { a as applyChromiumProjectionLayerWorkaround, i as ChromiumProjectionLayerWorkaroundResult, n as BASELAYER_WINDOW_MIN, o as needsBaseLayerPersistence, r as ChromeVersion, s as parseChromeVersion, t as BASELAYER_WINDOW_MAX } from "../chromium-camera-access-workaround-Jqbn0apH.js";
1
+ import { a as applyChromiumProjectionLayerWorkaround, i as ChromiumProjectionLayerWorkaroundResult, n as BASELAYER_WINDOW_MIN, o as needsBaseLayerPersistence, r as ChromeVersion, s as parseChromeVersion, t as BASELAYER_WINDOW_MAX } from "../chromium-camera-access-workaround-D4K2uwwQ.js";
2
2
  export { BASELAYER_WINDOW_MAX, BASELAYER_WINDOW_MIN, ChromeVersion, ChromiumProjectionLayerWorkaroundResult, applyChromiumProjectionLayerWorkaround, needsBaseLayerPersistence, parseChromeVersion };
@@ -0,0 +1,2 @@
1
+ import { n as createDepthGridLookup, t as DepthGridLookup } from "../depth-grid-lookup-DQ-IYhO3.js";
2
+ export { DepthGridLookup, createDepthGridLookup };
@@ -0,0 +1,43 @@
1
+ //#region ../src/ar/depth-grid-lookup.ts
2
+ /** A node's depth if finite and positive, else `null` (a grid hole). */
3
+ function validDepth(points, index) {
4
+ const p = points[index];
5
+ if (!p) return null;
6
+ const d = p.depthM;
7
+ return Number.isFinite(d) && d > 0 ? d : null;
8
+ }
9
+ /**
10
+ * Build a bilinear lookup over a depth-sampler grid.
11
+ *
12
+ * @param points - the grid `DepthPoint`s (row-major, `row·g + col`).
13
+ * @param gridSize - points-per-side; inferred as `round(√points.length)` when
14
+ * omitted (the sampler always emits a full `g²` grid).
15
+ */
16
+ function createDepthGridLookup(points, gridSize) {
17
+ const g = gridSize ?? Math.round(Math.sqrt(points.length));
18
+ if (g < 2 || points.length < g * g) return { depthAt() {
19
+ for (let i = 0; i < points.length; i++) {
20
+ const d = validDepth(points, i);
21
+ if (d !== null) return d;
22
+ }
23
+ return null;
24
+ } };
25
+ return { depthAt(screenX, screenY) {
26
+ const gx = screenX * (g + 1) - 1;
27
+ const gy = screenY * (g + 1) - 1;
28
+ if (gx < 0 || gx > g - 1 || gy < 0 || gy > g - 1) return null;
29
+ const col0 = Math.min(Math.floor(gx), g - 2);
30
+ const row0 = Math.min(Math.floor(gy), g - 2);
31
+ const fx = gx - col0;
32
+ const fy = gy - row0;
33
+ const d00 = validDepth(points, row0 * g + col0);
34
+ const d10 = validDepth(points, row0 * g + col0 + 1);
35
+ const d01 = validDepth(points, (row0 + 1) * g + col0);
36
+ const d11 = validDepth(points, (row0 + 1) * g + col0 + 1);
37
+ if (d00 === null || d10 === null || d01 === null || d11 === null) return null;
38
+ const top = d00 + (d10 - d00) * fx;
39
+ return top + (d01 + (d11 - d01) * fx - top) * fy;
40
+ } };
41
+ }
42
+ //#endregion
43
+ export { createDepthGridLookup };
@@ -1,3 +1,3 @@
1
- import { i as DepthSample } from "../ar-types-Dan1MVTi.js";
2
- import { a as wrapXRDepthInfo, i as DepthSamplerConfig, n as DepthSampler, r as DepthSamplerCallbacks, t as DepthInfo } from "../depth-sampler-Bhanfwla.js";
1
+ import { i as DepthSample } from "../ar-types-BFX2r1wk.js";
2
+ import { a as wrapXRDepthInfo, i as DepthSamplerConfig, n as DepthSampler, r as DepthSamplerCallbacks, t as DepthInfo } from "../depth-sampler-asc8exHt.js";
3
3
  export { DepthInfo, DepthSample, DepthSampler, DepthSamplerCallbacks, DepthSamplerConfig, wrapXRDepthInfo };
@@ -56,10 +56,8 @@ var DepthSampler = class {
56
56
  unavailableCallbackFired = false;
57
57
  constructor(callbacks, config) {
58
58
  this.callbacks = callbacks;
59
- this.config = {
60
- ...DEFAULT_CONFIG,
61
- ...config
62
- };
59
+ this.config = { ...DEFAULT_CONFIG };
60
+ if (config) this.updateConfig(config);
63
61
  }
64
62
  /**
65
63
  * Start depth sampling.
@@ -1,2 +1,2 @@
1
- import { n as createDepthUnprojector, r as unprojectDepthPoint, t as DepthUnprojector } from "../depth-unprojection-Y6i_mJuT.js";
1
+ import { n as createDepthUnprojector, r as unprojectDepthPoint, t as DepthUnprojector } from "../depth-unprojection-DjsbJW9L.js";
2
2
  export { DepthUnprojector, createDepthUnprojector, unprojectDepthPoint };
@@ -1,2 +1,2 @@
1
- import { a as EnableGpsArState, i as EnableGpsArResult, n as EnableGpsArController, o as EnableGpsArStatus, r as EnableGpsArDeps, s as createEnableGpsArController, t as EnableGpsArConfig } from "../enable-gps-ar-BfUJOgpW.js";
1
+ import { a as EnableGpsArState, i as EnableGpsArResult, n as EnableGpsArController, o as EnableGpsArStatus, r as EnableGpsArDeps, s as createEnableGpsArController, t as EnableGpsArConfig } from "../enable-gps-ar-DkNhFv4Y.js";
2
2
  export { EnableGpsArConfig, EnableGpsArController, EnableGpsArDeps, EnableGpsArResult, EnableGpsArState, EnableGpsArStatus, createEnableGpsArController };
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../utils/logger.js";
2
+ import { a as endARSession, b as isWebXRSupported, y as initAR } from "../webxr-session-DG-eNfny.js";
2
3
  import { requestGeolocationPermission, requestOrientationPermission, requestWebXRWithDepthPermission } from "../sensors/permission-checker.js";
3
4
  import { startGpsWatch, startOrientationWatch, stopGpsWatch, stopOrientationWatch } from "../sensors/gps.js";
4
- import { _ as isWebXRSupported, g as initAR, i as endARSession } from "../webxr-session-TIaD883f.js";
5
5
  //#region ../src/ar/enable-gps-ar.ts
6
6
  const log = createLogger("EnableGpsAr");
7
7
  const defaultDeps = {
@@ -74,10 +74,12 @@ function createEnableGpsArController(deps = {}) {
74
74
  error: "AR is already starting, running or stopping."
75
75
  };
76
76
  setState({ status: "starting" });
77
+ let sessionStarted = false;
77
78
  try {
78
79
  const permissionError = await requestPermissions(config);
79
80
  if (permissionError !== null) return fail(permissionError);
80
81
  await resolved.initAR(config.container, config.isolationOptions, { requestHitTest: config.requestHitTest });
82
+ sessionStarted = true;
81
83
  if (config.onGpsPosition) {
82
84
  resolved.startGpsWatch(config.onGpsPosition);
83
85
  gpsWatchActive = true;
@@ -89,6 +91,29 @@ function createEnableGpsArController(deps = {}) {
89
91
  setState({ status: "running" });
90
92
  return { ok: true };
91
93
  } catch (err) {
94
+ if (sessionStarted) {
95
+ if (gpsWatchActive) {
96
+ try {
97
+ resolved.stopGpsWatch();
98
+ } catch (cleanupErr) {
99
+ log.error("stopGpsWatch during enable() cleanup threw:", cleanupErr);
100
+ }
101
+ gpsWatchActive = false;
102
+ }
103
+ if (orientationWatchActive) {
104
+ try {
105
+ resolved.stopOrientationWatch();
106
+ } catch (cleanupErr) {
107
+ log.error("stopOrientationWatch during enable() cleanup threw:", cleanupErr);
108
+ }
109
+ orientationWatchActive = false;
110
+ }
111
+ try {
112
+ await resolved.endARSession();
113
+ } catch (cleanupErr) {
114
+ log.error("Cleanup after enable() failure threw; continuing:", cleanupErr);
115
+ }
116
+ }
92
117
  return fail(err instanceof Error ? err.message : String(err));
93
118
  }
94
119
  }
@@ -1,2 +1,2 @@
1
- import { i as runFrameUpdates, n as clearFrameUpdates, r as registerFrameUpdate, t as FrameUpdate } from "../frame-loop-CMewS8cY.js";
1
+ import { i as runFrameUpdates, n as clearFrameUpdates, r as registerFrameUpdate, t as FrameUpdate } from "../frame-loop-CpVjQ1dH.js";
2
2
  export { FrameUpdate, clearFrameUpdates, registerFrameUpdate, runFrameUpdates };
@@ -1,2 +1,2 @@
1
- import { a as ImageCaptureConfig, i as ImageCaptureCallbacks, n as CapturedImage, o as ImageCaptureManager, r as DEFAULT_CAPTURE_CONFIG, s as MIN_VALID_IMAGE_BYTES, t as CapturedFrame } from "../image-capture-qAZ5Fh5X.js";
2
- export { CapturedFrame, CapturedImage, DEFAULT_CAPTURE_CONFIG, ImageCaptureCallbacks, ImageCaptureConfig, ImageCaptureManager, MIN_VALID_IMAGE_BYTES };
1
+ import { a as ImageCaptureCallbacks, c as MIN_VALID_IMAGE_BYTES, i as FrameQualityVerdict, n as CapturedImage, o as ImageCaptureConfig, r as DEFAULT_CAPTURE_CONFIG, s as ImageCaptureManager, t as CapturedFrame } from "../image-capture-CNZDrQXG.js";
2
+ export { CapturedFrame, CapturedImage, DEFAULT_CAPTURE_CONFIG, FrameQualityVerdict, ImageCaptureCallbacks, ImageCaptureConfig, ImageCaptureManager, MIN_VALID_IMAGE_BYTES };
@@ -1,155 +1,2 @@
1
- import { createLogger } from "../utils/logger.js";
2
- //#region ../src/ar/image-capture.ts
3
- /**
4
- * Image Capture Module
5
- *
6
- * Captures periodic JPEG screenshots from the WebGL canvas during AR recording.
7
- * Uses async toBlob() for better performance (non-blocking).
8
- *
9
- * Includes validation to detect suspiciously small images (likely black/empty)
10
- * which can occur on mobile devices when the WebGL context hasn't composited yet.
11
- */
12
- const log = createLogger("ImageCapture");
13
- /**
14
- * Minimum expected blob size in bytes for a valid JPEG image.
15
- * A black/empty 1920x1080 JPEG still compresses to ~2-3KB due to headers.
16
- * A real camera frame at 0.7 quality should be 50KB+.
17
- * We use a conservative threshold to catch obviously broken captures.
18
- */
19
- const MIN_VALID_IMAGE_BYTES = 5e3;
20
- /**
21
- * Default capture configuration
22
- */
23
- const DEFAULT_CAPTURE_CONFIG = {
24
- intervalMs: 2e3,
25
- quality: .7,
26
- captureTimeoutMs: 5e3,
27
- resolutionDivisor: 1
28
- };
29
- /**
30
- * Manages periodic image capture from a canvas.
31
- *
32
- * Usage:
33
- * 1. Create with canvas and callbacks
34
- * 2. Call start() when recording begins
35
- * 3. Call onFrame(time) each XR frame
36
- * 4. Call stop() when recording ends
37
- */
38
- var ImageCaptureManager = class {
39
- canvas;
40
- callbacks;
41
- config;
42
- capturing = false;
43
- lastCaptureTime = 0;
44
- frameCount = 0;
45
- captureInProgress = false;
46
- captureTimeoutId = null;
47
- constructor(canvas, callbacks, config = DEFAULT_CAPTURE_CONFIG) {
48
- this.canvas = canvas;
49
- this.callbacks = callbacks;
50
- this.config = config;
51
- }
52
- /**
53
- * Start capturing images.
54
- * Resets frame counter and last capture time.
55
- */
56
- start() {
57
- this.capturing = true;
58
- this.lastCaptureTime = 0;
59
- this.frameCount = 0;
60
- }
61
- /**
62
- * Stop capturing images.
63
- * Clears any pending safety timeout and resets in-flight capture state.
64
- */
65
- stop() {
66
- this.capturing = false;
67
- this.clearCaptureTimeout();
68
- this.captureInProgress = false;
69
- }
70
- /**
71
- * Check if capture manager is active.
72
- */
73
- isCapturing() {
74
- return this.capturing;
75
- }
76
- /**
77
- * Get the current frame count.
78
- */
79
- getFrameCount() {
80
- return this.frameCount;
81
- }
82
- /**
83
- * Called each XR frame to check if a capture is needed.
84
- *
85
- * @param time - Frame timestamp in milliseconds (from requestAnimationFrame)
86
- */
87
- onFrame(time) {
88
- if (!this.capturing) return;
89
- if (this.captureInProgress) return;
90
- const elapsed = time - this.lastCaptureTime;
91
- if (this.lastCaptureTime > 0 && elapsed < this.config.intervalMs) return;
92
- const pose = this.callbacks.getCurrentPose();
93
- if (!pose) return;
94
- this.captureInProgress = true;
95
- this.lastCaptureTime = time;
96
- const timestamp = performance.timeOrigin + time;
97
- const screenRotation = this.callbacks.getScreenRotation();
98
- const frameIndex = ++this.frameCount;
99
- this.captureTimeoutId = setTimeout(() => {
100
- if (this.captureInProgress) {
101
- log.error(`Capture timeout after ${this.config.captureTimeoutMs}ms — force-resetting captureInProgress`);
102
- this.captureInProgress = false;
103
- this.captureTimeoutId = null;
104
- }
105
- }, this.config.captureTimeoutMs);
106
- if (this.callbacks.captureFrame) this.callbacks.captureFrame(this.config.quality).then((frame) => {
107
- this.handleCapturedBlob(frame?.blob ?? null, frame?.width, frame?.height, timestamp, frameIndex, pose, screenRotation);
108
- }).catch(() => {
109
- this.clearCaptureTimeout();
110
- this.captureInProgress = false;
111
- this.callbacks.onCaptureFailed?.();
112
- });
113
- else this.canvas.toBlob((blob) => {
114
- this.handleCapturedBlob(blob, this.canvas.width, this.canvas.height, timestamp, frameIndex, pose, screenRotation);
115
- }, "image/jpeg", this.config.quality);
116
- }
117
- /**
118
- * Clear the safety timeout for captureInProgress.
119
- * Called when capture completes (success or failure) before the timeout fires.
120
- */
121
- clearCaptureTimeout() {
122
- if (this.captureTimeoutId !== null) {
123
- clearTimeout(this.captureTimeoutId);
124
- this.captureTimeoutId = null;
125
- }
126
- }
127
- /**
128
- * Common handler for captured blobs (from either canvas.toBlob or captureFrame).
129
- * Handles null blobs, suspicious image detection, and dispatching onCaptured.
130
- */
131
- handleCapturedBlob(blob, width, height, timestamp, frameIndex, pose, screenRotation) {
132
- this.clearCaptureTimeout();
133
- this.captureInProgress = false;
134
- if (!blob) {
135
- this.callbacks.onCaptureFailed?.();
136
- return;
137
- }
138
- if (blob.size < 5e3) {
139
- log.error(`Suspicious image at frame ${frameIndex}: blob size ${blob.size} bytes is below minimum ${MIN_VALID_IMAGE_BYTES} bytes. Image may be black/empty.`);
140
- this.callbacks.onSuspiciousImage?.(blob.size, frameIndex);
141
- }
142
- this.callbacks.onCaptured({
143
- blob,
144
- timestamp,
145
- frameIndex,
146
- position: pose.position,
147
- rotation: pose.orientation,
148
- screenRotation,
149
- ...width && width > 0 ? { width } : {},
150
- ...height && height > 0 ? { height } : {}
151
- });
152
- }
153
- };
154
- //#endregion
1
+ import { n as ImageCaptureManager, r as MIN_VALID_IMAGE_BYTES, t as DEFAULT_CAPTURE_CONFIG } from "../image-capture-B2-b6tKK.js";
155
2
  export { DEFAULT_CAPTURE_CONFIG, ImageCaptureManager, MIN_VALID_IMAGE_BYTES };
@@ -0,0 +1,2 @@
1
+ import { a as QualityFilterConfig, c as meanLuminance, i as ImageQualityGate, l as rgbaToGrayscale, n as DEFAULT_SHARPNESS_HISTORY_SIZE, o as QualityRejectReason, r as DEFAULT_SHARPNESS_MIN_SAMPLES, s as QualityVerdict, t as DEFAULT_QUALITY_FILTER, u as sharpnessScore } from "../image-quality-smCBoFj1.js";
2
+ export { DEFAULT_QUALITY_FILTER, DEFAULT_SHARPNESS_HISTORY_SIZE, DEFAULT_SHARPNESS_MIN_SAMPLES, ImageQualityGate, QualityFilterConfig, QualityRejectReason, QualityVerdict, meanLuminance, rgbaToGrayscale, sharpnessScore };