@tileflow/vue 0.1.0-alpha.10
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 +31 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +389 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @tileflow/vue
|
|
2
|
+
|
|
3
|
+
Vue component for rendering Tileflow maps with MapLibre.
|
|
4
|
+
|
|
5
|
+
Install `maplibre-gl` alongside the package and import its CSS once in your app.
|
|
6
|
+
|
|
7
|
+
```vue
|
|
8
|
+
<script setup lang="ts">
|
|
9
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
10
|
+
import {TileflowMap} from '@tileflow/vue';
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<TileflowMap
|
|
15
|
+
map="madrid"
|
|
16
|
+
:center="[-3.7038, 40.4168]"
|
|
17
|
+
:zoom="12"
|
|
18
|
+
:map-options="{
|
|
19
|
+
cooperativeGestures: true,
|
|
20
|
+
maxZoom: 18,
|
|
21
|
+
}"
|
|
22
|
+
/>
|
|
23
|
+
</template>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`mapOptions` accepts native MapLibre options except `container` and `style`, which
|
|
27
|
+
Tileflow resolves from the map name, manifest, or explicit style props. Direct
|
|
28
|
+
Tileflow props such as `center`, `zoom`, and `interactive` take priority when
|
|
29
|
+
provided.
|
|
30
|
+
|
|
31
|
+
Docs: https://tileflow.dev/docs
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
import { PropType } from 'vue';
|
|
3
|
+
import maplibregl, { MapOptions, Map } from 'maplibre-gl';
|
|
4
|
+
import { TileflowAnalytics, TileflowConfig, MapLibreStyle, TileflowMapMarker, TileflowProjectThemes } from '@tileflow/core';
|
|
5
|
+
|
|
6
|
+
type TileflowMapMode = 'interactive' | 'image';
|
|
7
|
+
type TileflowMapOptions = Omit<MapOptions, 'container' | 'style'>;
|
|
8
|
+
type TileflowMapProps = {
|
|
9
|
+
alt?: string;
|
|
10
|
+
analytics?: TileflowAnalytics;
|
|
11
|
+
center?: [number, number];
|
|
12
|
+
className?: string;
|
|
13
|
+
config?: TileflowConfig;
|
|
14
|
+
height?: number | string;
|
|
15
|
+
imageLoading?: HTMLImageElement['loading'];
|
|
16
|
+
imageUrl?: string;
|
|
17
|
+
interactive?: boolean;
|
|
18
|
+
manifestUrl?: string;
|
|
19
|
+
map?: string;
|
|
20
|
+
mapOptions?: TileflowMapOptions;
|
|
21
|
+
mapStyle?: MapLibreStyle;
|
|
22
|
+
markers?: TileflowMapMarker[];
|
|
23
|
+
mode?: TileflowMapMode;
|
|
24
|
+
preferLocalDev?: boolean;
|
|
25
|
+
styleBaseUrl?: string;
|
|
26
|
+
styleUrl?: string;
|
|
27
|
+
themes?: TileflowProjectThemes;
|
|
28
|
+
tileBaseUrl?: string;
|
|
29
|
+
zoom?: number;
|
|
30
|
+
};
|
|
31
|
+
declare const TileflowMap: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
32
|
+
alt: {
|
|
33
|
+
default: string;
|
|
34
|
+
type: StringConstructor;
|
|
35
|
+
};
|
|
36
|
+
analytics: PropType<TileflowAnalytics>;
|
|
37
|
+
center: PropType<[number, number]>;
|
|
38
|
+
className: StringConstructor;
|
|
39
|
+
config: PropType<TileflowConfig>;
|
|
40
|
+
height: {
|
|
41
|
+
default: number;
|
|
42
|
+
type: PropType<number | string>;
|
|
43
|
+
};
|
|
44
|
+
imageLoading: {
|
|
45
|
+
default: string;
|
|
46
|
+
type: PropType<HTMLImageElement["loading"]>;
|
|
47
|
+
};
|
|
48
|
+
imageUrl: StringConstructor;
|
|
49
|
+
interactive: {
|
|
50
|
+
default: undefined;
|
|
51
|
+
type: PropType<boolean | undefined>;
|
|
52
|
+
};
|
|
53
|
+
manifestUrl: {
|
|
54
|
+
default: string;
|
|
55
|
+
type: StringConstructor;
|
|
56
|
+
};
|
|
57
|
+
map: StringConstructor;
|
|
58
|
+
mapOptions: PropType<TileflowMapOptions>;
|
|
59
|
+
mapStyle: PropType<MapLibreStyle>;
|
|
60
|
+
markers: {
|
|
61
|
+
default: () => never[];
|
|
62
|
+
type: PropType<TileflowMapMarker[]>;
|
|
63
|
+
};
|
|
64
|
+
mode: {
|
|
65
|
+
default: string;
|
|
66
|
+
type: PropType<TileflowMapMode>;
|
|
67
|
+
};
|
|
68
|
+
preferLocalDev: {
|
|
69
|
+
default: boolean;
|
|
70
|
+
type: BooleanConstructor;
|
|
71
|
+
};
|
|
72
|
+
styleBaseUrl: StringConstructor;
|
|
73
|
+
styleUrl: StringConstructor;
|
|
74
|
+
themes: PropType<TileflowProjectThemes>;
|
|
75
|
+
tileBaseUrl: StringConstructor;
|
|
76
|
+
zoom: NumberConstructor;
|
|
77
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
78
|
+
[key: string]: any;
|
|
79
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
80
|
+
load: (_map: Map) => true;
|
|
81
|
+
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
82
|
+
alt: {
|
|
83
|
+
default: string;
|
|
84
|
+
type: StringConstructor;
|
|
85
|
+
};
|
|
86
|
+
analytics: PropType<TileflowAnalytics>;
|
|
87
|
+
center: PropType<[number, number]>;
|
|
88
|
+
className: StringConstructor;
|
|
89
|
+
config: PropType<TileflowConfig>;
|
|
90
|
+
height: {
|
|
91
|
+
default: number;
|
|
92
|
+
type: PropType<number | string>;
|
|
93
|
+
};
|
|
94
|
+
imageLoading: {
|
|
95
|
+
default: string;
|
|
96
|
+
type: PropType<HTMLImageElement["loading"]>;
|
|
97
|
+
};
|
|
98
|
+
imageUrl: StringConstructor;
|
|
99
|
+
interactive: {
|
|
100
|
+
default: undefined;
|
|
101
|
+
type: PropType<boolean | undefined>;
|
|
102
|
+
};
|
|
103
|
+
manifestUrl: {
|
|
104
|
+
default: string;
|
|
105
|
+
type: StringConstructor;
|
|
106
|
+
};
|
|
107
|
+
map: StringConstructor;
|
|
108
|
+
mapOptions: PropType<TileflowMapOptions>;
|
|
109
|
+
mapStyle: PropType<MapLibreStyle>;
|
|
110
|
+
markers: {
|
|
111
|
+
default: () => never[];
|
|
112
|
+
type: PropType<TileflowMapMarker[]>;
|
|
113
|
+
};
|
|
114
|
+
mode: {
|
|
115
|
+
default: string;
|
|
116
|
+
type: PropType<TileflowMapMode>;
|
|
117
|
+
};
|
|
118
|
+
preferLocalDev: {
|
|
119
|
+
default: boolean;
|
|
120
|
+
type: BooleanConstructor;
|
|
121
|
+
};
|
|
122
|
+
styleBaseUrl: StringConstructor;
|
|
123
|
+
styleUrl: StringConstructor;
|
|
124
|
+
themes: PropType<TileflowProjectThemes>;
|
|
125
|
+
tileBaseUrl: StringConstructor;
|
|
126
|
+
zoom: NumberConstructor;
|
|
127
|
+
}>> & Readonly<{
|
|
128
|
+
onLoad?: ((_map: maplibregl.Map) => any) | undefined;
|
|
129
|
+
}>, {
|
|
130
|
+
interactive: boolean | undefined;
|
|
131
|
+
alt: string;
|
|
132
|
+
height: string | number;
|
|
133
|
+
imageLoading: "eager" | "lazy";
|
|
134
|
+
manifestUrl: string;
|
|
135
|
+
markers: TileflowMapMarker[];
|
|
136
|
+
mode: TileflowMapMode;
|
|
137
|
+
preferLocalDev: boolean;
|
|
138
|
+
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
139
|
+
|
|
140
|
+
export { TileflowMap, type TileflowMapMode, type TileflowMapOptions, type TileflowMapProps, TileflowMap as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import maplibregl from "maplibre-gl";
|
|
3
|
+
import {
|
|
4
|
+
computed,
|
|
5
|
+
defineComponent,
|
|
6
|
+
h,
|
|
7
|
+
onBeforeUnmount,
|
|
8
|
+
onMounted,
|
|
9
|
+
ref,
|
|
10
|
+
shallowRef,
|
|
11
|
+
watch
|
|
12
|
+
} from "vue";
|
|
13
|
+
import {
|
|
14
|
+
createTileflowSessionId,
|
|
15
|
+
defaultTileflowManifestUrl,
|
|
16
|
+
loadTileflowManifest,
|
|
17
|
+
mergeTileflowAnalytics,
|
|
18
|
+
normalizeTileflowStaticImageSize,
|
|
19
|
+
resolveTileflowAnalyticsRequestUrl,
|
|
20
|
+
resolveTileflowManifestMap,
|
|
21
|
+
resolveTileflowMapMode,
|
|
22
|
+
resolveTileflowRuntimeStyle,
|
|
23
|
+
resolveTileflowStaticImageUrl,
|
|
24
|
+
shouldLoadTileflowManifest,
|
|
25
|
+
startTileflowSession
|
|
26
|
+
} from "@tileflow/core";
|
|
27
|
+
var defaultCenter = [0, 20];
|
|
28
|
+
var defaultZoom = 2;
|
|
29
|
+
var TileflowMap = defineComponent({
|
|
30
|
+
name: "TileflowMap",
|
|
31
|
+
inheritAttrs: false,
|
|
32
|
+
props: {
|
|
33
|
+
alt: {
|
|
34
|
+
default: "",
|
|
35
|
+
type: String
|
|
36
|
+
},
|
|
37
|
+
analytics: Object,
|
|
38
|
+
center: Array,
|
|
39
|
+
className: String,
|
|
40
|
+
config: Object,
|
|
41
|
+
height: {
|
|
42
|
+
default: 420,
|
|
43
|
+
type: [Number, String]
|
|
44
|
+
},
|
|
45
|
+
imageLoading: {
|
|
46
|
+
default: "eager",
|
|
47
|
+
type: String
|
|
48
|
+
},
|
|
49
|
+
imageUrl: String,
|
|
50
|
+
interactive: {
|
|
51
|
+
default: void 0,
|
|
52
|
+
type: Boolean
|
|
53
|
+
},
|
|
54
|
+
manifestUrl: {
|
|
55
|
+
default: defaultTileflowManifestUrl,
|
|
56
|
+
type: String
|
|
57
|
+
},
|
|
58
|
+
map: String,
|
|
59
|
+
mapOptions: Object,
|
|
60
|
+
mapStyle: Object,
|
|
61
|
+
markers: {
|
|
62
|
+
default: () => [],
|
|
63
|
+
type: Array
|
|
64
|
+
},
|
|
65
|
+
mode: {
|
|
66
|
+
default: "interactive",
|
|
67
|
+
type: String
|
|
68
|
+
},
|
|
69
|
+
preferLocalDev: {
|
|
70
|
+
default: true,
|
|
71
|
+
type: Boolean
|
|
72
|
+
},
|
|
73
|
+
styleBaseUrl: String,
|
|
74
|
+
styleUrl: String,
|
|
75
|
+
themes: Object,
|
|
76
|
+
tileBaseUrl: String,
|
|
77
|
+
zoom: Number
|
|
78
|
+
},
|
|
79
|
+
emits: {
|
|
80
|
+
load: (_map) => true
|
|
81
|
+
},
|
|
82
|
+
setup(props, { attrs, emit }) {
|
|
83
|
+
const containerRef = ref(null);
|
|
84
|
+
const manifestMap = shallowRef(null);
|
|
85
|
+
const imageSize = shallowRef(null);
|
|
86
|
+
const mapRef = shallowRef(null);
|
|
87
|
+
const sessionId = createTileflowSessionId();
|
|
88
|
+
const markerInstances = [];
|
|
89
|
+
const sessionStarts = /* @__PURE__ */ new Set();
|
|
90
|
+
let imageResizeObserver = null;
|
|
91
|
+
let mapResizeObserver = null;
|
|
92
|
+
let manifestLoadId = 0;
|
|
93
|
+
const resolvedMode = computed(
|
|
94
|
+
() => resolveTileflowMapMode({
|
|
95
|
+
imageUrl: props.imageUrl,
|
|
96
|
+
mode: props.mode,
|
|
97
|
+
preferLocalDev: props.preferLocalDev
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
const isImageMode = computed(() => resolvedMode.value === "image");
|
|
101
|
+
const imageCenter = computed(() => props.center ?? defaultCenter);
|
|
102
|
+
const imageZoom = computed(() => props.zoom ?? defaultZoom);
|
|
103
|
+
const resolvedCenter = computed(
|
|
104
|
+
() => props.center ?? props.mapOptions?.center ?? defaultCenter
|
|
105
|
+
);
|
|
106
|
+
const resolvedZoom = computed(() => props.zoom ?? props.mapOptions?.zoom ?? defaultZoom);
|
|
107
|
+
const resolvedInteractive = computed(
|
|
108
|
+
() => props.interactive ?? props.mapOptions?.interactive ?? true
|
|
109
|
+
);
|
|
110
|
+
const runtimeStyle = computed(
|
|
111
|
+
() => isImageMode.value ? null : resolveTileflowRuntimeStyle({
|
|
112
|
+
config: props.config,
|
|
113
|
+
manifestMap: manifestMap.value,
|
|
114
|
+
map: props.map,
|
|
115
|
+
preferLocalDev: props.preferLocalDev,
|
|
116
|
+
style: props.mapStyle,
|
|
117
|
+
styleBaseUrl: props.styleBaseUrl,
|
|
118
|
+
styleUrl: props.styleUrl,
|
|
119
|
+
themes: props.themes,
|
|
120
|
+
tileBaseUrl: props.tileBaseUrl
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
const resolvedAnalytics = computed(
|
|
124
|
+
() => mergeTileflowAnalytics(props.analytics, runtimeStyle.value?.analytics)
|
|
125
|
+
);
|
|
126
|
+
const runtimeImageUrl = computed(
|
|
127
|
+
() => props.imageUrl ?? (isImageMode.value ? resolveTileflowStaticImageUrl({
|
|
128
|
+
center: imageCenter.value,
|
|
129
|
+
imageSize: imageSize.value,
|
|
130
|
+
manifestMap: manifestMap.value,
|
|
131
|
+
zoom: imageZoom.value
|
|
132
|
+
}) : void 0)
|
|
133
|
+
);
|
|
134
|
+
const frameStyle = computed(() => ({
|
|
135
|
+
height: formatHeight(props.height),
|
|
136
|
+
minHeight: "240px",
|
|
137
|
+
overflow: "hidden",
|
|
138
|
+
position: "relative",
|
|
139
|
+
width: "100%"
|
|
140
|
+
}));
|
|
141
|
+
const refreshManifest = async () => {
|
|
142
|
+
const shouldLoad = shouldLoadTileflowManifest({
|
|
143
|
+
config: props.config,
|
|
144
|
+
imageMode: isImageMode.value,
|
|
145
|
+
imageUrl: props.imageUrl,
|
|
146
|
+
map: props.map,
|
|
147
|
+
style: props.mapStyle,
|
|
148
|
+
styleBaseUrl: props.styleBaseUrl,
|
|
149
|
+
styleUrl: props.styleUrl
|
|
150
|
+
});
|
|
151
|
+
if (!shouldLoad) {
|
|
152
|
+
manifestMap.value = null;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const loadId = ++manifestLoadId;
|
|
156
|
+
manifestMap.value = null;
|
|
157
|
+
try {
|
|
158
|
+
const manifest = await loadTileflowManifest(props.manifestUrl);
|
|
159
|
+
if (loadId === manifestLoadId) {
|
|
160
|
+
manifestMap.value = manifest && props.map ? resolveTileflowManifestMap(manifest, props.map) : null;
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (loadId === manifestLoadId) {
|
|
164
|
+
console.error("Failed to load Tileflow manifest", error);
|
|
165
|
+
manifestMap.value = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const updateImageResizeObserver = () => {
|
|
170
|
+
imageResizeObserver?.disconnect();
|
|
171
|
+
imageResizeObserver = null;
|
|
172
|
+
imageSize.value = null;
|
|
173
|
+
if (!isImageMode.value || props.imageUrl || !containerRef.value) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const element = containerRef.value;
|
|
177
|
+
const updateImageSize = () => {
|
|
178
|
+
const nextSize = normalizeTileflowStaticImageSize({
|
|
179
|
+
height: element.clientHeight,
|
|
180
|
+
width: element.clientWidth
|
|
181
|
+
});
|
|
182
|
+
imageSize.value = imageSize.value?.height === nextSize.height && imageSize.value.width === nextSize.width ? imageSize.value : nextSize;
|
|
183
|
+
};
|
|
184
|
+
imageResizeObserver = new ResizeObserver(updateImageSize);
|
|
185
|
+
imageResizeObserver.observe(element);
|
|
186
|
+
updateImageSize();
|
|
187
|
+
};
|
|
188
|
+
const destroyMap = () => {
|
|
189
|
+
mapResizeObserver?.disconnect();
|
|
190
|
+
mapResizeObserver = null;
|
|
191
|
+
clearMarkers(markerInstances);
|
|
192
|
+
mapRef.value?.remove();
|
|
193
|
+
mapRef.value = null;
|
|
194
|
+
};
|
|
195
|
+
const recreateMap = () => {
|
|
196
|
+
destroyMap();
|
|
197
|
+
if (!containerRef.value || !runtimeStyle.value || isImageMode.value) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const runtime = runtimeStyle.value;
|
|
201
|
+
const map = new maplibregl.Map({
|
|
202
|
+
...props.mapOptions,
|
|
203
|
+
attributionControl: props.mapOptions?.attributionControl ?? { compact: true },
|
|
204
|
+
center: resolvedCenter.value,
|
|
205
|
+
container: containerRef.value,
|
|
206
|
+
interactive: resolvedInteractive.value,
|
|
207
|
+
style: runtime.style,
|
|
208
|
+
transformRequest: createTransformRequest(
|
|
209
|
+
resolvedAnalytics.value,
|
|
210
|
+
sessionId,
|
|
211
|
+
props.mapOptions?.transformRequest
|
|
212
|
+
),
|
|
213
|
+
zoom: resolvedZoom.value
|
|
214
|
+
});
|
|
215
|
+
mapRef.value = map;
|
|
216
|
+
if (resolvedInteractive.value) {
|
|
217
|
+
map.addControl(new maplibregl.NavigationControl(), "top-right");
|
|
218
|
+
}
|
|
219
|
+
mapResizeObserver = new ResizeObserver(() => {
|
|
220
|
+
map.resize();
|
|
221
|
+
});
|
|
222
|
+
mapResizeObserver.observe(containerRef.value);
|
|
223
|
+
map.on("load", () => {
|
|
224
|
+
const analyticsForLoad = resolvedAnalytics.value;
|
|
225
|
+
const styleId = analyticsForLoad?.styleId ?? (typeof runtime.style === "string" ? runtime.style : props.map);
|
|
226
|
+
emit("load", map);
|
|
227
|
+
if (analyticsForLoad?.mapId) {
|
|
228
|
+
const sessionKey = `${sessionId}:${analyticsForLoad.mapId}:${styleId ?? ""}`;
|
|
229
|
+
if (!sessionStarts.has(sessionKey)) {
|
|
230
|
+
sessionStarts.add(sessionKey);
|
|
231
|
+
startTileflowSession(analyticsForLoad, {
|
|
232
|
+
mapId: analyticsForLoad.mapId,
|
|
233
|
+
sessionId,
|
|
234
|
+
source: "vue",
|
|
235
|
+
styleId
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
syncMarkers();
|
|
241
|
+
};
|
|
242
|
+
const syncView = () => {
|
|
243
|
+
mapRef.value?.jumpTo({
|
|
244
|
+
center: resolvedCenter.value,
|
|
245
|
+
zoom: resolvedZoom.value
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
const syncMarkers = () => {
|
|
249
|
+
const map = mapRef.value;
|
|
250
|
+
clearMarkers(markerInstances);
|
|
251
|
+
if (!map) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
for (const marker of props.markers) {
|
|
255
|
+
const markerInstance = new maplibregl.Marker({
|
|
256
|
+
color: marker.color ?? "#C6A15B"
|
|
257
|
+
}).setLngLat(marker.coordinates).addTo(map);
|
|
258
|
+
markerInstance.getElement().title = marker.label ?? marker.id;
|
|
259
|
+
markerInstances.push(markerInstance);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
onMounted(() => {
|
|
263
|
+
void refreshManifest();
|
|
264
|
+
updateImageResizeObserver();
|
|
265
|
+
recreateMap();
|
|
266
|
+
});
|
|
267
|
+
onBeforeUnmount(() => {
|
|
268
|
+
imageResizeObserver?.disconnect();
|
|
269
|
+
destroyMap();
|
|
270
|
+
});
|
|
271
|
+
watch(
|
|
272
|
+
() => [
|
|
273
|
+
props.config,
|
|
274
|
+
props.imageUrl,
|
|
275
|
+
props.manifestUrl,
|
|
276
|
+
props.map,
|
|
277
|
+
props.mapStyle,
|
|
278
|
+
props.mode,
|
|
279
|
+
props.preferLocalDev,
|
|
280
|
+
props.styleBaseUrl,
|
|
281
|
+
props.styleUrl
|
|
282
|
+
],
|
|
283
|
+
() => {
|
|
284
|
+
void refreshManifest();
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
watch(
|
|
288
|
+
() => [props.imageUrl, props.mode, props.preferLocalDev],
|
|
289
|
+
() => updateImageResizeObserver(),
|
|
290
|
+
{ flush: "post" }
|
|
291
|
+
);
|
|
292
|
+
watch(
|
|
293
|
+
() => [
|
|
294
|
+
props.config,
|
|
295
|
+
props.analytics,
|
|
296
|
+
props.interactive,
|
|
297
|
+
props.map,
|
|
298
|
+
props.mapOptions,
|
|
299
|
+
props.mapStyle,
|
|
300
|
+
props.mode,
|
|
301
|
+
props.preferLocalDev,
|
|
302
|
+
props.styleBaseUrl,
|
|
303
|
+
props.styleUrl,
|
|
304
|
+
props.themes,
|
|
305
|
+
props.tileBaseUrl,
|
|
306
|
+
manifestMap.value
|
|
307
|
+
],
|
|
308
|
+
() => recreateMap(),
|
|
309
|
+
{ flush: "post" }
|
|
310
|
+
);
|
|
311
|
+
watch(
|
|
312
|
+
() => [props.center, props.zoom, props.mapOptions?.center, props.mapOptions?.zoom],
|
|
313
|
+
() => syncView(),
|
|
314
|
+
{ flush: "post" }
|
|
315
|
+
);
|
|
316
|
+
watch(
|
|
317
|
+
() => props.markers,
|
|
318
|
+
() => syncMarkers(),
|
|
319
|
+
{ flush: "post" }
|
|
320
|
+
);
|
|
321
|
+
return () => {
|
|
322
|
+
const rootAttrs = { ...attrs };
|
|
323
|
+
const classValue = [attrs.class, props.className];
|
|
324
|
+
const styleValue = [attrs.style, frameStyle.value];
|
|
325
|
+
delete rootAttrs.class;
|
|
326
|
+
delete rootAttrs.style;
|
|
327
|
+
return h(
|
|
328
|
+
"div",
|
|
329
|
+
{
|
|
330
|
+
...rootAttrs,
|
|
331
|
+
class: classValue,
|
|
332
|
+
ref: containerRef,
|
|
333
|
+
style: styleValue
|
|
334
|
+
},
|
|
335
|
+
isImageMode.value && runtimeImageUrl.value ? h("img", {
|
|
336
|
+
alt: props.alt,
|
|
337
|
+
decoding: "async",
|
|
338
|
+
loading: props.imageLoading,
|
|
339
|
+
src: runtimeImageUrl.value,
|
|
340
|
+
style: {
|
|
341
|
+
display: "block",
|
|
342
|
+
height: "100%",
|
|
343
|
+
objectFit: "cover",
|
|
344
|
+
width: "100%"
|
|
345
|
+
}
|
|
346
|
+
}) : void 0
|
|
347
|
+
);
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
var index_default = TileflowMap;
|
|
352
|
+
function createTransformRequest(analytics, sessionId, userTransformRequest) {
|
|
353
|
+
if ((!analytics || analytics.enabled === false) && !userTransformRequest) {
|
|
354
|
+
return void 0;
|
|
355
|
+
}
|
|
356
|
+
return (url, resourceType) => {
|
|
357
|
+
const request = userTransformRequest?.(url, resourceType);
|
|
358
|
+
if (isPromiseLike(request)) {
|
|
359
|
+
return request.then(
|
|
360
|
+
(resolvedRequest) => applyTileflowAnalyticsRequest(url, resolvedRequest, analytics, sessionId) ?? resolvedRequest
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
return applyTileflowAnalyticsRequest(url, request, analytics, sessionId);
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function applyTileflowAnalyticsRequest(url, request, analytics, sessionId) {
|
|
367
|
+
const requestUrl = request?.url ?? url;
|
|
368
|
+
const nextUrl = resolveTileflowAnalyticsRequestUrl(requestUrl, analytics, sessionId);
|
|
369
|
+
if (!nextUrl) {
|
|
370
|
+
return request;
|
|
371
|
+
}
|
|
372
|
+
return request ? { ...request, url: nextUrl } : { url: nextUrl };
|
|
373
|
+
}
|
|
374
|
+
function isPromiseLike(value) {
|
|
375
|
+
return Boolean(value && typeof value.then === "function");
|
|
376
|
+
}
|
|
377
|
+
function formatHeight(height) {
|
|
378
|
+
return typeof height === "number" ? `${height}px` : height;
|
|
379
|
+
}
|
|
380
|
+
function clearMarkers(markerInstances) {
|
|
381
|
+
for (const marker of markerInstances) {
|
|
382
|
+
marker.remove();
|
|
383
|
+
}
|
|
384
|
+
markerInstances.splice(0);
|
|
385
|
+
}
|
|
386
|
+
export {
|
|
387
|
+
TileflowMap,
|
|
388
|
+
index_default as default
|
|
389
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tileflow/vue",
|
|
3
|
+
"version": "0.1.0-alpha.10",
|
|
4
|
+
"description": "Vue component for rendering Tileflow maps with MapLibre.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"homepage": "https://tileflow.dev",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/tileflow/tileflow.git",
|
|
11
|
+
"directory": "packages/vue"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/tileflow/tileflow/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"tileflow",
|
|
18
|
+
"vue",
|
|
19
|
+
"maps",
|
|
20
|
+
"maplibre",
|
|
21
|
+
"tiles"
|
|
22
|
+
],
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@tileflow/core": "0.1.0-alpha.10"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"maplibre-gl": ">=5",
|
|
43
|
+
"vue": ">=3.3"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"maplibre-gl": "^5.24.0",
|
|
47
|
+
"vue": "^3.5.26"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup src/index.ts --format esm --dts --clean --external vue --external maplibre-gl",
|
|
51
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
52
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
53
|
+
}
|
|
54
|
+
}
|