@tileflow/vue 0.1.0-alpha.16 → 0.1.0-alpha.18

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 (3) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +72 -91
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -28,6 +28,10 @@ Tileflow resolves from the map name, manifest, or explicit style props. Direct
28
28
  Tileflow props such as `center`, `zoom`, and `interactive` take priority when
29
29
  provided.
30
30
 
31
+ Hosted maps automatically preflight a short-lived commercial session grant before eligible
32
+ resources. Setting `analytics` with `enabled: false` disables the optional beacon only; it does not
33
+ remove hosted authorization or override a user `mapOptions.transformRequest` callback.
34
+
31
35
  ## Headless capture readiness
32
36
 
33
37
  Pass `capture-id` when a page contains multiple copies of the same named map:
package/dist/index.js CHANGED
@@ -12,20 +12,24 @@ import {
12
12
  watch
13
13
  } from "vue";
14
14
  import {
15
- createTileflowSessionId,
15
+ createTileflowSessionController,
16
16
  defaultTileflowManifestUrl,
17
17
  loadTileflowManifest,
18
18
  mergeTileflowAnalytics,
19
19
  normalizeTileflowCaptureId,
20
20
  normalizeTileflowStaticImageSize,
21
- resolveTileflowAnalyticsRequestUrl,
22
21
  resolveTileflowManifestMap,
23
22
  resolveTileflowMapMode,
24
23
  resolveTileflowRuntimeStyle,
25
24
  resolveTileflowStaticImageUrl,
26
- shouldLoadTileflowManifest,
27
- startTileflowSession
25
+ shouldLoadTileflowManifest
28
26
  } from "@tileflow/core";
27
+ import {
28
+ attachTileflowMapLifecycle,
29
+ createTileflowMarkerController,
30
+ createTileflowSessionStarter,
31
+ createTileflowTransformRequest
32
+ } from "@tileflow/core/browser";
29
33
  var defaultCenter = [0, 20];
30
34
  var defaultZoom = 2;
