@osm-editor-kit/street-imagery-react 0.1.0-alpha.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -10
  3. package/dist/MapillaryPanel-SOHGB7JA.js +3 -0
  4. package/dist/PanoramaxPanel-5P5LWMRY.js +3 -0
  5. package/dist/StreetLevelImageryViewer.d.ts +19 -5
  6. package/dist/{chunk-6EMFFIL2.js → chunk-3DFVM6VK.js} +57 -13
  7. package/dist/{chunk-25UGGXIE.js → chunk-GYUS2JVV.js} +24 -4
  8. package/dist/chunk-LZR5SZDS.js +498 -0
  9. package/dist/chunk-R6BDVYWM.js +665 -0
  10. package/dist/chunk-XLBFXACK.js +56 -0
  11. package/dist/filters/PhotoDateRangeFilter.d.ts +4 -1
  12. package/dist/filters/dateSliderPointer.d.ts +21 -0
  13. package/dist/hooks/useMapViewportBbox.d.ts +3 -5
  14. package/dist/hooks/useProviderData.d.ts +9 -3
  15. package/dist/index.d.ts +12 -12
  16. package/dist/index.js +3835 -1563
  17. package/dist/mapillary/lookAt.d.ts +26 -0
  18. package/dist/mapillary/useMapillaryFeatures.d.ts +5 -5
  19. package/dist/panels/MapillaryPanel.d.ts +8 -3
  20. package/dist/panels/PanoramaxPanel.d.ts +16 -9
  21. package/dist/panels/PanoramaxWebViewerPanel.d.ts +25 -0
  22. package/dist/panels/mapillaryLookAt.d.ts +2 -26
  23. package/dist/panels/panoramaxDataProvider.d.ts +44 -0
  24. package/dist/panels/panoramaxItem.d.ts +98 -0
  25. package/dist/panels/photoView.d.ts +19 -0
  26. package/dist/panoramax-web-viewer/index.d.ts +1 -0
  27. package/dist/{chunk-KZTMKQT5.js → panoramax-web-viewer.js} +299 -93
  28. package/dist/photo-details.js +222 -151
  29. package/dist/viewer/index.d.ts +1 -0
  30. package/dist/viewer-panels/index.d.ts +3 -1
  31. package/dist/viewer-panels.js +4 -3
  32. package/dist/viewer.js +98 -0
  33. package/dist/viewpoints/FloatingPhotoViewer.d.ts +22 -7
  34. package/dist/viewpoints/floatingViewerPosition.d.ts +18 -0
  35. package/dist/viewpoints/usePhotosLookingAt.d.ts +26 -0
  36. package/package.json +38 -7
  37. package/dist/MapillaryPanel-FAXVZH37.js +0 -2
  38. package/dist/PanoramaxPanel-BTHEMKYY.js +0 -2
  39. package/dist/chunk-SGIB7AVC.js +0 -309
@@ -1,4 +1,5 @@
1
- import { useStreetImageryI18n } from './chunk-6EMFFIL2.js';
1
+ import { useStreetImageryI18n } from './chunk-3DFVM6VK.js';
2
+ import { c } from 'react/compiler-runtime';
2
3
  import { providerById, formatLocalDateTime, formatDate, formatRelativeDate } from '@osm-editor-kit/street-imagery';
3
4
  import { useRef, useEffect } from 'react';
4
5
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -68,168 +69,238 @@ var PHOTO_DETAILS_LABELS = {
68
69
  };
69
70
  var formatBytes = (bytes) => bytes >= 1e6 ? `${(bytes / 1e6).toFixed(1)} MB` : `${Math.round(bytes / 1e3)} kB`;
70
71
  var LINK_CLASS = "text-zinc-950 underline decoration-zinc-950/30 hover:decoration-zinc-950";
