@tileflow/vue 0.1.0-alpha.14 → 0.1.0-alpha.16
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 +13 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +72 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -28,4 +28,17 @@ 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
|
+
## Headless capture readiness
|
|
32
|
+
|
|
33
|
+
Pass `capture-id` when a page contains multiple copies of the same named map:
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<TileflowMap map="madrid" capture-id="checkout-map" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The root exposes `data-tileflow-map`, optional `data-tileflow-capture-id`, and
|
|
40
|
+
`data-tileflow-state="loading|idle|error"`. It becomes idle only after MapLibre idle plus two
|
|
41
|
+
animation frames (or image decode/load in image mode), returns to loading for new style/data work,
|
|
42
|
+
and marks terminal load errors. Application capture selects exactly one ready target.
|
|
43
|
+
|
|
31
44
|
Docs: https://tileflow.dev/docs
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ type TileflowMapProps = {
|
|
|
9
9
|
alt?: string;
|
|
10
10
|
analytics?: TileflowAnalytics;
|
|
11
11
|
center?: [number, number];
|
|
12
|
+
captureId?: string;
|
|
12
13
|
className?: string;
|
|
13
14
|
config?: TileflowConfig;
|
|
14
15
|
height?: number | string;
|
|
@@ -35,6 +36,7 @@ declare const TileflowMap: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
35
36
|
};
|
|
36
37
|
analytics: PropType<TileflowAnalytics>;
|
|
37
38
|
center: PropType<[number, number]>;
|
|
39
|
+
captureId: StringConstructor;
|
|
38
40
|
className: StringConstructor;
|
|
39
41
|
config: PropType<TileflowConfig>;
|
|
40
42
|
height: {
|
|
@@ -85,6 +87,7 @@ declare const TileflowMap: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
85
87
|
};
|
|
86
88
|
analytics: PropType<TileflowAnalytics>;
|
|
87
89
|
center: PropType<[number, number]>;
|
|
90
|
+
captureId: StringConstructor;
|
|
88
91
|
className: StringConstructor;
|
|
89
92
|
config: PropType<TileflowConfig>;
|
|
90
93
|
height: {
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
computed,
|
|
5
5
|
defineComponent,
|
|
6
6
|
h,
|
|
7
|
+
nextTick,
|
|
7
8
|
onBeforeUnmount,
|
|
8
9
|
onMounted,
|
|
9
10
|
ref,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
defaultTileflowManifestUrl,
|
|
16
17
|
loadTileflowManifest,
|
|
17
18
|
mergeTileflowAnalytics,
|
|
19
|
+
normalizeTileflowCaptureId,
|
|
18
20
|
normalizeTileflowStaticImageSize,
|
|
19
21
|
resolveTileflowAnalyticsRequestUrl,
|
|
20
22
|
resolveTileflowManifestMap,
|
|
@@ -36,6 +38,7 @@ var TileflowMap = defineComponent({
|
|
|
36
38
|
},
|
|
37
39
|
analytics: Object,
|
|
38
40
|
center: Array,
|
|
41
|
+
captureId: String,
|
|
39
42
|
className: String,
|
|
40
43
|
config: Object,
|
|
41
44
|
height: {
|
|
@@ -84,12 +87,14 @@ var TileflowMap = defineComponent({
|
|
|
84
87
|
const manifestMap = shallowRef(null);
|
|
85
88
|
const imageSize = shallowRef(null);
|
|
86
89
|
const mapRef = shallowRef(null);
|
|
90
|
+
const captureState = ref("loading");
|
|
87
91
|
const sessionId = createTileflowSessionId();
|
|
88
92
|
const markerInstances = [];
|
|
89
93
|
const sessionStarts = /* @__PURE__ */ new Set();
|
|
90
94
|
let imageResizeObserver = null;
|
|
91
95
|
let mapResizeObserver = null;
|
|
92
96
|
let manifestLoadId = 0;
|
|
97
|
+
let readinessRunId = 0;
|
|
93
98
|
const resolvedMode = computed(
|
|
94
99
|
() => resolveTileflowMapMode({
|
|
95
100
|
imageUrl: props.imageUrl,
|
|
@@ -138,6 +143,7 @@ var TileflowMap = defineComponent({
|
|
|
138
143
|
position: "relative",
|
|
139
144
|
width: "100%"
|
|
140
145
|
}));
|
|
146
|
+
const resolvedCaptureId = computed(() => normalizeTileflowCaptureId(props.captureId));
|
|
141
147
|
const refreshManifest = async () => {
|
|
142
148
|
const shouldLoad = shouldLoadTileflowManifest({
|
|
143
149
|
config: props.config,
|
|
@@ -186,6 +192,7 @@ var TileflowMap = defineComponent({
|
|
|
186
192
|
updateImageSize();
|
|
187
193
|
};
|
|
188
194
|
const destroyMap = () => {
|
|
195
|
+
readinessRunId += 1;
|
|
189
196
|
mapResizeObserver?.disconnect();
|
|
190
197
|
mapResizeObserver = null;
|
|
191
198
|
clearMarkers(markerInstances);
|
|
@@ -194,6 +201,7 @@ var TileflowMap = defineComponent({
|
|
|
194
201
|
};
|
|
195
202
|
const recreateMap = () => {
|
|
196
203
|
destroyMap();
|
|
204
|
+
captureState.value = "loading";
|
|
197
205
|
if (!containerRef.value || !runtimeStyle.value || isImageMode.value) {
|
|
198
206
|
return;
|
|
199
207
|
}
|
|
@@ -237,6 +245,28 @@ var TileflowMap = defineComponent({
|
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
247
|
});
|
|
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
|
+
});
|
|
240
270
|
syncMarkers();
|
|
241
271
|
};
|
|
242
272
|
const syncView = () => {
|
|
@@ -259,10 +289,37 @@ var TileflowMap = defineComponent({
|
|
|
259
289
|
markerInstances.push(markerInstance);
|
|
260
290
|
}
|
|
261
291
|
};
|
|
292
|
+
const markImageReady = async (image) => {
|
|
293
|
+
const runId = ++readinessRunId;
|
|
294
|
+
try {
|
|
295
|
+
if (typeof image.decode === "function") await image.decode();
|
|
296
|
+
} catch {
|
|
297
|
+
if (!image.complete || image.naturalWidth === 0) {
|
|
298
|
+
if (runId === readinessRunId) captureState.value = "error";
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (runId === readinessRunId) captureState.value = "idle";
|
|
303
|
+
};
|
|
304
|
+
const resetImageReadiness = async () => {
|
|
305
|
+
if (!isImageMode.value) return;
|
|
306
|
+
const runId = ++readinessRunId;
|
|
307
|
+
captureState.value = "loading";
|
|
308
|
+
await nextTick();
|
|
309
|
+
if (runId !== readinessRunId) return;
|
|
310
|
+
const image = containerRef.value?.querySelector("img");
|
|
311
|
+
if (!image?.complete) return;
|
|
312
|
+
if (image.naturalWidth === 0) {
|
|
313
|
+
captureState.value = "error";
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
await markImageReady(image);
|
|
317
|
+
};
|
|
262
318
|
onMounted(() => {
|
|
263
319
|
void refreshManifest();
|
|
264
320
|
updateImageResizeObserver();
|
|
265
321
|
recreateMap();
|
|
322
|
+
void resetImageReadiness();
|
|
266
323
|
});
|
|
267
324
|
onBeforeUnmount(() => {
|
|
268
325
|
imageResizeObserver?.disconnect();
|
|
@@ -284,6 +341,13 @@ var TileflowMap = defineComponent({
|
|
|
284
341
|
void refreshManifest();
|
|
285
342
|
}
|
|
286
343
|
);
|
|
344
|
+
watch(
|
|
345
|
+
() => [isImageMode.value, runtimeImageUrl.value],
|
|
346
|
+
() => {
|
|
347
|
+
void resetImageReadiness();
|
|
348
|
+
},
|
|
349
|
+
{ flush: "post" }
|
|
350
|
+
);
|
|
287
351
|
watch(
|
|
288
352
|
() => [props.imageUrl, props.mode, props.preferLocalDev],
|
|
289
353
|
() => updateImageResizeObserver(),
|
|
@@ -329,6 +393,9 @@ var TileflowMap = defineComponent({
|
|
|
329
393
|
{
|
|
330
394
|
...rootAttrs,
|
|
331
395
|
class: classValue,
|
|
396
|
+
"data-tileflow-capture-id": resolvedCaptureId.value,
|
|
397
|
+
"data-tileflow-map": props.map,
|
|
398
|
+
"data-tileflow-state": captureState.value,
|
|
332
399
|
ref: containerRef,
|
|
333
400
|
style: styleValue
|
|
334
401
|
},
|
|
@@ -336,6 +403,11 @@ var TileflowMap = defineComponent({
|
|
|
336
403
|
alt: props.alt,
|
|
337
404
|
decoding: "async",
|
|
338
405
|
loading: props.imageLoading,
|
|
406
|
+
onError: () => {
|
|
407
|
+
readinessRunId += 1;
|
|
408
|
+
captureState.value = "error";
|
|
409
|
+
},
|
|
410
|
+
onLoad: (event) => void markImageReady(event.currentTarget),
|
|
339
411
|
src: runtimeImageUrl.value,
|
|
340
412
|
style: {
|
|
341
413
|
display: "block",
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/vue",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.16",
|
|
4
4
|
"description": "Vue component 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/vue"
|
|
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",
|
|
@@ -36,18 +36,22 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@tileflow/core": "0.1.0-alpha.
|
|
39
|
+
"@tileflow/core": "0.1.0-alpha.16"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"maplibre-gl": ">=5",
|
|
43
43
|
"vue": ">=3.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
+
"@vue/server-renderer": "3.5.39",
|
|
46
47
|
"maplibre-gl": "^5.24.0",
|
|
48
|
+
"tsx": "^4.23.1",
|
|
47
49
|
"vue": "^3.5.26"
|
|
48
50
|
},
|
|
49
51
|
"scripts": {
|
|
50
52
|
"build": "tsup src/index.ts --format esm --dts --clean --external vue --external maplibre-gl",
|
|
53
|
+
"test": "tsx --test test/*.test.ts",
|
|
54
|
+
"verify": "pnpm run build && pnpm run test",
|
|
51
55
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
52
56
|
"lint": "tsc -p tsconfig.json --noEmit"
|
|
53
57
|
}
|