@tileflow/react 0.1.0-alpha.16 → 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.
Files changed (2) hide show
  1. package/dist/index.js +86 -90
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -16,14 +16,18 @@ import {
16
16
  mergeTileflowAnalytics,
17
17
  normalizeTileflowCaptureId,
18
18
  normalizeTileflowStaticImageSize,
19
- resolveTileflowAnalyticsRequestUrl,
20
19
  resolveTileflowManifestMap,
21
20
  resolveTileflowMapMode,
22
21
  resolveTileflowRuntimeStyle,
23
22
  resolveTileflowStaticImageUrl,
24
- shouldLoadTileflowManifest,
25
- startTileflowSession
23
+ shouldLoadTileflowManifest
26
24
  } from "@tileflow/core";
25
+ import {
26
+ attachTileflowMapLifecycle,
27
+ createTileflowMarkerController,
28
+ createTileflowSessionStarter,
29
+ createTileflowTransformRequest
30
+ } from "@tileflow/core/browser";
27
31
  import { jsx } from "react/jsx-runtime";
28
32
  var defaultCenter = [0, 20];
29
33
  var defaultMarkers = [];
@@ -55,7 +59,6 @@ function Map({
55
59
  const containerRef = useRef(null);
56
60
  const imageRef = useRef(null);
57
61
  const mapRef = useRef(null);
58
- const markerInstancesRef = useRef([]);
59
62
  const stableMapOptions = useStableMapOptions(mapOptions);
60
63
  const resolvedCenter = useStableMapOptionValue(
61
64
  center ?? stableMapOptions?.center ?? defaultCenter
@@ -68,9 +71,29 @@ function Map({
68
71
  const onLoadRef = useRef(onLoad);
69
72
  const mapNameRef = useRef(mapName);
70
73
  const resolvedAnalyticsRef = useRef(void 0);
71
- const sessionStartsRef = useRef(/* @__PURE__ */ new Set());
72
74
  const readinessRunRef = useRef(0);
73
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
+ );
74
97
  const [manifestMap, setManifestMap] = useState(null);
75
98
  const [imageSize, setImageSize] = useState(null);
76
99
  const [captureState, setCaptureState] = useState("loading");
@@ -166,11 +189,13 @@ function Map({
166
189
  [imageSize, imageUrl, isImageMode, manifestMap, resolvedZoom, staticImageCenter]
167
190
  );
168
191
  const transformRequest = useMemo(
169
- () => createTransformRequest(
170
- () => resolvedAnalyticsRef.current,
192
+ () => createTileflowTransformRequest({
193
+ always: true,
194
+ asyncAnalyticsTiming: "resolution",
195
+ getAnalytics: () => resolvedAnalyticsRef.current,
171
196
  sessionId,
172
- stableMapOptions?.transformRequest
173
- ),
197
+ transformRequest: stableMapOptions?.transformRequest ?? void 0
198
+ }),
174
199
  [sessionId, stableMapOptions?.transformRequest]
175
200
  );
176
201
  useEffect(() => {
@@ -199,25 +224,8 @@ function Map({
199
224
  if (!containerRef.current || !runtimeStyle) {
200
225
  return;
201
226
  }
202
- const setLoading = () => {
203
- readinessRunRef.current += 1;
204
- setCaptureState("loading");
205
- };
206
- const setError = () => {
207
- readinessRunRef.current += 1;
208
- setCaptureState("error");
209
- };
210
- const setIdleAfterFrames = () => {
211
- const run = ++readinessRunRef.current;
212
- requestAnimationFrame(() => {
213
- requestAnimationFrame(() => {
214
- if (readinessRunRef.current === run && mapRef.current === map) {
215
- setCaptureState("idle");
216
- }
217
- });
218
- });
219
- };
220
- setLoading();
227
+ readinessRunRef.current += 1;
228
+ setCaptureState("loading");
221
229
  const map = new maplibregl.Map({
222
230
  ...stableMapOptions,
223
231
  container: containerRef.current,
@@ -237,36 +245,57 @@ function Map({
237
245
  map.resize();
238
246
  });
239
247
  resizeObserver.observe(containerRef.current);
240
- map.on("load", () => {
241
- const analyticsForLoad = resolvedAnalyticsRef.current;
242
- const styleId = analyticsForLoad?.styleId ?? (typeof runtimeStyle.style === "string" ? runtimeStyle.style : mapNameRef.current);
243
- onLoadRef.current?.(map);
244
- if (analyticsForLoad?.mapId) {
245
- const sessionKey = `${sessionId}:${analyticsForLoad.mapId}:${styleId ?? ""}`;
246
- if (!sessionStartsRef.current.has(sessionKey)) {
247
- sessionStartsRef.current.add(sessionKey);
248
- startTileflowSession(analyticsForLoad, {
249
- mapId: analyticsForLoad.mapId,
250
- sessionId,
251
- source: "react",
252
- styleId
253
- });
254
- }
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();
255
269
  }
256
270
  });
257
- map.on("dataloading", setLoading);
258
- map.on("styledataloading", setLoading);
259
- map.on("idle", setIdleAfterFrames);
260
- map.on("error", setError);
261
271
  return () => {
262
272
  readinessRunRef.current += 1;
263
- resizeObserver.disconnect();
264
- clearMarkers(markerInstancesRef.current);
265
- markerInstancesRef.current = [];
266
- map.remove();
267
- mapRef.current = null;
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
+ }
268
290
  };
269
- }, [resolvedInteractive, runtimeStyle, sessionId, stableMapOptions, transformRequest]);
291
+ }, [
292
+ markerController,
293
+ resolvedInteractive,
294
+ runtimeStyle,
295
+ sessionStarter,
296
+ stableMapOptions,
297
+ transformRequest
298
+ ]);
270
299
  useLayoutEffect(() => {
271
300
  if (!isImageMode) return;
272
301
  readinessRunRef.current += 1;
@@ -291,23 +320,15 @@ function Map({
291
320
  }
292
321
  useEffect(() => {
293
322
  const map = mapRef.current;
294
- clearMarkers(markerInstancesRef.current);
295
- markerInstancesRef.current = [];
323
+ markerController.clear();
296
324
  if (!map) {
297
325
  return;
298
326
  }
299
- markerInstancesRef.current = markers.map((marker) => {
300
- const markerInstance = new maplibregl.Marker({
301
- color: marker.color ?? "#C6A15B"
302
- }).setLngLat(marker.coordinates).addTo(map);
303
- markerInstance.getElement().title = marker.label ?? marker.id;
304
- return markerInstance;
305
- });
327
+ markerController.replace(map, markers);
306
328
  return () => {
307
- clearMarkers(markerInstancesRef.current);
308
- markerInstancesRef.current = [];
329
+ markerController.clear();
309
330
  };
310
- }, [markers, runtimeStyle]);
331
+ }, [markerController, markers, runtimeStyle]);
311
332
  const frameStyle = {
312
333
  height,
313
334
  minHeight: 240,
@@ -361,31 +382,6 @@ function Map({
361
382
  }
362
383
  );
363
384
  }
364
- function createTransformRequest(getAnalytics, sessionId, userTransformRequest) {
365
- return (url, resourceType) => {
366
- const request = userTransformRequest?.(url, resourceType);
367
- if (isPromiseLike(request)) {
368
- return request.then(
369
- (resolvedRequest) => applyTileflowAnalyticsRequest(url, resolvedRequest, getAnalytics(), sessionId) ?? resolvedRequest
370
- );
371
- }
372
- return applyTileflowAnalyticsRequest(url, request, getAnalytics(), sessionId);
373
- };
374
- }
375
- function applyTileflowAnalyticsRequest(url, request, analytics, sessionId) {
376
- const requestUrl = request?.url ?? url;
377
- const nextUrl = resolveTileflowAnalyticsRequestUrl(requestUrl, analytics, sessionId);
378
- if (!nextUrl) {
379
- return request;
380
- }
381
- return request ? { ...request, url: nextUrl } : { url: nextUrl };
382
- }
383
- function isPromiseLike(value) {
384
- return Boolean(value && typeof value.then === "function");
385
- }
386
- function clearMarkers(markerInstances) {
387
- markerInstances.forEach((marker) => marker.remove());
388
- }
389
385
  function useStableMapOptions(options) {
390
386
  return useStableMapOptionValue(options);
391
387
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/react",
3
- "version": "0.1.0-alpha.16",
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,
@@ -41,8 +41,8 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@tileflow/core": "0.1.0-alpha.16",
45
- "@tileflow/static": "0.1.0-alpha.16"
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",