@tileflow/vue 0.1.0-alpha.23 → 0.1.0-alpha.24
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 +127 -155
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,65 @@
|
|
|
1
1
|
# @tileflow/vue
|
|
2
2
|
|
|
3
|
-
Vue
|
|
3
|
+
Vue components for interactive Tileflow maps, annotations, and existing-image display.
|
|
4
|
+
The component reads prepared manifests and styles; it does not compile `tileflow.config.ts` in the
|
|
5
|
+
browser.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
> Related packages and guides: [documentation index](https://raw.githubusercontent.com/tileflow/tileflow-sdk/main/llms.txt).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Use an existing Vue 3 application. Supported peers are Vue `>=3.3 <4` and MapLibre GL JS
|
|
12
|
+
`>=6.4.1 <7`. The local build workflow below requires Node.js 22 or newer.
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @tileflow/vue@alpha @tileflow/core@alpha @tileflow/maps@alpha "maplibre-gl@^6.4.1"
|
|
16
|
+
npm install --save-dev --save-exact tileflow@alpha
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Prepare a map
|
|
20
|
+
|
|
21
|
+
Create `tileflow.config.ts` at the application root:
|
|
22
|
+
|
|
23
|
+
<!-- docs:check -->
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import {defineMap} from '@tileflow/core';
|
|
27
|
+
import {streets} from '@tileflow/maps';
|
|
28
|
+
|
|
29
|
+
export default defineMap({
|
|
30
|
+
id: 'madrid',
|
|
31
|
+
version: 1,
|
|
32
|
+
extends: streets,
|
|
33
|
+
view: {center: [-3.7038, 40.4168], zoom: 12},
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npx tileflow build --out public/tileflow
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Serve `public/` at the application's URL root. Rebuild after map or asset changes, or use the
|
|
42
|
+
[Vite integration](https://github.com/tileflow/tileflow-sdk/blob/main/packages/vite/README.md)
|
|
43
|
+
for watched development and production output. Local build and validation need no API key;
|
|
44
|
+
rendering may still request configured remote tiles and fonts.
|
|
45
|
+
|
|
46
|
+
## Configure the worker
|
|
47
|
+
|
|
48
|
+
For Vite, add the following to the existing client entry before `createApp(...).mount(...)`:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
|
|
52
|
+
import {configureTileflowMapLibre} from '@tileflow/vue';
|
|
53
|
+
|
|
54
|
+
configureTileflowMapLibre({workerUrl});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Configure this once before mounting an interactive map. The worker must come from the same installed
|
|
58
|
+
MapLibre package as the main module. The `?worker&url` import is Vite-specific; use the
|
|
59
|
+
[Webpack recipe](https://github.com/tileflow/tileflow-sdk/blob/main/packages/webpack/README.md)
|
|
60
|
+
for Webpack. Keep MapLibre's CSS in the client application as well.
|
|
61
|
+
|
|
62
|
+
## Render a map
|
|
6
63
|
|
|
7
64
|
```vue
|
|
8
65
|
<script setup lang="ts">
|
|
@@ -16,142 +73,66 @@ import {TileflowMap} from '@tileflow/vue';
|
|
|
16
73
|
theme="system"
|
|
17
74
|
:center="[-3.7038, 40.4168]"
|
|
18
75
|
:zoom="12"
|
|
19
|
-
:
|
|
20
|
-
|
|
21
|
-
maxZoom: 18,
|
|
22
|
-
}"
|
|
76
|
+
:height="420"
|
|
77
|
+
:map-options="{cooperativeGestures: true, maxZoom: 18}"
|
|
23
78
|
/>
|
|
24
79
|
</template>
|
|
25
80
|
```
|
|
26
81
|
|
|
27
|
-
|
|
82
|
+
Coordinates are `[longitude, latitude]`. `source.map` is the config's portable ID, not a hosted
|
|
83
|
+
`map_...` identifier. The default manifest URL is exactly `/tileflow/manifest.json`; provide
|
|
84
|
+
`source.manifestUrl` explicitly for a subpath, reverse proxy, or external host. The component does
|
|
85
|
+
not infer build-tool configuration.
|
|
28
86
|
|
|
29
|
-
|
|
30
|
-
|
|
87
|
+
Omitting `theme` uses `defaultTheme`. `system` needs the map's explicit light/dark mapping, which
|
|
88
|
+
Streets supplies. Switching themes preserves the map, camera, and interactions, with rollback on
|
|
89
|
+
failure. Listen to `themeChange` for transitions.
|
|
31
90
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
91
|
+
`mapOptions` accepts native MapLibre options except `container` and `style`. Direct props take
|
|
92
|
+
priority over those options, then the published view, then shared defaults. An unmanaged
|
|
93
|
+
`source: {kind: 'maplibre', style: styleUrl}` loads a single style without Tileflow theme selection
|
|
94
|
+
or manifest traceability; do not combine it with a Tileflow theme.
|
|
36
95
|
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
This is the Vite setup. Run it before `createApp(...).mount(...)`; `mode="image"` remains
|
|
41
|
-
MapLibre-free. MapLibre GL JS 6.4.1-6.x is supported. Use the `@tileflow/next` or
|
|
42
|
-
`@tileflow/webpack` README for their worker-delivery recipes.
|
|
43
|
-
|
|
44
|
-
`mapOptions` accepts native MapLibre options except `container` and `style`, which
|
|
45
|
-
Tileflow resolves from `source`. Direct
|
|
46
|
-
Tileflow props such as `center`, `zoom`, and `interactive` take priority when
|
|
47
|
-
provided. Camera resolution is the same in interactive and image modes: direct props, then
|
|
48
|
-
`mapOptions`, then the published manifest view, then Tileflow's shared runtime defaults.
|
|
49
|
-
|
|
50
|
-
Every map has exactly one discriminated `source`. Use `kind: 'tileflow'` with `map` and an optional
|
|
51
|
-
`manifestUrl` for published delivery. `kind: 'maplibre'` is an unmanaged escape hatch for one direct
|
|
52
|
-
style object or URL; it has no Tileflow theme identity, `system` selection, switching, or manifest
|
|
53
|
-
traceability. Browser components do not compile `tileflow.config.ts`.
|
|
96
|
+
## Add annotations and native popup UI
|
|
54
97
|
|
|
55
|
-
|
|
56
|
-
path, reverse proxy, or Tileflow plugin publishes it elsewhere, set the final public URL explicitly;
|
|
57
|
-
the component does not guess it. Manifest 404s, unknown map IDs, unresolved styles, and unresolved
|
|
58
|
-
image URLs enter `data-tileflow-state="error"`.
|
|
98
|
+
Install the contracts when importing them directly:
|
|
59
99
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
interaction state, with rollback on failure. Listen to `themeChange` for transition state.
|
|
63
|
-
|
|
64
|
-
```vue
|
|
65
|
-
<TileflowMap
|
|
66
|
-
:source="{
|
|
67
|
-
kind: 'tileflow',
|
|
68
|
-
map: 'madrid',
|
|
69
|
-
manifestUrl: 'https://cdn.example.com/tileflow/manifest.json',
|
|
70
|
-
}"
|
|
71
|
-
/>
|
|
72
|
-
|
|
73
|
-
<TileflowMap
|
|
74
|
-
:source="{
|
|
75
|
-
kind: 'maplibre',
|
|
76
|
-
style: 'https://cdn.example.com/tileflow/styles/madrid/dark.json',
|
|
77
|
-
}"
|
|
78
|
-
/>
|
|
100
|
+
```sh
|
|
101
|
+
npm install @tileflow/interactions@alpha
|
|
79
102
|
```
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
or evaluating MapLibre. All environments follow the same published manifest contract.
|
|
83
|
-
|
|
84
|
-
## Annotations, semantic POIs, and native Vue views
|
|
85
|
-
|
|
86
|
-
Use `annotations` for small, application-owned DOM markers. The portable annotation data and
|
|
87
|
-
interaction state remain JSON-safe. Use `interactions` to bind tooltip or popup behavior to
|
|
88
|
-
manifest-declared semantic POIs already rendered by the map style; this avoids creating one DOM
|
|
89
|
-
marker per feature. Scoped slots render native Vue UI into hosts owned by the shared interaction
|
|
90
|
-
runtime.
|
|
104
|
+
This component uses the worker and CSS setup above:
|
|
91
105
|
|
|
92
106
|
```vue
|
|
93
107
|
<script setup lang="ts">
|
|
94
108
|
import {ref} from 'vue';
|
|
95
|
-
import type {
|
|
96
|
-
TileflowAnnotation,
|
|
97
|
-
TileflowInteractionBinding,
|
|
98
|
-
TileflowInteractionState,
|
|
99
|
-
} from '@tileflow/interactions';
|
|
109
|
+
import type {TileflowAnnotation, TileflowInteractionState} from '@tileflow/interactions';
|
|
100
110
|
import {TileflowMap} from '@tileflow/vue';
|
|
101
111
|
|
|
102
|
-
type Property = {address: string; price: number};
|
|
103
|
-
|
|
104
112
|
const annotations = [
|
|
105
113
|
{
|
|
106
|
-
kind: 'marker',
|
|
107
114
|
id: 'property-42',
|
|
108
|
-
|
|
115
|
+
kind: 'marker',
|
|
116
|
+
coordinate: [-3.7038, 40.4168],
|
|
109
117
|
ariaLabel: 'Apartment in Madrid',
|
|
110
|
-
|
|
111
|
-
tooltip: {content: {kind: 'field', field: 'address'}},
|
|
118
|
+
tooltip: {content: {kind: 'text', text: 'View apartment'}},
|
|
112
119
|
popup: {content: {kind: 'view', name: 'property-card'}},
|
|
113
120
|
},
|
|
114
|
-
] satisfies readonly TileflowAnnotation
|
|
115
|
-
|
|
116
|
-
const interactions = [
|
|
117
|
-
{
|
|
118
|
-
id: 'restaurant-details',
|
|
119
|
-
target: {kind: 'semantic-feature', domain: 'poi', categories: ['food-drink']},
|
|
120
|
-
tooltip: {content: {kind: 'field', field: 'name', fallback: 'Restaurant'}},
|
|
121
|
-
popup: {content: {kind: 'view', name: 'poi-card'}},
|
|
122
|
-
},
|
|
123
|
-
] satisfies readonly TileflowInteractionBinding[];
|
|
121
|
+
] satisfies readonly TileflowAnnotation[];
|
|
124
122
|
|
|
125
|
-
const
|
|
123
|
+
const state = ref<TileflowInteractionState>({popup: null});
|
|
126
124
|
</script>
|
|
127
125
|
|
|
128
126
|
<template>
|
|
129
127
|
<TileflowMap
|
|
130
|
-
v-model:interaction-state="
|
|
128
|
+
v-model:interaction-state="state"
|
|
131
129
|
:source="{kind: 'tileflow', map: 'madrid'}"
|
|
132
130
|
:annotations="annotations"
|
|
133
|
-
|
|
134
|
-
@interaction-event="(event) => console.log(event.type, event.target)"
|
|
135
|
-
@interaction-diagnostic="(diagnostic) => console.warn(diagnostic.code)"
|
|
131
|
+
@interaction-diagnostic="(diagnostic) => console.error(diagnostic.code)"
|
|
136
132
|
>
|
|
137
|
-
<template #marker="{annotation}">
|
|
138
|
-
<span class="price-marker">{{ annotation.data.price.toLocaleString() }}</span>
|
|
139
|
-
</template>
|
|
140
|
-
|
|
141
|
-
<template #tooltip="{target}">
|
|
142
|
-
<span v-if="target.kind === 'annotation'">{{ target.annotation.data.address }}</span>
|
|
143
|
-
<span v-else-if="target.kind === 'semantic-feature'">
|
|
144
|
-
{{ target.feature.properties.name }}
|
|
145
|
-
</span>
|
|
146
|
-
</template>
|
|
147
|
-
|
|
148
133
|
<template #popup="{target, close}">
|
|
149
134
|
<article v-if="target.kind === 'annotation'">
|
|
150
|
-
<
|
|
151
|
-
<button type="button" @click="close">Close</button>
|
|
152
|
-
</article>
|
|
153
|
-
<article v-else-if="target.kind === 'semantic-feature'">
|
|
154
|
-
<strong>{{ target.feature.properties.name }}</strong>
|
|
135
|
+
<h2>{{ target.annotation.ariaLabel }}</h2>
|
|
155
136
|
<button type="button" @click="close">Close</button>
|
|
156
137
|
</article>
|
|
157
138
|
</template>
|
|
@@ -159,58 +140,49 @@ const interactionState = ref<TileflowInteractionState>({popup: null});
|
|
|
159
140
|
</template>
|
|
160
141
|
```
|
|
161
142
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
The `marker` slot is annotation-only and preserves the annotation's generic `data` type.
|
|
167
|
-
`tooltip` and `popup` receive the general `TileflowInteractionViewContext`; narrow
|
|
168
|
-
`target.kind` to access either `target.annotation` or the resolved semantic feature. Semantic POI
|
|
169
|
-
bindings require a compatible `tileflow:interaction-manifest` in the active style. Bindings are
|
|
170
|
-
validated before reaching MapLibre, POI hit tests are coalesced with `requestAnimationFrame`, and
|
|
171
|
-
annotation plus semantic runtimes share one controlled or uncontrolled popup state.
|
|
172
|
-
Values in `target.categories` use Tileflow's semantic taxonomy (for example `food` or `coffee`),
|
|
173
|
-
not raw OpenMapTiles classes.
|
|
174
|
-
|
|
175
|
-
Text content is inserted as text, `field` is a bounded declarative lookup, and `view` is only a
|
|
176
|
-
dispatch name for the corresponding application-owned scoped slot. No interaction path evaluates
|
|
177
|
-
HTML. Passing annotations, semantic interactions, or interaction state to `mode="image"` emits an `UNSUPPORTED_MODE`
|
|
178
|
-
diagnostic, marks capture readiness as `error`, and still does not load or evaluate MapLibre.
|
|
179
|
-
|
|
180
|
-
Changing annotations, semantic bindings, slots, state listeners, or diagnostic listeners
|
|
181
|
-
reconciles the existing runtimes; it does not recreate the map. The semantic runtime is initialized
|
|
182
|
-
lazily, and the component and its interaction imports remain SSR-safe.
|
|
183
|
-
|
|
184
|
-
Hosted maps automatically preflight a short-lived commercial session grant before eligible
|
|
185
|
-
resources. Setting `analytics` with `enabled: false` disables the optional beacon only; it does not
|
|
186
|
-
remove hosted authorization or override a user `mapOptions.transformRequest` callback.
|
|
187
|
-
Use `:analytics="{surfaceId: 'store-locator'}"` when the same Map is embedded in several stable
|
|
188
|
-
product locations. Missing or invalid Surface IDs become `default`; do not use URLs, branches,
|
|
189
|
-
random instance IDs, or user IDs.
|
|
190
|
-
Direct Tileflow World maps keep early `GRACE` silent, show a compact accessible owner-action pill
|
|
191
|
-
when late `GRACE` is activated, and show a stronger banner in `MANAGED_REQUIRED`. Missing tiles and
|
|
192
|
-
MapLibre failures do not remove that recovery path.
|
|
193
|
-
|
|
194
|
-
## Headless capture readiness
|
|
195
|
-
|
|
196
|
-
Pass `capture-id` when a page contains multiple copies of the same named map:
|
|
143
|
+
Annotations require a stable `id`, singular `coordinate`, and non-empty `ariaLabel`; optional data
|
|
144
|
+
must be JSON-safe. `marker` receives annotation-only context. `tooltip` and `popup` receive the
|
|
145
|
+
shared interaction context; narrow `target.kind` before reading annotation or semantic feature data.
|
|
197
146
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
147
|
+
Use `interactions` with `target: {kind: 'semantic-feature', domain: 'poi'}` for POIs already rendered
|
|
148
|
+
by the style. Categories use Tileflow's taxonomy, such as `food-drink` or `retail`, not raw source
|
|
149
|
+
classes. Semantic bindings require compatible metadata in the active style and avoid creating one
|
|
150
|
+
DOM marker per feature.
|
|
151
|
+
|
|
152
|
+
Omit controlled state and use `default-interaction-state` for uncontrolled ownership. Do not supply
|
|
153
|
+
both or change ownership during a component's lifetime. Annotations, bindings, slots, and callbacks
|
|
154
|
+
reconcile without recreating MapLibre. Text/field descriptors render as text; `view` dispatches to
|
|
155
|
+
an application slot and never evaluates HTML. Tooltips must remain non-interactive; use a popup for
|
|
156
|
+
links, buttons, or forms.
|
|
157
|
+
|
|
158
|
+
## Display an existing image
|
|
159
|
+
|
|
160
|
+
`mode="image"` renders an explicit `imageUrl` or a published manifest image without loading MapLibre.
|
|
161
|
+
A local style build does not generate an image. This mode does not create or poll a static render;
|
|
162
|
+
use the server-side [Static Maps client](https://github.com/tileflow/tileflow-sdk/blob/main/packages/static/README.md)
|
|
163
|
+
for that operation and keep privileged keys on the server.
|
|
164
|
+
|
|
165
|
+
Do not pass annotations, semantic bindings, state, or interaction slots to image mode. Unsupported
|
|
166
|
+
interaction input reports `UNSUPPORTED_MODE` and capture readiness `error`; it does not silently
|
|
167
|
+
pretend the image contains live overlays.
|
|
168
|
+
|
|
169
|
+
## Capture, authorization, and troubleshooting
|
|
201
170
|
|
|
202
|
-
The root exposes `data-tileflow-map`,
|
|
203
|
-
`data-tileflow-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
application capture selects exactly one ready target.
|
|
171
|
+
Pass `capture-id` when multiple components show the same map. The root exposes `data-tileflow-map`,
|
|
172
|
+
resolved `data-tileflow-theme`, optional `data-tileflow-capture-id`, and
|
|
173
|
+
`data-tileflow-state="loading|idle|error"`. Readiness includes MapLibre or image loading plus committed
|
|
174
|
+
Vue interaction views. Application capture needs exactly one ready target and the application's
|
|
175
|
+
normal loopback server.
|
|
208
176
|
|
|
209
|
-
|
|
177
|
+
For a blank/error map, check that the manifest URL returns JSON, the map and theme exist, MapLibre
|
|
178
|
+
CSS is imported, and the matching worker/shared assets are served. Manifest 404s and unresolved
|
|
179
|
+
styles/images are errors; the component does not guess another URL.
|
|
210
180
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
Hosted maps preflight a short-lived session grant. `:analytics="{enabled: false}"` disables only the
|
|
182
|
+
optional beacon, not authorization. Use a stable product `surfaceId` rather than a user ID or URL.
|
|
183
|
+
Direct World maps can show owner-action notices when managed delivery is required. Imports and the
|
|
184
|
+
image path remain SSR-safe; interactive rendering needs a browser with WebGL.
|
|
215
185
|
|
|
216
|
-
|
|
186
|
+
See the [interaction guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/interactions/README.md)
|
|
187
|
+
and [browser runtime contract](https://github.com/tileflow/tileflow-sdk/blob/main/docs/contracts/framework-browser-runtime.md).
|
|
188
|
+
Use the installed package's declarations and README for a release; `main` can include newer changes.
|
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.24",
|
|
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.25 <0.1.0-beta.0",
|
|
42
|
+
"@tileflow/interactions": ">=0.1.0-alpha.4 <0.1.0-beta.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"maplibre-gl": ">=6.4.1 <7",
|