@osm-editor-kit/street-imagery-react 0.1.0-alpha.8 → 1.0.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 (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +118 -9
  3. package/dist/MapillaryPanel-SOHGB7JA.js +3 -0
  4. package/dist/PanoramaxPanel-5P5LWMRY.js +3 -0
  5. package/dist/StreetLevelImagerySelectionOverlay.d.ts +3 -1
  6. package/dist/StreetLevelImagerySourcesAndLayers.d.ts +10 -0
  7. package/dist/StreetLevelImageryViewCone.d.ts +3 -1
  8. package/dist/StreetLevelImageryViewer.d.ts +18 -4
  9. package/dist/{chunk-ZAIXGYAH.js → chunk-3DFVM6VK.js} +59 -15
  10. package/dist/{chunk-25UGGXIE.js → chunk-GYUS2JVV.js} +24 -4
  11. package/dist/chunk-LZR5SZDS.js +498 -0
  12. package/dist/chunk-R6BDVYWM.js +665 -0
  13. package/dist/chunk-XLBFXACK.js +56 -0
  14. package/dist/filters/PhotoDateRangeFilter.d.ts +10 -2
  15. package/dist/filters/dateSliderPointer.d.ts +21 -0
  16. package/dist/hooks/useMapViewportBbox.d.ts +3 -5
  17. package/dist/hooks/useProviderData.d.ts +14 -3
  18. package/dist/index.d.ts +12 -13
  19. package/dist/index.js +3942 -1461
  20. package/dist/mapillary/useMapillaryFeatures.d.ts +5 -5
  21. package/dist/panels/MapillaryPanel.d.ts +7 -2
  22. package/dist/panels/PanoramaxPanel.d.ts +16 -8
  23. package/dist/panels/PanoramaxWebViewerPanel.d.ts +25 -0
  24. package/dist/panels/panoramaxDataProvider.d.ts +44 -0
  25. package/dist/panels/panoramaxItem.d.ts +98 -0
  26. package/dist/panels/photoView.d.ts +19 -0
  27. package/dist/panoramax-web-viewer/index.d.ts +1 -0
  28. package/dist/{chunk-EQ2JKLGT.js → panoramax-web-viewer.js} +299 -92
  29. package/dist/photo-details.js +222 -151
  30. package/dist/streetImageryClick.d.ts +4 -0
  31. package/dist/viewer-panels/index.d.ts +5 -0
  32. package/dist/viewer-panels.js +4 -0
  33. package/dist/viewpoints/FloatingPhotoViewer.d.ts +39 -11
  34. package/dist/viewpoints/floatingViewerPosition.d.ts +18 -0
  35. package/dist/viewpoints/usePhotosLookingAt.d.ts +26 -0
  36. package/package.json +32 -6
  37. package/dist/MapillaryPanel-N45NQY4C.js +0 -2
  38. package/dist/PanoramaxPanel-MFI4L67Z.js +0 -2
  39. package/dist/chunk-53RA4OSJ.js +0 -304
@@ -0,0 +1,498 @@
1
+ import { watchMapillaryJsView } from './chunk-XLBFXACK.js';
2
+ import { useViewerActions } from './chunk-GYUS2JVV.js';
3
+ import { c } from 'react/compiler-runtime';
4
+ import { viewFromOutline, SIGN_TARGET, viewFromFlatCamera, cameraPitch, panoX, bearingDeg, viewFromLocation, getStreetImageryConfig, fetchImageDetections } from '@osm-editor-kit/street-imagery';
5
+ import 'mapillary-js/dist/mapillary.css';
6
+ import { OutlineTag, PolygonGeometry, Viewer } from 'mapillary-js';
7
+ import { useRef, useEffectEvent, useEffect } from 'react';
8
+ import { jsx } from 'react/jsx-runtime';
9
+
10
+ var isSpherical = (image) => image.cameraType === "spherical" || image.cameraType === "equirectangular";
11
+ var mapillaryViewFor = async (viewer, image, {
12
+ lngLat,
13
+ shape = SIGN_TARGET,
14
+ outline
15
+ }) => {
16
+ const spherical = isSpherical(image);
17
+ if (outline?.length) {
18
+ return viewFromOutline(outline, spherical, shape.maxZoom);
19
+ }
20
+ const position = image.lngLat ?? image.originalLngLat;
21
+ const imageLngLat = [position.lng, position.lat];
22
+ const compass = image.computedCompassAngle ?? image.compassAngle;
23
+ if (!spherical) {
24
+ const focal = image.cameraParameters?.[0];
25
+ return focal ? viewFromFlatCamera({
26
+ focal,
27
+ width: image.width,
28
+ height: image.height,
29
+ compassAngle: compass,
30
+ pitch: cameraPitch(image.rotation)
31
+ }, imageLngLat, lngLat, shape) : void 0;
32
+ }
33
+ let x = panoX(bearingDeg(imageLngLat, lngLat), compass);
34
+ try {
35
+ viewer.setCenter([x, 0.5]);
36
+ const pixel = await viewer.project({
37
+ lng: lngLat[0],
38
+ lat: lngLat[1]
39
+ });
40
+ const basic = pixel ? await viewer.unprojectToBasic(pixel) : null;
41
+ const projected = basic?.[0];
42
+ if (projected != null && projected >= 0 && projected <= 1) {
43
+ x = projected;
44
+ }
45
+ } catch {
46
+ }
47
+ return viewFromLocation(x, {
48
+ lngLat: imageLngLat,
49
+ isPano: true
50
+ }, lngLat, shape);
51
+ };
52
+ var xDistance = (a, b, spherical) => {
53
+ const distance = Math.abs(a - b);
54
+ return spherical ? Math.min(distance, 1 - distance) : distance;
55
+ };
56
+ var findOwnDetection = async (image, value, estimate) => {
57
+ const spherical = isSpherical(image);
58
+ const candidates = await fetchImageDetections(image.id, {
59
+ filter: (v) => v === value
60
+ }).catch(() => []);
61
+ const centerX = (detection) => viewFromOutline(detection.outline, spherical)?.center[0] ?? 0.5;
62
+ return candidates.sort((a, b) => estimate ? xDistance(centerX(a), estimate.center[0], spherical) - xDistance(centerX(b), estimate.center[0], spherical) : 0)[0];
63
+ };
64
+ var turnMapillaryViewerTo = async (viewer, image, lookAt) => {
65
+ let outline = lookAt.outline?.length ? lookAt.outline : void 0;
66
+ let outlineId = `look-at-${image.id}`;
67
+ let view;
68
+ if (!outline) {
69
+ view = await mapillaryViewFor(viewer, image, lookAt);
70
+ const own = lookAt.value ? await findOwnDetection(image, lookAt.value, view) : void 0;
71
+ if (own) {
72
+ outline = own.outline;
73
+ outlineId = own.id;
74
+ }
75
+ }
76
+ if (outline) {
77
+ view = viewFromOutline(outline, isSpherical(image), (lookAt.shape ?? SIGN_TARGET).maxZoom);
78
+ }
79
+ if (!view) {
80
+ return false;
81
+ }
82
+ viewer.setCenter(view.center);
83
+ viewer.setZoom(view.zoom);
84
+ return outline ? {
85
+ id: outlineId,
86
+ outline,
87
+ label: lookAt.label
88
+ } : null;
89
+ };
90
+ var setMapillaryViewerOutlines = (viewer, outlines) => {
91
+ const tags = viewer.getComponent("tag");
92
+ tags.removeAll();
93
+ tags.add(outlines.filter(({
94
+ outline
95
+ }) => outline.length >= 3).map(({
96
+ id,
97
+ outline,
98
+ label,
99
+ color = 16776960
100
+ }) => {
101
+ const first = outline[0];
102
+ const last = outline[outline.length - 1];
103
+ const closed = first[0] === last[0] && first[1] === last[1] ? outline : [...outline, first];
104
+ return new OutlineTag(id, new PolygonGeometry(closed), {
105
+ text: label,
106
+ textColor: color,
107
+ lineColor: color,
108
+ lineWidth: 2,
109
+ fillColor: color,
110
+ fillOpacity: 0.3
111
+ });
112
+ }));
113
+ };
114
+ var panoCenterX = (bearing, compassAngle) => ((0.5 + (bearing - compassAngle) / 360) % 1 + 1) % 1;
115
+ var MapillaryPanel = (t0) => {
116
+ const $ = c(49);
117
+ const {
118
+ photo,
119
+ onPhotoSelected,
120
+ onEaseMapToPoint,
121
+ onViewerPhoto,
122
+ onViewerView,
123
+ lookAtBearing,
124
+ lookAt,
125
+ outlines,
126
+ hideAttribution: t1
127
+ } = t0;
128
+ const hideAttribution = t1 === void 0 ? false : t1;
129
+ const containerRef = useRef(null);
130
+ const viewerRef = useRef(null);
131
+ const navigableRef = useRef(false);
132
+ const pendingImageIdRef = useRef(null);
133
+ const lastViewerPhotoIdRef = useRef(null);
134
+ const bearingRafRef = useRef(null);
135
+ const pendingBearingRef = useRef(null);
136
+ const actions = useViewerActions();
137
+ const initialPhotoIdRef = useRef(photo.photoId);
138
+ const initialHideAttributionRef = useRef(hideAttribution);
139
+ const emitPhotoSelected = useEffectEvent(onPhotoSelected);
140
+ const emitEaseMapToPoint = useEffectEvent(onEaseMapToPoint);
141
+ let t2;
142
+ if ($[0] !== lookAt || $[1] !== lookAtBearing || $[2] !== outlines || $[3] !== photo.photoId) {
143
+ t2 = (viewer, image) => {
144
+ if (image.id !== photo.photoId) {
145
+ return;
146
+ }
147
+ if (lookAt) {
148
+ turnMapillaryViewerTo(viewer, image, lookAt).then((aimedAt) => {
149
+ if (aimedAt && !outlines && lastViewerPhotoIdRef.current === image.id) {
150
+ setMapillaryViewerOutlines(viewer, [aimedAt]);
151
+ }
152
+ }).catch(_temp);
153
+ return;
154
+ }
155
+ const spherical = image.cameraType === "spherical" || image.cameraType === "equirectangular";
156
+ const compass = image.computedCompassAngle ?? image.compassAngle;
157
+ if (lookAtBearing != null && spherical && compass != null) {
158
+ viewer.setCenter([panoCenterX(lookAtBearing, compass), 0.5]);
159
+ }
160
+ };
161
+ $[0] = lookAt;
162
+ $[1] = lookAtBearing;
163
+ $[2] = outlines;
164
+ $[3] = photo.photoId;
165
+ $[4] = t2;
166
+ } else {
167
+ t2 = $[4];
168
+ }
169
+ const turnToWantedBearing = useEffectEvent(t2);
170
+ let t3;
171
+ if ($[5] !== outlines) {
172
+ t3 = (viewer_0) => {
173
+ setMapillaryViewerOutlines(viewer_0, outlines ?? []);
174
+ };
175
+ $[5] = outlines;
176
+ $[6] = t3;
177
+ } else {
178
+ t3 = $[6];
179
+ }
180
+ const drawOutlines = useEffectEvent(t3);
181
+ let t4;
182
+ if ($[7] !== onViewerPhoto) {
183
+ t4 = (viewerPhoto) => onViewerPhoto?.(viewerPhoto);
184
+ $[7] = onViewerPhoto;
185
+ $[8] = t4;
186
+ } else {
187
+ t4 = $[8];
188
+ }
189
+ const emitViewerPhoto = useEffectEvent(t4);
190
+ let t5;
191
+ if ($[9] !== actions) {
192
+ t5 = function resetViewerStoreOnProviderChange() {
193
+ return () => {
194
+ actions.reset();
195
+ };
196
+ };
197
+ $[9] = actions;
198
+ $[10] = t5;
199
+ } else {
200
+ t5 = $[10];
201
+ }
202
+ let t6;
203
+ if ($[11] !== actions || $[12] !== photo.providerId) {
204
+ t6 = [actions, photo.providerId];
205
+ $[11] = actions;
206
+ $[12] = photo.providerId;
207
+ $[13] = t6;
208
+ } else {
209
+ t6 = $[13];
210
+ }
211
+ useEffect(t5, t6);
212
+ let t7;
213
+ if ($[14] !== actions || $[15] !== drawOutlines || $[16] !== emitEaseMapToPoint || $[17] !== emitPhotoSelected || $[18] !== emitViewerPhoto || $[19] !== turnToWantedBearing) {
214
+ t7 = function mountMapillaryViewer() {
215
+ const container = containerRef.current;
216
+ if (!container) {
217
+ return;
218
+ }
219
+ const viewer_1 = new Viewer({
220
+ accessToken: getStreetImageryConfig().mapillaryToken,
221
+ container,
222
+ imageId: initialPhotoIdRef.current,
223
+ component: {
224
+ attribution: !initialHideAttributionRef.current,
225
+ cover: false,
226
+ sequence: {
227
+ visible: true
228
+ },
229
+ tag: true
230
+ }
231
+ });
232
+ viewerRef.current = viewer_1;
233
+ lastViewerPhotoIdRef.current = initialPhotoIdRef.current;
234
+ const flushPendingMove = () => {
235
+ const pendingId = pendingImageIdRef.current;
236
+ if (!pendingId) {
237
+ return;
238
+ }
239
+ pendingImageIdRef.current = null;
240
+ viewer_1.moveTo(pendingId).catch(_temp2);
241
+ };
242
+ const onNavigable = (event) => {
243
+ navigableRef.current = event.navigable;
244
+ if (event.navigable) {
245
+ flushPendingMove();
246
+ }
247
+ };
248
+ const onImage = (event_0) => {
249
+ const {
250
+ image: image_0
251
+ } = event_0;
252
+ lastViewerPhotoIdRef.current = image_0.id;
253
+ turnToWantedBearing(viewer_1, image_0);
254
+ drawOutlines(viewer_1);
255
+ emitPhotoSelected({
256
+ provider: "mapillary",
257
+ sequenceId: image_0.sequenceId,
258
+ photoId: image_0.id
259
+ });
260
+ const position = image_0.lngLat ?? image_0.originalLngLat;
261
+ if (!position) {
262
+ return;
263
+ }
264
+ emitViewerPhoto({
265
+ providerId: "mapillary",
266
+ photoId: image_0.id,
267
+ sequenceId: image_0.sequenceId,
268
+ capturedAt: image_0.capturedAt,
269
+ isPano: image_0.cameraType === "spherical" || image_0.cameraType === "equirectangular",
270
+ heading: image_0.computedCompassAngle ?? image_0.compassAngle,
271
+ lngLat: [position.lng, position.lat],
272
+ ...image_0.creatorUsername ? {
273
+ creatorName: image_0.creatorUsername
274
+ } : {}
275
+ });
276
+ const isFlat = image_0.cameraType !== "spherical" && image_0.cameraType !== "equirectangular";
277
+ const compass_0 = image_0.computedCompassAngle ?? image_0.compassAngle;
278
+ actions.setPov({
279
+ lngLat: [position.lng, position.lat],
280
+ ...isFlat && compass_0 != null ? {
281
+ bearing: compass_0
282
+ } : {}
283
+ });
284
+ emitEaseMapToPoint(position.lng, position.lat);
285
+ };
286
+ const flushBearing = () => {
287
+ bearingRafRef.current = null;
288
+ if (pendingBearingRef.current != null) {
289
+ actions.setPov({
290
+ bearing: pendingBearingRef.current
291
+ });
292
+ pendingBearingRef.current = null;
293
+ }
294
+ viewer_1.getFieldOfView().then((fov) => {
295
+ actions.setPov({
296
+ hfov: fov
297
+ });
298
+ }).catch(_temp3);
299
+ };
300
+ const onBearing = (event_1) => {
301
+ pendingBearingRef.current = event_1.bearing;
302
+ if (bearingRafRef.current == null) {
303
+ bearingRafRef.current = requestAnimationFrame(flushBearing);
304
+ }
305
+ };
306
+ viewer_1.on("navigable", onNavigable);
307
+ viewer_1.on("image", onImage);
308
+ viewer_1.on("bearing", onBearing);
309
+ const resizeObserver = new ResizeObserver(() => {
310
+ viewer_1.resize();
311
+ });
312
+ resizeObserver.observe(container);
313
+ return () => {
314
+ if (bearingRafRef.current != null) {
315
+ cancelAnimationFrame(bearingRafRef.current);
316
+ bearingRafRef.current = null;
317
+ }
318
+ resizeObserver.disconnect();
319
+ viewer_1.off("navigable", onNavigable);
320
+ viewer_1.off("image", onImage);
321
+ viewer_1.off("bearing", onBearing);
322
+ viewer_1.remove();
323
+ viewerRef.current = null;
324
+ };
325
+ };
326
+ $[14] = actions;
327
+ $[15] = drawOutlines;
328
+ $[16] = emitEaseMapToPoint;
329
+ $[17] = emitPhotoSelected;
330
+ $[18] = emitViewerPhoto;
331
+ $[19] = turnToWantedBearing;
332
+ $[20] = t7;
333
+ } else {
334
+ t7 = $[20];
335
+ }
336
+ let t8;
337
+ if ($[21] !== actions) {
338
+ t8 = [actions];
339
+ $[21] = actions;
340
+ $[22] = t8;
341
+ } else {
342
+ t8 = $[22];
343
+ }
344
+ useEffect(t7, t8);
345
+ let t9;
346
+ if ($[23] !== onViewerView) {
347
+ t9 = (view) => onViewerView?.(view);
348
+ $[23] = onViewerView;
349
+ $[24] = t9;
350
+ } else {
351
+ t9 = $[24];
352
+ }
353
+ const emitViewerView = useEffectEvent(t9);
354
+ const reportsView = onViewerView !== void 0;
355
+ let t10;
356
+ if ($[25] !== emitViewerView || $[26] !== reportsView) {
357
+ t10 = function reportViewInPhoto() {
358
+ const viewer_2 = viewerRef.current;
359
+ if (!viewer_2 || !reportsView) {
360
+ return;
361
+ }
362
+ const read = async () => {
363
+ const [image_1, t112, zoom] = await Promise.all([viewer_2.getImage(), viewer_2.getCenter(), viewer_2.getZoom()]);
364
+ const [t122, t132] = t112;
365
+ const x = t122 === void 0 ? 0.5 : t122;
366
+ const y = t132 === void 0 ? 0.5 : t132;
367
+ return {
368
+ providerId: "mapillary",
369
+ photoId: image_1.id,
370
+ x,
371
+ y,
372
+ zoom
373
+ };
374
+ };
375
+ return watchMapillaryJsView(viewer_2, read, (view_0) => emitViewerView(view_0));
376
+ };
377
+ $[25] = emitViewerView;
378
+ $[26] = reportsView;
379
+ $[27] = t10;
380
+ } else {
381
+ t10 = $[27];
382
+ }
383
+ let t11;
384
+ if ($[28] !== actions || $[29] !== reportsView) {
385
+ t11 = [actions, reportsView];
386
+ $[28] = actions;
387
+ $[29] = reportsView;
388
+ $[30] = t11;
389
+ } else {
390
+ t11 = $[30];
391
+ }
392
+ useEffect(t10, t11);
393
+ let t12;
394
+ let t13;
395
+ if ($[31] !== actions || $[32] !== photo.photoId) {
396
+ t12 = function syncExternalPhotoSelection() {
397
+ const viewer_3 = viewerRef.current;
398
+ if (!viewer_3 || photo.photoId === lastViewerPhotoIdRef.current) {
399
+ return;
400
+ }
401
+ actions.reset();
402
+ lastViewerPhotoIdRef.current = photo.photoId;
403
+ if (navigableRef.current) {
404
+ viewer_3.moveTo(photo.photoId).catch(_temp4);
405
+ } else {
406
+ pendingImageIdRef.current = photo.photoId;
407
+ }
408
+ };
409
+ t13 = [actions, photo.photoId];
410
+ $[31] = actions;
411
+ $[32] = photo.photoId;
412
+ $[33] = t12;
413
+ $[34] = t13;
414
+ } else {
415
+ t12 = $[33];
416
+ t13 = $[34];
417
+ }
418
+ useEffect(t12, t13);
419
+ let t14;
420
+ if ($[35] !== lookAt || $[36] !== lookAtBearing) {
421
+ t14 = lookAt ? `${lookAt.lngLat.join(",")}|${lookAt.outline?.length ?? 0}|${lookAt.value ?? ""}` : String(lookAtBearing);
422
+ $[35] = lookAt;
423
+ $[36] = lookAtBearing;
424
+ $[37] = t14;
425
+ } else {
426
+ t14 = $[37];
427
+ }
428
+ const lookAtKey = t14;
429
+ let t15;
430
+ if ($[38] !== photo.photoId || $[39] !== turnToWantedBearing) {
431
+ t15 = function turnToTargetOnChange() {
432
+ const viewer_4 = viewerRef.current;
433
+ if (!viewer_4 || lastViewerPhotoIdRef.current !== photo.photoId) {
434
+ return;
435
+ }
436
+ viewer_4.getImage().then((image_2) => turnToWantedBearing(viewer_4, image_2)).catch(_temp5);
437
+ };
438
+ $[38] = photo.photoId;
439
+ $[39] = turnToWantedBearing;
440
+ $[40] = t15;
441
+ } else {
442
+ t15 = $[40];
443
+ }
444
+ let t16;
445
+ if ($[41] !== lookAtKey || $[42] !== photo.photoId) {
446
+ t16 = [lookAtKey, photo.photoId];
447
+ $[41] = lookAtKey;
448
+ $[42] = photo.photoId;
449
+ $[43] = t16;
450
+ } else {
451
+ t16 = $[43];
452
+ }
453
+ useEffect(t15, t16);
454
+ let t17;
455
+ if ($[44] !== drawOutlines) {
456
+ t17 = function redrawOutlinesOnChange() {
457
+ const viewer_5 = viewerRef.current;
458
+ if (viewer_5 && navigableRef.current) {
459
+ drawOutlines(viewer_5);
460
+ }
461
+ };
462
+ $[44] = drawOutlines;
463
+ $[45] = t17;
464
+ } else {
465
+ t17 = $[45];
466
+ }
467
+ let t18;
468
+ if ($[46] !== outlines) {
469
+ t18 = [outlines];
470
+ $[46] = outlines;
471
+ $[47] = t18;
472
+ } else {
473
+ t18 = $[47];
474
+ }
475
+ useEffect(t17, t18);
476
+ let t19;
477
+ if ($[48] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
478
+ t19 = /* @__PURE__ */ jsx("div", { ref: containerRef, className: "min-h-48 overflow-hidden rounded-lg border border-slate-200 bg-slate-900", style: {
479
+ aspectRatio: "4 / 3"
480
+ } });
481
+ $[48] = t19;
482
+ } else {
483
+ t19 = $[48];
484
+ }
485
+ return t19;
486
+ };
487
+ function _temp() {
488
+ }
489
+ function _temp2() {
490
+ }
491
+ function _temp3() {
492
+ }
493
+ function _temp4() {
494
+ }
495
+ function _temp5() {
496
+ }
497
+
498
+ export { MapillaryPanel, mapillaryViewFor, setMapillaryViewerOutlines, turnMapillaryViewerTo };