gps-plus-slam-app-framework 1.0.0 → 1.0.6

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 (131) hide show
  1. package/dist/{app-selectors-DyMzxCEC.d.ts → app-selectors-CHt7DLuq.d.ts} +9 -8
  2. package/dist/ar/depth-sampler.js +1 -1
  3. package/dist/ar/tracking-state.js +1 -1
  4. package/dist/ar/webxr-session.js +1 -1
  5. package/dist/combined-root-state-B3SvPNjU.d.ts +6 -0
  6. package/dist/core/index.d.ts +2 -0
  7. package/dist/core/index.js +2 -0
  8. package/dist/create-slam-app-store-DBm7g2Zd.d.ts +85 -0
  9. package/dist/file-system-DD5TczSO.d.ts +84 -0
  10. package/dist/geo/h3-proximity.d.ts +2 -0
  11. package/dist/{ref-points/h3-ref-point.js → geo/h3-proximity.js} +16 -12
  12. package/dist/geo/index.d.ts +2 -0
  13. package/dist/geo/index.js +2 -0
  14. package/dist/gps-anchored-mesh-manager-CovAFK4g.d.ts +56 -0
  15. package/dist/gps-ar-pose-sampler-D_Zso40V.d.ts +43 -0
  16. package/dist/{recording-coordinator-DzflP07_.d.ts → gps-event-coordinator-fwvmVfku.d.ts} +6 -5
  17. package/dist/{h3-ref-point-CFhayNSZ.d.ts → h3-proximity-GwesPTFT.d.ts} +16 -12
  18. package/dist/index.d.ts +31 -34
  19. package/dist/index.js +14 -19
  20. package/dist/{leaflet-map-overlay-CvfQXTye.d.ts → leaflet-map-overlay-CQZcnxbc.d.ts} +10 -6
  21. package/dist/licensing/index.d.ts +1 -1
  22. package/dist/licensing/index.js +1 -1
  23. package/dist/{null-storage-backend-CsWvQwN8.d.ts → null-storage-backend-C0TiwwzQ.d.ts} +4 -2
  24. package/dist/{opfs-storage-ChOzF_Wp.d.ts → opfs-storage-Dlq1I_Gb.d.ts} +54 -51
  25. package/dist/opfs-storage-backend-Gt3rd76D.d.ts +13 -0
  26. package/dist/{persistence-middleware-DrptY02i.d.ts → persistence-middleware-z-75iisb.d.ts} +4 -4
  27. package/dist/{recording-replayer-oOzPITrd.d.ts → recording-replayer-BFhFs7Mc.d.ts} +2 -2
  28. package/dist/recording-slice-BiktUIWF.d.ts +28 -0
  29. package/dist/{replay-engine-DuX316ae.d.ts → replay-engine-B88Va62x.d.ts} +4 -1
  30. package/dist/sensors/gps-error-handler.d.ts +1 -1
  31. package/dist/sensors/gps.d.ts +1 -1
  32. package/dist/sensors/index.d.ts +3 -3
  33. package/dist/sensors/index.js +1 -1
  34. package/dist/sensors/permission-checker.d.ts +1 -1
  35. package/dist/state/app-selectors.d.ts +1 -1
  36. package/dist/state/create-slam-app-store.d.ts +2 -0
  37. package/dist/state/create-slam-app-store.js +61 -0
  38. package/dist/state/gps-ar-pose-sampler.d.ts +4 -0
  39. package/dist/state/gps-ar-pose-sampler.js +19 -0
  40. package/dist/state/{recording-coordinator.d.ts → gps-event-coordinator.d.ts} +1 -1
  41. package/dist/state/{recording-coordinator.js → gps-event-coordinator.js} +3 -4
  42. package/dist/state/index.d.ts +15 -16
  43. package/dist/state/index.js +7 -7
  44. package/dist/state/persistence-middleware.d.ts +1 -1
  45. package/dist/state/persistence-middleware.js +8 -8
  46. package/dist/state/recording-replayer.d.ts +3 -2
  47. package/dist/state/recording-replayer.js +2 -2
  48. package/dist/state/recording-slice.d.ts +2 -0
  49. package/dist/state/{recorder-slice.js → recording-slice.js} +7 -15
  50. package/dist/state/replay-engine.d.ts +1 -1
  51. package/dist/state/replay-engine.js +3 -3
  52. package/dist/state/store-subscribers.d.ts +2 -2
  53. package/dist/state/store-subscribers.js +1 -9
  54. package/dist/state/subscribe-to-selector.d.ts +1 -1
  55. package/dist/storage/file-system-utils.d.ts +1 -1
  56. package/dist/storage/file-system.d.ts +2 -2
  57. package/dist/storage/file-system.js +103 -94
  58. package/dist/storage/index.d.ts +9 -11
  59. package/dist/storage/index.js +5 -7
  60. package/dist/storage/null-storage-backend.d.ts +1 -1
  61. package/dist/storage/null-storage-backend.js +7 -0
  62. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  63. package/dist/storage/opfs-storage-backend.js +7 -1
  64. package/dist/storage/opfs-storage.d.ts +2 -2
  65. package/dist/storage/opfs-storage.js +69 -85
  66. package/dist/storage/storage-backend.d.ts +2 -2
  67. package/dist/storage/zip-export.d.ts +2 -2
  68. package/dist/storage/zip-export.js +55 -62
  69. package/dist/storage/zip-reader.d.ts +2 -2
  70. package/dist/storage/zip-reader.js +24 -1
  71. package/dist/storage-backend-yVnuWGTr.d.ts +28 -0
  72. package/dist/{store-subscribers-CuoIzB5T.d.ts → store-subscribers-DKKHld49.d.ts} +1 -2
  73. package/dist/{subscribe-to-selector-UTZ0KkAc.d.ts → subscribe-to-selector-ghDKYtap.d.ts} +1 -1
  74. package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
  75. package/dist/test-utils/zip-round-trip-helpers.js +4 -4
  76. package/dist/visualization/gps-anchored-mesh-manager.d.ts +2 -0
  77. package/dist/visualization/gps-anchored-mesh-manager.js +128 -0
  78. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  79. package/dist/visualization/gps-event-markers.d.ts +1 -1
  80. package/dist/visualization/index.d.ts +9 -9
  81. package/dist/visualization/index.js +2 -2
  82. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  83. package/dist/visualization/leaflet-map-overlay.js +23 -19
  84. package/dist/visualization/lerp-utils.d.ts +1 -1
  85. package/dist/visualization/map-overlay.d.ts +1 -1
  86. package/dist/visualization/three-dispose.d.ts +1 -1
  87. package/dist/visualization/vis-colors.d.ts +1 -1
  88. package/dist/{zip-export-Rtpi75JJ.d.ts → zip-export-BjrQPv0X.d.ts} +58 -7
  89. package/dist/{zip-reader-D7pkpX8K.d.ts → zip-reader-KgJEXbca.d.ts} +33 -1
  90. package/package.json +15 -4
  91. package/dist/community-license-key-ChZLCJyO.d.ts +0 -21
  92. package/dist/file-system-BsQgYCU3.d.ts +0 -128
  93. package/dist/licensing/community-license-key.d.ts +0 -2
  94. package/dist/licensing/community-license-key.js +0 -21
  95. package/dist/opfs-storage-backend-CVcmfJHN.d.ts +0 -11
  96. package/dist/recorder-slice-fcwAXrsh.d.ts +0 -35
  97. package/dist/ref-point-importer-B_wn5ABk.d.ts +0 -62
  98. package/dist/ref-point-loader-Pt1smgHS.d.ts +0 -117
  99. package/dist/ref-points/h3-ref-point.d.ts +0 -2
  100. package/dist/ref-points/index.d.ts +0 -2
  101. package/dist/ref-points/index.js +0 -2
  102. package/dist/ref-points-slice-tC-Wd6XJ.d.ts +0 -48
  103. package/dist/reference-points-CFWy8_wj.d.ts +0 -68
  104. package/dist/routing-slice-BlHTM8eh.d.ts +0 -23
  105. package/dist/state/recorder-slice.d.ts +0 -2
  106. package/dist/state/ref-points-slice.d.ts +0 -2
  107. package/dist/state/ref-points-slice.js +0 -44
  108. package/dist/state/routing-slice.d.ts +0 -2
  109. package/dist/state/routing-slice.js +0 -13
  110. package/dist/state/store.d.ts +0 -9
  111. package/dist/state/store.js +0 -71
  112. package/dist/storage/ref-point-importer.d.ts +0 -2
  113. package/dist/storage/ref-point-importer.js +0 -163
  114. package/dist/storage/ref-point-loader.d.ts +0 -2
  115. package/dist/storage/ref-point-loader.js +0 -248
  116. package/dist/storage/ref-point-recovery.d.ts +0 -28
  117. package/dist/storage/ref-point-recovery.js +0 -159
  118. package/dist/storage-backend-BcEItnFr.d.ts +0 -20
  119. package/dist/store-C7PKOj8S.d.ts +0 -96
  120. package/dist/visualization/reference-points.d.ts +0 -2
  121. package/dist/visualization/reference-points.js +0 -160
  122. /package/dist/{file-system-utils-5cWO8Xyv.d.ts → file-system-utils-BH8FdyIu.d.ts} +0 -0
  123. /package/dist/{gps-Ddzr2KlX.d.ts → gps-GKc6_Cly.d.ts} +0 -0
  124. /package/dist/{gps-compass-cubes-C-6JEnpR.d.ts → gps-compass-cubes-jRIJMOuh.d.ts} +0 -0
  125. /package/dist/{gps-error-handler-VPuNOuf8.d.ts → gps-error-handler-CH1S528z.d.ts} +0 -0
  126. /package/dist/{gps-event-markers-DpEy2qRd.d.ts → gps-event-markers-sVyO9utS.d.ts} +0 -0
  127. /package/dist/{lerp-utils-87NWjUOD.d.ts → lerp-utils-CZgQlrmu.d.ts} +0 -0
  128. /package/dist/{map-overlay-DuiZuCTx.d.ts → map-overlay-C9ifl_4-.d.ts} +0 -0
  129. /package/dist/{permission-checker-jO2ziCWC.d.ts → permission-checker-Cu3nbH1S.d.ts} +0 -0
  130. /package/dist/{three-dispose-CCBHjE_a.d.ts → three-dispose-qt_r5wR1.d.ts} +0 -0
  131. /package/dist/{vis-colors-Qi2vlRGt.d.ts → vis-colors-BKkdTIKb.d.ts} +0 -0
