@osm-editor-kit/street-imagery-react 0.1.0-alpha.12 → 0.1.0-alpha.14

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 CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  } from '@osm-editor-kit/street-imagery-react'
27
27
  import { createStreetImageryConfig } from '@osm-editor-kit/street-imagery'
28
28
 
29
- const bbox = useMapViewportBbox('main', map)
29
+ const bbox = useMapViewportBbox('main')
30
30
 
31
31
  <StreetLevelImagerySourcesAndLayers
32
32
  providers={['mapillary', 'panoramax']}
@@ -106,6 +106,58 @@ const { suggestions } = useViewSuggestions(viewpoints, { maxAgeYears: 2 })
106
106
  Render `FloatingPhotoViewer` inside a positioned map container. Photos from suggestions open in
107
107
  `StreetLevelImageryViewer` with `lookAtBearing={suggestion.direction.bearing}`.
108
108
 
109
+ A host without suggested views leaves out `suggestions`, `activeDirectionKey` and `onSelectSuggestion`; the chips are then not shown. Its own buttons and links go in `titleActions`. They keep their size next to a long title and do not start a drag.
110
+
111
+ For a free window over the whole page, use the viewport as container and let the box leave it until a share of it shows:
112
+
113
+ ```tsx
114
+ <FloatingPhotoViewer position="fixed" minVisibleShare={0.2} onClose={close} title="Photo">
115
+ {viewer}
116
+ </FloatingPhotoViewer>
117
+ ```
118
+
119
+ `position="fixed"` (default `absolute`) needs an ancestor without `transform` or `filter`, and a stacking order that puts the box above the page. `minVisibleShare` (0–1) never lets the box go over the top edge, because the header is what moves it. The limit also holds when the box or the container changes size, and a minimized viewer stays within reach. Without `minVisibleShare` the box keeps 8px from the right and bottom edge.
120
+
121
+ To ask "who sees this spot" instead of "what looks north here", use `usePhotosLookingAt`: flat photos within `maxDistanceMeters` (50) whose heading points at the place within `maxFlatAngleDeg` (35), and 360° photos within the distance, best first. Each candidate has `bearingToPlace`.
122
+
123
+ ```tsx
124
+ const [place, setPlace] = useState<LngLat | null>(null) // set on map click
125
+ const [index, setIndex] = useState(0)
126
+ const { candidates } = usePhotosLookingAt(place, { maxAgeYears: 2, enabled: place != null })
127
+ const candidate = candidates[index]
128
+
129
+ {candidate ? (
130
+ <FloatingPhotoViewer
131
+ title="Photos of this place"
132
+ onClose={() => setPlace(null)}
133
+ step={{
134
+ onPrevious: index > 0 ? () => setIndex(index - 1) : undefined,
135
+ onNext: index < candidates.length - 1 ? () => setIndex(index + 1) : undefined,
136
+ previousLabel: 'Previous photo',
137
+ nextLabel: 'Next photo',
138
+ }}
139
+ >
140
+ <StreetLevelImageryViewer
141
+ photo={candidate.photo}
142
+ lookAtBearing={candidate.bearingToPlace}
143
+ … />
144
+ </FloatingPhotoViewer>
145
+ ) : null}
146
+ ```
147
+
148
+ The list needs no chips: `step` gives the `<` `>` buttons and Alt + arrow keys. `lookAtBearing` turns Mapillary 360° photos only. The pure ranking is `rankPhotosLookingAt(place, photos, options)` in the core package.
149
+
150
+ For a link that opens the same photo with the same zoom and pan, keep the view the viewer reports and pass it to `providerExternalLink`:
151
+
152
+ ```tsx
153
+ const [view, setView] = useState<PhotoView | null>(null)
154
+
155
+ <StreetLevelImageryViewer onViewerView={setView} … />
156
+ <a href={providerExternalLink(photo, view)}>Open on Mapillary</a>
157
+ ```
158
+
159
+ `onViewerView` runs when the view has stopped moving and when the photo changes, not during a drag, for Mapillary (`x`, `y`, `zoom`) and Panoramax (`heading`, `pitch`, `zoom`). A view of another photo is ignored by the link. What a link shows also depends on the size of the window it opens in. Panoramax in the default panel: the viewers differ, so direction and height of the view carry over, not every pixel.
160
+
109
161
  **Tailwind:** components use Tailwind classes. Tailwind does not scan `node_modules`, so add to your CSS:
110
162
 
111
163
  ```css
@@ -181,7 +233,7 @@ const { photos } = useAllProviderPhotos(providers, bbox, zoom) // no date: all p
181
233
  />
182
234
  ```
183
235
 
184
- A handle at its end means no limit, so the left end also shows photos older than the slider spans (`maxYears`, default 10). The scale itself is in the core package (`dateSliderPosition`, `dateSliderBins`, …) for a host that draws its own chart. The texts are in `messages.dateFilter`.
236
+ A click or tap on the chart moves the nearer handle to that exact place, and a press on the chart can go on as a drag. Handles on the same spot come apart in the direction of the drag. Handles stay separate targets for mouse and touch, at least 44px high and wide, and a vertical swipe on a phone scrolls the page. A handle at its end means no limit, so the left end also shows photos older than the slider spans (`maxYears`, default 10). The scale itself is in the core package (`dateSliderPosition`, `dateSliderBins`, …) for a host that draws its own chart. The texts are in `messages.dateFilter`.
185
237
 
186
238
  ## Pick a place on the map to open elsewhere
187
239
 
@@ -0,0 +1,3 @@
1
+ export { MapillaryPanel } from './chunk-LZR5SZDS.js';
2
+ import './chunk-XLBFXACK.js';
3
+ import './chunk-GYUS2JVV.js';
@@ -0,0 +1,3 @@
1
+ export { PanoramaxPanel } from './chunk-BZGY6BZC.js';
2
+ import './chunk-XLBFXACK.js';
3
+ import './chunk-GYUS2JVV.js';
@@ -1,4 +1,4 @@
1
- import type { NormalizedPhoto } from '@osm-editor-kit/street-imagery';
1
+ import type { NormalizedPhoto, PhotoView } from '@osm-editor-kit/street-imagery';
2
2
  import { type ComponentType } from 'react';
3
3
  import type { MapillaryLookAt, MapillaryViewerOutline } from './panels/mapillaryLookAt';
4
4
  import type { PanoramaxPanelProps } from './panels/PanoramaxPanel';
@@ -10,6 +10,12 @@ type StreetLevelImageryViewerProps = {
10
10
  onEaseMapToPoint: (lng: number, lat: number) => void;
11
11
  /** Mapillary, Panoramax: full photo data (creator, licence …) for each image the viewer shows. */
12
12
  onViewerPhoto?: (photo: NormalizedPhoto) => void;
13
+ /**
14
+ * Mapillary, Panoramax: the view inside the shown photo (pan and zoom), after it has stopped
15
+ * moving and when the photo changes. Pass it to `providerExternalLink` for a link that opens the
16
+ * same view on the provider's site.
17
+ */
18
+ onViewerView?: (view: PhotoView) => void;
13
19
  /** Mapillary 360° photos: initial view bearing (e.g. a suggested view direction). */
14
20
  lookAtBearing?: number | null;
15
21
  /** Mapillary: turn and zoom to a place (sign, traffic light, junction); wins over `lookAtBearing`. */
@@ -28,5 +34,5 @@ type StreetLevelImageryViewerProps = {
28
34
  */
29
35
  panoramaxPanel?: ComponentType<PanoramaxPanelProps>;
30
36
  };
31
- export declare const StreetLevelImageryViewer: ({ photo, groupPhotos, onPhotoSelected, onEaseMapToPoint, onViewerPhoto, lookAtBearing, lookAt, outlines, hideAttribution, panoramaxPanel: PanoramaxPanelOverride, }: StreetLevelImageryViewerProps) => import("react").JSX.Element | null;
37
+ export declare const StreetLevelImageryViewer: ({ photo, groupPhotos, onPhotoSelected, onEaseMapToPoint, onViewerPhoto, onViewerView, lookAtBearing, lookAt, outlines, hideAttribution, panoramaxPanel: PanoramaxPanelOverride, }: StreetLevelImageryViewerProps) => import("react").JSX.Element | null;
32
38
  export {};
@@ -1,3 +1,4 @@
1
+ import { c } from 'react/compiler-runtime';
1
2
  import { DEFAULT_STREET_IMAGERY_LOCALE } from '@osm-editor-kit/street-imagery';
2
3
  import { createContext, use } from 'react';
3
4
  import { jsx } from 'react/jsx-runtime';
@@ -58,7 +59,12 @@ var en = {
58
59
  }
59
60
  }