71
- var Section = ({ title, rows }) => {
72
- const filled = rows.filter(([, value]) => value != null && value !== "");
73
- if (filled.length === 0) {
74
- return null;
72
+ var Section = (t0) => {
73
+ const $ = c(16);
74
+ const {
75
+ title,
76
+ rows
77
+ } = t0;
78
+ let t1;
79
+ let t2;
80
+ let t3;
81
+ let t4;
82
+ let t5;
83
+ if ($[0] !== rows || $[1] !== title) {
84
+ t5 = /* @__PURE__ */ Symbol.for("react.early_return_sentinel");
85
+ bb0: {
86
+ const filled = rows.filter(_temp);
87
+ if (filled.length === 0) {
88
+ t5 = null;
89
+ break bb0;
90
+ }
91
+ t3 = "mt-6 first:mt-0";
92
+ if ($[7] !== title) {
93
+ t4 = /* @__PURE__ */ jsx("h3", { className: "text-xs/5 font-semibold tracking-wide text-zinc-500 uppercase", children: title });
94
+ $[7] = title;
95
+ $[8] = t4;
96
+ } else {
97
+ t4 = $[8];
98
+ }
99
+ t1 = "mt-1 grid grid-cols-[minmax(7rem,35%)_1fr] text-sm/6";
100
+ t2 = filled.map(_temp2);
101
+ }
102
+ $[0] = rows;
103
+ $[1] = title;
104
+ $[2] = t1;
105
+ $[3] = t2;
106
+ $[4] = t3;
107
+ $[5] = t4;
108
+ $[6] = t5;
109
+ } else {
110
+ t1 = $[2];
111
+ t2 = $[3];
112
+ t3 = $[4];
113
+ t4 = $[5];
114
+ t5 = $[6];
115
+ }
116
+ if (t5 !== /* @__PURE__ */ Symbol.for("react.early_return_sentinel")) {
117
+ return t5;
118
+ }
119
+ let t6;
120
+ if ($[9] !== t1 || $[10] !== t2) {
121
+ t6 = /* @__PURE__ */ jsx("dl", { className: t1, children: t2 });
122
+ $[9] = t1;
123
+ $[10] = t2;
124
+ $[11] = t6;
125
+ } else {
126
+ t6 = $[11];
75
127
  }
76
- return /* @__PURE__ */ jsxs("section", { className: "mt-6 first:mt-0", children: [
77
- /* @__PURE__ */ jsx("h3", { className: "text-xs/5 font-semibold tracking-wide text-zinc-500 uppercase", children: title }),
78
- /* @__PURE__ */ jsx("dl", { className: "mt-1 grid grid-cols-[minmax(7rem,35%)_1fr] text-sm/6", children: filled.map(([term, value]) => /* @__PURE__ */ jsxs("div", { className: "col-span-2 grid grid-cols-subgrid border-t border-zinc-950/5", children: [
79
- /* @__PURE__ */ jsx("dt", { className: "py-2 pr-3 text-zinc-500", children: term }),
80
- /* @__PURE__ */ jsx("dd", { className: "min-w-0 py-2 wrap-break-word text-zinc-950", children: value })
81
- ] }, term)) })
82
- ] });
128
+ let t7;
129
+ if ($[12] !== t3 || $[13] !== t4 || $[14] !== t6) {
130
+ t7 = /* @__PURE__ */ jsxs("section", { className: t3, children: [
131
+ t4,
132
+ t6
133
+ ] });
134
+ $[12] = t3;
135
+ $[13] = t4;
136
+ $[14] = t6;
137
+ $[15] = t7;
138
+ } else {
139
+ t7 = $[15];
140
+ }
141
+ return t7;
83
142
  };
84
- var PhotoDetailsDialog = ({
85
- photo,
86
- open,
87
- onClose,
88
- externalUrl,
89
- labels
90
- }) => {
91
- const { locale } = useStreetImageryI18n();
92
- const t = { ...PHOTO_DETAILS_LABELS[locale], ...labels };
143
+ var PhotoDetailsDialog = (t0) => {
144
+ const $ = c(19);
145
+ const {
146
+ photo,
147
+ open,
148
+ onClose,
149
+ externalUrl,
150
+ labels
151
+ } = t0;
152
+ const {
153
+ locale
154
+ } = useStreetImageryI18n();
155
+ const t = {
156
+ ...PHOTO_DETAILS_LABELS[locale],
157
+ ...labels
158
+ };
93
159
  const dialogRef = useRef(null);
94
- useEffect(
95
- function syncOpenState() {
160
+ let t1;
161
+ let t2;
162
+ if ($[0] !== open) {
163
+ t1 = function syncOpenState() {
96
164
  const dialog = dialogRef.current;
97
165
  if (!dialog) {
98
166
  return;
99
167
  }
100
168
  if (open && !dialog.open) {
101
169
  dialog.showModal();
102
- dialog.firstElementChild?.scrollTo({ top: 0 });
103
- } else if (!open && dialog.open) {
104
- dialog.close();
170
+ dialog.firstElementChild?.scrollTo({
171
+ top: 0
172
+ });
173
+ } else {
174
+ if (!open && dialog.open) {
175
+ dialog.close();
176
+ }
105
177
  }
106
- },
107
- [open]
108
- );
109
- const details = photo.details ?? {};
178
+ };
179
+ t2 = [open];
180
+ $[0] = open;
181
+ $[1] = t1;
182
+ $[2] = t2;
183
+ } else {
184
+ t1 = $[1];
185
+ t2 = $[2];
186
+ }
187
+ useEffect(t1, t2);
188
+ let t3;
189
+ if ($[3] !== photo.details) {
190
+ t3 = photo.details ?? {};
191
+ $[3] = photo.details;
192
+ $[4] = t3;
193
+ } else {
194
+ t3 = $[4];
195
+ }
196
+ const details = t3;
110
197
  const provider = providerById[photo.providerId];
111
198
  const capturedAt = (details.capturedAtLocal ? formatLocalDateTime(details.capturedAtLocal, locale) : null) ?? (photo.capturedAt != null ? formatDate(photo.capturedAt, locale) : null);
112
- const contact = details.creatorContact?.includes("@") ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: `mailto:${details.creatorContact}`, children: details.creatorContact }) : details.creatorContact;
113
- const license = details.license && details.licenseUrl ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: details.licenseUrl, rel: "noreferrer", target: "_blank", children: details.license }) : details.license;
114
- const photoId = externalUrl ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: externalUrl, rel: "noreferrer", target: "_blank", children: photo.photoId }) : photo.photoId;
115
- const exif = Object.entries(details.exif ?? {}).sort(([a], [b]) => a.localeCompare(b));
116
- return /* @__PURE__ */ jsx(
117
- "dialog",
118
- {
119
- "aria-labelledby": "photo-details-title",
120
- className: "m-auto w-full max-w-lg rounded-2xl bg-white p-0 shadow-lg ring-1 ring-zinc-950/10 backdrop:bg-zinc-950/25",
121
- ref: dialogRef,
122
- onClick: (event) => {
123
- if (event.target === event.currentTarget) {
124
- onClose();
125
- }
126
- },
127
- onClose,
128
- onKeyDown: (event) => {
129
- if (event.key === "Escape") {
130
- event.stopPropagation();
131
- }
132
- },
133
- children: /* @__PURE__ */ jsxs("div", { className: "max-h-[85vh] overflow-y-auto p-6 sm:p-8", children: [
134
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
135
- /* @__PURE__ */ jsxs("h2", { className: "text-base/6 font-semibold text-zinc-950", id: "photo-details-title", children: [
136
- t.title,
137
- /* @__PURE__ */ jsx("span", { className: "ml-2 font-normal text-zinc-500", children: provider.label })
138
- ] }),
139
- /* @__PURE__ */ jsx(
140
- "button",
141
- {
142
- className: "-m-1 rounded-md p-1 text-sm/6 font-medium text-zinc-500 hover:bg-zinc-950/5 hover:text-zinc-950",
143
- type: "button",
144
- onClick: onClose,
145
- children: t.close
146
- }
147
- )
148
- ] }),
149
- /* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
150
- /* @__PURE__ */ jsx(
151
- Section,
152
- {
153
- rows: [
154
- [t.creator, photo.creatorName],
155
- [t.contact, contact],
156
- [
157
- t.capturedAt,
158
- capturedAt && photo.capturedAt != null ? `${capturedAt} \xB7 ${formatRelativeDate(photo.capturedAt, locale)}` : capturedAt
159
- ],
160
- [
161
- t.uploadedAt,
162
- details.uploadedAt != null ? formatDate(details.uploadedAt, locale) : null
163
- ],
164
- [t.license, license]
165
- ],
166
- title: t.sectionCapture
167
- }
168
- ),
169
- /* @__PURE__ */ jsx(
170
- Section,
171
- {
172
- rows: [
173
- [t.type, photo.isPano == null ? null : photo.isPano ? t.pano : t.flat],
174
- [t.camera, details.camera],
175
- [t.focalLength, details.focalLengthMm != null ? `${details.focalLengthMm} mm` : null],
176
- [
177
- t.fieldOfView,
178
- details.fieldOfViewDeg != null ? `${Math.round(details.fieldOfViewDeg)}\xB0` : null
179
- ]
180
- ],
181
- title: t.sectionCamera
182
- }
183
- ),
184
- /* @__PURE__ */ jsx(
185
- Section,
186
- {
187
- rows: [
188
- [t.coordinates, `${photo.lngLat[1].toFixed(6)}, ${photo.lngLat[0].toFixed(6)}`],
189
- [t.heading, photo.heading != null ? `${Math.round(photo.heading)}\xB0` : null],
190
- [
191
- t.accuracy,
192
- details.positionAccuracyMeters != null ? `\xB1 ${details.positionAccuracyMeters} m` : null
193
- ]
194
- ],
195
- title: t.sectionPosition
196
- }
197
- ),
198
- /* @__PURE__ */ jsx(
199
- Section,
200
- {
201
- rows: [
202
- [t.provider, provider.label],
203
- [t.instance, details.instance],
204
- [t.photoId, photoId],
205
- [t.sequence, photo.sequenceId],
206
- [t.rankInSequence, details.rankInSequence],
207
- [
208
- t.file,
209
- details.originalFileName ? `${details.originalFileName}${details.originalFileSizeBytes != null ? ` (${formatBytes(details.originalFileSizeBytes)})` : ""}` : null
210
- ]
211
- ],
212
- title: t.sectionSource
213
- }
214
- ),
215
- exif.length > 0 ? /* @__PURE__ */ jsxs("details", { className: "mt-6 border-t border-zinc-950/5 pt-3", children: [
216
- /* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-xs/5 font-semibold tracking-wide text-zinc-500 uppercase hover:text-zinc-950", children: t.exif(exif.length) }),
217
- /* @__PURE__ */ jsx("dl", { className: "mt-2 grid grid-cols-[minmax(7rem,45%)_1fr] text-xs/5", children: exif.map(([key, value]) => /* @__PURE__ */ jsxs(
218
- "div",
219
- {
220
- className: "col-span-2 grid grid-cols-subgrid border-t border-zinc-950/5",
221
- children: [
222
- /* @__PURE__ */ jsx("dt", { className: "py-1 pr-3 wrap-break-word text-zinc-500", children: key }),
223
- /* @__PURE__ */ jsx("dd", { className: "min-w-0 py-1 wrap-break-word text-zinc-950", children: value })
224
- ]
225
- },
226
- key
227
- )) })
228
- ] }) : null
229
- ] })
230
- ] })
231
- }
232
- );
199
+ let t4;
200
+ if ($[5] !== details.creatorContact) {
201
+ t4 = details.creatorContact?.includes("@") ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: `mailto:${details.creatorContact}`, children: details.creatorContact }) : details.creatorContact;
202
+ $[5] = details.creatorContact;
203
+ $[6] = t4;
204
+ } else {
205
+ t4 = $[6];
206
+ }
207
+ const contact = t4;
208
+ let t5;
209
+ if ($[7] !== details.license || $[8] !== details.licenseUrl) {
210
+ t5 = details.license && details.licenseUrl ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: details.licenseUrl, rel: "noreferrer", target: "_blank", children: details.license }) : details.license;
211
+ $[7] = details.license;
212
+ $[8] = details.licenseUrl;
213
+ $[9] = t5;
214
+ } else {
215
+ t5 = $[9];
216
+ }
217
+ const license = t5;
218
+ let t6;
219
+ if ($[10] !== externalUrl || $[11] !== photo.photoId) {
220
+ t6 = externalUrl ? /* @__PURE__ */ jsx("a", { className: LINK_CLASS, href: externalUrl, rel: "noreferrer", target: "_blank", children: photo.photoId }) : photo.photoId;
221
+ $[10] = externalUrl;
222
+ $[11] = photo.photoId;
223
+ $[12] = t6;
224
+ } else {
225
+ t6 = $[12];
226
+ }
227
+ const photoId = t6;
228
+ let t7;
229
+ if ($[13] !== details.exif) {
230
+ t7 = details.exif ?? {};
231
+ $[13] = details.exif;
232
+ $[14] = t7;
233
+ } else {
234
+ t7 = $[14];
235
+ }
236
+ const exif = Object.entries(t7).sort(_temp3);
237
+ let t8;
238
+ if ($[15] !== onClose) {
239
+ t8 = (event) => {
240
+ if (event.target === event.currentTarget) {
241
+ onClose();
242
+ }
243
+ };
244
+ $[15] = onClose;
245
+ $[16] = t8;
246
+ } else {
247
+ t8 = $[16];
248
+ }
249
+ let t9;
250
+ if ($[17] !== provider.label) {
251
+ t9 = /* @__PURE__ */ jsx("span", { className: "ml-2 font-normal text-zinc-500", children: provider.label });
252
+ $[17] = provider.label;
253
+ $[18] = t9;
254
+ } else {
255
+ t9 = $[18];
256
+ }
257
+ return /* @__PURE__ */ jsx("dialog", { "aria-labelledby": "photo-details-title", className: "m-auto w-full max-w-lg rounded-2xl bg-white p-0 shadow-lg ring-1 ring-zinc-950/10 backdrop:bg-zinc-950/25", ref: dialogRef, onClick: t8, onClose, onKeyDown: _temp4, children: /* @__PURE__ */ jsxs("div", { className: "max-h-[85vh] overflow-y-auto p-6 sm:p-8", children: [
258
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
259
+ /* @__PURE__ */ jsxs("h2", { className: "text-base/6 font-semibold text-zinc-950", id: "photo-details-title", children: [
260
+ t.title,
261
+ t9
262
+ ] }),
263
+ /* @__PURE__ */ jsx("button", { className: "-m-1 rounded-md p-1 text-sm/6 font-medium text-zinc-500 hover:bg-zinc-950/5 hover:text-zinc-950", type: "button", onClick: onClose, children: t.close })
264
+ ] }),
265
+ /* @__PURE__ */ jsxs("div", { className: "mt-6", children: [
266
+ /* @__PURE__ */ jsx(Section, { rows: [[t.creator, photo.creatorName], [t.contact, contact], [t.capturedAt, capturedAt && photo.capturedAt != null ? `${capturedAt} \xB7 ${formatRelativeDate(photo.capturedAt, locale)}` : capturedAt], [t.uploadedAt, details.uploadedAt != null ? formatDate(details.uploadedAt, locale) : null], [t.license, license]], title: t.sectionCapture }),
267
+ /* @__PURE__ */ jsx(Section, { rows: [[t.type, photo.isPano == null ? null : photo.isPano ? t.pano : t.flat], [t.camera, details.camera], [t.focalLength, details.focalLengthMm != null ? `${details.focalLengthMm} mm` : null], [t.fieldOfView, details.fieldOfViewDeg != null ? `${Math.round(details.fieldOfViewDeg)}\xB0` : null]], title: t.sectionCamera }),
268
+ /* @__PURE__ */ jsx(Section, { rows: [[t.coordinates, `${photo.lngLat[1].toFixed(6)}, ${photo.lngLat[0].toFixed(6)}`], [t.heading, photo.heading != null ? `${Math.round(photo.heading)}\xB0` : null], [t.accuracy, details.positionAccuracyMeters != null ? `\xB1 ${details.positionAccuracyMeters} m` : null]], title: t.sectionPosition }),
269
+ /* @__PURE__ */ jsx(Section, { rows: [[t.provider, provider.label], [t.instance, details.instance], [t.photoId, photoId], [t.sequence, photo.sequenceId], [t.rankInSequence, details.rankInSequence], [t.file, details.originalFileName ? `${details.originalFileName}${details.originalFileSizeBytes != null ? ` (${formatBytes(details.originalFileSizeBytes)})` : ""}` : null]], title: t.sectionSource }),
270
+ exif.length > 0 ? /* @__PURE__ */ jsxs("details", { className: "mt-6 border-t border-zinc-950/5 pt-3", children: [
271
+ /* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-xs/5 font-semibold tracking-wide text-zinc-500 uppercase hover:text-zinc-950", children: t.exif(exif.length) }),
272
+ /* @__PURE__ */ jsx("dl", { className: "mt-2 grid grid-cols-[minmax(7rem,45%)_1fr] text-xs/5", children: exif.map(_temp5) })
273
+ ] }) : null
274
+ ] })
275
+ ] }) });
233
276
  };