@@ -22,9 +22,16 @@ const log = createLogger("ZipExport");
22
22
  /**
23
23
  * Get the OPFS scenarios directory handle.
24
24
  * Re-acquires from navigator.storage to avoid holding stale references.
25
+ * Creates on demand so it works even when initOpfsStorage only creates sessions/.
25
26
  */
26
27
  async function getScenariosHandle() {
27
- return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-recorder")).getDirectoryHandle("scenarios");
28
+ return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-plus-slam")).getDirectoryHandle("scenarios", { create: true });
29
+ }
30
+ /**
31
+ * Get the OPFS sessions directory handle (flat layout).
32
+ */
33
+ async function getSessionsHandle() {
34
+ return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-plus-slam")).getDirectoryHandle("sessions");
28
35
  }
29
36
  /**
30
37
  * Stream all files from a directory recursively into a ZipWriter.
@@ -49,80 +56,66 @@ async function streamDirectoryToZip(dirHandle, zipWriter, basePath = "") {
49
56
  return count;
50
57
  }
51
58
  /**
52
- * Filter and stream per-session ref point observations into a ZipWriter.
53
- *
54
- * Reads each ref point JSON from the scenario-level refPoints/ directory,
55
- * keeps only observations where `sessionId` matches `sessionName`, and writes
56
- * the filtered definition into the ZIP under `refPoints/{h3}.json`.
57
- *
58
- * Ref points with no observations for the current session are skipped entirely.
59
- * If the refPoints/ directory doesn't exist yet (new scenario), returns 0.
60
- *
61
- * @returns Number of ref point files added
62
- */
63
- async function streamSessionRefPointsToZip(scenarioHandle, sessionName, zipWriter) {
64
- let count = 0;
65
- let refPointsHandle;
66
- try {
67
- refPointsHandle = await scenarioHandle.getDirectoryHandle("refPoints");
68
- } catch {
69
- return 0;
70
- }
71
- for await (const [name, handle] of refPointsHandle.entries()) {
72
- if (handle.kind !== "file" || !name.endsWith(".json")) continue;
73
- try {
74
- const text = await (await handle.getFile()).text();
75
- const def = JSON.parse(text);
76
- if (!Array.isArray(def.observations)) continue;
77
- const sessionObs = def.observations.filter((o) => o.sessionId === sessionName);
78
- if (sessionObs.length === 0) continue;
79
- const filtered = {
80
- ...def,
81
- observations: sessionObs
82
- };
83
- const blob = new Blob([JSON.stringify(filtered, null, 2)], { type: "application/json" });
84
- await zipWriter.add(`refPoints/${name}`, new BlobReader(blob));
85
- count++;
86
- } catch (err) {
87
- log.warn(`Failed to process ref point ${name}:`, err);
88
- }
89
- }
90
- return count;
91
- }
92
- /**
93
59
  * Export a session from OPFS as a ZIP blob.
94
60
  *
95
61
  * The ZIP structure mirrors the OPFS session structure:
96
62
  * - session.json (at root)
97
63
  * - actions/000001.json, actions/000002.json, ...
98
64
  * - frames/frame-000001.jpg, frames/frame-000002.jpg, ...
99
- * - refPoints/{h3}.json (only observations from this session)
65
+ * - refPoints/{h3}.json (only observations from this session, scenario layout only)
100
66
  *
101
67
  * Uses "store" mode (compression level 0) for fast packaging.
102
68
  *
103
- * @param scenarioName - Name of the scenario
104
- * @param sessionName - Name of the session folder
69
+ * Supports both flat and scenario-based layouts:
70
+ * - `exportSessionAsZip(sessionName)` flat layout (sessions/)
71
+ * - `exportSessionAsZip(scenarioName, sessionName)` — scenario layout (scenarios/{name}/)
72
+ *
105
73
  * @returns ZIP export result with blob and file count
106
- * @throws Error if scenario or session not found
74
+ * @throws Error if session not found
107
75
  */
