@tileflow/vue 0.1.0-alpha.35 → 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 CHANGED
@@ -98,7 +98,7 @@ Add `time-of-day="dusk"` beside `theme` to select a map's optional `day`, `dawn`
98
98
  `night` preset. For Streets, `theme="light"` with this preset selects the existing `dusk` palette.
99
99
  Maps without this capability ignore the option; omitting it keeps the selected theme unchanged.
100
100
  Changing it uses the existing theme transition. `themeBlend` takes precedence. See the
101
- [authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md#style-with-themes-and-semantic-modules).
101
+ [authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/REFERENCE.md#style-with-themes-and-semantic-modules).
102
102
 
103
103
  Theme and `time-of-day` changes cross-fade over 450 ms by default, respecting reduced motion.
104
104
  `:theme-transition="{duration: 700}"` customizes the duration; use `duration: 0` for an immediate change.
@@ -191,6 +191,26 @@ reconcile without recreating MapLibre. Text/field descriptors render as text; `v
191
191
  an application slot and never evaluates HTML. Tooltips must remain non-interactive; use a popup for
192
192
  links, buttons, or forms.
193
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
+
194
214
  ## Display an existing image
195
215
 
196
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";
@@ -58,6 +59,7 @@ import {
58
59
  initialTileflowInteractionState
59
60
  } from "@tileflow/interactions";
60
61
  import {
62
+ createTileflowMapLibreDataRuntime,
61
63
  createTileflowMapLibreDomRuntime,
62
64
  createTileflowMapLibreInteractionCoordinator,
63
65
  createTileflowMapLibreSemanticDomRuntime
@@ -222,10 +224,13 @@ var TileflowMap = defineComponent({
222
224
  type: String
223
225
  },
224
226
  analytics: Object,
227
+ annotationClusters: Object,
225
228
  annotations: Array,
226
229
  center: Array,
227
230
  captureId: String,
228
231
  className: String,
232
+ dataOverlays: Object,
233
+ dataSources: Object,
229
234
  defaultInteractionState: Object,
230
235
  height: {
231
236
  default: 420,
@@ -284,6 +289,7 @@ var TileflowMap = defineComponent({
284
289
  );
285
290
  const controlledInteractionOwnership = props.interactionState !== void 0;
286
291
  let annotationRuntime = null;
292
+ let dataRuntime = null;
287
293
  let semanticRuntime = null;
288
294
  let interactionRuntimesDisposing = false;
289
295
  let initializeSemanticRuntime = null;
@@ -343,7 +349,7 @@ var TileflowMap = defineComponent({
343
349
  return diagnostics;
344
350
  });
345
351
  const hasInteractionConfiguration = computed(
346
- () => 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
347
353
  );
348
354
  const interactionInputDiagnostics = computed(() => {
349
355
  const diagnostics = [
@@ -656,6 +662,8 @@ var TileflowMap = defineComponent({
656
662
  const controller = themeController;
657
663
  const scene = sceneAttachment;
658
664
  sceneAttachment = null;
665
+ dataRuntime?.dispose();
666
+ dataRuntime = null;
659
667
  const annotationInteractionsForMap = annotationRuntime;
660
668
  const semanticInteractionsForMap = semanticRuntime;
661
669
  const worldRequestBridge = mapWorldRequestBridge;
@@ -728,6 +736,24 @@ var TileflowMap = defineComponent({
728
736
  reportOverlayFailure("Unable to reconcile the Tileflow annotation runtime.");
729
737
  }
730
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
+ };
731
757
  const syncSemanticRuntime = () => {
732
758
  const resolution = interactionBindingResolution.value;
733
759
  const bindings = resolution.ok && !isImageMode.value ? resolution.bindings : [];
@@ -931,6 +957,17 @@ var TileflowMap = defineComponent({
931
957
  annotationRenderTargets.value = mapInteractions.getRenderTargets();
932
958
  syncInteractionRenderTargetReadiness();
933
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();
934
971
  } catch {
935
972
  reportOverlayFailure("Unable to initialize the Tileflow annotation runtime.");
936
973
  }
@@ -1168,9 +1205,17 @@ var TileflowMap = defineComponent({
1168
1205
  );
1169
1206
  watch(
1170
1207
  () => props.annotations,
1171
- () => syncAnnotationRuntime(),
1208
+ () => {
1209
+ syncAnnotationRuntime();
1210
+ syncDataRuntime();
1211
+ },
1172
1212
  { deep: true, flush: "post" }
1173
1213
  );
1214
+ watch(
1215
+ () => [props.annotationClusters, props.dataOverlays, props.dataSources],
1216
+ () => syncDataRuntime(),
1217
+ { flush: "post" }
1218
+ );
1174
1219
  watch(
1175
1220
  () => props.interactions,
1176
1221
  () => syncSemanticRuntime(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/vue",
3
- "version": "0.1.0-alpha.35",
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.45 <0.1.0-beta.0",
42
- "@tileflow/interactions": ">=0.1.0-alpha.7 <0.1.0-beta.0"
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",