60
61
  };
61
- var COMPASS_DE = { N: "Norden", E: "Osten", S: "S\xFCden", W: "Westen" };
62
+ var COMPASS_DE = {
63
+ N: "Norden",
64
+ E: "Osten",
65
+ S: "S\xFCden",
66
+ W: "Westen"
67
+ };
62
68
  var de = {
63
69
  viewer: {
64
70
  regionLabel: "Fotoansicht",
@@ -125,23 +131,61 @@ var DEFAULT_I18N = {
125
131
  var I18nContext = createContext(DEFAULT_I18N);
126
132
  var mergeMessages = (base, overrides) => overrides ? {
127
133
  unknownDate: overrides.unknownDate ?? base.unknownDate,
128
- dateFilter: { ...base.dateFilter, ...overrides.dateFilter },
129
- viewer: { ...base.viewer, ...overrides.viewer },
130
- viewpointRole: { ...base.viewpointRole, ...overrides.viewpointRole },
134
+ dateFilter: {
135
+ ...base.dateFilter,
136
+ ...overrides.dateFilter
137
+ },
138
+ viewer: {
139
+ ...base.viewer,
140
+ ...overrides.viewer
141
+ },
142
+ viewpointRole: {
143
+ ...base.viewpointRole,
144
+ ...overrides.viewpointRole
145
+ },
131
146
  compass: overrides.compass?.length === 8 ? overrides.compass : base.compass,
132
147
  viewDirection: overrides.viewDirection ?? base.viewDirection
133
148
  } : base;
134
- var StreetImageryLocaleProvider = ({
135
- locale,
136
- messages,
137
- children
138
- }) => /* @__PURE__ */ jsx(
139
- I18nContext,
140
- {
141
- value: { locale, messages: mergeMessages(STREET_IMAGERY_MESSAGES[locale], messages) },
149
+ var StreetImageryLocaleProvider = (t0) => {
150
+ const $ = c(9);
151
+ const {
152
+ locale,
153
+ messages,
142
154
  children
155
+ } = t0;
156
+ const t1 = STREET_IMAGERY_MESSAGES[locale];
157
+ let t2;
158
+ if ($[0] !== messages || $[1] !== t1) {
159
+ t2 = mergeMessages(t1, messages);
160
+ $[0] = messages;
161
+ $[1] = t1;
162
+ $[2] = t2;
163
+ } else {
164
+ t2 = $[2];
165
+ }
166
+ let t3;
167
+ if ($[3] !== locale || $[4] !== t2) {
168
+ t3 = {
169
+ locale,
170
+ messages: t2
171
+ };
172
+ $[3] = locale;
173
+ $[4] = t2;
174
+ $[5] = t3;
175
+ } else {
176
+ t3 = $[5];
143
177
  }
144
- );
178
+ let t4;
179
+ if ($[6] !== children || $[7] !== t3) {
180
+ t4 = /* @__PURE__ */ jsx(I18nContext, { value: t3, children });
181
+ $[6] = children;
182
+ $[7] = t3;
183
+ $[8] = t4;
184
+ } else {
185
+ t4 = $[8];
186
+ }
187
+ return t4;
188
+ };
145
189
  var useStreetImageryI18n = () => use(I18nContext);
146
190
 
147
191
  export { STREET_IMAGERY_MESSAGES, StreetImageryLocaleProvider, useStreetImageryI18n };