277
+ function _temp(t0) {
278
+ const [, value] = t0;
279
+ return value != null && value !== "";
280
+ }
281
+ function _temp2(t0) {
282
+ const [term, value_0] = t0;
283
+ return /* @__PURE__ */ jsxs("div", { className: "col-span-2 grid grid-cols-subgrid border-t border-zinc-950/5", children: [
284
+ /* @__PURE__ */ jsx("dt", { className: "py-2 pr-3 text-zinc-500", children: term }),
285
+ /* @__PURE__ */ jsx("dd", { className: "min-w-0 py-2 wrap-break-word text-zinc-950", children: value_0 })
286
+ ] }, term);
287
+ }
288
+ function _temp3(t0, t1) {
289
+ const [a] = t0;
290
+ const [b] = t1;
291
+ return a.localeCompare(b);
292
+ }
293
+ function _temp4(event_0) {
294
+ if (event_0.key === "Escape") {
295
+ event_0.stopPropagation();
296
+ }
297
+ }
298
+ function _temp5(t0) {
299
+ const [key, value] = t0;
300
+ return /* @__PURE__ */ jsxs("div", { className: "col-span-2 grid grid-cols-subgrid border-t border-zinc-950/5", children: [
301
+ /* @__PURE__ */ jsx("dt", { className: "py-1 pr-3 wrap-break-word text-zinc-500", children: key }),
302
+ /* @__PURE__ */ jsx("dd", { className: "min-w-0 py-1 wrap-break-word text-zinc-950", children: value })
303
+ ] }, key);
304
+ }
234
305
 
