@tileflow/react 0.1.0-alpha.23 → 0.1.0-alpha.25

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
@@ -1,12 +1,80 @@
1
1
  # @tileflow/react
2
2
 
3
- React components for rendering Tileflow maps with MapLibre.
3
+ React components for interactive Tileflow maps, annotations, and static-image display.
4
+ Interactive maps use MapLibre GL JS; browser components read prepared assets rather than compiling
5
+ `tileflow.config.ts`.
4
6
 
5
- Install `maplibre-gl` alongside the package and import its CSS once in your app.
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 React 18 or 19 application with matching `react-dom`. The following local build
12
+ workflow needs Node.js 22 or newer:
13
+
14
+ ```sh
15
+ npm install @tileflow/react@alpha @tileflow/core@alpha @tileflow/maps@alpha "maplibre-gl@^6.4.1"
16
+ npm install --save-dev --save-exact tileflow@alpha
17
+ ```
18
+
19
+ The supported peer ranges are React/React DOM 18–19 and MapLibre GL JS `>=6.4.1 <7`. The worker
20
+ must come from the same MapLibre installation as the main module.
21
+
22
+ ## Prepare a map
23
+
24
+ Create `tileflow.config.ts` at the application root:
25
+
26
+ <!-- docs:check -->
27
+
28
+ ```ts
29
+ import {defineMap} from '@tileflow/core';
30
+ import {streets} from '@tileflow/maps';
31
+
32
+ export default defineMap({
33
+ id: 'madrid',
34
+ version: 1,
35
+ extends: streets,
36
+ view: {center: [-3.7038, 40.4168], zoom: 12},
37
+ });
38
+ ```
39
+
40
+ Build the assets into the application's public directory:
41
+
42
+ ```sh
43
+ npx tileflow build --out public/tileflow
44
+ ```
45
+
46
+ This assumes the application serves `public/` at its URL root. Rebuild after config or asset
47
+ changes, or use the [Vite](https://github.com/tileflow/tileflow-sdk/blob/main/packages/vite/README.md),
48
+ [Next.js](https://github.com/tileflow/tileflow-sdk/blob/main/packages/next/README.md), or
49
+ [Webpack](https://github.com/tileflow/tileflow-sdk/blob/main/packages/webpack/README.md) integration
50
+ for watched development and production builds. Do not use both workflows to overwrite the same
51
+ hosted manifest.
52
+
53
+ ## Configure the worker
54
+
55
+ In a Vite application's client entry, add this before mounting React:
56
+
57
+ ```ts
58
+ import workerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url';
59
+ import {configureTileflowMapLibre} from '@tileflow/react';
60
+
61
+ configureTileflowMapLibre({workerUrl});
62
+ ```
63
+
64
+ This import syntax is specific to Vite. Use the Next.js or Webpack guide linked above for that
65
+ bundler's worker-delivery recipe. Configure the worker once, outside component rendering. Do not
66
+ use a CDN worker from another MapLibre version. Next.js interactive components belong behind a
67
+ `'use client'` boundary.
68
+
69
+ ## Render a map
70
+
71
+ Import MapLibre's CSS once in the application. After the worker and assets are ready, render:
72
+
73
+ <!-- docs:check -->
6
74
 
7
75
  ```tsx
8
- import {Map} from '@tileflow/react';
9
76
  import 'maplibre-gl/dist/maplibre-gl.css';
77
+ import {Map} from '@tileflow/react';
10
78
 
11
79
  export function App() {
12
80
  return (
@@ -15,56 +83,69 @@ export function App() {
15
83
  theme="system"
16
84
  center={[-3.7038, 40.4168]}
17
85
  zoom={12}
18
- mapOptions={{
19
- cooperativeGestures: true,
20
- maxZoom: 18,
21
- }}
86
+ mapOptions={{cooperativeGestures: true, maxZoom: 18}}
22
87
  />
23
88
  );
24
89
  }
25
90
  ```
26
91
 
27
- ## Annotations, tooltips, and popups
92
+ Coordinates are `[longitude, latitude]`. `source.map` must match the config's portable map ID,
93
+ not a hosted `map_...` identifier. The default manifest URL is exactly `/tileflow/manifest.json`.
94
+ For a subpath or external host, provide `manifestUrl` in the source; the component does not infer
95
+ bundler configuration or search for assets.
96
+
97
+ `theme` selects a published concrete theme. Omission uses `defaultTheme`; `system` requires an
98
+ explicit light/dark mapping, which Streets supplies. Theme changes preserve the MapLibre instance,
99
+ camera, and interactions, and roll back on failure. `onThemeChange` reports transitions.
100
+
101
+ `mapOptions` accepts native MapLibre options except `container` and `style`. Direct camera props
102
+ take priority over `mapOptions`, then the manifest view, then shared defaults. To load one unmanaged
103
+ style, use `source={{kind: 'maplibre', style: styleUrl}}`; that source has no Tileflow theme switching
104
+ or manifest identity. Do not supply a Tileflow theme with an unmanaged source.
105
+
106
+ ## Add annotations and popups
107
+
108
+ Install the contract package when importing its types directly:
109
+
110
+ ```sh
111
+ npm install @tileflow/interactions@alpha
112
+ ```
113
+
114
+ Annotations are small, application-owned marker sets. Every annotation has a stable `id`, singular
115
+ `coordinate`, and non-empty `ariaLabel`. Data must be JSON-safe. Native React renderers use portals
116
+ into hosts managed by the interaction runtime:
28
117
 
29
- Use `annotations` for small application-owned marker sets. Annotation data is serializable, while
30
- `renderMarker`, `renderTooltip`, and `renderPopup` render native React UI through portals into the
31
- MapLibre-owned marker and overlay hosts.
118
+ <!-- docs:check -->
32
119
 
33
120
  ```tsx
34
- import {Map} from '@tileflow/react';
35
121
  import {useState} from 'react';
36
122
  import type {TileflowAnnotation, TileflowInteractionState} from '@tileflow/interactions';
123
+ import {Map} from '@tileflow/react';
37
124
 
38
- type Property = {
39
- price: number;
40
- title: string;
41
- };
125
+ type Property = {price: number; title: string};
42
126
 
43
127
  const annotations = [
44
128
  {
45
- ariaLabel: 'Apartment in Madrid',
46
- coordinate: [-3.7038, 40.4168],
47
- data: {price: 320_000, title: 'Apartment in Madrid'},
48
129
  id: 'property-42',
49
130
  kind: 'marker',
50
- marker: {content: {kind: 'field', field: 'price'}},
131
+ coordinate: [-3.7038, 40.4168],
132
+ ariaLabel: 'Apartment in Madrid',
133
+ data: {price: 320_000, title: 'Apartment in Madrid'},
51
134
  tooltip: {content: {kind: 'field', field: 'title'}},
52
135
  popup: {content: {kind: 'view', name: 'property-card'}},
53
136
  },
54
137
  ] satisfies readonly TileflowAnnotation<Property>[];
55
138
 
56
139
  export function PropertyMap() {
57
- const [interactionState, setInteractionState] = useState<TileflowInteractionState>({popup: null});
140
+ const [state, setState] = useState<TileflowInteractionState>({popup: null});
58
141
 
59
142
  return (
60
143
  <Map
61
144
  source={{kind: 'tileflow', map: 'madrid'}}
62
145
  annotations={annotations}
63
- interactionState={interactionState}
64
- onInteractionStateChange={setInteractionState}
65
- onInteractionDiagnostic={(diagnostic) => console.error(diagnostic)}
66
- onInteractionEvent={(event) => console.log(event.type, event.target)}
67
- renderMarker={({annotation}) => <strong>EUR {annotation.data.price.toLocaleString()}</strong>}
146
+ interactionState={state}
147
+ onInteractionStateChange={setState}
148
+ onInteractionDiagnostic={(diagnostic) => console.error(diagnostic.code)}
68
149
  renderPopup={({annotation, close}) => (
69
150
  <article>
70
151
  <h2>{annotation.data.title}</h2>
@@ -79,208 +160,107 @@ export function PropertyMap() {
79
160
  }
80
161
  ```
81
162
 
82
- Omit `interactionState` and use `defaultInteractionState` for uncontrolled popup state. Callback and
83
- renderer identity changes, annotation updates, and popup state changes do not recreate the MapLibre
84
- map. Updating an annotation with the same ID preserves its compatible Marker instance and portal
85
- host.
163
+ This uses the worker/CSS setup from the preceding sections. Omit controlled `interactionState` and
164
+ use `defaultInteractionState` for uncontrolled state; never supply both or switch ownership during
165
+ the component's lifetime. Updating annotations, renderers, callbacks, or state does not recreate
166
+ the map. Reusing an annotation ID preserves a compatible marker host.
86
167
 
87
- `renderMarker` is always annotation-only. Without `interactions`, `renderTooltip` and `renderPopup`
88
- also infer the annotation-specific context, including typed `annotation.data`. When `interactions`
89
- is present, they receive the common `TileflowInteractionViewContext`; narrow `context.target.kind`
90
- (or check `annotation in context`) when one renderer serves both annotation and semantic targets.
168
+ Use `interactions` with `target: {kind: 'semantic-feature', domain: 'poi'}` for POIs already in the
169
+ compiled map instead of creating a DOM marker for every feature. Optional categories use Tileflow's
170
+ semantic taxonomy, such as `food-drink` or `retail`, not raw source classes. The style must contain
171
+ compatible interaction metadata. With semantic bindings, narrow `context.target.kind` in
172
+ `renderTooltip` or `renderPopup` before accessing annotation or feature data. `renderMarker` remains
173
+ annotation-only. See the
174
+ [interaction guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/interactions/README.md).
91
175
 
92
- ## Semantic POI interactions
176
+ Text/field content uses safe text defaults. A `view` is an application renderer name, not HTML.
177
+ Keep tooltips non-interactive; put buttons, links, and forms in popups.
93
178
 
94
- Use `interactions` to attach tooltip or popup behavior to POIs already rendered by a finalized
95
- Tileflow style. Application code names the `poi` domain, never compiler-generated MapLibre layer
96
- IDs. The runtime queries only manifest-declared layers and mounts DOM only for the active overlay.
179
+ ## Display an image or create a render
97
180
 
98
- ```tsx
99
- import {Map} from '@tileflow/react';
100
- import type {TileflowInteractionBinding} from '@tileflow/interactions';
181
+ `<Map mode="image">` displays an existing explicit `imageUrl` or an image URL in the published
182
+ manifest. It does not create a static render, poll an operation, or load MapLibre. A local style
183
+ build alone does not create that image. Annotations, semantic bindings, and interaction state are
184
+ not supported in image mode.
101
185
 
102
- const interactions = [
103
- {
104
- id: 'poi-details',
105
- target: {kind: 'semantic-feature', domain: 'poi', categories: ['food-drink', 'retail']},
106
- tooltip: {content: {kind: 'field', field: 'name', fallback: 'Point of interest'}},
107
- popup: {content: {kind: 'view', name: 'poi-card'}},
108
- },
109
- ] satisfies readonly TileflowInteractionBinding[];
186
+ To request a new static render, use `StaticMap` from `@tileflow/react/static`. First install the
187
+ shared client/types used by this example:
110
188
 
111
- export function PoiMap() {
112
- return (
113
- <Map
114
- source={{kind: 'tileflow', map: 'madrid'}}
115
- interactions={interactions}
116
- renderPopup={(context) =>
117
- context.target.kind === 'semantic-feature' ? (
118
- <article>
119
- <h2>{String(context.target.feature.properties.name ?? 'Point of interest')}</h2>
120
- <button type="button" onClick={context.close}>
121
- Close
122
- </button>
123
- </article>
124
- ) : null
125
- }
126
- />
127
- );
128
- }
189
+ ```sh
190
+ npm install @tileflow/static@alpha
129
191
  ```
130
192
 
131
- Bindings and popup state are validated before reconciliation. An invalid replacement leaves the
132
- last valid runtime state active and reports structured diagnostics. `interactionState` and
133
- `defaultInteractionState` are mutually exclusive. Annotation and semantic overlays share one popup
134
- state, so replacing either target closes the previous popup before opening the next.
135
-
136
- `MapProps` rejects controlled and default interaction state together. Its `mode="image"` branch
137
- excludes annotations, semantic bindings, interaction state, renderers, and interaction callbacks.
138
- JavaScript callers and widened inputs still receive the corresponding runtime diagnostics.
139
-
140
- `onInteractionDiagnostic` receives each newly reported structured runtime diagnostic. Changing any
141
- callback identity does not resubscribe the runtime or recreate MapLibre.
142
-
143
- Custom portal targets move capture readiness to `loading` until React commits the target and two
144
- current animation frames complete. Removing or replacing a target invalidates pending frames.
145
-
146
- When no render prop is present, text and safe field descriptors use the shared unbranded DOM
147
- defaults. A `view` descriptor is a dispatch name for an application renderer; it is not HTML or a
148
- serialized component tree. Tooltip content remains non-interactive, while popup content may contain
149
- normal React controls.
193
+ The application must implement an authorized `/api/static-maps` endpoint that forwards the normalized
194
+ scene and idempotency key to the hosted service and returns its result contract. Keep privileged
195
+ Tileflow credentials on that server, not in React props or a browser bundle.
150
196
 
151
- `annotations` is the only application-owned marker input. Its singular `coordinate`, required
152
- `ariaLabel`, and optional `marker` descriptor feed the keyed runtime directly. `mode="image"`
153
- cannot render interaction configuration and shows an explicit `UNSUPPORTED_MODE` diagnostic
154
- without loading MapLibre.
155
-
156
- `mapOptions` accepts native MapLibre options except `container` and `style`, which
157
- Tileflow resolves from `source`. Direct
158
- Tileflow props such as `center`, `zoom`, and `interactive` take priority when
159
- provided. Camera resolution is the same in interactive and image modes: direct props, then
160
- `mapOptions`, then the published manifest view, then Tileflow's shared runtime defaults.
161
-
162
- Every map has exactly one discriminated `source`. Use `kind: 'tileflow'` for a map published in a
163
- Tileflow manifest. `kind: 'maplibre'` is the unmanaged MapLibre escape hatch for one direct style
164
- object or URL: it deliberately has no Tileflow theme identity, `system` selection, switching, or
165
- manifest traceability. Browser components do not compile `tileflow.config.ts`.
166
-
167
- Without `manifestUrl`, the exact default is `/tileflow/manifest.json`. If Vite, Webpack, Next, a
168
- reverse proxy, or the Tileflow plugin publishes it anywhere else, set the final public URL
169
- explicitly; the component does not attempt runtime base-path discovery. Manifest 404s, unknown map
170
- IDs, unresolved styles, and unresolved image URLs enter `data-tileflow-state="error"`.
171
-
172
- `theme` selects a published theme name. Omitting it uses the map's `defaultTheme`; `"system"` is
173
- available only when the map declares explicit light and dark mappings. Changes preload fonts, diff
174
- the style on the existing MapLibre instance, preserve camera and interactions, and roll back if the
175
- new style fails. `onThemeChange` reports preloading, applying, ready, and error transitions.
176
-
177
- To reuse one published map across multiple repos, point every app at the same
178
- manifest:
197
+ <!-- docs:check -->
179
198
 
180
199
  ```tsx
181
- <Map
182
- source={{
183
- kind: 'tileflow',
184
- map: 'madrid',
185
- manifestUrl: 'https://cdn.example.com/tileflow/manifest.json',
186
- }}
187
- />
188
- ```
189
-
190
- Or deliberately leave the Tileflow theme contract and load one concrete Style JSON directly:
191
-
192
- ```tsx
193
- <Map
194
- source={{
195
- kind: 'maplibre',
196
- style: 'https://cdn.example.com/tileflow/styles/madrid/dark.json',
197
- }}
198
- />
199
- ```
200
-
201
- For a lightweight display of an already hosted static image, use image mode:
202
-
203
- ```tsx
204
- <Map
205
- source={{kind: 'tileflow', map: 'madrid'}}
206
- mode="image"
207
- center={[-3.7038, 40.4168]}
208
- zoom={12}
209
- />
210
- ```
211
-
212
- `Map mode="image"` only resolves an existing image URL (explicitly or from the published map
213
- manifest) and renders an `<img>`; it does not submit a render scene, create an operation, poll, or
214
- apply `StaticMap` overlays. This path does not load or evaluate MapLibre. Without an explicit
215
- `imageUrl`, all environments use the image URL published for the Tileflow source.
216
-
217
- For a new, fully specified render with exact size, center/bounds camera, overlays, idempotency, and
218
- asynchronous create/poll behavior, use `StaticMap` from `@tileflow/react/static` or helpers from
219
- `@tileflow/static`.
220
-
221
- ```tsx
222
- import {StaticMap} from '@tileflow/react/static';
223
200
  import {useState} from 'react';
224
- import {createStaticMapIdempotencyKey} from '@tileflow/static';
201
+ import {StaticMap} from '@tileflow/react/static';
202
+ import type {StaticMapAttributionEntry} from '@tileflow/static';
225
203
 
226
- export function Preview() {
227
- const [idempotencyKey] = useState(createStaticMapIdempotencyKey);
204
+ export function StaticPreview({idempotencyKey}: {idempotencyKey: string}) {
205
+ const [entries, setEntries] = useState<readonly StaticMapAttributionEntry[]>([]);
228
206
 
229
207
  return (
230
- <StaticMap
231
- map="madrid"
232
- camera={{type: 'center', center: [-3.7038, 40.4168], zoom: 12}}
233
- attribution={{mode: 'external'}}
234
- size={{width: 1200, height: 800}}
235
- createUrl="/api/static-maps"
236
- idempotencyKey={idempotencyKey}
237
- onReady={(result) => {
238
- if (result.resultVersion === 2) showAttribution(result.attribution.entries);
239
- }}
240
- />
208
+ <figure>
209
+ <StaticMap
210
+ map="madrid"
211
+ theme="dark"
212
+ alt="Map of central Madrid"
213
+ camera={{type: 'center', center: [-3.7038, 40.4168], zoom: 12}}
214
+ size={{width: 1200, height: 800}}
215
+ attribution={{mode: 'external'}}
216
+ createUrl="/api/static-maps"
217
+ idempotencyKey={idempotencyKey}
218
+ onReady={(result) => {
219
+ if ('attribution' in result) setEntries(result.attribution.entries);
220
+ }}
221
+ />
222
+ <figcaption>
223
+ {entries.map((entry, index) => (
224
+ <p key={index}>
225
+ {entry.text}{' '}
226
+ {entry.links.map((link) => (
227
+ <a key={link.url} href={link.url}>
228
+ {link.label}
229
+ </a>
230
+ ))}
231
+ </p>
232
+ ))}
233
+ </figcaption>
234
+ </figure>
241
235
  );
242
236
  }
243
237
  ```
244
238
 
245
- `idempotencyKey` is required in create mode. Keep one key for one intentional create action and
246
- reuse it across retries and remounts. Concurrent React consumers share work only when URL,
247
- normalized scene, and idempotency key all identify the same operation; unmounting the final
248
- consumer aborts its in-flight request.
249
-
250
- `StaticMap` forwards `attribution` as part of the normalized scene and request identity. Omission
251
- uses embedded automatic placement. With `mode: 'external'`, the component still renders the image,
252
- but the application must render every structured `onReady` attribution entry beside it. Existing
253
- `imageUrl` mode has no operation result and cannot infer attribution from an immutable image URL.
254
-
255
- Hosted interactive maps automatically preflight a short-lived commercial session grant before
256
- eligible resources. Setting `analytics={{enabled: false}}` disables the optional beacon only; it
257
- does not remove hosted authorization or override a user `mapOptions.transformRequest` callback.
258
- Use `analytics={{surfaceId: 'store-locator'}}` when the same Map is embedded in several stable
259
- product locations. Missing or invalid Surface IDs become `default`; do not use URLs, branches,
260
- random instance IDs, or user IDs.
261
- Direct Tileflow World maps keep early `GRACE` silent, show a compact accessible owner-action pill
262
- when late `GRACE` is activated, and show a stronger banner in `MANAGED_REQUIRED`. Missing tiles and
263
- MapLibre failures do not remove that recovery path.
264
-
265
- ## Headless capture readiness
266
-
267
- Use `captureId` to disambiguate multiple maps with the same configured name:
268
-
269
- ```tsx
270
- <Map source={{kind: 'tileflow', map: 'madrid'}} captureId="checkout-map" />
271
- ```
272
-
273
- The root element exposes `data-tileflow-map`, optional `data-tileflow-capture-id`, and
274
- `data-tileflow-state="loading|idle|error"`. Interactive mode becomes idle after MapLibre is idle
275
- and two animation frames; style/data work returns it to loading. Image mode waits for decode or a
276
- successful load fallback, including cached hydration. `tileflow capture` uses these markers for
277
- application scenes and requires exactly one target.
278
-
279
- ## Compatibility
280
-
281
- The supported peer window is React 18-19 and MapLibre GL JS 5-6. Compatibility smoke tests install
282
- the exact lower bound and the first release of every accepted major from packed Tileflow tarballs,
283
- typecheck a consumer, and render the image/SSR path while rejecting any MapLibre import. Future
284
- majors stay outside the peer range until that matrix passes.
285
-
286
- Docs: https://tileflow.dev/docs
239
+ Create the key with `createStaticMapIdempotencyKey()` once per intentional render action and retain
240
+ it in the owning application state across retries and remounts. Pass it into this component; do not
241
+ regenerate it on every render. A new scene is a new action and needs a new key.
242
+
243
+ Hosted results have `resultVersion: 1` and attribution. `onReady` also supports existing-image
244
+ results, which have no attribution field; narrow the union before reading it. External attribution
245
+ must remain visible beside the image. Omitted attribution uses embedded automatic placement.
246
+ See the [Static Maps guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/static/README.md)
247
+ for server transport, errors, overlays, and limits.
248
+
249
+ ## Capture, authorization, and errors
250
+
251
+ `captureId` disambiguates repeated maps on a page. The root exposes `data-tileflow-map`, the resolved
252
+ `data-tileflow-theme`, optional `data-tileflow-capture-id`, and `data-tileflow-state="loading|idle|error"`.
253
+ Capture waits for MapLibre/image readiness and committed custom interaction views. Manifest 404s,
254
+ unknown maps/themes, and missing styles or images enter the error state rather than silently using
255
+ another map.
256
+
257
+ Hosted interactive maps acquire a short-lived session grant before eligible resource requests.
258
+ `analytics={{enabled: false}}` disables the optional beacon, not hosted authorization. A stable
259
+ `surfaceId`, such as `store-locator`, identifies a product location; do not use user IDs or URLs.
260
+ Existing request transforms remain application-owned, and direct World use can display an
261
+ owner-action notice when managed delivery is required.
262
+
263
+ The image/SSR path does not load MapLibre. Interactive rendering needs a browser with WebGL and the
264
+ matching worker assets. For release-specific APIs, use the installed declarations and README;
265
+ source `main` may be ahead of npm. Report defects in the
266
+ [issue tracker](https://github.com/tileflow/tileflow-sdk/issues).
package/dist/index.d.ts CHANGED
@@ -69,4 +69,10 @@ type MapImageProps = MapSharedProps & {
69
69
  type MapProps<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = (MapInteractiveProps<TAnnotation> | MapImageProps) & TileflowMapStyleSourceProps;
70
70
  declare function Map<TAnnotation extends TileflowAnnotation = TileflowAnnotation>(props: MapProps<TAnnotation>): react.JSX.Element;
71
71
 
72
- export { Map, type MapProps, type TileflowAnnotationRenderer, type TileflowInteractionRenderer, type TileflowMapOptions, type TileflowMapSource };
72
+ type TileflowMapLibreConfiguration = Readonly<{
73
+ workerUrl: string;
74
+ }>;
75
+ /** Configure the application-owned worker before mounting an interactive Tileflow map. */
76
+ declare function configureTileflowMapLibre(configuration: TileflowMapLibreConfiguration): void;
77
+
78
+ export { Map, type MapProps, type TileflowAnnotationRenderer, type TileflowInteractionRenderer, type TileflowMapLibreConfiguration, type TileflowMapOptions, type TileflowMapSource, configureTileflowMapLibre };
package/dist/index.js CHANGED
@@ -189,8 +189,21 @@ function assertTileflowMapStyleInputs(input) {
189
189
 
190
190
  // src/maplibre.ts
191
191
  var mapLibrePromise;
192
+ var mapLibre;
193
+ var workerUrl;
194
+ function configureTileflowMapLibre(configuration) {
195
+ const nextWorkerUrl = configuration.workerUrl;
196
+ if (typeof nextWorkerUrl !== "string" || nextWorkerUrl.trim().length === 0) {
197
+ throw new TypeError("Tileflow MapLibre workerUrl must be a non-empty string.");
198
+ }
199
+ if (workerUrl !== void 0 && workerUrl !== nextWorkerUrl) {
200
+ throw new Error("Tileflow MapLibre workerUrl is already configured.");
201
+ }
202
+ workerUrl = nextWorkerUrl;
203
+ mapLibre?.setWorkerUrl(nextWorkerUrl);
204
+ }
192
205
  function loadTileflowMapLibre() {
193
- mapLibrePromise ??= import("maplibre-gl").then(resolveMapLibreModule).catch((error) => {
206
+ mapLibrePromise ??= import("maplibre-gl").then(resolveMapLibreModule).then(configureTileflowMapLibreModule).catch((error) => {
194
207
  mapLibrePromise = void 0;
195
208
  throw error;
196
209
  });
@@ -200,6 +213,11 @@ function resolveMapLibreModule(module) {
200
213
  const defaultExport = module.default;
201
214
  return defaultExport ?? module;
202
215
  }
216
+ function configureTileflowMapLibreModule(maplibregl) {
217
+ if (workerUrl !== void 0) maplibregl.setWorkerUrl(workerUrl);
218
+ mapLibre = maplibregl;
219
+ return maplibregl;
220
+ }
203
221
 
204
222
  // src/map.tsx
205
223
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -1218,10 +1236,11 @@ function wrapMapLibrePositioned(positioned) {
1218
1236
  };
1219
1237
  }
1220
1238
  function createTileflowMapLibrePoiMap(map) {
1239
+ const poiMap = map;
1221
1240
  return {
1222
1241
  getStyle: () => map.getStyle(),
1223
1242
  on(event, listener) {
1224
- return map.on(event, listener);
1243
+ return poiMap.on(event, listener);
1225
1244
  },
1226
1245
  queryRenderedFeatures(point, options) {
1227
1246
  return map.queryRenderedFeatures(point, {
@@ -1298,5 +1317,6 @@ function isPlainObject(value) {
1298
1317
  return prototype === Object.prototype || prototype === null;
1299
1318
  }
1300
1319
  export {
1301
- Map2 as Map
1320
+ Map2 as Map,
1321
+ configureTileflowMapLibre
1302
1322
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/react",
3
- "version": "0.1.0-alpha.23",
3
+ "version": "0.1.0-alpha.25",
4
4
  "license": "Apache-2.0",
5
5
  "description": "React components for rendering Tileflow maps with MapLibre.",
6
6
  "type": "module",
@@ -43,19 +43,19 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@tileflow/core": ">=0.1.0-alpha.24 <0.1.0-beta.0",
47
- "@tileflow/interactions": ">=0.1.0-alpha.2 <0.1.0-beta.0",
48
- "@tileflow/static": ">=0.1.0-alpha.23 <0.1.0-beta.0"
46
+ "@tileflow/core": ">=0.1.0-alpha.25 <0.1.0-beta.0",
47
+ "@tileflow/interactions": ">=0.1.0-alpha.4 <0.1.0-beta.0",
48
+ "@tileflow/static": ">=0.1.0-alpha.26 <0.1.0-beta.0"
49
49
  },
50
50
  "peerDependencies": {
51
- "maplibre-gl": ">=5 <7",
51
+ "maplibre-gl": ">=6.4.1 <7",
52
52
  "react": ">=18 <20",
53
53
  "react-dom": ">=18 <20"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/react": "^19.2.17",
57
57
  "@types/react-dom": "^19.2.3",
58
- "maplibre-gl": "^5.24.0",
58
+ "maplibre-gl": "6.9.0",
59
59
  "react": "^19.2.7",
60
60
  "react-dom": "^19.2.7"
61
61
  },