108
- async function exportSessionAsZip(scenarioName, sessionName) {
109
- log.info(`Exporting session: ${scenarioName}/${sessionName}`);
110
- const scenariosDir = await getScenariosHandle();
111
- let scenarioHandle;
112
- try {
113
- scenarioHandle = await scenariosDir.getDirectoryHandle(scenarioName);
114
- } catch {
115
- throw new Error(`Scenario "${scenarioName}" not found in OPFS storage`);
116
- }
76
+ async function exportSessionAsZip(scenarioNameOrSessionName, sessionName, options) {
117
77
  let sessionHandle;
118
- try {
119
- sessionHandle = await scenarioHandle.getDirectoryHandle(sessionName);
120
- } catch {
121
- throw new Error(`Session "${sessionName}" not found in scenario "${scenarioName}"`);
78
+ if (sessionName) {
79
+ const scenarioName = scenarioNameOrSessionName;
80
+ log.info(`Exporting session: ${scenarioName}/${sessionName}`);
81
+ const scenariosDir = await getScenariosHandle();
82
+ let scenarioHandle;
83
+ try {
84
+ scenarioHandle = await scenariosDir.getDirectoryHandle(scenarioName);
85
+ } catch {
86
+ throw new Error(`Scenario "${scenarioName}" not found in OPFS storage`);
87
+ }
88
+ try {
89
+ sessionHandle = await scenarioHandle.getDirectoryHandle(sessionName);
90
+ } catch {
91
+ throw new Error(`Session "${sessionName}" not found in scenario "${scenarioName}"`);
92
+ }
93
+ } else {
94
+ log.info(`Exporting session: ${scenarioNameOrSessionName}`);
95
+ const sessionsDir = await getSessionsHandle();
96
+ try {
97
+ sessionHandle = await sessionsDir.getDirectoryHandle(scenarioNameOrSessionName);
98
+ } catch {
99
+ throw new Error(`Session "${scenarioNameOrSessionName}" not found in OPFS storage`);
100
+ }
122
101
  }
123
102
  const zipWriter = new ZipWriter(new BlobWriter("application/zip"), { level: 0 });
124
103
  let fileCount = await streamDirectoryToZip(sessionHandle, zipWriter);
125
- fileCount += await streamSessionRefPointsToZip(scenarioHandle, sessionName, zipWriter);
104
+ const contributors = options?.contributors ?? [];
105
+ const seenSubdirs = /* @__PURE__ */ new Set();
106
+ for (const contributor of contributors) {
107
+ const subdir = contributor.subdir;
108
+ if (!subdir || subdir.includes("/") || subdir.startsWith(".")) throw new Error(`ZipExportContributor.subdir must be a non-empty single path segment, got: ${JSON.stringify(subdir)}`);
109
+ if (seenSubdirs.has(subdir)) throw new Error(`Duplicate ZipExportContributor.subdir registered: ${subdir}`);
110
+ seenSubdirs.add(subdir);
111
+ const addFile = async (relativePath, blob) => {
112
+ if (relativePath.startsWith("/")) throw new Error(`ZipExportContributor relative path must not start with '/' (got ${relativePath})`);
113
+ if (relativePath.includes("\\")) throw new Error(`ZipExportContributor relative path must not contain '\\' (got ${relativePath})`);
114
+ if (relativePath.split("/").some((s) => s === ".." || s === ".")) throw new Error(`ZipExportContributor relative path must not contain '.' or '..' segments (got ${relativePath})`);
115
+ await zipWriter.add(`${subdir}/${relativePath}`, new BlobReader(blob));
116
+ };
117
+ fileCount += await contributor.contribute(addFile);
118
+ }
126
119
  const blob = await zipWriter.close();
127
120
  log.info(`ZIP created: ${blob.size} bytes, ${fileCount} files`);
128
121
  return {
@@ -148,9 +141,9 @@ async function exportSessionAsZip(scenarioName, sessionName) {
148
141
  * @returns ZIP export result with blob and file count
149
142
  * @throws Error if scenario or session not found
150
143
  */
151
- async function syncToExternalZip(fileHandle, scenarioName, sessionName) {
144
+ async function syncToExternalZip(fileHandle, scenarioName, sessionName, options) {
152
145
  log.info(`Syncing to external ZIP: ${scenarioName}/${sessionName}`);
153
- const result = await exportSessionAsZip(scenarioName, sessionName);
146
+ const result = await exportSessionAsZip(scenarioName, sessionName, options);
154
147
  const writable = await fileHandle.createWritable();
155
148
  await writable.write(result.blob);
156
149
  await writable.close();
@@ -1,2 +1,2 @@
1
- import { a as ZipActionEntry, c as loadSessionMetadata, i as RecordedAction, l as loadSessionMetadataFromBlob, n as GpsPathCoord, o as loadActionsFromZip, r as MAX_ACTION_FILE_SIZE, s as loadGpsPathFromBlob, t as Entry, u as readZipEntries } from "../zip-reader-D7pkpX8K.js";
2
- export { Entry, GpsPathCoord, MAX_ACTION_FILE_SIZE, RecordedAction, ZipActionEntry, loadActionsFromZip, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
1
+ import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-KgJEXbca.js";
2
+ export { Entry, GpsPathCoord, MAX_ACTION_FILE_SIZE, RecordedAction, ZipActionEntry, ZipSubdirEntry, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
@@ -186,5 +186,28 @@ async function loadGpsPathFromBlob(blob, maxFileSize = MAX_ACTION_FILE_SIZE) {
186
186
  } catch {}
187
187
  }
188
188
  }
189
+ /**
190
+ * Enumerate every file under a single top-level subdirectory of a recording
191
+ * zip. Mirrors the writer-side {@link ZipExportContributor} seam so consumers
192
+ * (typically the recorder) can read back what they wrote without
193
+ * re-implementing zip enumeration.
194
+ *
195
+ * Skips directory entries and files outside `subdir`. Sorts entries by
196
+ * `relativePath` for deterministic iteration. Returns an empty array when
197
+ * the subdir is absent (graceful degradation for older zips).
198
+ *
199
+ * @param data - The zip file content as a Uint8Array
200
+ * @param subdir - Top-level subdir to scan (no leading or trailing `/`)
201
+ */
202
+ async function loadEntriesFromSubdir(data, subdir) {
203
+ if (!subdir || subdir.includes("/") || subdir.startsWith(".")) throw new Error(`subdir must be a non-empty single path segment, got: ${JSON.stringify(subdir)}`);
204
+ const prefix = `${subdir}/`;
205
+ return (await readZipEntries(data)).filter((e) => !e.directory && e.filename.startsWith(prefix) && e.filename !== prefix).sort((a, b) => a.filename.localeCompare(b.filename)).map((entry) => ({
206
+ relativePath: entry.filename.slice(prefix.length),
207
+ fullPath: entry.filename,
208
+ uncompressedSize: entry.uncompressedSize,
209
+ getText: () => entry.getData(new TextWriter())
210
+ }));
211
+ }
189
212
  //#endregion
190
- export { MAX_ACTION_FILE_SIZE, loadActionsFromZip, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
213
+ export { MAX_ACTION_FILE_SIZE, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
@@ -0,0 +1,28 @@
1
+ import { n as SessionMetadata } from "./opfs-storage-Dlq1I_Gb.js";
2
+
3
+ //#region ../src/storage/storage-backend.d.ts
4
+ interface CreateSessionResult {
5
+ sessionName: string;
6
+ }
7
+ /**
8
+ * Contract for session lifecycle and recording persistence.
9
+ *
10
+ * Implementations:
11
+ * - OpfsStorageBackend: production — flat sessions under OPFS
12
+ * - NullStorageBackend: tests/replay — silent no-ops
13
+ * - ScenarioWrappingStorageBackend (recorder): layers scenario hierarchy on top
14
+ */
15
+ interface StorageBackend {
16
+ /** Create a new recording session. Returns the session name for reference. */
17
+ createSession(timestamp: Date, contextTag?: string): Promise<CreateSessionResult>;
18
+ /** List all session names managed by this backend. */
19
+ listSessions(): Promise<string[]>;
20
+ /** Persist a Redux action as a numbered JSON file. */
21
+ writeAction(action: unknown, index: number): Promise<void>;
22
+ /** Persist a captured camera frame as a numbered JPEG. */
23
+ writeFrame(blob: Blob, index: number): Promise<void>;
24
+ /** Persist session metadata (session.json). */
25
+ writeSessionMetadata(metadata: SessionMetadata): Promise<void>;
26
+ }
27
+ //#endregion
28
+ export { StorageBackend as n, CreateSessionResult as t };
@@ -1,4 +1,4 @@
1
- import { t as SubscribableStore } from "./subscribe-to-selector-UTZ0KkAc.js";
1
+ import { t as SubscribableStore } from "./subscribe-to-selector-ghDKYtap.js";
2
2
  import { LatLong, Matrix4, Quaternion, Vector3 } from "gps-plus-slam-js";
3
3
 
4
4
  //#region ../src/state/store-subscribers.d.ts
@@ -22,7 +22,6 @@ interface StoreSubscriberDeps {
22
22
  addRawGpsPoint?: (lat: number, lon: number) => void;
23
23
  addFusedPoint?: (lat: number, lon: number) => void;
24
24
  addAlignmentSnapshot?: (lat: number, lon: number) => void;
25
- addRefPoint?: (lat: number, lon: number, name: string) => void;
26
25
  } | null;
27
26
  /**
28
27
  * Optional callback invoked with the GPS world-space coordinates of each
@@ -1,4 +1,4 @@
1
- import { n as CombinedRootState } from "./store-C7PKOj8S.js";
1
+ import { t as CombinedRootState } from "./combined-root-state-B3SvPNjU.js";
2
2
 
3
3
  //#region ../src/state/subscribe-to-selector.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as RecordedAction } from "../zip-reader-D7pkpX8K.js";
1
+ import { i as RecordedAction } from "../zip-reader-KgJEXbca.js";
2
2
  import { LatLong } from "gps-plus-slam-js";
3
3
 
4
4
  //#region ../src/test-utils/zip-round-trip-helpers.d.ts
@@ -65,7 +65,7 @@ async function produceTestZip(opts) {
65
65
  const { cleanup } = installOPFSMocks();
66
66
  try {
67
67
  await initOpfsStorage();
68
- const { scenarioName, sessionName } = await createSession(options.scenarioName, options.sessionTimestamp);
68
+ const { sessionName } = await createSession(options.sessionTimestamp, options.scenarioName);
69
69
  const allActions = [];
70
70
  let actionIndex = 0;
71
71
  /** Increment index, persist to OPFS, and record for later assertions. */
@@ -75,7 +75,7 @@ async function produceTestZip(opts) {
75
75
  allActions.push(action);
76
76
  };
77
77
  await writeAndRecordAction({
78
- type: "recorder/startSession",
78
+ type: "recording/startSession",
79
79
  payload: {
80
80
  scenarioName: options.scenarioName,
81
81
  sessionName,
@@ -174,12 +174,12 @@ async function produceTestZip(opts) {
174
174
  version: 1,
175
175
  startedAt: options.sessionTimestamp.toISOString(),
176
176
  endedAt: new Date(options.sessionTimestamp.getTime() + actionIndex * 1e3 + 5e3).toISOString(),
177
- scenarioName: options.scenarioName,
177
+ contextTag: options.scenarioName,
178
178
  actionCount: actionIndex,
179
179
  frameCount: options.frameCount,
180
180
  userAgent: options.deviceInfo
181
181
  });
182
- const { blob } = await exportSessionAsZip(scenarioName, sessionName);
182
+ const { blob } = await exportSessionAsZip(sessionName);
183
183
  return {
184
184
  zipData: new Uint8Array(await blob.arrayBuffer()),
185
185
  totalActionCount: actionIndex,
@@ -0,0 +1,2 @@
1
+ import { n as GpsAnchoredMeshManager, r as GpsAnchoredMeshManagerOptions, t as GpsAnchoredItem } from "../gps-anchored-mesh-manager-CovAFK4g.js";
2
+ export { GpsAnchoredItem, GpsAnchoredMeshManager, GpsAnchoredMeshManagerOptions };
@@ -0,0 +1,128 @@
1
+ import { createLogger } from "../utils/logger.js";
2
+ import { disposeMeshArray } from "./three-dispose.js";
3
+ import { getScene } from "../ar/webxr-session.js";
4
+ import * as THREE from "three";
5
+ import { calcRelativeCoordsInMeters } from "gps-plus-slam-js";
6
+ //#region ../src/visualization/gps-anchored-mesh-manager.ts
7
+ /**
8
+ * GPS-Anchored Mesh Manager
9
+ *
10
+ * Generic mechanism for placing Three.js meshes at GPS coordinates relative
11
+ * to a configured GPS zero reference. This is the recorder-agnostic core
12
+ * that was extracted in Iter 4 from the recorder-flavoured
13
+ * `RefPointVisualizer` (which now lives in the RecorderApp and composes two
14
+ * instances of this manager — prior=green, current=red).
15
+ *
16
+ * The manager is intentionally narrow: it knows how to convert
17
+ * `{ lat, lon, altitude? }` into local meters via the framework's GPS zero
18
+ * reference, allocate a single shared geometry + material per instance, and
19
+ * keep the resulting mesh group in sync with caller-provided items. It does
20
+ * not know anything about ref points, sessions, or recorder semantics.
21
+ */
22
+ const DEFAULT_RADIUS = .1;
23
+ /**
24
+ * Manages a single colored mesh group anchored to GPS coordinates.
25
+ * One instance == one color/group.
26
+ */
27
+ var GpsAnchoredMeshManager = class {
28
+ color;
29
+ radius;
30
+ namePrefix;
31
+ log;
32
+ meshes = [];
33
+ zeroRef = null;
34
+ geometry = null;
35
+ material = null;
36
+ constructor(options) {
37
+ this.color = options.color;
38
+ this.radius = options.radius ?? DEFAULT_RADIUS;
39
+ this.namePrefix = options.namePrefix;
40
+ this.log = createLogger(options.loggerLabel ?? "GpsAnchoredMeshManager");
41
+ }
42
+ /** Set the GPS origin used to project items into local meters. */
43
+ setZeroRef(zero) {
44
+ this.zeroRef = zero;
45
+ }
46
+ getZeroRef() {
47
+ return this.zeroRef;
48
+ }
49
+ /**
50
+ * Replace the entire mesh group with one mesh per provided item.
51
+ * Items without GPS or before `setZeroRef` are skipped.
52
+ */
53
+ setItems(items) {
54
+ if (!this.zeroRef) {
55
+ this.log.warn("No zero reference set");
56
+ return;
57
+ }
58
+ const scene = getScene();
59
+ if (!scene) {
60
+ this.log.warn("Scene not available");
61
+ return;
62
+ }
63
+ this.clear();
64
+ const geometry = this.geometry ??= new THREE.SphereGeometry(this.radius, 16, 16);
65
+ const material = this.material ??= new THREE.MeshBasicMaterial({ color: this.color });
66
+ let visibleCount = 0;
67
+ for (const item of items) {
68
+ const coords = calcRelativeCoordsInMeters(this.zeroRef, {
69
+ lat: item.lat,
70
+ lon: item.lon
71
+ }, item.altitude ?? 0, 0);
72
+ const mesh = new THREE.Mesh(geometry, material);
73
+ mesh.position.set(coords[0], coords[1], coords[2]);
74
+ mesh.name = `${this.namePrefix}-${item.id}`;
75
+ scene.add(mesh);
76
+ this.meshes.push(mesh);
77
+ visibleCount++;
78
+ }
79
+ this.log.info(`Displayed ${visibleCount}/${items.length} anchored meshes`);
80
+ }
81
+ /** Append a single item to the existing mesh group. */
82
+ addItem(item) {
83
+ if (!this.zeroRef) {
84
+ this.log.warn("Cannot add item — no zero reference");
85
+ return;
86
+ }
87
+ const scene = getScene();
88
+ if (!scene) {
89
+ this.log.warn("Scene not available");
90
+ return;
91
+ }
92
+ const geometry = this.geometry ??= new THREE.SphereGeometry(this.radius, 16, 16);
93
+ const material = this.material ??= new THREE.MeshBasicMaterial({ color: this.color });
94
+ const coords = calcRelativeCoordsInMeters(this.zeroRef, {
95
+ lat: item.lat,
96
+ lon: item.lon
97
+ }, item.altitude ?? 0, 0);
98
+ const mesh = new THREE.Mesh(geometry, material);
99
+ mesh.position.set(coords[0], coords[1], coords[2]);
100
+ mesh.name = `${this.namePrefix}-${item.id}`;
101
+ scene.add(mesh);
102
+ this.meshes.push(mesh);
103
+ this.log.info(`Added anchored mesh: ${item.id}`);
104
+ }
105
+ /** Remove all meshes and dispose the shared geometry/material. */
106
+ clear() {
107
+ const scene = getScene();
108
+ disposeMeshArray(this.meshes, scene, {
109
+ skipGeometry: true,
110
+ skipMaterial: true
111
+ });
112
+ this.geometry?.dispose();
113
+ this.geometry = null;
114
+ this.material?.dispose();
115
+ this.material = null;
116
+ }
117
+ /** Number of meshes currently rendered. */
118
+ getCount() {
119
+ return this.meshes.length;
120
+ }
121
+ /** Convenience: clear and forget the zero reference. */
122
+ dispose() {
123
+ this.clear();
124
+ this.zeroRef = null;
125
+ }
126
+ };
127
+ //#endregion
128
+ export { GpsAnchoredMeshManager };
@@ -1,2 +1,2 @@
1
- import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-C-6JEnpR.js";
1
+ import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-jRIJMOuh.js";
2
2
  export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, GpsCompassCubes, createGpsCompassCubes };
@@ -1,2 +1,2 @@
1
- import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-DpEy2qRd.js";
1
+ import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-sVyO9utS.js";
2
2
  export { GpsEventVisualizer, gpsEventVisualizer };
@@ -1,12 +1,12 @@
1
1
  import { n as createCameraFollower, t as CameraFollower } from "../camera-follower-BMqPddxx.js";
2
2
  import { n as createAlignmentLerper, t as AlignmentLerper } from "../alignment-lerper-D9BeDwZX.js";
3
3
  import { n as createCss3dRendererManager, t as Css3dRendererManager } from "../css3d-renderer-manager-rgLMVAvd.js";
4
- import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-C-6JEnpR.js";
5
- import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-DpEy2qRd.js";
6
- import { a as DEFAULT_Z_OFFSET, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions } from "../leaflet-map-overlay-CvfQXTye.js";
7
- import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-87NWjUOD.js";
8
- import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-DuiZuCTx.js";
9
- import { n as refPointVisualizer, t as RefPointVisualizer } from "../reference-points-CFWy8_wj.js";
10
- import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-CCBHjE_a.js";
11
- import { t as VIS_COLORS } from "../vis-colors-Qi2vlRGt.js";
12
- export { type AlignmentLerper, COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, type CameraFollower, type Css3dRendererManager, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, type DisposeOptions, type GpsCompassCubes, GpsEventVisualizer, LeafletMapOverlay, type LeafletMapOverlayOptions, MapOverlay, type MapOverlayOptions, RefPointVisualizer, type TextureLoaderInterface, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, refPointVisualizer, tileXYToLatLon };
4
+ import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-jRIJMOuh.js";
5
+ import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-sVyO9utS.js";
6
+ import { a as DEFAULT_Z_OFFSET, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions } from "../leaflet-map-overlay-CQZcnxbc.js";
7
+ import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-CZgQlrmu.js";
8
+ import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-C9ifl_4-.js";
9
+ import { n as GpsAnchoredMeshManager, r as GpsAnchoredMeshManagerOptions, t as GpsAnchoredItem } from "../gps-anchored-mesh-manager-CovAFK4g.js";
10
+ import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-qt_r5wR1.js";
11
+ import { t as VIS_COLORS } from "../vis-colors-BKkdTIKb.js";
12
+ export { type AlignmentLerper, COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, type CameraFollower, type Css3dRendererManager, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, type DisposeOptions, type GpsAnchoredItem, GpsAnchoredMeshManager, type GpsAnchoredMeshManagerOptions, type GpsCompassCubes, GpsEventVisualizer, LeafletMapOverlay, type LeafletMapOverlayOptions, MapOverlay, type MapOverlayOptions, type TextureLoaderInterface, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, tileXYToLatLon };
@@ -8,5 +8,5 @@ import { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, createGpsCompassCubes } from
8
8
  import { GpsEventVisualizer, gpsEventVisualizer } from "./gps-event-markers.js";
9
9
  import { DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_WORLD_SIZE, DEFAULT_Z_OFFSET, LeafletMapOverlay } from "./leaflet-map-overlay.js";
10
10
  import { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, latLonToTileXY, tileXYToLatLon } from "./map-overlay.js";
11
- import { RefPointVisualizer, refPointVisualizer } from "./reference-points.js";
12
- export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, GpsEventVisualizer, LeafletMapOverlay, MapOverlay, RefPointVisualizer, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, refPointVisualizer, tileXYToLatLon };
11
+ import { GpsAnchoredMeshManager } from "./gps-anchored-mesh-manager.js";
12
+ export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, GpsAnchoredMeshManager, GpsEventVisualizer, LeafletMapOverlay, MapOverlay, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, tileXYToLatLon };
@@ -1,2 +1,2 @@
1
- import { a as DEFAULT_Z_OFFSET, i as DEFAULT_ZOOM, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions, t as DEFAULT_HEIGHT_OFFSET } from "../leaflet-map-overlay-CvfQXTye.js";
1
+ import { a as DEFAULT_Z_OFFSET, i as DEFAULT_ZOOM, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions, t as DEFAULT_HEIGHT_OFFSET } from "../leaflet-map-overlay-CQZcnxbc.js";
2
2
  export { DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, LeafletMapOverlay, LeafletMapOverlayOptions };
@@ -38,7 +38,7 @@ var LeafletMapOverlay = class {
38
38
  rawGpsPoints = [];
39
39
  fusedPoints = [];
40
40
  snapshotPoints = [];
41
- refPoints = [];
41
+ namedMarkers = [];
42
42
  userMarker = null;
43
43
  rawGpsPolyline = null;
44
44
  fusedPolyline = null;
@@ -126,9 +126,10 @@ var LeafletMapOverlay = class {
126
126
  this.snapshotPolyline.addLatLng([lat, lon]);
127
127
  }
128
128
  }
129
- addRefPoint(lat, lon, name) {
130
- const marker = this.leafletMap ? this.createRefPointMarker(lat, lon, name, false) : null;
131
- this.refPoints.push({
129
+ /** Add a "current" named marker (red). Buffered if map is not yet shown. */
130
+ addCurrentMarker(lat, lon, name) {
131
+ const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, false) : null;
132
+ this.namedMarkers.push({
132
133
  lat,
133
134
  lng: lon,
134
135
  name,
@@ -136,9 +137,10 @@ var LeafletMapOverlay = class {
136
137
  marker
137
138
  });
138
139
  }
139
- addPriorRefPoint(lat, lon, name) {
140
- const marker = this.leafletMap ? this.createRefPointMarker(lat, lon, name, true) : null;
141
- this.refPoints.push({
140
+ /** Add a "prior" named marker (green, decorated). Buffered if not shown. */
141
+ addPriorMarker(lat, lon, name) {
142
+ const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, true) : null;
143
+ this.namedMarkers.push({
142
144
  lat,
143
145
  lng: lon,
144
146
  name,
@@ -146,13 +148,15 @@ var LeafletMapOverlay = class {
146
148
  marker
147
149
  });
148
150
  }
149
- addPriorRefPoints(refPoints) {
150
- for (const rp of refPoints) this.addPriorRefPoint(rp.lat, rp.lon, rp.name);
151
+ /** Bulk add prior markers. */
152
+ addPriorMarkers(markers) {
153
+ for (const m of markers) this.addPriorMarker(m.lat, m.lon, m.name);
151
154
  }
152
- clearPriorRefPoints() {
153
- this.refPoints = this.refPoints.filter((rp) => {
154
- if (rp.isPrior) {
155
- rp.marker?.remove();
155
+ /** Remove all prior markers; current markers are unaffected. */
156
+ clearPriorMarkers() {
157
+ this.namedMarkers = this.namedMarkers.filter((m) => {
158
+ if (m.isPrior) {
159
+ m.marker?.remove();
156
160
  return false;
157
161
  }
158
162
  return true;
@@ -198,7 +202,7 @@ var LeafletMapOverlay = class {
198
202
  this.rawGpsPoints = [];
199
203
  this.fusedPoints = [];
200
204
  this.snapshotPoints = [];
201
- this.refPoints = [];
205
+ this.namedMarkers = [];
202
206
  this.cssObject = null;
203
207
  log.info("Leaflet map overlay disposed");
204
208
  }
@@ -236,9 +240,9 @@ var LeafletMapOverlay = class {
236
240
  this.fusedPolyline = null;
237
241
  this.snapshotPolyline?.remove();
238
242
  this.snapshotPolyline = null;
239
- for (const rp of this.refPoints) {
240
- rp.marker?.remove();
241
- rp.marker = null;
243
+ for (const m of this.namedMarkers) {
244
+ m.marker?.remove();
245
+ m.marker = null;
242
246
  }
243
247
  if (this.leafletMap) {
244
248
  this.leafletMap.remove();
@@ -285,7 +289,7 @@ var LeafletMapOverlay = class {
285
289
  weight: 3,
286
290
  opacity: .8
287
291
  }).addTo(this.leafletMap);
288
- for (const rp of this.refPoints) if (!rp.marker) rp.marker = this.createRefPointMarker(rp.lat, rp.lng, rp.name, rp.isPrior);
292
+ for (const m of this.namedMarkers) if (!m.marker) m.marker = this.createNamedMarker(m.lat, m.lng, m.name, m.isPrior);
289
293
  }
290
294
  updateUserMarker() {
291
295
  if (!this.gpsPosition || !this.leafletMap) return;
@@ -297,7 +301,7 @@ var LeafletMapOverlay = class {
297
301
  iconAnchor: [7, 7]
298
302
  }) }).addTo(this.leafletMap);
299
303
  }
300
- createRefPointMarker(lat, lon, name, isPrior) {
304
+ createNamedMarker(lat, lon, name, isPrior) {
301
305
  const color = isPrior ? VIS_COLORS.PRIOR_REF_POINT.css : VIS_COLORS.CURRENT_REF_POINT.css;
302
306
  const opacity = isPrior ? "opacity:0.8;" : "";
303
307
  const label = isPrior ? `📌 ${name} (prior)` : name;
@@ -1,2 +1,2 @@
1
- import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-87NWjUOD.js";
1
+ import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-CZgQlrmu.js";
2
2
  export { DEFAULT_LERP_RATE, clampedAlpha };
@@ -1,2 +1,2 @@
1
- import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-DuiZuCTx.js";
1
+ import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-C9ifl_4-.js";
2
2
  export { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, MapOverlayOptions, TextureLoaderInterface, latLonToTileXY, tileXYToLatLon };
@@ -1,2 +1,2 @@
1
- import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-CCBHjE_a.js";
1
+ import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-qt_r5wR1.js";
2
2
  export { DisposeOptions, disposeMeshArray, disposeObject3D };
@@ -1,2 +1,2 @@
1
- import { t as VIS_COLORS } from "../vis-colors-Qi2vlRGt.js";
1
+ import { t as VIS_COLORS } from "../vis-colors-BKkdTIKb.js";
2
2
  export { VIS_COLORS };