235
306
  export { PHOTO_DETAILS_LABELS, PhotoDetailsDialog };
@@ -0,0 +1 @@
1
+ export { StreetLevelImageryViewer } from '../StreetLevelImageryViewer';
@@ -1,3 +1,5 @@
1
1
  export { MapillaryPanel } from '../panels/MapillaryPanel';
2
- export { PanoramaxPanel } from '../panels/PanoramaxPanel';
2
+ export { PanoramaxPanel, type PanoramaxPanelProps } from '../panels/PanoramaxPanel';
3
+ export { PanoramaxDataProvider, type PanoramaxDataProviderOptions, } from '../panels/panoramaxDataProvider';
4
+ export { panoramaxPhotoFromItem, type PanoramaxItem } from '../panels/panoramaxItem';
3
5
  export { mapillaryViewFor, setMapillaryViewerOutlines, turnMapillaryViewerTo, } from '../panels/mapillaryLookAt';
@@ -1,3 +1,4 @@
1
- export { MapillaryPanel, mapillaryViewFor, setMapillaryViewerOutlines, turnMapillaryViewerTo } from './chunk-SGIB7AVC.js';
2
- export { PanoramaxPanel } from './chunk-KZTMKQT5.js';
3
- import './chunk-25UGGXIE.js';
1
+ export { MapillaryPanel, mapillaryViewFor, setMapillaryViewerOutlines, turnMapillaryViewerTo } from './chunk-LZR5SZDS.js';
2
+ export { PanoramaxDataProvider, PanoramaxPanel, panoramaxPhotoFromItem } from './chunk-R6BDVYWM.js';
3
+ import './chunk-XLBFXACK.js';
4
+ import './chunk-GYUS2JVV.js';
package/dist/viewer.js ADDED
@@ -0,0 +1,98 @@
1
+ import { useStreetImageryI18n } from './chunk-3DFVM6VK.js';
2
+ import { c } from 'react/compiler-runtime';
3
+ import { lazy, Suspense } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var MapillaryPanel = lazy(() => import('./MapillaryPanel-SOHGB7JA.js').then((module) => ({
7
+ default: module.MapillaryPanel
8
+ })));
9
+ var PanoramaxPanel = lazy(() => import('./PanoramaxPanel-5P5LWMRY.js').then((module) => ({
10
+ default: module.PanoramaxPanel
11
+ })));
12
+ var ViewerPanelPlaceholder = () => {
13
+ const $ = c(2);
14
+ const {
15
+ messages
16
+ } = useStreetImageryI18n();
17
+ let t0;
18
+ if ($[0] !== messages.viewer.loading) {
19
+ t0 = /* @__PURE__ */ jsx("div", { className: "flex min-h-48 animate-pulse items-center justify-center rounded-lg border border-slate-200 bg-slate-100", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-slate-500", children: messages.viewer.loading }) });
20
+ $[0] = messages.viewer.loading;
21
+ $[1] = t0;
22
+ } else {
23
+ t0 = $[1];
24
+ }
25
+ return t0;
26
+ };
27
+ var StreetLevelImageryViewer = (t0) => {
28
+ const $ = c(22);
29
+ const {
30
+ photo,
31
+ groupPhotos,
32
+ onPhotoSelected,
33
+ onEaseMapToPoint,
34
+ onViewerPhoto,
35
+ onViewerView,
36
+ lookAtBearing,
37
+ lookAt,
38
+ outlines,
39
+ hideAttribution,
40
+ panoramaxPanel: PanoramaxPanelOverride
41
+ } = t0;
42
+ if (photo.providerId === "mapillary") {
43
+ let t1;
44
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
45
+ t1 = /* @__PURE__ */ jsx(ViewerPanelPlaceholder, {});
46
+ $[0] = t1;
47
+ } else {
48
+ t1 = $[0];
49
+ }
50
+ let t2;
51
+ if ($[1] !== groupPhotos || $[2] !== hideAttribution || $[3] !== lookAt || $[4] !== lookAtBearing || $[5] !== onEaseMapToPoint || $[6] !== onPhotoSelected || $[7] !== onViewerPhoto || $[8] !== onViewerView || $[9] !== outlines || $[10] !== photo) {
52
+ t2 = /* @__PURE__ */ jsx(Suspense, { fallback: t1, children: /* @__PURE__ */ jsx(MapillaryPanel, { groupPhotos, hideAttribution, onEaseMapToPoint, onPhotoSelected, lookAt, lookAtBearing, outlines, onViewerPhoto, onViewerView, photo }) });
53
+ $[1] = groupPhotos;
54
+ $[2] = hideAttribution;
55
+ $[3] = lookAt;
56
+ $[4] = lookAtBearing;
57
+ $[5] = onEaseMapToPoint;
58
+ $[6] = onPhotoSelected;
59
+ $[7] = onViewerPhoto;
60
+ $[8] = onViewerView;
61
+ $[9] = outlines;
62
+ $[10] = photo;
63
+ $[11] = t2;
64
+ } else {
65
+ t2 = $[11];
66
+ }
67
+ return t2;
68
+ }
69
+ if (photo.providerId === "panoramax") {
70
+ const Panel = PanoramaxPanelOverride ?? PanoramaxPanel;
71
+ let t1;
72
+ if ($[12] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
73
+ t1 = /* @__PURE__ */ jsx(ViewerPanelPlaceholder, {});
74
+ $[12] = t1;
75
+ } else {
76
+ t1 = $[12];
77
+ }
78
+ let t2;
79
+ if ($[13] !== Panel || $[14] !== groupPhotos || $[15] !== hideAttribution || $[16] !== onEaseMapToPoint || $[17] !== onPhotoSelected || $[18] !== onViewerPhoto || $[19] !== onViewerView || $[20] !== photo) {
80
+ t2 = /* @__PURE__ */ jsx(Suspense, { fallback: t1, children: /* @__PURE__ */ jsx(Panel, { groupPhotos, hideAttribution, onViewerPhoto, onViewerView, onEaseMapToPoint, onPhotoSelected, photo }) });
81
+ $[13] = Panel;
82
+ $[14] = groupPhotos;
83
+ $[15] = hideAttribution;
84
+ $[16] = onEaseMapToPoint;
85
+ $[17] = onPhotoSelected;
86
+ $[18] = onViewerPhoto;
87
+ $[19] = onViewerView;
88
+ $[20] = photo;
89
+ $[21] = t2;
90
+ } else {
91
+ t2 = $[21];
92
+ }
93
+ return t2;
94
+ }
95
+ return null;
96
+ };
97
+
98
+ export { StreetLevelImageryViewer };
@@ -7,16 +7,19 @@ export declare const FloatingViewerInfoButton: ({ label, onClick, }: {
7
7
  }) => import("react").JSX.Element;
8
8
  export type FloatingPhotoViewerProps = {
9
9
  title: ReactNode;
10
- /** Buttons right after the title, e.g. `<FloatingViewerInfoButton>` for the photo's details. */
10
+ /**
11
+ * Buttons or links right after the title, e.g. `<FloatingViewerInfoButton>` for the photo's
12
+ * details. They keep their size; a long title gives way.
13
+ */
11
14
  titleActions?: ReactNode;
12
- /** Suggested views (viewpoint × direction); shown as chips. Empty hides the strip. */
13
- suggestions: ViewSuggestion[];
14
- activeDirectionKey: string | null;
15
+ /** Suggested views (viewpoint × direction); shown as chips. Empty or left out hides the strip. */
16
+ suggestions?: ViewSuggestion[];
17
+ activeDirectionKey?: string | null;
15
18
  /**
16
19
  * A view button was clicked. `candidate` is the photo to show: the view's best one, or the next
17
20
  * one when the active view is clicked again.
18
21
  */
19
- onSelectSuggestion: (suggestion: ViewSuggestion, candidate: PhotoCandidate) => void;
22
+ onSelectSuggestion?: (suggestion: ViewSuggestion, candidate: PhotoCandidate) => void;
20
23
  /** The photo in the viewer, so the active view can show which of its photos that is. */
21
24
  shownPhotoId?: string | null;
22
25
  /**
@@ -64,10 +67,22 @@ export type FloatingPhotoViewerProps = {
64
67
  left?: number;
65
68
  top?: number;
66
69
  };
70
+ /**
71
+ * What the box moves in: its positioned parent (`absolute`, default), or the viewport (`fixed`),
72
+ * for a box over the whole page. A `fixed` box needs an ancestor without `transform` or `filter`.
73
+ */
74
+ position?: 'absolute' | 'fixed';
75
+ /**
76
+ * Lets the box leave its container until only this share (0–1) of its width and height shows,
77
+ * like a free window; never over the top, where the header is. It also stays that way when the
78
+ * container or the box changes size. Without it the box keeps 8px from the right and bottom edge.
79
+ */
80
+ minVisibleShare?: number;
67
81
  };
68
82
  /**
69
- * Photo viewer box floating over the map. Render inside a positioned (relative) map container.
83
+ * Photo viewer box floating over the map. Render inside a positioned (relative) map container,
84
+ * or anywhere with `position="fixed"`.
70
85
  * Drag the header to move, drag the left edge to resize. Keys: Esc closes, [ and ] step history,
71
86
  * Alt + arrow left/right step along (`step`).
72
87
  */
73
- export declare const FloatingPhotoViewer: ({ title, titleActions, suggestions, activeDirectionKey, onSelectSuggestion, shownPhotoId, canGoBack, canGoForward, onBack, onForward, onClose, step, toolbar, status, children, footer, drawer, storageKey, defaultPosition, }: FloatingPhotoViewerProps) => import("react").JSX.Element;
88
+ export declare const FloatingPhotoViewer: ({ title, titleActions, suggestions, activeDirectionKey, onSelectSuggestion, shownPhotoId, canGoBack, canGoForward, onBack, onForward, onClose, step, toolbar, status, children, footer, drawer, storageKey, defaultPosition, position, minVisibleShare, }: FloatingPhotoViewerProps) => import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ type Size = {
2
+ width: number;
3
+ height: number;
4
+ };
5
+ /** Offset of the box from the right and bottom edge of its container. */
6
+ export type FloatingViewerPosition = {
7
+ right: number;
8
+ bottom: number;
9
+ };
10
+ /** Distance the box keeps from the right and bottom edge without `minVisibleShare`. */
11
+ export declare const FLOATING_VIEWER_EDGE = 8;
12
+ /**
13
+ * Keeps the box in its container. With `minVisibleShare` (0–1) it may leave the container until
14
+ * only that share of its width and height shows, but never over the top: the header up there is
15
+ * what moves it, so the top limit wins when the box is taller than the container.
16
+ */
17
+ export declare const clampFloatingViewerPosition: ({ right, bottom }: FloatingViewerPosition, box: Size, container: Size, minVisibleShare?: number) => FloatingViewerPosition;
18
+ export {};
@@ -0,0 +1,26 @@
1
+ import { type LngLat, type NormalizedPhoto, type PhotoLookingAt, type PhotoTypeFilter, type ViewpointPhotoSource } from '@osm-editor-kit/street-imagery';
2
+ export type PhotosLookingAtOptions = {
3
+ /** Only photos from the last N years. */
4
+ maxAgeYears?: number;
5
+ photoTypes?: PhotoTypeFilter[];
6
+ /** Default 50; a source may not reach further (the Mapillary radius search ends at 50 m). */
7
+ maxDistanceMeters?: number;
8
+ /** A flat photo's heading must point within this many degrees of the place. Default 35. */
9
+ maxFlatAngleDeg?: number;
10
+ /** Candidates kept. Default 20. */
11
+ limit?: number;
12
+ /** Extra app filter (e.g. date range), applied before ranking. */
13
+ filterPhoto?: (photo: NormalizedPhoto) => boolean;
14
+ /** Where photos come from; default Mapillary. Pass several to rank across providers. */
15
+ sources?: ViewpointPhotoSource[];
16
+ /** Set after the click; nothing is requested before. */
17
+ enabled?: boolean;
18
+ };
19
+ export type PhotosLookingAtResult = {
20
+ /** Best first. */
21
+ candidates: PhotoLookingAt[];
22
+ isLoading: boolean;
23
+ isError: boolean;
24
+ };
25
+ /** The photos from all `sources` that see `place`, best first; `null` while there is no place. */
26
+ export declare const usePhotosLookingAt: (place: LngLat | null, { maxAgeYears, photoTypes, maxDistanceMeters, maxFlatAngleDeg, limit, filterPhoto, sources, enabled, }?: PhotosLookingAtOptions) => PhotosLookingAtResult;