@osm-editor-kit/street-imagery-react 0.1.0-alpha.8 → 0.1.0-alpha.9
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.
- package/README.md +6 -2
- package/dist/MapillaryPanel-FAXVZH37.js +2 -0
- package/dist/PanoramaxPanel-BTHEMKYY.js +2 -0
- package/dist/StreetLevelImagerySelectionOverlay.d.ts +3 -1
- package/dist/StreetLevelImagerySourcesAndLayers.d.ts +10 -0
- package/dist/StreetLevelImageryViewCone.d.ts +3 -1
- package/dist/{chunk-ZAIXGYAH.js → chunk-6EMFFIL2.js} +2 -2
- package/dist/{chunk-EQ2JKLGT.js → chunk-KZTMKQT5.js} +1 -0
- package/dist/{chunk-53RA4OSJ.js → chunk-SGIB7AVC.js} +6 -1
- package/dist/filters/PhotoDateRangeFilter.d.ts +6 -1
- package/dist/hooks/useProviderData.d.ts +8 -3
- package/dist/index.d.ts +1 -3
- package/dist/index.js +172 -54
- package/dist/panels/PanoramaxPanel.d.ts +3 -2
- package/dist/photo-details.js +1 -1
- package/dist/streetImageryClick.d.ts +4 -0
- package/dist/viewer-panels/index.d.ts +3 -0
- package/dist/viewer-panels.js +3 -0
- package/dist/viewpoints/FloatingPhotoViewer.d.ts +18 -5
- package/package.json +10 -2
- package/dist/MapillaryPanel-N45NQY4C.js +0 -2
- package/dist/PanoramaxPanel-MFI4L67Z.js +0 -2
package/README.md
CHANGED
|
@@ -40,6 +40,8 @@ const bbox = useMapViewportBbox('main', map)
|
|
|
40
40
|
selectedPhoto,
|
|
41
41
|
photoCircleColor: '#3b82f6',
|
|
42
42
|
mapFeatureCircleColor: '#94a3b8',
|
|
43
|
+
beforeId: 'road-label', // optional: draw everything below this layer of your style
|
|
44
|
+
minZoom: 10, // optional: below this zoom nothing is requested or drawn
|
|
43
45
|
}}
|
|
44
46
|
/>
|
|
45
47
|
|
|
@@ -50,9 +52,11 @@ const hits = queryStreetImageryFeatures(event)
|
|
|
50
52
|
onPhotoSelected={setSelection} onEaseMapToPoint={(lng, lat) => map.easeTo({ center: [lng, lat] })} />
|
|
51
53
|
```
|
|
52
54
|
|
|
55
|
+
**Before photos are loaded:** where a provider has own vector tiles with its track lines (Mapillary: zoom 6 to 15), MapLibre reads those itself. Same colours and filters; the lines are not clickable. Zoomed far out these tiles are several MB each in dense areas; set `options.minZoom` to skip them.
|
|
56
|
+
|
|
53
57
|
**Mapillary:** `createStreetImageryConfig({ mapillaryToken })` or `setStreetImageryConfig` at boot (`@osm-editor-kit/street-imagery`). **Panoramax + Vite:** see `app/vite.config.ts` for the consuming-app setup.
|
|
54
58
|
|
|
55
|
-
Also: `useAllProviderPhotos`, `useProviderPhotos` / `useProviderSequences` / `useProviderMapFeatures`, `usePhotoThumbnails`, `resolveSelectedSequence`, `StreetLevelImageryViewCone`, `useViewerBearing` / `useViewerActions
|
|
59
|
+
Also: `useAllProviderPhotos`, `useProviderPhotos` / `useProviderSequences` / `useProviderMapFeatures`, `usePhotoThumbnails`, `resolveSelectedSequence`, `StreetLevelImageryViewCone`, `useViewerBearing` / `useViewerActions`. The panels themselves (`MapillaryPanel`, `PanoramaxPanel`) are in `@osm-editor-kit/street-imagery-react/viewer-panels`; `StreetLevelImageryViewer` loads them on demand, so `mapillary-js` and `@panoramax/web-viewer` are only loaded when a photo is shown.
|
|
56
60
|
|
|
57
61
|
## Viewpoints and floating viewer
|
|
58
62
|
|
|
@@ -119,7 +123,7 @@ const { data: detections } = useMapillaryImageDetections(photo.photoId, {
|
|
|
119
123
|
|
|
120
124
|
- Map layers: `filter.mapFeatureValue` limits which signs/objects are drawn: `signGroupFilter(['parking', 'bike'])` for sign groups, or `matchesAnyGroup(…)`.
|
|
121
125
|
- Suggested views: `useViewSuggestions(viewpoints, { sources: [mapillaryPhotoSource, streetViewPhotoSource] })`.
|
|
122
|
-
- `turnMapillaryViewerTo` / `setMapillaryViewerOutlines` work on a mapillary-js `Viewer` you own.
|
|
126
|
+
- `turnMapillaryViewerTo` / `setMapillaryViewerOutlines` (from `@osm-editor-kit/street-imagery-react/viewer-panels`) work on a mapillary-js `Viewer` you own.
|
|
123
127
|
|
|
124
128
|
## A selected sign: viewer, bar and map highlight
|
|
125
129
|
|
|
@@ -15,12 +15,14 @@ export type StreetLevelImagerySelectionOverlayProps = {
|
|
|
15
15
|
cameraLngLat?: [number, number] | null;
|
|
16
16
|
/** Layer to draw the sequence line below, so photo dots stay on top of it. */
|
|
17
17
|
sequenceBeforeId?: string;
|
|
18
|
+
/** Id of a layer of the host's style to draw the whole overlay below. */
|
|
19
|
+
beforeId?: string;
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* The shown photo on the map, bottom to top: its sequence line (only passed when the provider's
|
|
21
23
|
* own layers are off; else that layer marks it), a filled marker on its photo dot, and — when the camera position differs from the
|
|
22
24
|
* dot — a dashed connector and a pin at the camera position.
|
|
23
25
|
*/
|
|
24
|
-
export declare const StreetLevelImagerySelectionOverlay: ({ selectedPhoto, selectedSequence, cameraLngLat, sequenceBeforeId, }: StreetLevelImagerySelectionOverlayProps) => import("react").JSX.Element | null;
|
|
26
|
+
export declare const StreetLevelImagerySelectionOverlay: ({ selectedPhoto, selectedSequence, cameraLngLat, sequenceBeforeId, beforeId, }: StreetLevelImagerySelectionOverlayProps) => import("react").JSX.Element | null;
|
|
25
27
|
/** Resolve sequence geometry for highlight when only photo + fetched sequences are available. */
|
|
26
28
|
export declare const resolveSelectedSequence: (selectedPhoto: NormalizedPhoto | null | undefined, sequences: NormalizedSequence[], sequenceId: string | null | undefined) => NormalizedSequence | null;
|
|
@@ -41,6 +41,16 @@ export type StreetLevelImagerySourcesAndLayersProps = {
|
|
|
41
41
|
/** Length of the shown photo's view cone, as a multiple of the per-photo shapes. Default 2.5. */
|
|
42
42
|
viewConeScale?: number;
|
|
43
43
|
mapFeatureCircleColor: DataDrivenPropertyValueSpecification<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Id of a layer of the host's style: all layers are drawn below it (e.g. below road names).
|
|
46
|
+
* The layer must exist when this component mounts. Default: on top of the style.
|
|
47
|
+
*/
|
|
48
|
+
beforeId?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Below this map zoom nothing is requested or drawn. Each provider also has its own minimum
|
|
51
|
+
* zooms (photos, lines); the higher one counts. Default: only the providers' own.
|
|
52
|
+
*/
|
|
53
|
+
minZoom?: number;
|
|
44
54
|
};
|
|
45
55
|
};
|
|
46
56
|
export declare const StreetLevelImagerySourcesAndLayers: ({ providers, filter, bbox, zoom, options, }: StreetLevelImagerySourcesAndLayersProps) => import("react").JSX.Element;
|
|
@@ -17,5 +17,7 @@ export type StreetLevelImageryViewConeProps = {
|
|
|
17
17
|
color?: DataDrivenPropertyValueSpecification<string>;
|
|
18
18
|
/** Cone length as a multiple of the per-photo view-direction shapes. Default 2.5. */
|
|
19
19
|
scale?: number;
|
|
20
|
+
/** Id of a layer of the host's style to draw the cone below. */
|
|
21
|
+
beforeId?: string;
|
|
20
22
|
};
|
|
21
|
-
export declare const StreetLevelImageryViewCone: ({ selectedPhoto, zoom, viewerPov, color, scale, }: StreetLevelImageryViewConeProps) => import("react").JSX.Element | null;
|
|
23
|
+
export declare const StreetLevelImageryViewCone: ({ selectedPhoto, zoom, viewerPov, color, scale, beforeId, }: StreetLevelImageryViewConeProps) => import("react").JSX.Element | null;
|
|
@@ -31,7 +31,7 @@ var en = {
|
|
|
31
31
|
exactDates: "Exact dates",
|
|
32
32
|
from: "From",
|
|
33
33
|
to: "To",
|
|
34
|
-
photoCount: (count) => count === 1 ? "1 photo" : `${count} photos`
|
|
34
|
+
photoCount: (count) => count === 1 ? "1 photo" : `${count.toLocaleString("en")} photos`
|
|
35
35
|
},
|
|
36
36
|
viewpointRole: {
|
|
37
37
|
here: "Here",
|
|
@@ -87,7 +87,7 @@ var de = {
|
|
|
87
87
|
exactDates: "Genaue Daten",
|
|
88
88
|
from: "Von",
|
|
89
89
|
to: "Bis",
|
|
90
|
-
photoCount: (count) => count === 1 ? "1 Foto" : `${count} Fotos`
|
|
90
|
+
photoCount: (count) => count === 1 ? "1 Foto" : `${count.toLocaleString("de")} Fotos`
|
|
91
91
|
},
|
|
92
92
|
viewpointRole: {
|
|
93
93
|
here: "Hier",
|
|
@@ -211,7 +211,12 @@ var MapillaryPanel = ({
|
|
|
211
211
|
lngLat: [position.lng, position.lat],
|
|
212
212
|
...image.creatorUsername ? { creatorName: image.creatorUsername } : {}
|
|
213
213
|
});
|
|
214
|
-
|
|
214
|
+
const isFlat = image.cameraType !== "spherical" && image.cameraType !== "equirectangular";
|
|
215
|
+
const compass = image.computedCompassAngle ?? image.compassAngle;
|
|
216
|
+
actions.setPov({
|
|
217
|
+
lngLat: [position.lng, position.lat],
|
|
218
|
+
...isFlat && compass != null ? { bearing: compass } : {}
|
|
219
|
+
});
|
|
215
220
|
emitEaseMapToPoint(position.lng, position.lat);
|
|
216
221
|
};
|
|
217
222
|
const flushBearing = () => {
|
|
@@ -31,6 +31,11 @@ export type PhotoDateRangeFilterProps = {
|
|
|
31
31
|
* or left out.
|
|
32
32
|
*/
|
|
33
33
|
dateInputs?: 'collapsed' | 'open' | 'none';
|
|
34
|
+
/**
|
|
35
|
+
* The "All dates" action next to the chosen range, which removes both limits. Default true;
|
|
36
|
+
* without it the user moves both handles to the ends.
|
|
37
|
+
*/
|
|
38
|
+
allDatesAction?: boolean;
|
|
34
39
|
className?: string;
|
|
35
40
|
};
|
|
36
41
|
/**
|
|
@@ -38,4 +43,4 @@ export type PhotoDateRangeFilterProps = {
|
|
|
38
43
|
* gives recent years more room, marks that show how many photos there are at each time, lines at
|
|
39
44
|
* whole years, and optional fixed markers. Controlled: `value` in, `onChange` out.
|
|
40
45
|
*/
|
|
41
|
-
export declare const PhotoDateRangeFilter: ({ value, onChange, capturedAt, yearLines, recommendedMaxAgeYears, markers, maxYears, now: nowProp, dateInputs, className, }: PhotoDateRangeFilterProps) => import("react").JSX.Element;
|
|
46
|
+
export declare const PhotoDateRangeFilter: ({ value, onChange, capturedAt, yearLines, recommendedMaxAgeYears, markers, maxYears, now: nowProp, dateInputs, className, allDatesAction, }: PhotoDateRangeFilterProps) => import("react").JSX.Element;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Bbox } from '@osm-editor-kit/street-imagery';
|
|
2
2
|
import { type ProviderId } from '@osm-editor-kit/street-imagery';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/** Host limit on top of the provider's own minimum zooms: below it nothing is requested. */
|
|
4
|
+
type ProviderDataOptions = {
|
|
5
|
+
minZoom?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const useProviderPhotos: (providerId: ProviderId, bbox: Bbox | null, zoom: number, { minZoom }?: ProviderDataOptions) => import("@tanstack/react-query").UseQueryResult<NoInfer<import("@osm-editor-kit/street-imagery").NormalizedPhoto[]>, Error>;
|
|
8
|
+
export declare const useProviderSequences: (providerId: ProviderId, bbox: Bbox | null, zoom: number, { minZoom }?: ProviderDataOptions) => import("@tanstack/react-query").UseQueryResult<NoInfer<import("@osm-editor-kit/street-imagery").NormalizedSequence[]>, Error>;
|
|
9
|
+
export declare const useProviderMapFeatures: (providerId: ProviderId, bbox: Bbox | null, zoom: number, { minZoom }?: ProviderDataOptions) => import("@tanstack/react-query").UseQueryResult<NoInfer<import("@osm-editor-kit/street-imagery").NormalizedMapFeature[]>, Error>;
|
|
10
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -9,15 +9,13 @@ export * from './hooks/useAllProviderPhotos';
|
|
|
9
9
|
export * from './hooks/useMapViewportBbox';
|
|
10
10
|
export * from './hooks/useProviderData';
|
|
11
11
|
export * from './hooks/usePhotoThumbnails';
|
|
12
|
-
export { MapillaryPanel } from './panels/MapillaryPanel';
|
|
13
|
-
export { PanoramaxPanel } from './panels/PanoramaxPanel';
|
|
14
12
|
export * from './useViewerStore';
|
|
15
13
|
export { FloatingPhotoViewer, FloatingViewerInfoButton, type FloatingPhotoViewerProps, } from './viewpoints/FloatingPhotoViewer';
|
|
16
14
|
export { VIEWPOINT_DEFAULT_COLOR, VIEWPOINT_DIRECTION_LAYER_ID, ViewpointLayer, viewDirectionKeyFromFeatures, type ViewpointLayerProps, } from './viewpoints/ViewpointLayer';
|
|
17
15
|
export { viewSuggestionLabel } from './viewpoints/viewDirectionLabels';
|
|
18
16
|
export * from './viewpoints/useViewpointSessionStore';
|
|
19
17
|
export * from './viewpoints/useViewSuggestions';
|
|
20
|
-
export {
|
|
18
|
+
export type { MapillaryLookAt, MapillaryViewerOutline } from './panels/mapillaryLookAt';
|
|
21
19
|
export * from './mapillary/useMapillaryFeatures';
|
|
22
20
|
export { LocationPickOnMap, type LocationPickOnMapProps } from './openers/LocationPickOnMap';
|
|
23
21
|
export * from './openers/useLocationPickStore';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { useStreetImageryI18n } from './chunk-
|
|
2
|
-
export { STREET_IMAGERY_MESSAGES, StreetImageryLocaleProvider, useStreetImageryI18n } from './chunk-
|
|
3
|
-
export { MapillaryPanel, mapillaryViewFor, setMapillaryViewerOutlines, turnMapillaryViewerTo } from './chunk-53RA4OSJ.js';
|
|
4
|
-
export { PanoramaxPanel } from './chunk-EQ2JKLGT.js';
|
|
1
|
+
import { useStreetImageryI18n } from './chunk-6EMFFIL2.js';
|
|
2
|
+
export { STREET_IMAGERY_MESSAGES, StreetImageryLocaleProvider, useStreetImageryI18n } from './chunk-6EMFFIL2.js';
|
|
5
3
|
export { useViewerActions, useViewerBearing, useViewerHfov, useViewerLngLat } from './chunk-25UGGXIE.js';
|
|
6
|
-
import { distanceMeters, sequencesToFeatureCollection, emptyLineCollection, adapterById, providerById, providerCoversBbox, viewConeGeoJson, viewShapeRadiusMeters, setStreetImageryConfig, viewfieldLayerId, photoLayerId, featureLayerId, PROVIDER_IDS, mapFeatureMatchesDateRange, isBrowserAvailableProvider, photoMatchesFilters, resolvePhotoPanoramaUrl, photoFullUrlQueryKey, resolvePhotoThumbnailUrl, photoThumbnailQueryKey, formatLocalDateTime, formatMonth, formatRelativeDate, formatDateTooltip, mapillaryPhotoSource, buildViewSuggestions, yearsToMs, SIGN_TARGET, fetchMapFeatureImages, fetchMapillaryMapFeaturesInBbox, bboxAround, fetchImageDetections, bestTargetImage, findLocationOpener, MAP_FEATURE_COLOR, mapillaryValueName, mapillaryIconUrl, dateRangeToSliderPositions, sliderPositionsToDateRange, dateSliderBins, dateSliderPosition, yearsAgoMs, parseIsoDateStartMs, openLocationInNewTab, formatDate, isIsoDate, alignLineToPoints, coneRadiusMeters, mapFeaturesToFeatureCollection, emptyPointCollection, buildMapFeatureLayerFilter, featureSourceId, photosToFeatureCollection, photosToViewfieldsFeatureCollection, emptyPolygonCollection, buildPhotoLayerFilter, photoSourceId, viewfieldSourceId, sequenceSourceId, sequenceLayerId, viewfieldLineLayerId, VIEWFIELD_MIN_ZOOM } from '@osm-editor-kit/street-imagery';
|
|
4
|
+
import { distanceMeters, sequencesToFeatureCollection, emptyLineCollection, adapterById, providerById, providerCoversBbox, fetchedSequencesMinZoom, viewConeGeoJson, viewShapeRadiusMeters, setStreetImageryConfig, viewfieldLayerId, photoLayerId, photoTargetLayerId, featureLayerId, PROVIDER_IDS, mapFeatureMatchesDateRange, isBrowserAvailableProvider, photoMatchesFilters, resolvePhotoPanoramaUrl, photoFullUrlQueryKey, resolvePhotoThumbnailUrl, photoThumbnailQueryKey, formatLocalDateTime, formatMonth, formatRelativeDate, formatDateTooltip, mapillaryPhotoSource, buildViewSuggestions, yearsToMs, SIGN_TARGET, fetchMapFeatureImages, fetchMapillaryMapFeaturesInBbox, bboxAround, fetchImageDetections, bestTargetImage, findLocationOpener, MAP_FEATURE_COLOR, mapillaryValueName, mapillaryIconUrl, dateRangeToSliderPositions, sliderPositionsToDateRange, dateSliderBins, dateSliderPosition, yearsAgoMs, parseIsoDateStartMs, openLocationInNewTab, formatDate, isIsoDate, alignLineToPoints, coneRadiusMeters, mapFeaturesToFeatureCollection, emptyPointCollection, buildMapFeatureLayerFilter, featureSourceId, photosToFeatureCollection, photosToViewfieldsFeatureCollection, emptyPolygonCollection, buildPhotoLayerFilter, photoSourceId, viewfieldSourceId, sequenceTilesSourceId, renameExpressionProperties, sequenceTilesLayerId, sequenceSourceId, sequenceLayerId, viewfieldLineLayerId, VIEWFIELD_MIN_ZOOM } from '@osm-editor-kit/street-imagery';
|
|
7
5
|
import { Source, Layer, useMap } from 'react-map-gl/maplibre';
|
|
8
6
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
9
7
|
import { lazy, useEffect, Fragment as Fragment$1, Suspense, useState, useRef, useEffectEvent } from 'react';
|
|
@@ -21,7 +19,8 @@ var StreetLevelImagerySelectionOverlay = ({
|
|
|
21
19
|
selectedPhoto,
|
|
22
20
|
selectedSequence,
|
|
23
21
|
cameraLngLat,
|
|
24
|
-
sequenceBeforeId
|
|
22
|
+
sequenceBeforeId,
|
|
23
|
+
beforeId
|
|
25
24
|
}) => {
|
|
26
25
|
const photoLngLat = selectedPhoto?.lngLat;
|
|
27
26
|
const cameraDiffers = photoLngLat != null && cameraLngLat != null && distanceMeters(photoLngLat, cameraLngLat) > SAME_POSITION_METERS;
|
|
@@ -73,7 +72,7 @@ var StreetLevelImagerySelectionOverlay = ({
|
|
|
73
72
|
/* @__PURE__ */ jsx(
|
|
74
73
|
Layer,
|
|
75
74
|
{
|
|
76
|
-
beforeId: sequenceBeforeId,
|
|
75
|
+
beforeId: sequenceBeforeId ?? beforeId,
|
|
77
76
|
id: "sequence-highlight-layer",
|
|
78
77
|
type: "line",
|
|
79
78
|
source: SEQUENCE_HIGHLIGHT_SOURCE_ID,
|
|
@@ -85,6 +84,7 @@ var StreetLevelImagerySelectionOverlay = ({
|
|
|
85
84
|
/* @__PURE__ */ jsx(
|
|
86
85
|
Layer,
|
|
87
86
|
{
|
|
87
|
+
beforeId,
|
|
88
88
|
id: "selection-connector-layer",
|
|
89
89
|
type: "line",
|
|
90
90
|
source: CONNECTOR_SOURCE_ID,
|
|
@@ -95,6 +95,7 @@ var StreetLevelImagerySelectionOverlay = ({
|
|
|
95
95
|
/* @__PURE__ */ jsx(
|
|
96
96
|
Layer,
|
|
97
97
|
{
|
|
98
|
+
beforeId,
|
|
98
99
|
id: "selection-highlight-layer",
|
|
99
100
|
type: "circle",
|
|
100
101
|
source: POINTS_SOURCE_ID,
|
|
@@ -110,6 +111,7 @@ var StreetLevelImagerySelectionOverlay = ({
|
|
|
110
111
|
/* @__PURE__ */ jsx(
|
|
111
112
|
Layer,
|
|
112
113
|
{
|
|
114
|
+
beforeId,
|
|
113
115
|
id: "selection-camera-layer",
|
|
114
116
|
type: "circle",
|
|
115
117
|
source: POINTS_SOURCE_ID,
|
|
@@ -137,10 +139,10 @@ var withinBbox = (bbox) => (item) => {
|
|
|
137
139
|
const [lng, lat] = item.lngLat;
|
|
138
140
|
return lng >= bbox[0] && lng <= bbox[2] && lat >= bbox[1] && lat <= bbox[3];
|
|
139
141
|
};
|
|
140
|
-
var useProviderPhotos = (providerId, bbox, zoom) => {
|
|
142
|
+
var useProviderPhotos = (providerId, bbox, zoom, { minZoom = 0 } = {}) => {
|
|
141
143
|
const adapter = adapterById[providerId];
|
|
142
144
|
const meta = providerById[providerId];
|
|
143
|
-
const enabled = meta.kind === "photo" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= meta.minZoom && adapter?.fetchPhotos != null;
|
|
145
|
+
const enabled = meta.kind === "photo" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= Math.max(meta.minZoom, minZoom) && adapter?.fetchPhotos != null;
|
|
144
146
|
return useQuery({
|
|
145
147
|
queryKey: ["provider-photos", providerId, bboxKey(bbox), zoom],
|
|
146
148
|
queryFn: async ({ signal }) => {
|
|
@@ -151,11 +153,11 @@ var useProviderPhotos = (providerId, bbox, zoom) => {
|
|
|
151
153
|
placeholderData: (previous) => previous
|
|
152
154
|
});
|
|
153
155
|
};
|
|
154
|
-
var useProviderSequences = (providerId, bbox, zoom) => {
|
|
156
|
+
var useProviderSequences = (providerId, bbox, zoom, { minZoom = 0 } = {}) => {
|
|
155
157
|
const adapter = adapterById[providerId];
|
|
156
158
|
const meta = providerById[providerId];
|
|
157
|
-
const sequencesMinZoom =
|
|
158
|
-
const enabled = meta.kind === "photo" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= sequencesMinZoom && adapter?.fetchSequences != null;
|
|
159
|
+
const sequencesMinZoom = fetchedSequencesMinZoom(providerId);
|
|
160
|
+
const enabled = meta.kind === "photo" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= Math.max(sequencesMinZoom, minZoom) && adapter?.fetchSequences != null;
|
|
159
161
|
return useQuery({
|
|
160
162
|
queryKey: ["provider-sequences", providerId, bboxKey(bbox), zoom],
|
|
161
163
|
queryFn: ({ signal }) => adapter?.fetchSequences?.(bbox, zoom, signal) ?? [],
|
|
@@ -163,10 +165,10 @@ var useProviderSequences = (providerId, bbox, zoom) => {
|
|
|
163
165
|
placeholderData: (previous) => previous
|
|
164
166
|
});
|
|
165
167
|
};
|
|
166
|
-
var useProviderMapFeatures = (providerId, bbox, zoom) => {
|
|
168
|
+
var useProviderMapFeatures = (providerId, bbox, zoom, { minZoom = 0 } = {}) => {
|
|
167
169
|
const adapter = adapterById[providerId];
|
|
168
170
|
const meta = providerById[providerId];
|
|
169
|
-
const enabled = meta.kind === "mapFeature" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= meta.minZoom && adapter?.fetchMapFeatures != null;
|
|
171
|
+
const enabled = meta.kind === "mapFeature" && bbox != null && providerCoversBbox(providerId, bbox) && zoom >= Math.max(meta.minZoom, minZoom) && adapter?.fetchMapFeatures != null;
|
|
170
172
|
return useQuery({
|
|
171
173
|
queryKey: ["provider-map-features", providerId, bboxKey(bbox), zoom],
|
|
172
174
|
queryFn: async ({ signal }) => {
|
|
@@ -194,7 +196,8 @@ var StreetLevelImageryViewCone = ({
|
|
|
194
196
|
zoom,
|
|
195
197
|
viewerPov,
|
|
196
198
|
color = SELECTION_COLOR,
|
|
197
|
-
scale = 2.5
|
|
199
|
+
scale = 2.5,
|
|
200
|
+
beforeId
|
|
198
201
|
}) => {
|
|
199
202
|
const apex = viewerPov?.lngLat ?? selectedPhoto.lngLat;
|
|
200
203
|
const isPano = selectedPhoto.isPano === true;
|
|
@@ -207,6 +210,9 @@ var StreetLevelImageryViewCone = ({
|
|
|
207
210
|
} else if (selectedPhoto.providerId === "panoramax") {
|
|
208
211
|
bearing = viewerPov?.bearing ?? selectedPhoto.heading;
|
|
209
212
|
fov = 30;
|
|
213
|
+
} else if (selectedPhoto.providerId === "mapillary") {
|
|
214
|
+
bearing = viewerPov?.bearing ?? selectedPhoto.heading;
|
|
215
|
+
fov = viewerPov?.hfov ?? 30;
|
|
210
216
|
} else {
|
|
211
217
|
bearing = selectedPhoto.heading;
|
|
212
218
|
fov = 30;
|
|
@@ -224,6 +230,7 @@ var StreetLevelImageryViewCone = ({
|
|
|
224
230
|
/* @__PURE__ */ jsx(
|
|
225
231
|
Layer,
|
|
226
232
|
{
|
|
233
|
+
beforeId,
|
|
227
234
|
id: CONE_FILL_LAYER_ID,
|
|
228
235
|
type: "fill",
|
|
229
236
|
source: CONE_SOURCE_ID,
|
|
@@ -271,6 +278,7 @@ var AGE_SHADE = [
|
|
|
271
278
|
BASE_COLOR
|
|
272
279
|
]
|
|
273
280
|
];
|
|
281
|
+
var PHOTO_TARGET_RADIUS_PX = 10;
|
|
274
282
|
var PHOTO_SORT_KEY = ["coalesce", ["get", "capturedAt"], 0];
|
|
275
283
|
var FEATURE_SORT_KEY = ["coalesce", ["get", "lastSeenAt"], 0];
|
|
276
284
|
var PhotoProviderLayer = ({
|
|
@@ -283,15 +291,20 @@ var PhotoProviderLayer = ({
|
|
|
283
291
|
photoCircleColor,
|
|
284
292
|
activeSequenceId,
|
|
285
293
|
hasActiveSequence,
|
|
286
|
-
shownPhotoId
|
|
294
|
+
shownPhotoId,
|
|
295
|
+
beforeId,
|
|
296
|
+
minZoom
|
|
287
297
|
}) => {
|
|
288
298
|
const adapter = adapterById[providerId];
|
|
289
299
|
const meta = providerById[providerId];
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
const
|
|
300
|
+
const photosMinZoom = Math.max(meta.minZoom, minZoom);
|
|
301
|
+
const fetchedLinesMinZoom = fetchedSequencesMinZoom(providerId);
|
|
302
|
+
const sequencesMinZoom = Math.max(fetchedLinesMinZoom, minZoom);
|
|
303
|
+
const { data: photos = [] } = useProviderPhotos(providerId, bbox, zoom, { minZoom });
|
|
304
|
+
const { data: sequences = [] } = useProviderSequences(providerId, bbox, zoom, { minZoom });
|
|
305
|
+
const visiblePhotos = zoom >= photosMinZoom ? photos.filter((photo) => photoMatchesFilters(photo, filter?.photoTypes, filter?.date)) : [];
|
|
293
306
|
const drawBbox = bbox ? padBbox(bbox, 0.25) : null;
|
|
294
|
-
const photoCollection = zoom >=
|
|
307
|
+
const photoCollection = zoom >= photosMinZoom ? photosToFeatureCollection(
|
|
295
308
|
drawBbox ? visiblePhotos.filter((photo) => lngLatInBbox(photo.lngLat, drawBbox)) : visiblePhotos
|
|
296
309
|
) : emptyPointCollection();
|
|
297
310
|
const viewfieldsActive = showViewfields && zoom >= VIEWFIELD_MIN_ZOOM;
|
|
@@ -342,7 +355,7 @@ var PhotoProviderLayer = ({
|
|
|
342
355
|
sequenceCapturedAtById.set(photo.sequenceId, photo.capturedAt);
|
|
343
356
|
}
|
|
344
357
|
}
|
|
345
|
-
const filteredSequences = showSequences && zoom >=
|
|
358
|
+
const filteredSequences = showSequences && zoom >= sequencesMinZoom ? sequences.map((sequence) => {
|
|
346
359
|
if (sequence.capturedAt != null) return sequence;
|
|
347
360
|
const fromPhotos = sequenceCapturedAtById.get(sequence.sequenceId);
|
|
348
361
|
return fromPhotos != null ? { ...sequence, capturedAt: fromPhotos } : sequence;
|
|
@@ -385,6 +398,8 @@ var PhotoProviderLayer = ({
|
|
|
385
398
|
}
|
|
386
399
|
};
|
|
387
400
|
});
|
|
401
|
+
const sequenceTiles = showSequences ? adapter?.sequenceTiles?.() : null;
|
|
402
|
+
const sequenceTilesMinZoom = sequenceTiles ? Math.max(sequenceTiles.minZoom, minZoom) : 0;
|
|
388
403
|
const sequenceCollection = alignedSequences.length > 0 ? sequencesToFeatureCollection(alignedSequences) : emptyLineCollection();
|
|
389
404
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
390
405
|
meta.coverageTiles ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -401,6 +416,7 @@ var PhotoProviderLayer = ({
|
|
|
401
416
|
/* @__PURE__ */ jsx(
|
|
402
417
|
Layer,
|
|
403
418
|
{
|
|
419
|
+
beforeId,
|
|
404
420
|
id: `coverage-tiles-${providerId}`,
|
|
405
421
|
minzoom: meta.coverageTiles.minZoom,
|
|
406
422
|
paint: { "raster-opacity": 0.7 },
|
|
@@ -409,6 +425,48 @@ var PhotoProviderLayer = ({
|
|
|
409
425
|
}
|
|
410
426
|
)
|
|
411
427
|
] }) : null,
|
|
428
|
+
sequenceTiles && sequenceTilesMinZoom < fetchedLinesMinZoom ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
429
|
+
/* @__PURE__ */ jsx(
|
|
430
|
+
Source,
|
|
431
|
+
{
|
|
432
|
+
id: sequenceTilesSourceId(providerId),
|
|
433
|
+
type: "vector",
|
|
434
|
+
tiles: sequenceTiles.tiles,
|
|
435
|
+
minzoom: sequenceTiles.minZoom,
|
|
436
|
+
maxzoom: sequenceTiles.maxZoom
|
|
437
|
+
},
|
|
438
|
+
sequenceTilesSourceId(providerId)
|
|
439
|
+
),
|
|
440
|
+
/* @__PURE__ */ jsx(
|
|
441
|
+
Layer,
|
|
442
|
+
{
|
|
443
|
+
beforeId,
|
|
444
|
+
id: sequenceTilesLayerId(providerId),
|
|
445
|
+
type: "line",
|
|
446
|
+
source: sequenceTilesSourceId(providerId),
|
|
447
|
+
"source-layer": sequenceTiles.sourceLayer,
|
|
448
|
+
minzoom: sequenceTilesMinZoom,
|
|
449
|
+
maxzoom: fetchedLinesMinZoom,
|
|
450
|
+
filter: renameExpressionProperties(photoFilter, sequenceTiles.properties),
|
|
451
|
+
layout: {
|
|
452
|
+
"line-cap": "round",
|
|
453
|
+
"line-join": "round",
|
|
454
|
+
"line-sort-key": renameExpressionProperties(
|
|
455
|
+
["case", inActiveSequence, 1, 0],
|
|
456
|
+
sequenceTiles.properties
|
|
457
|
+
)
|
|
458
|
+
},
|
|
459
|
+
paint: {
|
|
460
|
+
"line-color": renameExpressionProperties(photoCircleColor, sequenceTiles.properties),
|
|
461
|
+
"line-width": renameExpressionProperties(
|
|
462
|
+
["case", inActiveSequence, ACTIVE_LINE_WIDTH, 1.25],
|
|
463
|
+
sequenceTiles.properties
|
|
464
|
+
),
|
|
465
|
+
"line-opacity": renameExpressionProperties(lineOpacity, sequenceTiles.properties)
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
] }) : null,
|
|
412
470
|
adapter?.fetchSequences && showSequences ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
413
471
|
/* @__PURE__ */ jsx(
|
|
414
472
|
Source,
|
|
@@ -422,6 +480,7 @@ var PhotoProviderLayer = ({
|
|
|
422
480
|
/* @__PURE__ */ jsx(
|
|
423
481
|
Layer,
|
|
424
482
|
{
|
|
483
|
+
beforeId,
|
|
425
484
|
id: sequenceLayerId(providerId),
|
|
426
485
|
type: "line",
|
|
427
486
|
source: sequenceSourceId(providerId),
|
|
@@ -451,6 +510,7 @@ var PhotoProviderLayer = ({
|
|
|
451
510
|
/* @__PURE__ */ jsx(
|
|
452
511
|
Layer,
|
|
453
512
|
{
|
|
513
|
+
beforeId,
|
|
454
514
|
id: viewfieldLayerId(providerId),
|
|
455
515
|
type: "fill",
|
|
456
516
|
source: viewfieldSrcId,
|
|
@@ -465,6 +525,7 @@ var PhotoProviderLayer = ({
|
|
|
465
525
|
/* @__PURE__ */ jsx(
|
|
466
526
|
Layer,
|
|
467
527
|
{
|
|
528
|
+
beforeId,
|
|
468
529
|
id: viewfieldLineLayerId(providerId),
|
|
469
530
|
type: "line",
|
|
470
531
|
source: viewfieldSrcId,
|
|
@@ -490,6 +551,19 @@ var PhotoProviderLayer = ({
|
|
|
490
551
|
/* @__PURE__ */ jsx(
|
|
491
552
|
Layer,
|
|
492
553
|
{
|
|
554
|
+
beforeId,
|
|
555
|
+
id: photoTargetLayerId(providerId),
|
|
556
|
+
type: "circle",
|
|
557
|
+
source: photoSrcId,
|
|
558
|
+
filter: photoFilter,
|
|
559
|
+
layout: { "circle-sort-key": PHOTO_SORT_KEY },
|
|
560
|
+
paint: { "circle-radius": PHOTO_TARGET_RADIUS_PX, "circle-opacity": 0 }
|
|
561
|
+
}
|
|
562
|
+
),
|
|
563
|
+
/* @__PURE__ */ jsx(
|
|
564
|
+
Layer,
|
|
565
|
+
{
|
|
566
|
+
beforeId,
|
|
493
567
|
id: photoLayerId(providerId),
|
|
494
568
|
type: "circle",
|
|
495
569
|
source: photoSrcId,
|
|
@@ -508,12 +582,14 @@ var MapFeatureProviderLayer = ({
|
|
|
508
582
|
bbox,
|
|
509
583
|
zoom,
|
|
510
584
|
filter,
|
|
511
|
-
mapFeatureCircleColor
|
|
585
|
+
mapFeatureCircleColor,
|
|
586
|
+
beforeId,
|
|
587
|
+
minZoom
|
|
512
588
|
}) => {
|
|
513
589
|
const meta = providerById[providerId];
|
|
514
|
-
const { data: features = [] } = useProviderMapFeatures(providerId, bbox, zoom);
|
|
590
|
+
const { data: features = [] } = useProviderMapFeatures(providerId, bbox, zoom, { minZoom });
|
|
515
591
|
const valueFilter = filter?.mapFeatureValue;
|
|
516
|
-
const featureCollection = zoom >= meta.minZoom ? mapFeaturesToFeatureCollection(
|
|
592
|
+
const featureCollection = zoom >= Math.max(meta.minZoom, minZoom) ? mapFeaturesToFeatureCollection(
|
|
517
593
|
valueFilter ? features.filter((feature) => valueFilter(feature.value)) : features
|
|
518
594
|
) : emptyPointCollection();
|
|
519
595
|
const featureFilter = buildMapFeatureLayerFilter(filter?.date);
|
|
@@ -532,6 +608,7 @@ var MapFeatureProviderLayer = ({
|
|
|
532
608
|
/* @__PURE__ */ jsx(
|
|
533
609
|
Layer,
|
|
534
610
|
{
|
|
611
|
+
beforeId,
|
|
535
612
|
id: featureLayerId(providerId),
|
|
536
613
|
type: "circle",
|
|
537
614
|
source: featureSrcId,
|
|
@@ -567,7 +644,9 @@ var StreetLevelImagerySourcesAndLayers = ({
|
|
|
567
644
|
viewConeColor,
|
|
568
645
|
viewConeScale,
|
|
569
646
|
photoCircleColor,
|
|
570
|
-
mapFeatureCircleColor
|
|
647
|
+
mapFeatureCircleColor,
|
|
648
|
+
beforeId,
|
|
649
|
+
minZoom = 0
|
|
571
650
|
} = options;
|
|
572
651
|
useEffect(
|
|
573
652
|
function applyStreetImageryConfig() {
|
|
@@ -594,6 +673,8 @@ var StreetLevelImagerySourcesAndLayers = ({
|
|
|
594
673
|
providers.map((providerId) => /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(
|
|
595
674
|
ProviderLayer,
|
|
596
675
|
{
|
|
676
|
+
beforeId,
|
|
677
|
+
minZoom,
|
|
597
678
|
bbox,
|
|
598
679
|
filter,
|
|
599
680
|
mapFeatureCircleColor,
|
|
@@ -610,6 +691,7 @@ var StreetLevelImagerySourcesAndLayers = ({
|
|
|
610
691
|
showViewCone && selectedPhoto ? /* @__PURE__ */ jsx(
|
|
611
692
|
StreetLevelImageryViewCone,
|
|
612
693
|
{
|
|
694
|
+
beforeId,
|
|
613
695
|
color: viewConeColor ?? SELECTION_COLOR,
|
|
614
696
|
scale: viewConeScale,
|
|
615
697
|
selectedPhoto,
|
|
@@ -620,6 +702,7 @@ var StreetLevelImagerySourcesAndLayers = ({
|
|
|
620
702
|
showSelectionHighlight ? /* @__PURE__ */ jsx(
|
|
621
703
|
StreetLevelImagerySelectionOverlay,
|
|
622
704
|
{
|
|
705
|
+
beforeId,
|
|
623
706
|
cameraLngLat: viewerPov?.lngLat,
|
|
624
707
|
selectedPhoto,
|
|
625
708
|
selectedSequence: providerDrawsSequences ? null : selectedSequence,
|
|
@@ -628,13 +711,13 @@ var StreetLevelImagerySourcesAndLayers = ({
|
|
|
628
711
|
) : null
|
|
629
712
|
] });
|
|
630
713
|
};
|
|
631
|
-
var
|
|
632
|
-
() => import('./MapillaryPanel-
|
|
714
|
+
var MapillaryPanel = lazy(
|
|
715
|
+
() => import('./MapillaryPanel-FAXVZH37.js').then((module) => ({
|
|
633
716
|
default: module.MapillaryPanel
|
|
634
717
|
}))
|
|
635
718
|
);
|
|
636
|
-
var
|
|
637
|
-
() => import('./PanoramaxPanel-
|
|
719
|
+
var PanoramaxPanel = lazy(
|
|
720
|
+
() => import('./PanoramaxPanel-BTHEMKYY.js').then((module) => ({
|
|
638
721
|
default: module.PanoramaxPanel
|
|
639
722
|
}))
|
|
640
723
|
);
|
|
@@ -655,7 +738,7 @@ var StreetLevelImageryViewer = ({
|
|
|
655
738
|
}) => {
|
|
656
739
|
if (photo.providerId === "mapillary") {
|
|
657
740
|
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ViewerPanelPlaceholder, {}), children: /* @__PURE__ */ jsx(
|
|
658
|
-
|
|
741
|
+
MapillaryPanel,
|
|
659
742
|
{
|
|
660
743
|
groupPhotos,
|
|
661
744
|
hideAttribution,
|
|
@@ -671,7 +754,7 @@ var StreetLevelImageryViewer = ({
|
|
|
671
754
|
}
|
|
672
755
|
if (photo.providerId === "panoramax") {
|
|
673
756
|
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(ViewerPanelPlaceholder, {}), children: /* @__PURE__ */ jsx(
|
|
674
|
-
|
|
757
|
+
PanoramaxPanel,
|
|
675
758
|
{
|
|
676
759
|
groupPhotos,
|
|
677
760
|
hideLegend: hideAttribution,
|
|
@@ -686,6 +769,7 @@ var StreetLevelImageryViewer = ({
|
|
|
686
769
|
};
|
|
687
770
|
var streetImageryInteractiveLayerIds = (providers) => [
|
|
688
771
|
...providers.map((providerId) => photoLayerId(providerId)),
|
|
772
|
+
...providers.map((providerId) => photoTargetLayerId(providerId)),
|
|
689
773
|
...providers.map((providerId) => viewfieldLayerId(providerId)),
|
|
690
774
|
...providers.map((providerId) => featureLayerId(providerId))
|
|
691
775
|
];
|
|
@@ -694,6 +778,10 @@ var parseProviderIdFromLayerId = (layerId) => {
|
|
|
694
778
|
if (photoMatch) {
|
|
695
779
|
return photoMatch[1];
|
|
696
780
|
}
|
|
781
|
+
const targetMatch = layerId.match(/^photo-targets-(.+)$/);
|
|
782
|
+
if (targetMatch) {
|
|
783
|
+
return targetMatch[1];
|
|
784
|
+
}
|
|
697
785
|
const viewfieldMatch = layerId.match(/^viewfields-(.+)$/);
|
|
698
786
|
if (viewfieldMatch) {
|
|
699
787
|
return viewfieldMatch[1];
|
|
@@ -718,7 +806,7 @@ var queryStreetImageryFeatures = (event) => {
|
|
|
718
806
|
continue;
|
|
719
807
|
}
|
|
720
808
|
const props = feature.properties ?? {};
|
|
721
|
-
if (layerId.startsWith("photos-") || layerId.startsWith("viewfields-")) {
|
|
809
|
+
if (layerId.startsWith("photos-") || layerId.startsWith("photo-targets-") || layerId.startsWith("viewfields-")) {
|
|
722
810
|
const photoId = props.photoId;
|
|
723
811
|
if (photoId == null) {
|
|
724
812
|
continue;
|
|
@@ -880,6 +968,13 @@ var viewSuggestionLabel = ({ viewpoint, direction }, messages) => messages.viewD
|
|
|
880
968
|
var DEFAULT_LAYOUT = { right: 16, bottom: 32, width: 420, minimized: false };
|
|
881
969
|
var MIN_WIDTH = 280;
|
|
882
970
|
var EDGE = 8;
|
|
971
|
+
var hasStoredLayout = (storageKey) => {
|
|
972
|
+
try {
|
|
973
|
+
return localStorage.getItem(storageKey) != null;
|
|
974
|
+
} catch {
|
|
975
|
+
return false;
|
|
976
|
+
}
|
|
977
|
+
};
|
|
883
978
|
var readLayout = (storageKey) => {
|
|
884
979
|
try {
|
|
885
980
|
const raw = localStorage.getItem(storageKey);
|
|
@@ -1024,8 +1119,8 @@ var FloatingPhotoViewer = ({
|
|
|
1024
1119
|
activeDirectionKey,
|
|
1025
1120
|
onSelectSuggestion,
|
|
1026
1121
|
shownPhotoId,
|
|
1027
|
-
canGoBack,
|
|
1028
|
-
canGoForward,
|
|
1122
|
+
canGoBack = false,
|
|
1123
|
+
canGoForward = false,
|
|
1029
1124
|
onBack,
|
|
1030
1125
|
onForward,
|
|
1031
1126
|
onClose,
|
|
@@ -1035,12 +1130,16 @@ var FloatingPhotoViewer = ({
|
|
|
1035
1130
|
children,
|
|
1036
1131
|
footer,
|
|
1037
1132
|
drawer,
|
|
1038
|
-
storageKey = "street-imagery:floating-viewer"
|
|
1133
|
+
storageKey = "street-imagery:floating-viewer",
|
|
1134
|
+
defaultPosition
|
|
1039
1135
|
}) => {
|
|
1040
1136
|
const { messages } = useStreetImageryI18n();
|
|
1041
1137
|
const severalViewpoints = new Set(suggestions.map((suggestion) => suggestion.viewpoint.id)).size > 1;
|
|
1042
1138
|
const [layout, setLayout] = useState(() => readLayout(storageKey));
|
|
1043
1139
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
1140
|
+
const [moved, setMoved] = useState(() => hasStoredLayout(storageKey));
|
|
1141
|
+
const atTopLeft = defaultPosition?.corner === "top-left" && !moved;
|
|
1142
|
+
const position = atTopLeft ? { left: defaultPosition.left ?? EDGE, top: defaultPosition.top ?? EDGE } : { right: layout.right, bottom: layout.bottom };
|
|
1044
1143
|
const dragRef = useRef(null);
|
|
1045
1144
|
const updateLayout = (next) => {
|
|
1046
1145
|
setLayout(next);
|
|
@@ -1054,9 +1153,9 @@ var FloatingPhotoViewer = ({
|
|
|
1054
1153
|
if (event.key === "Escape") {
|
|
1055
1154
|
onClose();
|
|
1056
1155
|
} else if (event.key === "[" && canGoBack) {
|
|
1057
|
-
onBack();
|
|
1156
|
+
onBack?.();
|
|
1058
1157
|
} else if (event.key === "]" && canGoForward) {
|
|
1059
|
-
onForward();
|
|
1158
|
+
onForward?.();
|
|
1060
1159
|
} else if (event.key === "ArrowLeft" && event.altKey) {
|
|
1061
1160
|
step?.onPrevious?.();
|
|
1062
1161
|
} else if (event.key === "ArrowRight" && event.altKey) {
|
|
@@ -1072,7 +1171,16 @@ var FloatingPhotoViewer = ({
|
|
|
1072
1171
|
return;
|
|
1073
1172
|
}
|
|
1074
1173
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
1075
|
-
|
|
1174
|
+
const box = event.currentTarget.closest("section");
|
|
1175
|
+
const container = box?.offsetParent;
|
|
1176
|
+
const start = atTopLeft && box && container ? {
|
|
1177
|
+
...layout,
|
|
1178
|
+
right: container.clientWidth - box.offsetLeft - box.offsetWidth,
|
|
1179
|
+
bottom: container.clientHeight - box.offsetTop - box.offsetHeight
|
|
1180
|
+
} : layout;
|
|
1181
|
+
setLayout(start);
|
|
1182
|
+
setMoved(true);
|
|
1183
|
+
dragRef.current = { x: event.clientX, y: event.clientY, layout: start, mode };
|
|
1076
1184
|
};
|
|
1077
1185
|
const onDrag = (event) => {
|
|
1078
1186
|
const drag = dragRef.current;
|
|
@@ -1102,7 +1210,7 @@ var FloatingPhotoViewer = ({
|
|
|
1102
1210
|
{
|
|
1103
1211
|
className: "absolute z-10 inline-flex items-center gap-2 rounded-full bg-white px-3 py-1.5 text-sm font-medium text-slate-800 shadow-lg ring-1 ring-slate-200 hover:bg-slate-50",
|
|
1104
1212
|
onClick: () => updateLayout({ ...layout, minimized: false }),
|
|
1105
|
-
style:
|
|
1213
|
+
style: position,
|
|
1106
1214
|
type: "button",
|
|
1107
1215
|
children: [
|
|
1108
1216
|
/* @__PURE__ */ jsx(Icon, { path: ICONS.expand }),
|
|
@@ -1117,8 +1225,7 @@ var FloatingPhotoViewer = ({
|
|
|
1117
1225
|
"aria-label": messages.viewer.regionLabel,
|
|
1118
1226
|
className: "absolute z-10 flex max-h-[calc(100%-1rem)] flex-col overflow-hidden rounded-xl bg-white shadow-xl ring-1 ring-slate-200",
|
|
1119
1227
|
style: {
|
|
1120
|
-
|
|
1121
|
-
bottom: layout.bottom,
|
|
1228
|
+
...position,
|
|
1122
1229
|
width: `min(${layout.width}px, calc(100% - 1rem))`
|
|
1123
1230
|
},
|
|
1124
1231
|
children: [
|
|
@@ -1162,16 +1269,26 @@ var FloatingPhotoViewer = ({
|
|
|
1162
1269
|
/* @__PURE__ */ jsx("h2", { className: "min-w-0 truncate px-1 text-sm font-semibold text-slate-800", children: title }),
|
|
1163
1270
|
titleActions
|
|
1164
1271
|
] }),
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1272
|
+
onBack && onForward ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1273
|
+
/* @__PURE__ */ jsx(
|
|
1274
|
+
ToolbarButton,
|
|
1275
|
+
{
|
|
1276
|
+
disabled: !canGoBack,
|
|
1277
|
+
label: messages.viewer.backInHistory,
|
|
1278
|
+
onClick: onBack,
|
|
1279
|
+
children: /* @__PURE__ */ jsx(Icon, { path: ICONS.undo })
|
|
1280
|
+
}
|
|
1281
|
+
),
|
|
1282
|
+
/* @__PURE__ */ jsx(
|
|
1283
|
+
ToolbarButton,
|
|
1284
|
+
{
|
|
1285
|
+
disabled: !canGoForward,
|
|
1286
|
+
label: messages.viewer.forwardInHistory,
|
|
1287
|
+
onClick: onForward,
|
|
1288
|
+
children: /* @__PURE__ */ jsx(Icon, { path: ICONS.redo })
|
|
1289
|
+
}
|
|
1290
|
+
)
|
|
1291
|
+
] }) : null,
|
|
1175
1292
|
/* @__PURE__ */ jsx(
|
|
1176
1293
|
ToolbarButton,
|
|
1177
1294
|
{
|
|
@@ -1725,7 +1842,8 @@ var PhotoDateRangeFilter = ({
|
|
|
1725
1842
|
maxYears,
|
|
1726
1843
|
now: nowProp,
|
|
1727
1844
|
dateInputs = "collapsed",
|
|
1728
|
-
className
|
|
1845
|
+
className,
|
|
1846
|
+
allDatesAction = true
|
|
1729
1847
|
}) => {
|
|
1730
1848
|
const { locale, messages } = useStreetImageryI18n();
|
|
1731
1849
|
const text = messages.dateFilter;
|
|
@@ -1799,7 +1917,7 @@ var PhotoDateRangeFilter = ({
|
|
|
1799
1917
|
{
|
|
1800
1918
|
className: `flex-1 rounded-t-[1px] ${inRange ? "bg-slate-500" : "bg-slate-300"}`,
|
|
1801
1919
|
style: {
|
|
1802
|
-
height: count === 0 ? 0 : Math.max(2, Math.
|
|
1920
|
+
height: count === 0 ? 0 : Math.max(2, Math.log1p(count) / Math.log1p(maxCount) * CHART_HEIGHT_PX)
|
|
1803
1921
|
},
|
|
1804
1922
|
title: count > 0 ? text.photoCount(count) : void 0
|
|
1805
1923
|
},
|
|
@@ -1905,7 +2023,7 @@ var PhotoDateRangeFilter = ({
|
|
|
1905
2023
|
)) }),
|
|
1906
2024
|
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-baseline justify-between gap-2 text-xs", children: [
|
|
1907
2025
|
/* @__PURE__ */ jsx("span", { className: "font-medium text-slate-700", children: rangeLabel }),
|
|
1908
|
-
isAllDates ? null : /* @__PURE__ */ jsx(
|
|
2026
|
+
isAllDates || !allDatesAction ? null : /* @__PURE__ */ jsx(
|
|
1909
2027
|
"button",
|
|
1910
2028
|
{
|
|
1911
2029
|
className: "shrink-0 font-medium text-slate-600 underline decoration-slate-300 underline-offset-2 hover:text-slate-900",
|
|
@@ -9,8 +9,9 @@ type PanoramaxPanelProps = {
|
|
|
9
9
|
/** The shown picture with creator, licence, local capture time and camera. */
|
|
10
10
|
onViewerPhoto?: (photo: NormalizedPhoto) => void;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* creator and licence itself, from
|
|
12
|
+
* Leave out the viewer's own widgets: the legend (a bottom drawer in narrow containers), the
|
|
13
|
+
* player and the zoom buttons. The host must then show creator and licence itself, from
|
|
14
|
+
* `onViewerPhoto`. Stepping through a sequence still works with the arrows in the photo.
|
|
14
15
|
*/
|
|
15
16
|
hideLegend?: boolean;
|
|
16
17
|
};
|
package/dist/photo-details.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useStreetImageryI18n } from './chunk-
|
|
1
|
+
import { useStreetImageryI18n } from './chunk-6EMFFIL2.js';
|
|
2
2
|
import { providerById, formatLocalDateTime, formatDate, formatRelativeDate } from '@osm-editor-kit/street-imagery';
|
|
3
3
|
import { useRef, useEffect } from 'react';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -7,6 +7,10 @@ export type StreetImageryClickFeature = {
|
|
|
7
7
|
featureId?: string;
|
|
8
8
|
sequenceId?: string;
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Layers to pass as `interactiveLayerIds`. A click returns the features of all layers it hits, the
|
|
12
|
+
* top one first: the photo dot itself, then view shapes, then the larger invisible targets.
|
|
13
|
+
*/
|
|
10
14
|
export declare const streetImageryInteractiveLayerIds: (providers: ProviderId[]) => string[];
|
|
11
15
|
export declare const queryStreetImageryFeatures: (event: {
|
|
12
16
|
features?: MapGeoJSONFeature[] | null;
|
|
@@ -19,10 +19,14 @@ export type FloatingPhotoViewerProps = {
|
|
|
19
19
|
onSelectSuggestion: (suggestion: ViewSuggestion, candidate: PhotoCandidate) => void;
|
|
20
20
|
/** The photo in the viewer, so the active view can show which of its photos that is. */
|
|
21
21
|
shownPhotoId?: string | null;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* History of shown photos: the back and forward buttons and the keys [ and ]. Leave out
|
|
24
|
+
* `onBack` and `onForward` for a host without a history; the buttons are then not shown.
|
|
25
|
+
*/
|
|
26
|
+
canGoBack?: boolean;
|
|
27
|
+
canGoForward?: boolean;
|
|
28
|
+
onBack?: () => void;
|
|
29
|
+
onForward?: () => void;
|
|
26
30
|
onClose: () => void;
|
|
27
31
|
/**
|
|
28
32
|
* Step to the neighbouring photo, e.g. along the clicked street: the `<` `>` buttons at the
|
|
@@ -51,10 +55,19 @@ export type FloatingPhotoViewerProps = {
|
|
|
51
55
|
};
|
|
52
56
|
/** localStorage key for position, width and minimized state. */
|
|
53
57
|
storageKey?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Where the box is until the user moves it: the bottom right corner (default), or the top left
|
|
60
|
+
* one with `left` and `top` in px from the container's edges, e.g. next to a side panel.
|
|
61
|
+
*/
|
|
62
|
+
defaultPosition?: {
|
|
63
|
+
corner: 'top-left';
|
|
64
|
+
left?: number;
|
|
65
|
+
top?: number;
|
|
66
|
+
};
|
|
54
67
|
};
|
|
55
68
|
/**
|
|
56
69
|
* Photo viewer box floating over the map. Render inside a positioned (relative) map container.
|
|
57
70
|
* Drag the header to move, drag the left edge to resize. Keys: Esc closes, [ and ] step history,
|
|
58
71
|
* Alt + arrow left/right step along (`step`).
|
|
59
72
|
*/
|
|
60
|
-
export declare const FloatingPhotoViewer: ({ title, titleActions, suggestions, activeDirectionKey, onSelectSuggestion, shownPhotoId, canGoBack, canGoForward, onBack, onForward, onClose, step, toolbar, status, children, footer, drawer, storageKey, }: FloatingPhotoViewerProps) => import("react").JSX.Element;
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osm-editor-kit/street-imagery-react",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.9",
|
|
4
4
|
"description": "React MapLibre layers and photo viewers for street-level imagery providers.",
|
|
5
5
|
"homepage": "https://github.com/osmberlin/street-space-editor/tree/main/packages/street-imagery-react",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"types": "./dist/photo-details/index.d.ts",
|
|
25
25
|
"import": "./dist/photo-details.js"
|
|
26
26
|
},
|
|
27
|
+
"./viewer-panels": {
|
|
28
|
+
"types": "./dist/viewer-panels/index.d.ts",
|
|
29
|
+
"import": "./dist/viewer-panels.js"
|
|
30
|
+
},
|
|
27
31
|
"./package.json": "./package.json"
|
|
28
32
|
},
|
|
29
33
|
"publishConfig": {
|
|
@@ -56,7 +60,7 @@
|
|
|
56
60
|
"zustand": "^5.0.7"
|
|
57
61
|
},
|
|
58
62
|
"peerDependencies": {
|
|
59
|
-
"@osm-editor-kit/street-imagery": "^0.1.0-alpha.
|
|
63
|
+
"@osm-editor-kit/street-imagery": "^0.1.0-alpha.8",
|
|
60
64
|
"@panoramax/web-viewer": "^5",
|
|
61
65
|
"@tanstack/react-query": "^5",
|
|
62
66
|
"mapillary-js": "^4",
|
|
@@ -75,6 +79,10 @@
|
|
|
75
79
|
"types": "./dist/photo-details/index.d.ts",
|
|
76
80
|
"import": "./dist/photo-details.js"
|
|
77
81
|
},
|
|
82
|
+
"./viewer-panels": {
|
|
83
|
+
"types": "./dist/viewer-panels/index.d.ts",
|
|
84
|
+
"import": "./dist/viewer-panels.js"
|
|
85
|
+
},
|
|
78
86
|
"./package.json": "./package.json"
|
|
79
87
|
}
|
|
80
88
|
}
|