@tileflow/react 0.1.0-alpha.14 → 0.1.0-alpha.17
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 +14 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +156 -80
- package/dist/static.d.ts +4 -3
- package/dist/static.js +40 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -55,4 +55,18 @@ the production image behavior locally.
|
|
|
55
55
|
For full static scenes with bounds, overlays, and server-side precache, use
|
|
56
56
|
`StaticMap` from `@tileflow/react/static` or helpers from `@tileflow/static`.
|
|
57
57
|
|
|
58
|
+
## Headless capture readiness
|
|
59
|
+
|
|
60
|
+
Use `captureId` to disambiguate multiple maps with the same configured name:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<Map map="madrid" captureId="checkout-map" />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The root element exposes `data-tileflow-map`, optional `data-tileflow-capture-id`, and
|
|
67
|
+
`data-tileflow-state="loading|idle|error"`. Interactive mode becomes idle after MapLibre is idle
|
|
68
|
+
and two animation frames; style/data work returns it to loading. Image mode waits for decode or a
|
|
69
|
+
successful load fallback, including cached hydration. `tileflow capture` uses these markers for
|
|
70
|
+
application scenes and requires exactly one target.
|
|
71
|
+
|
|
58
72
|
Docs: https://tileflow.dev/docs
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { TileflowConfig, MapLibreStyle, TileflowProjectThemes, TileflowMapMarker
|
|
|
6
6
|
type MapMarker = TileflowMapMarker;
|
|
7
7
|
type TileflowMapOptions = Omit<MapOptions, 'container' | 'style'>;
|
|
8
8
|
type MapProps = {
|
|
9
|
+
captureId?: string;
|
|
9
10
|
map?: string;
|
|
10
11
|
mode?: 'interactive' | 'image';
|
|
11
12
|
config?: TileflowConfig;
|
|
@@ -29,6 +30,6 @@ type MapProps = {
|
|
|
29
30
|
analytics?: TileflowAnalytics;
|
|
30
31
|
onLoad?: (map: Map$1) => void;
|
|
31
32
|
};
|
|
32
|
-
declare function Map({ map: mapName, mode, config, style, styleUrl, imageUrl, styleBaseUrl, tileBaseUrl, themes, manifestUrl, preferLocalDev, alt, center, zoom, className, height, imageLoading, interactive, mapOptions, markers, analytics, onLoad, }: MapProps): react.JSX.Element;
|
|
33
|
+
declare function Map({ captureId, map: mapName, mode, config, style, styleUrl, imageUrl, styleBaseUrl, tileBaseUrl, themes, manifestUrl, preferLocalDev, alt, center, zoom, className, height, imageLoading, interactive, mapOptions, markers, analytics, onLoad, }: MapProps): react.JSX.Element;
|
|
33
34
|
|
|
34
35
|
export { Map, type MapMarker, type MapProps, type TileflowMapOptions };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// src/map.tsx
|
|
4
4
|
import {
|
|
5
5
|
useEffect,
|
|
6
|
+
useLayoutEffect,
|
|
6
7
|
useMemo,
|
|
7
8
|
useRef,
|
|
8
9
|
useState
|
|
@@ -13,19 +14,25 @@ import {
|
|
|
13
14
|
defaultTileflowManifestUrl,
|
|
14
15
|
loadTileflowManifest,
|
|
15
16
|
mergeTileflowAnalytics,
|
|
17
|
+
normalizeTileflowCaptureId,
|
|
16
18
|
normalizeTileflowStaticImageSize,
|
|
17
|
-
resolveTileflowAnalyticsRequestUrl,
|
|
18
19
|
resolveTileflowManifestMap,
|
|
19
20
|
resolveTileflowMapMode,
|
|
20
21
|
resolveTileflowRuntimeStyle,
|
|
21
22
|
resolveTileflowStaticImageUrl,
|
|
22
|
-
shouldLoadTileflowManifest
|
|
23
|
-
startTileflowSession
|
|
23
|
+
shouldLoadTileflowManifest
|
|
24
24
|
} from "@tileflow/core";
|
|
25
|
+
import {
|
|
26
|
+
attachTileflowMapLifecycle,
|
|
27
|
+
createTileflowMarkerController,
|
|
28
|
+
createTileflowSessionStarter,
|
|
29
|
+
createTileflowTransformRequest
|
|
30
|
+
} from "@tileflow/core/browser";
|
|
25
31
|
import { jsx } from "react/jsx-runtime";
|
|
26
32
|
var defaultCenter = [0, 20];
|
|
27
33
|
var defaultMarkers = [];
|
|
28
34
|
function Map({
|
|
35
|
+
captureId,
|
|
29
36
|
map: mapName,
|
|
30
37
|
mode = "interactive",
|
|
31
38
|
config,
|
|
@@ -50,8 +57,8 @@ function Map({
|
|
|
50
57
|
onLoad
|
|
51
58
|
}) {
|
|
52
59
|
const containerRef = useRef(null);
|
|
60
|
+
const imageRef = useRef(null);
|
|
53
61
|
const mapRef = useRef(null);
|
|
54
|
-
const markerInstancesRef = useRef([]);
|
|
55
62
|
const stableMapOptions = useStableMapOptions(mapOptions);
|
|
56
63
|
const resolvedCenter = useStableMapOptionValue(
|
|
57
64
|
center ?? stableMapOptions?.center ?? defaultCenter
|
|
@@ -64,10 +71,33 @@ function Map({
|
|
|
64
71
|
const onLoadRef = useRef(onLoad);
|
|
65
72
|
const mapNameRef = useRef(mapName);
|
|
66
73
|
const resolvedAnalyticsRef = useRef(void 0);
|
|
67
|
-
const
|
|
74
|
+
const readinessRunRef = useRef(0);
|
|
68
75
|
const sessionId = useMemo(() => createTileflowSessionId(), []);
|
|
76
|
+
const sessionStarter = useMemo(
|
|
77
|
+
() => createTileflowSessionStarter({ sessionId, source: "react" }),
|
|
78
|
+
[sessionId]
|
|
79
|
+
);
|
|
80
|
+
const markerController = useMemo(
|
|
81
|
+
() => createTileflowMarkerController({
|
|
82
|
+
attach(markerInstance, map, marker) {
|
|
83
|
+
markerInstance.setLngLat(marker.coordinates).addTo(map);
|
|
84
|
+
markerInstance.getElement().title = marker.label ?? marker.id;
|
|
85
|
+
},
|
|
86
|
+
create(marker) {
|
|
87
|
+
return new maplibregl.Marker({
|
|
88
|
+
color: marker.color ?? "#C6A15B"
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
remove(markerInstance) {
|
|
92
|
+
markerInstance.remove();
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
[]
|
|
96
|
+
);
|
|
69
97
|
const [manifestMap, setManifestMap] = useState(null);
|
|
70
98
|
const [imageSize, setImageSize] = useState(null);
|
|
99
|
+
const [captureState, setCaptureState] = useState("loading");
|
|
100
|
+
const resolvedCaptureId = normalizeTileflowCaptureId(captureId);
|
|
71
101
|
const resolvedMode = resolveTileflowMapMode({ imageUrl, mode, preferLocalDev });
|
|
72
102
|
const isImageMode = resolvedMode === "image";
|
|
73
103
|
useEffect(() => {
|
|
@@ -159,11 +189,13 @@ function Map({
|
|
|
159
189
|
[imageSize, imageUrl, isImageMode, manifestMap, resolvedZoom, staticImageCenter]
|
|
160
190
|
);
|
|
161
191
|
const transformRequest = useMemo(
|
|
162
|
-
() =>
|
|
163
|
-
|
|
192
|
+
() => createTileflowTransformRequest({
|
|
193
|
+
always: true,
|
|
194
|
+
asyncAnalyticsTiming: "resolution",
|
|
195
|
+
getAnalytics: () => resolvedAnalyticsRef.current,
|
|
164
196
|
sessionId,
|
|
165
|
-
stableMapOptions?.transformRequest
|
|
166
|
-
),
|
|
197
|
+
transformRequest: stableMapOptions?.transformRequest ?? void 0
|
|
198
|
+
}),
|
|
167
199
|
[sessionId, stableMapOptions?.transformRequest]
|
|
168
200
|
);
|
|
169
201
|
useEffect(() => {
|
|
@@ -192,6 +224,8 @@ function Map({
|
|
|
192
224
|
if (!containerRef.current || !runtimeStyle) {
|
|
193
225
|
return;
|
|
194
226
|
}
|
|
227
|
+
readinessRunRef.current += 1;
|
|
228
|
+
setCaptureState("loading");
|
|
195
229
|
const map = new maplibregl.Map({
|
|
196
230
|
...stableMapOptions,
|
|
197
231
|
container: containerRef.current,
|
|
@@ -211,50 +245,90 @@ function Map({
|
|
|
211
245
|
map.resize();
|
|
212
246
|
});
|
|
213
247
|
resizeObserver.observe(containerRef.current);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
248
|
+
const lifecycle = attachTileflowMapLifecycle({
|
|
249
|
+
getSession: () => {
|
|
250
|
+
const analyticsForLoad = resolvedAnalyticsRef.current;
|
|
251
|
+
return {
|
|
252
|
+
analytics: analyticsForLoad,
|
|
253
|
+
styleId: analyticsForLoad?.styleId ?? (typeof runtimeStyle.style === "string" ? runtimeStyle.style : mapNameRef.current)
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
map,
|
|
257
|
+
onLoad: (loadedMap) => {
|
|
258
|
+
onLoadRef.current?.(loadedMap);
|
|
259
|
+
},
|
|
260
|
+
scheduler: {
|
|
261
|
+
cancelFrame: (frame) => cancelAnimationFrame(frame),
|
|
262
|
+
requestFrame: (callback) => requestAnimationFrame(callback)
|
|
263
|
+
},
|
|
264
|
+
sessionStarter,
|
|
265
|
+
setState: setCaptureState,
|
|
266
|
+
subscribe: (subscribedMap, event, listener) => {
|
|
267
|
+
const subscription = subscribedMap.on(event, listener);
|
|
268
|
+
return () => subscription.unsubscribe();
|
|
229
269
|
}
|
|
230
270
|
});
|
|
231
271
|
return () => {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
272
|
+
readinessRunRef.current += 1;
|
|
273
|
+
try {
|
|
274
|
+
lifecycle.dispose();
|
|
275
|
+
} finally {
|
|
276
|
+
try {
|
|
277
|
+
resizeObserver.disconnect();
|
|
278
|
+
} finally {
|
|
279
|
+
try {
|
|
280
|
+
markerController.clear();
|
|
281
|
+
} finally {
|
|
282
|
+
try {
|
|
283
|
+
map.remove();
|
|
284
|
+
} finally {
|
|
285
|
+
if (mapRef.current === map) mapRef.current = null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
237
290
|
};
|
|
238
|
-
}, [
|
|
291
|
+
}, [
|
|
292
|
+
markerController,
|
|
293
|
+
resolvedInteractive,
|
|
294
|
+
runtimeStyle,
|
|
295
|
+
sessionStarter,
|
|
296
|
+
stableMapOptions,
|
|
297
|
+
transformRequest
|
|
298
|
+
]);
|
|
299
|
+
useLayoutEffect(() => {
|
|
300
|
+
if (!isImageMode) return;
|
|
301
|
+
readinessRunRef.current += 1;
|
|
302
|
+
setCaptureState("loading");
|
|
303
|
+
const image = imageRef.current;
|
|
304
|
+
if (image?.complete) {
|
|
305
|
+
if (image.naturalWidth === 0) setCaptureState("error");
|
|
306
|
+
else void markImageReady(image);
|
|
307
|
+
}
|
|
308
|
+
}, [isImageMode, runtimeImageUrl]);
|
|
309
|
+
async function markImageReady(image) {
|
|
310
|
+
const run = ++readinessRunRef.current;
|
|
311
|
+
try {
|
|
312
|
+
if (typeof image.decode === "function") await image.decode();
|
|
313
|
+
} catch {
|
|
314
|
+
if (!image.complete || image.naturalWidth === 0) {
|
|
315
|
+
if (readinessRunRef.current === run) setCaptureState("error");
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (readinessRunRef.current === run) setCaptureState("idle");
|
|
320
|
+
}
|
|
239
321
|
useEffect(() => {
|
|
240
322
|
const map = mapRef.current;
|
|
241
|
-
|
|
242
|
-
markerInstancesRef.current = [];
|
|
323
|
+
markerController.clear();
|
|
243
324
|
if (!map) {
|
|
244
325
|
return;
|
|
245
326
|
}
|
|
246
|
-
|
|
247
|
-
const markerInstance = new maplibregl.Marker({
|
|
248
|
-
color: marker.color ?? "#C6A15B"
|
|
249
|
-
}).setLngLat(marker.coordinates).addTo(map);
|
|
250
|
-
markerInstance.getElement().title = marker.label ?? marker.id;
|
|
251
|
-
return markerInstance;
|
|
252
|
-
});
|
|
327
|
+
markerController.replace(map, markers);
|
|
253
328
|
return () => {
|
|
254
|
-
|
|
255
|
-
markerInstancesRef.current = [];
|
|
329
|
+
markerController.clear();
|
|
256
330
|
};
|
|
257
|
-
}, [markers, runtimeStyle]);
|
|
331
|
+
}, [markerController, markers, runtimeStyle]);
|
|
258
332
|
const frameStyle = {
|
|
259
333
|
height,
|
|
260
334
|
minHeight: 240,
|
|
@@ -263,48 +337,50 @@ function Map({
|
|
|
263
337
|
width: "100%"
|
|
264
338
|
};
|
|
265
339
|
if (isImageMode) {
|
|
266
|
-
return /* @__PURE__ */ jsx(
|
|
267
|
-
"
|
|
340
|
+
return /* @__PURE__ */ jsx(
|
|
341
|
+
"div",
|
|
268
342
|
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
343
|
+
className,
|
|
344
|
+
"data-tileflow-capture-id": resolvedCaptureId,
|
|
345
|
+
"data-tileflow-map": mapName,
|
|
346
|
+
"data-tileflow-state": captureState,
|
|
347
|
+
ref: containerRef,
|
|
348
|
+
style: frameStyle,
|
|
349
|
+
children: runtimeImageUrl ? /* @__PURE__ */ jsx(
|
|
350
|
+
"img",
|
|
351
|
+
{
|
|
352
|
+
alt,
|
|
353
|
+
decoding: "async",
|
|
354
|
+
loading: imageLoading,
|
|
355
|
+
onError: () => {
|
|
356
|
+
readinessRunRef.current += 1;
|
|
357
|
+
setCaptureState("error");
|
|
358
|
+
},
|
|
359
|
+
onLoad: (event) => void markImageReady(event.currentTarget),
|
|
360
|
+
ref: imageRef,
|
|
361
|
+
src: runtimeImageUrl,
|
|
362
|
+
style: {
|
|
363
|
+
display: "block",
|
|
364
|
+
height: "100%",
|
|
365
|
+
objectFit: "cover",
|
|
366
|
+
width: "100%"
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
) : null
|
|
279
370
|
}
|
|
280
|
-
)
|
|
371
|
+
);
|
|
281
372
|
}
|
|
282
|
-
return /* @__PURE__ */ jsx(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
373
|
+
return /* @__PURE__ */ jsx(
|
|
374
|
+
"div",
|
|
375
|
+
{
|
|
376
|
+
className,
|
|
377
|
+
"data-tileflow-capture-id": resolvedCaptureId,
|
|
378
|
+
"data-tileflow-map": mapName,
|
|
379
|
+
"data-tileflow-state": captureState,
|
|
380
|
+
ref: containerRef,
|
|
381
|
+
style: frameStyle
|
|
291
382
|
}
|
|
292
|
-
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
function applyTileflowAnalyticsRequest(url, request, analytics, sessionId) {
|
|
296
|
-
const requestUrl = request?.url ?? url;
|
|
297
|
-
const nextUrl = resolveTileflowAnalyticsRequestUrl(requestUrl, analytics, sessionId);
|
|
298
|
-
if (!nextUrl) {
|
|
299
|
-
return request;
|
|
300
|
-
}
|
|
301
|
-
return request ? { ...request, url: nextUrl } : { url: nextUrl };
|
|
302
|
-
}
|
|
303
|
-
function isPromiseLike(value) {
|
|
304
|
-
return Boolean(value && typeof value.then === "function");
|
|
305
|
-
}
|
|
306
|
-
function clearMarkers(markerInstances) {
|
|
307
|
-
markerInstances.forEach((marker) => marker.remove());
|
|
383
|
+
);
|
|
308
384
|
}
|
|
309
385
|
function useStableMapOptions(options) {
|
|
310
386
|
return useStableMapOptionValue(options);
|
package/dist/static.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ import { StaticSceneInput, StaticMapResult } from '@tileflow/static';
|
|
|
5
5
|
type StaticMapBaseProps = StaticSceneInput & {
|
|
6
6
|
alt?: string;
|
|
7
7
|
className?: string;
|
|
8
|
+
captureId?: string;
|
|
8
9
|
imageStyle?: CSSProperties;
|
|
9
10
|
keepPreviousImage?: boolean;
|
|
10
|
-
loading?: ImgHTMLAttributes<HTMLImageElement>[
|
|
11
|
+
loading?: ImgHTMLAttributes<HTMLImageElement>['loading'];
|
|
11
12
|
onError?: (error: Error) => void;
|
|
12
|
-
onImageLoad?: ImgHTMLAttributes<HTMLImageElement>[
|
|
13
|
+
onImageLoad?: ImgHTMLAttributes<HTMLImageElement>['onLoad'];
|
|
13
14
|
onReady?: (result: StaticMapResult) => void;
|
|
14
15
|
style?: CSSProperties;
|
|
15
16
|
};
|
|
@@ -22,6 +23,6 @@ type StaticMapCreateProps = {
|
|
|
22
23
|
imageUrl?: never;
|
|
23
24
|
};
|
|
24
25
|
type StaticMapProps = StaticMapBaseProps & (StaticMapCreateProps | StaticMapImageProps);
|
|
25
|
-
declare function StaticMap({ alt, camera, className, createUrl, imageStyle, imageUrl, keepPreviousImage, loading, map, onError, onImageLoad, onReady, overlays, size, style, }: StaticMapProps): react.JSX.Element;
|
|
26
|
+
declare function StaticMap({ alt, camera, className, captureId, createUrl, imageStyle, imageUrl, keepPreviousImage, loading, map, onError, onImageLoad, onReady, overlays, size, style, }: StaticMapProps): react.JSX.Element;
|
|
26
27
|
|
|
27
28
|
export { StaticMap, type StaticMapProps };
|
package/dist/static.js
CHANGED
|
@@ -3,16 +3,19 @@
|
|
|
3
3
|
// src/static-map.tsx
|
|
4
4
|
import {
|
|
5
5
|
useEffect,
|
|
6
|
+
useLayoutEffect,
|
|
6
7
|
useMemo,
|
|
7
8
|
useRef,
|
|
8
9
|
useState
|
|
9
10
|
} from "react";
|
|
11
|
+
import { normalizeTileflowCaptureId } from "@tileflow/core";
|
|
10
12
|
import { jsx } from "react/jsx-runtime";
|
|
11
13
|
var inFlightRequests = /* @__PURE__ */ new Map();
|
|
12
14
|
function StaticMap({
|
|
13
15
|
alt = "",
|
|
14
16
|
camera,
|
|
15
17
|
className,
|
|
18
|
+
captureId,
|
|
16
19
|
createUrl,
|
|
17
20
|
imageStyle,
|
|
18
21
|
imageUrl,
|
|
@@ -30,6 +33,10 @@ function StaticMap({
|
|
|
30
33
|
imageUrl ? imageResult(imageUrl) : null
|
|
31
34
|
);
|
|
32
35
|
const [error, setError] = useState(null);
|
|
36
|
+
const [captureState, setCaptureState] = useState("loading");
|
|
37
|
+
const imageLoadRunRef = useRef(0);
|
|
38
|
+
const imageRef = useRef(null);
|
|
39
|
+
const resolvedCaptureId = normalizeTileflowCaptureId(captureId);
|
|
33
40
|
const onErrorRef = useRef(onError);
|
|
34
41
|
const onReadyRef = useRef(onReady);
|
|
35
42
|
const sceneKey = useMemo(
|
|
@@ -37,6 +44,27 @@ function StaticMap({
|
|
|
37
44
|
[camera, map, overlays, size]
|
|
38
45
|
);
|
|
39
46
|
const requestKey = imageUrl ? `image:${imageUrl}` : `create:${createUrl}:${sceneKey}`;
|
|
47
|
+
useLayoutEffect(() => {
|
|
48
|
+
imageLoadRunRef.current += 1;
|
|
49
|
+
setCaptureState("loading");
|
|
50
|
+
const image = imageRef.current;
|
|
51
|
+
if (image?.complete) {
|
|
52
|
+
if (image.naturalWidth === 0) setCaptureState("error");
|
|
53
|
+
else void markImageReady(image);
|
|
54
|
+
}
|
|
55
|
+
}, [requestKey]);
|
|
56
|
+
async function markImageReady(image) {
|
|
57
|
+
const runId = ++imageLoadRunRef.current;
|
|
58
|
+
try {
|
|
59
|
+
if (typeof image.decode === "function") await image.decode();
|
|
60
|
+
} catch {
|
|
61
|
+
if (!image.complete || image.naturalWidth === 0) {
|
|
62
|
+
if (runId === imageLoadRunRef.current) setCaptureState("error");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (runId === imageLoadRunRef.current) setCaptureState("idle");
|
|
67
|
+
}
|
|
40
68
|
useEffect(() => {
|
|
41
69
|
onErrorRef.current = onError;
|
|
42
70
|
onReadyRef.current = onReady;
|
|
@@ -77,6 +105,8 @@ function StaticMap({
|
|
|
77
105
|
setResult(null);
|
|
78
106
|
}
|
|
79
107
|
setError(normalizedError);
|
|
108
|
+
imageLoadRunRef.current += 1;
|
|
109
|
+
setCaptureState("error");
|
|
80
110
|
onErrorRef.current?.(normalizedError);
|
|
81
111
|
});
|
|
82
112
|
return () => {
|
|
@@ -88,6 +118,9 @@ function StaticMap({
|
|
|
88
118
|
{
|
|
89
119
|
"aria-busy": !result && !error,
|
|
90
120
|
className,
|
|
121
|
+
"data-tileflow-capture-id": resolvedCaptureId,
|
|
122
|
+
"data-tileflow-map": map,
|
|
123
|
+
"data-tileflow-state": captureState,
|
|
91
124
|
style: {
|
|
92
125
|
aspectRatio: `${size.width} / ${size.height}`,
|
|
93
126
|
background: "#f4f4f2",
|
|
@@ -104,9 +137,15 @@ function StaticMap({
|
|
|
104
137
|
onError: () => {
|
|
105
138
|
const imageError = new Error("Static map image failed to load");
|
|
106
139
|
setError(imageError);
|
|
140
|
+
imageLoadRunRef.current += 1;
|
|
141
|
+
setCaptureState("error");
|
|
107
142
|
onErrorRef.current?.(imageError);
|
|
108
143
|
},
|
|
109
|
-
onLoad:
|
|
144
|
+
onLoad: (event) => {
|
|
145
|
+
onImageLoad?.(event);
|
|
146
|
+
void markImageReady(event.currentTarget);
|
|
147
|
+
},
|
|
148
|
+
ref: imageRef,
|
|
110
149
|
src: result.imageUrl,
|
|
111
150
|
style: {
|
|
112
151
|
display: "block",
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/react",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.17",
|
|
4
4
|
"description": "React components for rendering Tileflow maps with MapLibre.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"homepage": "https://tileflow.dev",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/tileflow/tileflow.git",
|
|
10
|
+
"url": "git+https://github.com/tileflow/tileflow-sdk.git",
|
|
11
11
|
"directory": "packages/react"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://github.com/tileflow/tileflow/issues"
|
|
14
|
+
"url": "https://github.com/tileflow/tileflow-sdk/issues"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
17
17
|
"tileflow",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@tileflow/core": "0.1.0-alpha.
|
|
45
|
-
"@tileflow/static": "0.1.0-alpha.
|
|
44
|
+
"@tileflow/core": ">=0.1.0-alpha.17 <0.1.0-beta.0",
|
|
45
|
+
"@tileflow/static": ">=0.1.0-alpha.16 <0.1.0-beta.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"maplibre-gl": ">=5",
|