@tileflow/vue 0.1.0-alpha.34 → 0.1.0-alpha.36
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 +27 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +77 -8
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -16,6 +16,12 @@ npm install @tileflow/vue@alpha @tileflow/core@alpha @tileflow/maps@alpha "mapli
|
|
|
16
16
|
npm install --save-dev --save-exact tileflow@alpha
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
Prepared styles may retain relative asset URLs. The component loads them through Core's shared
|
|
20
|
+
resource loader before creating the map and before changing or blending themes. Sprites, fonts,
|
|
21
|
+
data and model resources resolve against their declaring documents. Pending document loads are
|
|
22
|
+
cancelled when the map is replaced or unmounted; `mapOptions.transformRequest` also applies to
|
|
23
|
+
style and HTTP TileJSON requests.
|
|
24
|
+
|
|
19
25
|
## Prepare a map
|
|
20
26
|
|
|
21
27
|
Create `tileflow.config.ts` at the application root:
|
|
@@ -92,7 +98,7 @@ Add `time-of-day="dusk"` beside `theme` to select a map's optional `day`, `dawn`
|
|
|
92
98
|
`night` preset. For Streets, `theme="light"` with this preset selects the existing `dusk` palette.
|
|
93
99
|
Maps without this capability ignore the option; omitting it keeps the selected theme unchanged.
|
|
94
100
|
Changing it uses the existing theme transition. `themeBlend` takes precedence. See the
|
|
95
|
-
[authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/
|
|
101
|
+
[authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/REFERENCE.md#style-with-themes-and-semantic-modules).
|
|
96
102
|
|
|
97
103
|
Theme and `time-of-day` changes cross-fade over 450 ms by default, respecting reduced motion.
|
|
98
104
|
`:theme-transition="{duration: 700}"` customizes the duration; use `duration: 0` for an immediate change.
|
|
@@ -185,6 +191,26 @@ reconcile without recreating MapLibre. Text/field descriptors render as text; `v
|
|
|
185
191
|
an application slot and never evaluates HTML. Tooltips must remain non-interactive; use a popup for
|
|
186
192
|
links, buttons, or forms.
|
|
187
193
|
|
|
194
|
+
## Cluster points and draw density
|
|
195
|
+
|
|
196
|
+
Use `annotationClusters` for up to 1,000 annotations, or `dataSources` and `dataOverlays` for larger
|
|
197
|
+
GeoJSON sets. Clicking a cluster zooms in and reports a `cluster` target through `@interaction-event`.
|
|
198
|
+
|
|
199
|
+
<!-- docs:check -->
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import {clusterOverlay, geojsonSource} from '@tileflow/core/runtime';
|
|
203
|
+
|
|
204
|
+
export const dataSources = {stores: geojsonSource({cluster: true, clusterRadius: 50})};
|
|
205
|
+
export const dataOverlays = {
|
|
206
|
+
stores: clusterOverlay({id: 'stores', placement: 'above-labels', source: 'stores'}),
|
|
207
|
+
};
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
See the
|
|
211
|
+
[interactions reference](https://github.com/tileflow/tileflow-sdk/blob/main/packages/interactions/REFERENCE.md)
|
|
212
|
+
for heatmaps, events, and polygon drawing with Terra Draw.
|
|
213
|
+
|
|
188
214
|
## Display an existing image
|
|
189
215
|
|
|
190
216
|
`mode="image"` renders an explicit `imageUrl` or derives an image URL from the selected manifest
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { MapOptions, Map } from 'maplibre-gl';
|
|
2
2
|
import { DefineComponent, VNodeChild } from 'vue';
|
|
3
|
+
import { TileflowMapLibreOverlay, TileflowGeoJsonSource } from '@tileflow/core';
|
|
3
4
|
import { TileflowBrowserThemeBlendSelection, TileflowThemeTransitionOptions, TileflowViewMode, TileflowThemeTransition } from '@tileflow/core/browser';
|
|
4
5
|
import { TileflowRuntimeSource, TileflowThemeSelection, TileflowTimeOfDay, TileflowAnalytics } from '@tileflow/core/runtime';
|
|
5
6
|
import { TileflowAnnotation, TileflowInteractionJsonValue, TileflowInteractionState, TileflowInteractionBinding, TileflowInteractionDiagnostic, TileflowInteractionEvent, TileflowAnnotationViewContext, TileflowInteractionViewContext } from '@tileflow/interactions';
|
|
7
|
+
import { TileflowAnnotationClusterOptions } from '@tileflow/interactions/maplibre';
|
|
6
8
|
|
|
7
9
|
type TileflowMapStyleSourceProps = {
|
|
8
10
|
source: TileflowRuntimeSource;
|
|
@@ -57,13 +59,22 @@ type TileflowMapStateInput = {
|
|
|
57
59
|
interactionState?: never;
|
|
58
60
|
};
|
|
59
61
|
type TileflowMapInteractiveProps<TAnnotation extends TileflowAnnotation> = TileflowMapSharedProps & TileflowMapStateInput & {
|
|
62
|
+
/** Group `annotations` into accessible cluster buttons. Up to 1,000 annotations. */
|
|
63
|
+
annotationClusters?: TileflowAnnotationClusterOptions;
|
|
60
64
|
annotations?: readonly TAnnotation[];
|
|
65
|
+
/** Overlays drawn over `dataSources` or compiled sources, keyed as in `defineMap`. */
|
|
66
|
+
dataOverlays?: Readonly<Record<string, TileflowMapLibreOverlay>>;
|
|
67
|
+
/** Application GeoJSON, keyed as in `defineMap`. A compiled source of the same key is filled. */
|
|
68
|
+
dataSources?: Readonly<Record<string, TileflowGeoJsonSource>>;
|
|
61
69
|
interactions?: readonly TileflowInteractionBinding[];
|
|
62
70
|
interactive?: boolean;
|
|
63
71
|
mode?: 'interactive';
|
|
64
72
|
};
|
|
65
73
|
type TileflowMapImageProps = TileflowMapSharedProps & {
|
|
74
|
+
annotationClusters?: never;
|
|
66
75
|
annotations?: never;
|
|
76
|
+
dataOverlays?: never;
|
|
77
|
+
dataSources?: never;
|
|
67
78
|
defaultInteractionState?: never;
|
|
68
79
|
interactionState?: never;
|
|
69
80
|
interactions?: never;
|
|
@@ -73,7 +84,10 @@ type TileflowMapImageProps = TileflowMapSharedProps & {
|
|
|
73
84
|
type TileflowMapProps<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = (TileflowMapInteractiveProps<TAnnotation> | TileflowMapImageProps) & TileflowMapStyleSourceProps;
|
|
74
85
|
type RuntimeTileflowAnnotation = TileflowAnnotation<TileflowInteractionJsonValue>;
|
|
75
86
|
type RuntimeTileflowMapProps = TileflowMapSharedProps & TileflowMapStyleSourceProps & {
|
|
87
|
+
annotationClusters?: TileflowAnnotationClusterOptions;
|
|
76
88
|
annotations?: readonly RuntimeTileflowAnnotation[];
|
|
89
|
+
dataOverlays?: Readonly<Record<string, TileflowMapLibreOverlay>>;
|
|
90
|
+
dataSources?: Readonly<Record<string, TileflowGeoJsonSource>>;
|
|
77
91
|
defaultInteractionState?: TileflowInteractionState;
|
|
78
92
|
interactionState?: TileflowInteractionState;
|
|
79
93
|
interactions?: readonly TileflowInteractionBinding[];
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ref,
|
|
11
11
|
shallowRef,
|
|
12
12
|
Teleport,
|
|
13
|
+
toRaw,
|
|
13
14
|
watch,
|
|
14
15
|
watchEffect
|
|
15
16
|
} from "vue";
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
createTileflowThemeController,
|
|
27
28
|
createTileflowTransformRequest,
|
|
28
29
|
getTileflowSystemColorScheme,
|
|
30
|
+
loadTileflowRuntimeStyle,
|
|
29
31
|
loadTileflowStyleFonts,
|
|
30
32
|
registerTileflowContourProtocol,
|
|
31
33
|
registerTileflowPathGroundProtocol,
|
|
@@ -57,6 +59,7 @@ import {
|
|
|
57
59
|
initialTileflowInteractionState
|
|
58
60
|
} from "@tileflow/interactions";
|
|
59
61
|
import {
|
|
62
|
+
createTileflowMapLibreDataRuntime,
|
|
60
63
|
createTileflowMapLibreDomRuntime,
|
|
61
64
|
createTileflowMapLibreInteractionCoordinator,
|
|
62
65
|
createTileflowMapLibreSemanticDomRuntime
|
|
@@ -221,10 +224,13 @@ var TileflowMap = defineComponent({
|
|
|
221
224
|
type: String
|
|
222
225
|
},
|
|
223
226
|
analytics: Object,
|
|
227
|
+
annotationClusters: Object,
|
|
224
228
|
annotations: Array,
|
|
225
229
|
center: Array,
|
|
226
230
|
captureId: String,
|
|
227
231
|
className: String,
|
|
232
|
+
dataOverlays: Object,
|
|
233
|
+
dataSources: Object,
|
|
228
234
|
defaultInteractionState: Object,
|
|
229
235
|
height: {
|
|
230
236
|
default: 420,
|
|
@@ -283,6 +289,7 @@ var TileflowMap = defineComponent({
|
|
|
283
289
|
);
|
|
284
290
|
const controlledInteractionOwnership = props.interactionState !== void 0;
|
|
285
291
|
let annotationRuntime = null;
|
|
292
|
+
let dataRuntime = null;
|
|
286
293
|
let semanticRuntime = null;
|
|
287
294
|
let interactionRuntimesDisposing = false;
|
|
288
295
|
let initializeSemanticRuntime = null;
|
|
@@ -307,6 +314,7 @@ var TileflowMap = defineComponent({
|
|
|
307
314
|
let themeController = null;
|
|
308
315
|
let unsubscribeSystemColorScheme = null;
|
|
309
316
|
let mapLoadId = 0;
|
|
317
|
+
let resourceLifetime;
|
|
310
318
|
let manifestLoadId = 0;
|
|
311
319
|
let readinessRunId = 0;
|
|
312
320
|
let interactionReadinessRunId = 0;
|
|
@@ -341,7 +349,7 @@ var TileflowMap = defineComponent({
|
|
|
341
349
|
return diagnostics;
|
|
342
350
|
});
|
|
343
351
|
const hasInteractionConfiguration = computed(
|
|
344
|
-
() => props.annotations !== void 0 || props.interactions !== void 0 || props.interactionState !== void 0 || props.defaultInteractionState !== void 0 || slots.marker !== void 0 || slots.popup !== void 0 || slots.tooltip !== void 0
|
|
352
|
+
() => props.annotationClusters !== void 0 || props.annotations !== void 0 || props.dataOverlays !== void 0 || props.dataSources !== void 0 || props.interactions !== void 0 || props.interactionState !== void 0 || props.defaultInteractionState !== void 0 || slots.marker !== void 0 || slots.popup !== void 0 || slots.tooltip !== void 0
|
|
345
353
|
);
|
|
346
354
|
const interactionInputDiagnostics = computed(() => {
|
|
347
355
|
const diagnostics = [
|
|
@@ -643,6 +651,8 @@ var TileflowMap = defineComponent({
|
|
|
643
651
|
);
|
|
644
652
|
const destroyMap = () => {
|
|
645
653
|
mapLoadId += 1;
|
|
654
|
+
resourceLifetime?.abort();
|
|
655
|
+
resourceLifetime = void 0;
|
|
646
656
|
readinessRunId += 1;
|
|
647
657
|
invalidateInteractionReadiness();
|
|
648
658
|
const lifecycle = mapLifecycle;
|
|
@@ -652,6 +662,8 @@ var TileflowMap = defineComponent({
|
|
|
652
662
|
const controller = themeController;
|
|
653
663
|
const scene = sceneAttachment;
|
|
654
664
|
sceneAttachment = null;
|
|
665
|
+
dataRuntime?.dispose();
|
|
666
|
+
dataRuntime = null;
|
|
655
667
|
const annotationInteractionsForMap = annotationRuntime;
|
|
656
668
|
const semanticInteractionsForMap = semanticRuntime;
|
|
657
669
|
const worldRequestBridge = mapWorldRequestBridge;
|
|
@@ -724,6 +736,24 @@ var TileflowMap = defineComponent({
|
|
|
724
736
|
reportOverlayFailure("Unable to reconcile the Tileflow annotation runtime.");
|
|
725
737
|
}
|
|
726
738
|
};
|
|
739
|
+
const syncDataRuntime = () => {
|
|
740
|
+
const resolution = annotationResolution.value;
|
|
741
|
+
if (!dataRuntime) return;
|
|
742
|
+
try {
|
|
743
|
+
dataRuntime.reconcile({
|
|
744
|
+
annotationClusters: props.annotationClusters,
|
|
745
|
+
annotations: resolution.ok && !isImageMode.value ? resolution.annotations : [],
|
|
746
|
+
dataOverlays: props.dataOverlays,
|
|
747
|
+
dataSources: props.dataSources && Object.fromEntries(
|
|
748
|
+
Object.entries(toRaw(props.dataSources)).map(
|
|
749
|
+
([id, source]) => [id, { ...toRaw(source), data: toRaw(source.data) }]
|
|
750
|
+
)
|
|
751
|
+
)
|
|
752
|
+
});
|
|
753
|
+
} catch {
|
|
754
|
+
reportOverlayFailure("Unable to reconcile the Tileflow data layers.");
|
|
755
|
+
}
|
|
756
|
+
};
|
|
727
757
|
const syncSemanticRuntime = () => {
|
|
728
758
|
const resolution = interactionBindingResolution.value;
|
|
729
759
|
const bindings = resolution.ok && !isImageMode.value ? resolution.bindings : [];
|
|
@@ -767,16 +797,35 @@ var TileflowMap = defineComponent({
|
|
|
767
797
|
const loadId = mapLoadId;
|
|
768
798
|
const container = containerRef.value;
|
|
769
799
|
const runtime = runtimeStyle.value;
|
|
800
|
+
const session = createTileflowSessionController({ source: "vue" });
|
|
801
|
+
const lifetime = new AbortController();
|
|
802
|
+
resourceLifetime = lifetime;
|
|
803
|
+
const resourceTransform = createTileflowTransformRequest({
|
|
804
|
+
getAnalytics: () => resolvedAnalytics.value,
|
|
805
|
+
sessionController: session,
|
|
806
|
+
sessionId: session.sessionId,
|
|
807
|
+
transformRequest: props.mapOptions?.transformRequest ?? void 0
|
|
808
|
+
});
|
|
809
|
+
const styleLoadOptions = {
|
|
810
|
+
signal: lifetime.signal,
|
|
811
|
+
transformRequest: (url, type) => resourceTransform(
|
|
812
|
+
url,
|
|
813
|
+
type
|
|
814
|
+
)
|
|
815
|
+
};
|
|
770
816
|
let maplibregl;
|
|
817
|
+
let prepared;
|
|
771
818
|
try {
|
|
772
|
-
[maplibregl] = await Promise.all([
|
|
819
|
+
[maplibregl, prepared] = await Promise.all([
|
|
773
820
|
loadTileflowMapLibre(),
|
|
774
|
-
|
|
775
|
-
fontFaces:
|
|
821
|
+
loadTileflowRuntimeStyle(runtime, styleLoadOptions).then(async (loaded) => {
|
|
822
|
+
await loadTileflowStyleFonts(loaded.style, { fontFaces: loaded.fontFaces });
|
|
823
|
+
return loaded;
|
|
776
824
|
})
|
|
777
825
|
]);
|
|
778
826
|
} catch (error) {
|
|
779
827
|
if (loadId === mapLoadId) {
|
|
828
|
+
lifetime.abort();
|
|
780
829
|
console.error("Failed to load the Tileflow map runtime", error);
|
|
781
830
|
mapCaptureState.value = "error";
|
|
782
831
|
}
|
|
@@ -785,7 +834,6 @@ var TileflowMap = defineComponent({
|
|
|
785
834
|
if (loadId !== mapLoadId || containerRef.value !== container || isImageMode.value) {
|
|
786
835
|
return;
|
|
787
836
|
}
|
|
788
|
-
const session = createTileflowSessionController({ source: "vue" });
|
|
789
837
|
const sessionStarter = createTileflowSessionStarter({
|
|
790
838
|
getSessionId: () => session.sessionId,
|
|
791
839
|
sessionId: session.sessionId,
|
|
@@ -815,7 +863,7 @@ var TileflowMap = defineComponent({
|
|
|
815
863
|
container,
|
|
816
864
|
interactive: resolvedInteractive.value,
|
|
817
865
|
pitch: resolvedPitch.value,
|
|
818
|
-
style:
|
|
866
|
+
style: prepared.style,
|
|
819
867
|
transformRequest: createTileflowTransformRequest({
|
|
820
868
|
getAnalytics: () => resolvedAnalytics.value,
|
|
821
869
|
sessionController: session,
|
|
@@ -832,7 +880,9 @@ var TileflowMap = defineComponent({
|
|
|
832
880
|
attachTileflowLabelPlacement(map);
|
|
833
881
|
attachTileflowHorizonQueries(map);
|
|
834
882
|
themeController = runtime.theme === void 0 ? null : createTileflowThemeController({
|
|
835
|
-
initial: runtime,
|
|
883
|
+
initial: prepared.family ? prepared : runtime,
|
|
884
|
+
initialStyle: prepared.style,
|
|
885
|
+
styleLoadOptions,
|
|
836
886
|
map,
|
|
837
887
|
onTransition(transition) {
|
|
838
888
|
emit("themeChange", transition);
|
|
@@ -907,6 +957,17 @@ var TileflowMap = defineComponent({
|
|
|
907
957
|
annotationRenderTargets.value = mapInteractions.getRenderTargets();
|
|
908
958
|
syncInteractionRenderTargetReadiness();
|
|
909
959
|
syncAnnotationRuntime();
|
|
960
|
+
dataRuntime = createTileflowMapLibreDataRuntime({
|
|
961
|
+
createMarker: ({ element }) => new maplibregl.Marker({ element }),
|
|
962
|
+
document: container.ownerDocument,
|
|
963
|
+
map,
|
|
964
|
+
onDiagnostic: (diagnostic) => emit("interactionDiagnostic", diagnostic),
|
|
965
|
+
onInteractionEvent(event) {
|
|
966
|
+
if (!interactionRuntimesDisposing) emit("interactionEvent", event);
|
|
967
|
+
},
|
|
968
|
+
setHiddenAnnotations: mapInteractions.setHiddenAnnotations
|
|
969
|
+
});
|
|
970
|
+
syncDataRuntime();
|
|
910
971
|
} catch {
|
|
911
972
|
reportOverlayFailure("Unable to initialize the Tileflow annotation runtime.");
|
|
912
973
|
}
|
|
@@ -1144,9 +1205,17 @@ var TileflowMap = defineComponent({
|
|
|
1144
1205
|
);
|
|
1145
1206
|
watch(
|
|
1146
1207
|
() => props.annotations,
|
|
1147
|
-
() =>
|
|
1208
|
+
() => {
|
|
1209
|
+
syncAnnotationRuntime();
|
|
1210
|
+
syncDataRuntime();
|
|
1211
|
+
},
|
|
1148
1212
|
{ deep: true, flush: "post" }
|
|
1149
1213
|
);
|
|
1214
|
+
watch(
|
|
1215
|
+
() => [props.annotationClusters, props.dataOverlays, props.dataSources],
|
|
1216
|
+
() => syncDataRuntime(),
|
|
1217
|
+
{ flush: "post" }
|
|
1218
|
+
);
|
|
1150
1219
|
watch(
|
|
1151
1220
|
() => props.interactions,
|
|
1152
1221
|
() => syncSemanticRuntime(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/vue",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.36",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Vue component for rendering Tileflow maps with MapLibre.",
|
|
6
6
|
"type": "module",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@tileflow/core": ">=0.1.0-alpha.
|
|
42
|
-
"@tileflow/interactions": ">=0.1.0-alpha.
|
|
41
|
+
"@tileflow/core": ">=0.1.0-alpha.48 <0.1.0-beta.0",
|
|
42
|
+
"@tileflow/interactions": ">=0.1.0-alpha.8 <0.1.0-beta.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"maplibre-gl": ">=6.4.1 <7",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@vue/server-renderer": "3.5.43",
|
|
50
|
-
"maplibre-gl": "6.
|
|
50
|
+
"maplibre-gl": "6.16.0",
|
|
51
51
|
"tsx": "^4.23.15",
|
|
52
52
|
"vue": "^3.5.43"
|
|
53
53
|
},
|