31
35
  var TileflowMap = defineComponent({
@@ -88,10 +92,18 @@ var TileflowMap = defineComponent({
88
92
  const imageSize = shallowRef(null);
89
93
  const mapRef = shallowRef(null);
90
94
  const captureState = ref("loading");
91
- const sessionId = createTileflowSessionId();
92
- const markerInstances = [];
93
- const sessionStarts = /* @__PURE__ */ new Set();
95
+ const markerController = createTileflowMarkerController({
96
+ attach(markerInstance, map, marker) {
97
+ markerInstance.setLngLat(marker.coordinates).addTo(map);
98
+ markerInstance.getElement().title = marker.label ?? marker.id;
99
+ },
100
+ create: (marker) => new maplibregl.Marker({
101
+ color: marker.color ?? "#C6A15B"
102
+ }),
103
+ remove: (marker) => marker.remove()
104
+ });
94
105
  let imageResizeObserver = null;
106
+ let mapLifecycle = null;
95
107
  let mapResizeObserver = null;
96
108
  let manifestLoadId = 0;
97
109
  let readinessRunId = 0;
@@ -193,11 +205,25 @@ var TileflowMap = defineComponent({
193
205
  };
194
206
  const destroyMap = () => {
195
207
  readinessRunId += 1;
196
- mapResizeObserver?.disconnect();
208
+ const lifecycle = mapLifecycle;
209
+ const resizeObserver = mapResizeObserver;
210
+ const map = mapRef.value;
211
+ mapLifecycle = null;
197
212
  mapResizeObserver = null;
198
- clearMarkers(markerInstances);
199
- mapRef.value?.remove();
200
213
  mapRef.value = null;
214
+ try {
215
+ lifecycle?.dispose();
216
+ } finally {
217
+ try {
218
+ resizeObserver?.disconnect();
219
+ } finally {
220
+ try {
221
+ markerController.clear();
222
+ } finally {
223
+ map?.remove();
224
+ }
225
+ }
226
+ }
201
227
  };
202
228
  const recreateMap = () => {
203
229
  destroyMap();
@@ -206,6 +232,13 @@ var TileflowMap = defineComponent({
206
232
  return;
207
233
  }
208
234
  const runtime = runtimeStyle.value;
235
+ const analyticsForMap = resolvedAnalytics.value;
236
+ const session = createTileflowSessionController({ source: "vue" });
237
+ const sessionStarter = createTileflowSessionStarter({
238
+ getSessionId: () => session.sessionId,
239
+ sessionId: session.sessionId,
240
+ source: "vue"
241
+ });
209
242
  const map = new maplibregl.Map({
210
243
  ...props.mapOptions,
211
244
  attributionControl: props.mapOptions?.attributionControl ?? { compact: true },
@@ -213,11 +246,12 @@ var TileflowMap = defineComponent({
213
246
  container: containerRef.value,
214
247
  interactive: resolvedInteractive.value,
215
248
  style: runtime.style,
216
- transformRequest: createTransformRequest(
217
- resolvedAnalytics.value,
218
- sessionId,
219
- props.mapOptions?.transformRequest
220
- ),
249
+ transformRequest: createTileflowTransformRequest({
250
+ getAnalytics: () => analyticsForMap,
251
+ sessionController: session,
252
+ sessionId: session.sessionId,
253
+ transformRequest: props.mapOptions?.transformRequest ?? void 0
254
+ }),
221
255
  zoom: resolvedZoom.value
222
256
  });
223
257
  mapRef.value = map;
@@ -228,45 +262,29 @@ var TileflowMap = defineComponent({
228
262
  map.resize();
229
263
  });
230
264
  mapResizeObserver.observe(containerRef.value);
231
- map.on("load", () => {
232
- const analyticsForLoad = resolvedAnalytics.value;
233
- const styleId = analyticsForLoad?.styleId ?? (typeof runtime.style === "string" ? runtime.style : props.map);
234
- emit("load", map);
235
- if (analyticsForLoad?.mapId) {
236
- const sessionKey = `${sessionId}:${analyticsForLoad.mapId}:${styleId ?? ""}`;
237
- if (!sessionStarts.has(sessionKey)) {
238
- sessionStarts.add(sessionKey);
239
- startTileflowSession(analyticsForLoad, {
240
- mapId: analyticsForLoad.mapId,
241
- sessionId,
242
- source: "vue",
243
- styleId
244
- });
245
- }
265
+ mapLifecycle = attachTileflowMapLifecycle({
266
+ getSession: () => {
267
+ const analyticsForLoad = resolvedAnalytics.value;
268
+ return {
269
+ analytics: analyticsForLoad,
270
+ styleId: analyticsForLoad?.styleId ?? (typeof runtime.style === "string" ? runtime.style : props.map)
271
+ };
272
+ },
273
+ map,
274
+ onLoad: (loadedMap) => emit("load", loadedMap),
275
+ scheduler: {
276
+ cancelFrame: (frame) => cancelAnimationFrame(frame),
277
+ requestFrame: (callback) => requestAnimationFrame(callback)
278
+ },
279
+ sessionStarter,
280
+ setState: (state) => {
281
+ captureState.value = state;
282
+ },
283
+ subscribe: (subscribedMap, event, listener) => {
284
+ const subscription = subscribedMap.on(event, listener);
285
+ return () => subscription.unsubscribe();
246
286
  }
247
287
  });
248
- map.on("dataloading", () => {
249
- readinessRunId += 1;
250
- captureState.value = "loading";
251
- });
252
- map.on("styledataloading", () => {
253
- readinessRunId += 1;
254
- captureState.value = "loading";
255
- });
256
- map.on("idle", () => {
257
- const runId = ++readinessRunId;
258
- requestAnimationFrame(() => {
259
- requestAnimationFrame(() => {
260
- if (runId === readinessRunId && mapRef.value === map) {
261
- captureState.value = "idle";
262
- }
263
- });
264
- });
265
- });
266
- map.on("error", () => {
267
- readinessRunId += 1;
268
- captureState.value = "error";
269
- });
270
288
  syncMarkers();
271
289
  };
272
290
  const syncView = () => {
@@ -277,17 +295,11 @@ var TileflowMap = defineComponent({
277
295
  };
278
296
  const syncMarkers = () => {
279
297
  const map = mapRef.value;
280
- clearMarkers(markerInstances);
281
298
  if (!map) {
299
+ markerController.clear();
282
300
  return;
283
301
  }
284
- for (const marker of props.markers) {
285
- const markerInstance = new maplibregl.Marker({
286
- color: marker.color ?? "#C6A15B"
287
- }).setLngLat(marker.coordinates).addTo(map);
288
- markerInstance.getElement().title = marker.label ?? marker.id;
289
- markerInstances.push(markerInstance);
290
- }
302
+ markerController.replace(map, props.markers);
291
303
  };
292
304
  const markImageReady = async (image) => {
293
305
  const runId = ++readinessRunId;
@@ -421,40 +433,9 @@ var TileflowMap = defineComponent({
421
433
  }
422
434
  });
423
435
  var index_default = TileflowMap;
424
- function createTransformRequest(analytics, sessionId, userTransformRequest) {
425
- if ((!analytics || analytics.enabled === false) && !userTransformRequest) {
426
- return void 0;
427
- }
428
- return (url, resourceType) => {
429
- const request = userTransformRequest?.(url, resourceType);
430
- if (isPromiseLike(request)) {
431
- return request.then(
432
- (resolvedRequest) => applyTileflowAnalyticsRequest(url, resolvedRequest, analytics, sessionId) ?? resolvedRequest
433
- );
434
- }
435
- return applyTileflowAnalyticsRequest(url, request, analytics, sessionId);
436
- };
437
- }
438
- function applyTileflowAnalyticsRequest(url, request, analytics, sessionId) {
439
- const requestUrl = request?.url ?? url;
440
- const nextUrl = resolveTileflowAnalyticsRequestUrl(requestUrl, analytics, sessionId);
441
- if (!nextUrl) {
442
- return request;
443
- }
444
- return request ? { ...request, url: nextUrl } : { url: nextUrl };
445
- }
446
- function isPromiseLike(value) {
447
- return Boolean(value && typeof value.then === "function");
448
- }
449
436
  function formatHeight(height) {
450
437
  return typeof height === "number" ? `${height}px` : height;
451
438
  }
452
- function clearMarkers(markerInstances) {
453
- for (const marker of markerInstances) {
454
- marker.remove();
455
- }
456
- markerInstances.splice(0);
457
- }
458
439
  export {
459
440
  TileflowMap,
460
441
  index_default as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/vue",
3
- "version": "0.1.0-alpha.16",
3
+ "version": "0.1.0-alpha.18",
4
4
  "description": "Vue component for rendering Tileflow maps with MapLibre.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -36,7 +36,7 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@tileflow/core": "0.1.0-alpha.16"
39
+ "@tileflow/core": ">=0.1.0-alpha.18 <0.1.0-beta.0"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "maplibre-gl": ">=5",