@tileflow/react-native 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +14 -3
- package/TileflowNativeAdmission.podspec +1 -1
- package/android/build.gradle +3 -3
- package/dist/{contract-Bwl-gB-I.d.ts → contract-Bp-Im7tj.d.ts} +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -18
- package/dist/internal/camera.d.ts +1 -1
- package/dist/internal/hosted-binding.js +3 -1
- package/dist/internal/initial-view.d.ts +1 -1
- package/dist/internal/interactions.js +10 -13
- package/dist/internal/native-appearance.d.ts +1 -1
- package/dist/internal/native-configuration-bridge.js +3 -1
- package/dist/internal/source-state.d.ts +1 -1
- package/docs/native-admission.md +2 -2
- package/ios/tileflow_native_admission.rb +2 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`@tileflow/react-native` provides a Tileflow `Map` backed by MapLibre Native on iOS and Android. It is pre-release. The first alpha release requires the bootstrap and Trusted Publisher checks in the [publishing guide](https://github.com/tileflow/tileflow-sdk/blob/main/PUBLISHING.md).
|
|
4
4
|
|
|
5
|
-
The package targets exactly React 19.2.0, React Native 0.83.10 and `@maplibre/maplibre-react-native` 11.
|
|
5
|
+
The package targets exactly React 19.2.0, React Native 0.83.10 and `@maplibre/maplibre-react-native` 11.5.0, with MapLibre Native Android 13.6.1 and iOS 6.31.0 through the pinned integration below. Expo consumers use Expo 55.0.31 with a native development build; Expo Go does not contain the required native modules.
|
|
6
6
|
|
|
7
7
|
> Related packages and guides: [documentation index](https://raw.githubusercontent.com/tileflow/tileflow-sdk/main/llms.txt).
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ The package targets exactly React 19.2.0, React Native 0.83.10 and `@maplibre/ma
|
|
|
11
11
|
Start with an Expo development build or a bare React Native application matching those peers. Once the first alpha is available, install the package and its direct dependencies:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
npm install --save-exact @tileflow/react-native@alpha @tileflow/core@alpha @tileflow/interactions@alpha @maplibre/maplibre-react-native@11.
|
|
14
|
+
npm install --save-exact @tileflow/react-native@alpha @tileflow/core@alpha @tileflow/interactions@alpha @maplibre/maplibre-react-native@11.5.0
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Keep the lockfile. Complete the [native integration](#native-integration) before building the application. Source on `main` can precede npm; installation or local checks do not establish Hosted availability or physical-device acceptance.
|
|
@@ -87,6 +87,12 @@ and protected delivery still require HTTPS.
|
|
|
87
87
|
|
|
88
88
|
## Theme transitions and blends
|
|
89
89
|
|
|
90
|
+
Add `timeOfDay="dusk"` beside `theme` to select a map's optional `day`, `dawn`, `dusk`, or
|
|
91
|
+
`night` preset. For Streets, `theme="light"` with this preset selects the existing `dusk` palette.
|
|
92
|
+
Maps without this capability ignore the option; omitting it keeps the selected theme unchanged.
|
|
93
|
+
Changing it uses the existing theme transition. `themeBlend` takes precedence. See the
|
|
94
|
+
[authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md#style-with-themes-and-semantic-modules).
|
|
95
|
+
|
|
90
96
|
`themeTransition={{duration: 450}}` cross-fades theme changes: a snapshot of the drawn map covers it, follows the camera and fades out once the new theme is drawn. `themeBlend={{themes: ['night', 'dusk', 'day'], position}}` shows a continuous blend of the map's themes instead of `theme`; position 0 is the first theme and 1.5 is halfway from the second to the third:
|
|
91
97
|
|
|
92
98
|
```tsx
|
|
@@ -174,7 +180,7 @@ The public lifecycle surface remains:
|
|
|
174
180
|
|
|
175
181
|
## Native integration
|
|
176
182
|
|
|
177
|
-
Autolinking registers the private Android/iOS modules used by the mounted lifecycle. Android depends on the exact MapLibre React Native project and MapLibre Native 13.
|
|
183
|
+
Autolinking registers the private Android/iOS modules used by the mounted lifecycle. Android depends on the exact MapLibre React Native project and MapLibre Native 13.6.1. iOS uses the existing MapLibre React Native CocoaPod plus the exact MapLibre Native 6.31.0 Swift Package Manager product.
|
|
178
184
|
|
|
179
185
|
For the iOS post-install integration, retain the host's normal React Native/MapLibre setup and then call:
|
|
180
186
|
|
|
@@ -220,6 +226,11 @@ annotation or POI targets but no popup, callout, tooltip, sheet, panel or modal
|
|
|
220
226
|
The mounted component does not add location, selection-presentation UI, offline product APIs, an
|
|
221
227
|
Expo config plugin, CLI behavior, deployment or publication. The package remains pre-release.
|
|
222
228
|
|
|
229
|
+
Native maps do not draw a map's 3D scene. Core's 3D buildings, Tileflow landmarks, Team building
|
|
230
|
+
models, 3D trees and street lights are WebGL layers for MapLibre GL JS, which the web `Map`
|
|
231
|
+
components mount by default; a native map shows the style's 2D layers and the vegetation fallback
|
|
232
|
+
the map declares.
|
|
233
|
+
|
|
223
234
|
Source and tests describe contracts; they do not establish that a native build, simulator/device run, Hosted service, app-store submission or package publication succeeded. Qualify the exact source revision in the intended host before relying on it.
|
|
224
235
|
|
|
225
236
|
## Foreground location is application-owned
|
|
@@ -18,7 +18,7 @@ Pod::Spec.new do |s|
|
|
|
18
18
|
s.frameworks = 'Foundation', 'UIKit'
|
|
19
19
|
s.libraries = 'c++'
|
|
20
20
|
s.dependency 'React-Core', '0.83.10'
|
|
21
|
-
s.dependency 'MapLibreReactNative', '11.
|
|
21
|
+
s.dependency 'MapLibreReactNative', '11.5.0'
|
|
22
22
|
# Surface integration consumes only the pinned peer's private native view/camera headers.
|
|
23
23
|
# No Tileflow native header is promoted to a public CocoaPods header.
|
|
24
24
|
s.pod_target_xcconfig = {
|
package/android/build.gradle
CHANGED
|
@@ -6,9 +6,9 @@ if (agpMajor < 9 || (agpMajor == 9 && !providers.gradleProperty('android.builtIn
|
|
|
6
6
|
apply plugin: 'org.jetbrains.kotlin.android'
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
def nativeVersion = rootProject.ext.has('org.maplibre.reactnative.nativeVersion') ? rootProject.ext.get('org.maplibre.reactnative.nativeVersion').toString() : '13.
|
|
9
|
+
def nativeVersion = rootProject.ext.has('org.maplibre.reactnative.nativeVersion') ? rootProject.ext.get('org.maplibre.reactnative.nativeVersion').toString() : '13.6.1'
|
|
10
10
|
def nativeVariant = rootProject.ext.has('org.maplibre.reactnative.nativeVariant') ? rootProject.ext.get('org.maplibre.reactnative.nativeVariant').toString() : 'opengl'
|
|
11
|
-
if (nativeVersion != '13.
|
|
11
|
+
if (nativeVersion != '13.6.1') throw new GradleException('Tileflow native admission requires MapLibre Native 13.6.1')
|
|
12
12
|
|
|
13
13
|
android {
|
|
14
14
|
namespace 'dev.tileflow.reactnative'
|
|
@@ -35,7 +35,7 @@ repositories {
|
|
|
35
35
|
dependencies {
|
|
36
36
|
implementation project(':maplibre_maplibre-react-native')
|
|
37
37
|
implementation('com.facebook.react:react-android:0.83.10') { version { strictly '0.83.10' } }
|
|
38
|
-
implementation("org.maplibre.gl:android-sdk-${nativeVariant}:13.
|
|
38
|
+
implementation("org.maplibre.gl:android-sdk-${nativeVariant}:13.6.1") { version { strictly '13.6.1' } }
|
|
39
39
|
implementation('com.squareup.okhttp3:okhttp:4.12.0') { version { strictly '4.12.0' } }
|
|
40
40
|
testImplementation 'junit:junit:4.13.2'
|
|
41
41
|
testImplementation 'org.robolectric:robolectric:4.14.1'
|
|
@@ -49,6 +49,7 @@ type MapThemeBlend = Readonly<{
|
|
|
49
49
|
type MapSourceProps = Readonly<{
|
|
50
50
|
source: MapSource;
|
|
51
51
|
theme?: MapThemeSelection;
|
|
52
|
+
timeOfDay?: TileflowNativeSourceOptions['timeOfDay'];
|
|
52
53
|
/** Cross-fades theme changes, including entering and leaving a blend. */
|
|
53
54
|
themeTransition?: MapThemeTransition;
|
|
54
55
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { TileflowAnnotation } from '@tileflow/interactions';
|
|
3
3
|
export { TileflowAnnotation, TileflowInteractionBinding, TileflowInteractionCoordinate, TileflowInteractionDiagnostic, TileflowPoiCategory, TileflowResolvedAnnotationTarget, TileflowResolvedPoiFeatureTarget } from '@tileflow/interactions';
|
|
4
|
-
import { d as MapProps } from './contract-
|
|
5
|
-
export { e as MapBaseProps, c as MapCameraProps, f as MapColorScheme, g as MapErrorEvent, h as MapEventHandlers, b as MapInitialViewInputs, i as MapInteractionEvent, j as MapInteractionProps, k as MapLoadEvent, l as MapMarkerRenderContext, m as MapMarkerRenderer, n as MapOptions, o as MapPresentationProps, p as MapReadinessChangeEvent, q as MapRef, r as MapSelection, s as MapSource, t as MapSourceError, u as MapSourceProps, v as MapSourceState, w as MapTheme, x as MapThemeBlend, y as MapThemeChangeEvent, z as MapThemeSelection, A as MapThemeTransition, M as MapView, a as MapViewChangeEvent } from './contract-
|
|
4
|
+
import { d as MapProps } from './contract-Bp-Im7tj.js';
|
|
5
|
+
export { e as MapBaseProps, c as MapCameraProps, f as MapColorScheme, g as MapErrorEvent, h as MapEventHandlers, b as MapInitialViewInputs, i as MapInteractionEvent, j as MapInteractionProps, k as MapLoadEvent, l as MapMarkerRenderContext, m as MapMarkerRenderer, n as MapOptions, o as MapPresentationProps, p as MapReadinessChangeEvent, q as MapRef, r as MapSelection, s as MapSource, t as MapSourceError, u as MapSourceProps, v as MapSourceState, w as MapTheme, x as MapThemeBlend, y as MapThemeChangeEvent, z as MapThemeSelection, A as MapThemeTransition, M as MapView, a as MapViewChangeEvent } from './contract-Bp-Im7tj.js';
|
|
6
6
|
import '@maplibre/maplibre-react-native';
|
|
7
7
|
import 'react-native';
|
|
8
8
|
import '@tileflow/core/native';
|
package/dist/index.js
CHANGED
|
@@ -253,7 +253,7 @@ function parseManifest(style) {
|
|
|
253
253
|
if (nativeInteractionField(style, "version") !== 8) throw new Error();
|
|
254
254
|
const metadata = nativeInteractionField(style, "metadata");
|
|
255
255
|
const artifact = snapshotNativeInteractionJson(nativeInteractionField(metadata, "tileflow:interaction-manifest"));
|
|
256
|
-
if (nativeInteractionField(artifact, "version") !==
|
|
256
|
+
if (nativeInteractionField(artifact, "version") !== 3) throw new Error();
|
|
257
257
|
const poi = nativeInteractionField(nativeInteractionField(artifact, "domains"), "poi");
|
|
258
258
|
if (nativeInteractionField(poi, "identity") !== "maplibre-feature-id-if-present") throw new Error();
|
|
259
259
|
const hitTesting = nativeInteractionField(poi, "hitTesting");
|
|
@@ -296,10 +296,9 @@ function parseManifest(style) {
|
|
|
296
296
|
const layerId = nativeInteractionField(input, "layerId");
|
|
297
297
|
const source = nativeInteractionField(input, "source");
|
|
298
298
|
const sourceLayer = nativeInteractionField(input, "sourceLayer");
|
|
299
|
-
const layerCategory = nativeInteractionField(input, "category");
|
|
300
299
|
const kind = nativeInteractionField(input, "representation");
|
|
301
300
|
const priority = nativeInteractionField(input, "priority");
|
|
302
|
-
if (!name(layerId) || !name(source) || sourceLayer !== void 0 && !name(sourceLayer) || !
|
|
301
|
+
if (!name(layerId) || !name(source) || sourceLayer !== void 0 && !name(sourceLayer) || !representation(kind) || typeof priority !== "number" || !Number.isSafeInteger(priority) || priority < 0 || priority > 1e5 || ids.has(layerId) || nativeInteractionField(input, "anchor") !== "pointer-coordinate")
|
|
303
302
|
throw new Error();
|
|
304
303
|
const actual = physical.get(layerId);
|
|
305
304
|
if (!actual || nativeInteractionField(actual, "source") !== source || nativeInteractionField(actual, "source-layer") !== sourceLayer)
|
|
@@ -313,7 +312,6 @@ function parseManifest(style) {
|
|
|
313
312
|
layerId,
|
|
314
313
|
source,
|
|
315
314
|
...sourceLayer === void 0 ? {} : { sourceLayer },
|
|
316
|
-
category: layerCategory,
|
|
317
315
|
representation: kind,
|
|
318
316
|
priority
|
|
319
317
|
});
|
|
@@ -367,8 +365,11 @@ function choose(features, manifest, bindings, coordinate2, queried) {
|
|
|
367
365
|
if (!layer || !allowed2.has(layer.layerId)) continue;
|
|
368
366
|
if (nativeInteractionField(feature, "source") !== layer.source || nativeInteractionField(feature, "sourceLayer") !== layer.sourceLayer)
|
|
369
367
|
throw new Error();
|
|
368
|
+
const featureProperties = properties(nativeInteractionField(feature, "properties"), manifest.fields);
|
|
369
|
+
const featureCategory = featureProperties.category;
|
|
370
|
+
if (!category(featureCategory)) throw new Error();
|
|
370
371
|
const binding = bindings.find(
|
|
371
|
-
(value) => value.target.kind === "semantic-feature" && value.target.domain === "poi" && (!value.target.categories || value.target.categories.includes(
|
|
372
|
+
(value) => value.target.kind === "semantic-feature" && value.target.domain === "poi" && (!value.target.categories || value.target.categories.includes(featureCategory))
|
|
372
373
|
);
|
|
373
374
|
if (!binding) continue;
|
|
374
375
|
const stable = featureId(nativeInteractionField(feature, "id"));
|
|
@@ -378,9 +379,9 @@ function choose(features, manifest, bindings, coordinate2, queried) {
|
|
|
378
379
|
coordinate: coordinate2,
|
|
379
380
|
bindingId: binding.id,
|
|
380
381
|
feature: {
|
|
381
|
-
category:
|
|
382
|
+
category: featureCategory,
|
|
382
383
|
...stable === void 0 ? {} : { id: stable },
|
|
383
|
-
properties:
|
|
384
|
+
properties: featureProperties
|
|
384
385
|
}
|
|
385
386
|
});
|
|
386
387
|
const candidate = { layer, renderedIndex, match: Object.freeze({ binding, target }) };
|
|
@@ -443,7 +444,7 @@ function createNativePoiAdapter() {
|
|
|
443
444
|
},
|
|
444
445
|
supports(target) {
|
|
445
446
|
const parsed = manifest;
|
|
446
|
-
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed && parsed.layers.
|
|
447
|
+
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed && parsed.layers.length > 0 && category(target.feature.category);
|
|
447
448
|
},
|
|
448
449
|
replaceStyle(next) {
|
|
449
450
|
if (disposed) return emptyDiagnostics;
|
|
@@ -499,11 +500,7 @@ function createNativePoiAdapter() {
|
|
|
499
500
|
if (!owner || !selected) return answer(failure());
|
|
500
501
|
const ownership = inspect(owner, expected);
|
|
501
502
|
if (ownership !== "current") return answer(ownership === "error" ? failure() : stale);
|
|
502
|
-
const layers = selected.layers.
|
|
503
|
-
(layer) => bindings.some(
|
|
504
|
-
(binding) => binding.target.kind === "semantic-feature" && (!binding.target.categories || binding.target.categories.includes(layer.category))
|
|
505
|
-
)
|
|
506
|
-
).map((layer) => layer.layerId);
|
|
503
|
+
const layers = selected.layers.map((layer) => layer.layerId);
|
|
507
504
|
if (!layers.length) return answer(miss);
|
|
508
505
|
if (!invocationIsLive()) return Promise.resolve(stale);
|
|
509
506
|
const request = Object.freeze({
|
|
@@ -849,7 +846,7 @@ function requestedLayers(style, request) {
|
|
|
849
846
|
const physical = array2(nativeInteractionField(style, "layers"), 4096);
|
|
850
847
|
const sources = nativeInteractionField(style, "sources");
|
|
851
848
|
const artifact = nativeInteractionField(nativeInteractionField(style, "metadata"), "tileflow:interaction-manifest");
|
|
852
|
-
if (nativeInteractionField(artifact, "version") !==
|
|
849
|
+
if (nativeInteractionField(artifact, "version") !== 3) throw new Error();
|
|
853
850
|
const semantic = array2(nativeInteractionField(nativeInteractionField(nativeInteractionField(artifact, "domains"), "poi"), "layers"), 256);
|
|
854
851
|
let previous = physical.length;
|
|
855
852
|
return requested.map((id) => {
|
|
@@ -3445,7 +3442,9 @@ function snapshotHostedNativeManifestIdentity(source) {
|
|
|
3445
3442
|
if (sourceUrl !== expected || finalUrl !== expected) throw new Error();
|
|
3446
3443
|
const manifest = field(source, "manifest");
|
|
3447
3444
|
const maps = field(manifest, "maps");
|
|
3448
|
-
|
|
3445
|
+
const manifestVersion = field(manifest, "version");
|
|
3446
|
+
if (manifestVersion !== 1 && manifestVersion !== 2 || names(maps, 1)[0] !== name3)
|
|
3447
|
+
throw new Error();
|
|
3449
3448
|
const declared = field(maps, name3);
|
|
3450
3449
|
if (field(declared, "mapId") !== mapId || field(declared, "usageMode") !== "session")
|
|
3451
3450
|
throw new Error();
|
|
@@ -5574,6 +5573,8 @@ function createMountedMapOwner(ports2) {
|
|
|
5574
5573
|
let sourceKey;
|
|
5575
5574
|
let sourceObject;
|
|
5576
5575
|
let selectedTheme;
|
|
5576
|
+
let selectedTimeOfDay;
|
|
5577
|
+
const timeSelection = () => !blendSelection && props?.timeOfDay !== void 0 ? { timeOfDay: props.timeOfDay } : {};
|
|
5577
5578
|
let colorScheme;
|
|
5578
5579
|
let appearanceRelease;
|
|
5579
5580
|
let appearanceEpoch = 0;
|
|
@@ -5891,7 +5892,13 @@ function createMountedMapOwner(ports2) {
|
|
|
5891
5892
|
cancelJob(epoch);
|
|
5892
5893
|
epoch.cache.clear();
|
|
5893
5894
|
if (!disposed && foreground && current === epoch && epoch.live && props) {
|
|
5894
|
-
track(
|
|
5895
|
+
track(
|
|
5896
|
+
core.replace(props.source, {
|
|
5897
|
+
theme: selectionTheme(),
|
|
5898
|
+
colorScheme,
|
|
5899
|
+
...timeSelection()
|
|
5900
|
+
})
|
|
5901
|
+
);
|
|
5895
5902
|
}
|
|
5896
5903
|
return;
|
|
5897
5904
|
}
|
|
@@ -5928,7 +5935,7 @@ function createMountedMapOwner(ports2) {
|
|
|
5928
5935
|
function select() {
|
|
5929
5936
|
if (disposed || !props || !current?.live) return;
|
|
5930
5937
|
current.hosted.select();
|
|
5931
|
-
track(core.replace(props.source, { theme: selectionTheme(), colorScheme }));
|
|
5938
|
+
track(core.replace(props.source, { theme: selectionTheme(), colorScheme, ...timeSelection() }));
|
|
5932
5939
|
}
|
|
5933
5940
|
function appearance(theme) {
|
|
5934
5941
|
if (theme === "system" === Boolean(appearanceRelease)) return;
|
|
@@ -6007,7 +6014,7 @@ function createMountedMapOwner(ports2) {
|
|
|
6007
6014
|
if (changedBlend || !blend) blendTheme = nearest;
|
|
6008
6015
|
const key2 = source && JSON.stringify(source);
|
|
6009
6016
|
const changedSource = !initialized || key2 !== sourceKey || key2 === void 0 && sourceObject !== next.source;
|
|
6010
|
-
const changedTheme = !initialized || !blend && next.theme !== selectedTheme;
|
|
6017
|
+
const changedTheme = !initialized || !blend && (next.theme !== selectedTheme || next.timeOfDay !== selectedTimeOfDay);
|
|
6011
6018
|
const changedOptions = JSON.stringify(options) !== JSON.stringify(mapOptions);
|
|
6012
6019
|
camera = input;
|
|
6013
6020
|
mapOptions = options;
|
|
@@ -6020,6 +6027,7 @@ function createMountedMapOwner(ports2) {
|
|
|
6020
6027
|
sourceObject = next.source;
|
|
6021
6028
|
}
|
|
6022
6029
|
selectedTheme = next.theme;
|
|
6030
|
+
selectedTimeOfDay = next.timeOfDay;
|
|
6023
6031
|
initialized = true;
|
|
6024
6032
|
try {
|
|
6025
6033
|
appearance(next.theme);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-
|
|
1
|
+
import { M as MapView, a as MapViewChangeEvent, b as MapInitialViewInputs, c as MapCameraProps } from '../contract-Bp-Im7tj.js';
|
|
2
2
|
import '@maplibre/maplibre-react-native';
|
|
3
3
|
import 'react';
|
|
4
4
|
import 'react-native';
|
|
@@ -140,7 +140,9 @@ function snapshotHostedNativeManifestIdentity(source) {
|
|
|
140
140
|
if (sourceUrl !== expected || finalUrl !== expected) throw new Error();
|
|
141
141
|
const manifest = field(source, "manifest");
|
|
142
142
|
const maps = field(manifest, "maps");
|
|
143
|
-
|
|
143
|
+
const manifestVersion = field(manifest, "version");
|
|
144
|
+
if (manifestVersion !== 1 && manifestVersion !== 2 || names(maps, 1)[0] !== name)
|
|
145
|
+
throw new Error();
|
|
144
146
|
const declared = field(maps, name);
|
|
145
147
|
if (field(declared, "mapId") !== mapId || field(declared, "usageMode") !== "session")
|
|
146
148
|
throw new Error();
|
|
@@ -226,7 +226,7 @@ function parseManifest(style) {
|
|
|
226
226
|
if (nativeInteractionField(style, "version") !== 8) throw new Error();
|
|
227
227
|
const metadata = nativeInteractionField(style, "metadata");
|
|
228
228
|
const artifact = snapshotNativeInteractionJson(nativeInteractionField(metadata, "tileflow:interaction-manifest"));
|
|
229
|
-
if (nativeInteractionField(artifact, "version") !==
|
|
229
|
+
if (nativeInteractionField(artifact, "version") !== 3) throw new Error();
|
|
230
230
|
const poi = nativeInteractionField(nativeInteractionField(artifact, "domains"), "poi");
|
|
231
231
|
if (nativeInteractionField(poi, "identity") !== "maplibre-feature-id-if-present") throw new Error();
|
|
232
232
|
const hitTesting = nativeInteractionField(poi, "hitTesting");
|
|
@@ -269,10 +269,9 @@ function parseManifest(style) {
|
|
|
269
269
|
const layerId = nativeInteractionField(input, "layerId");
|
|
270
270
|
const source = nativeInteractionField(input, "source");
|
|
271
271
|
const sourceLayer = nativeInteractionField(input, "sourceLayer");
|
|
272
|
-
const layerCategory = nativeInteractionField(input, "category");
|
|
273
272
|
const kind = nativeInteractionField(input, "representation");
|
|
274
273
|
const priority = nativeInteractionField(input, "priority");
|
|
275
|
-
if (!name(layerId) || !name(source) || sourceLayer !== void 0 && !name(sourceLayer) || !
|
|
274
|
+
if (!name(layerId) || !name(source) || sourceLayer !== void 0 && !name(sourceLayer) || !representation(kind) || typeof priority !== "number" || !Number.isSafeInteger(priority) || priority < 0 || priority > 1e5 || ids.has(layerId) || nativeInteractionField(input, "anchor") !== "pointer-coordinate")
|
|
276
275
|
throw new Error();
|
|
277
276
|
const actual = physical.get(layerId);
|
|
278
277
|
if (!actual || nativeInteractionField(actual, "source") !== source || nativeInteractionField(actual, "source-layer") !== sourceLayer)
|
|
@@ -286,7 +285,6 @@ function parseManifest(style) {
|
|
|
286
285
|
layerId,
|
|
287
286
|
source,
|
|
288
287
|
...sourceLayer === void 0 ? {} : { sourceLayer },
|
|
289
|
-
category: layerCategory,
|
|
290
288
|
representation: kind,
|
|
291
289
|
priority
|
|
292
290
|
});
|
|
@@ -340,8 +338,11 @@ function choose(features, manifest, bindings, coordinate, queried) {
|
|
|
340
338
|
if (!layer || !allowed.has(layer.layerId)) continue;
|
|
341
339
|
if (nativeInteractionField(feature, "source") !== layer.source || nativeInteractionField(feature, "sourceLayer") !== layer.sourceLayer)
|
|
342
340
|
throw new Error();
|
|
341
|
+
const featureProperties = properties(nativeInteractionField(feature, "properties"), manifest.fields);
|
|
342
|
+
const featureCategory = featureProperties.category;
|
|
343
|
+
if (!category(featureCategory)) throw new Error();
|
|
343
344
|
const binding = bindings.find(
|
|
344
|
-
(value) => value.target.kind === "semantic-feature" && value.target.domain === "poi" && (!value.target.categories || value.target.categories.includes(
|
|
345
|
+
(value) => value.target.kind === "semantic-feature" && value.target.domain === "poi" && (!value.target.categories || value.target.categories.includes(featureCategory))
|
|
345
346
|
);
|
|
346
347
|
if (!binding) continue;
|
|
347
348
|
const stable = featureId(nativeInteractionField(feature, "id"));
|
|
@@ -351,9 +352,9 @@ function choose(features, manifest, bindings, coordinate, queried) {
|
|
|
351
352
|
coordinate,
|
|
352
353
|
bindingId: binding.id,
|
|
353
354
|
feature: {
|
|
354
|
-
category:
|
|
355
|
+
category: featureCategory,
|
|
355
356
|
...stable === void 0 ? {} : { id: stable },
|
|
356
|
-
properties:
|
|
357
|
+
properties: featureProperties
|
|
357
358
|
}
|
|
358
359
|
});
|
|
359
360
|
const candidate = { layer, renderedIndex, match: Object.freeze({ binding, target }) };
|
|
@@ -416,7 +417,7 @@ function createNativePoiAdapter() {
|
|
|
416
417
|
},
|
|
417
418
|
supports(target) {
|
|
418
419
|
const parsed = manifest;
|
|
419
|
-
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed && parsed.layers.
|
|
420
|
+
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed && parsed.layers.length > 0 && category(target.feature.category);
|
|
420
421
|
},
|
|
421
422
|
replaceStyle(next) {
|
|
422
423
|
if (disposed) return emptyDiagnostics;
|
|
@@ -472,11 +473,7 @@ function createNativePoiAdapter() {
|
|
|
472
473
|
if (!owner || !selected) return answer(failure());
|
|
473
474
|
const ownership = inspect(owner, expected);
|
|
474
475
|
if (ownership !== "current") return answer(ownership === "error" ? failure() : stale);
|
|
475
|
-
const layers = selected.layers.
|
|
476
|
-
(layer) => bindings.some(
|
|
477
|
-
(binding) => binding.target.kind === "semantic-feature" && (!binding.target.categories || binding.target.categories.includes(layer.category))
|
|
478
|
-
)
|
|
479
|
-
).map((layer) => layer.layerId);
|
|
476
|
+
const layers = selected.layers.map((layer) => layer.layerId);
|
|
480
477
|
if (!layers.length) return answer(miss);
|
|
481
478
|
if (!invocationIsLive()) return Promise.resolve(stale);
|
|
482
479
|
const request = Object.freeze({
|
|
@@ -143,7 +143,9 @@ function snapshotHostedNativeManifestIdentity(source) {
|
|
|
143
143
|
if (sourceUrl !== expected || finalUrl !== expected) throw new Error();
|
|
144
144
|
const manifest = field(source, "manifest");
|
|
145
145
|
const maps = field(manifest, "maps");
|
|
146
|
-
|
|
146
|
+
const manifestVersion = field(manifest, "version");
|
|
147
|
+
if (manifestVersion !== 1 && manifestVersion !== 2 || names(maps, 1)[0] !== name)
|
|
148
|
+
throw new Error();
|
|
147
149
|
const declared = field(maps, name);
|
|
148
150
|
if (field(declared, "mapId") !== mapId || field(declared, "usageMode") !== "session")
|
|
149
151
|
throw new Error();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TileflowNativeSourceState } from '@tileflow/core/native';
|
|
2
|
-
import { v as MapSourceState } from '../contract-
|
|
2
|
+
import { v as MapSourceState } from '../contract-Bp-Im7tj.js';
|
|
3
3
|
import '@maplibre/maplibre-react-native';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react-native';
|
package/docs/native-admission.md
CHANGED
|
@@ -6,7 +6,7 @@ The mounted owner prepares a **bounded Style/TileJSON resource closure** before
|
|
|
6
6
|
|
|
7
7
|
## Exact native dependencies
|
|
8
8
|
|
|
9
|
-
The source targets React 19.2.0, React Native 0.83.10, MapLibre React Native 11.
|
|
9
|
+
The source targets React 19.2.0, React Native 0.83.10, MapLibre React Native 11.5.0, MapLibre Native Android 13.6.1 and MapLibre Native iOS 6.31.0. Android's HTTP dependency is OkHttp 4.12.0. These pins and the existence of source tests are **not evidence** of a successful build, device run, Hosted service or app-store acceptance; qualify the exact revision in the intended host.
|
|
10
10
|
|
|
11
11
|
Android's library build uses the host's Android Gradle/Kotlin plugins and SDK settings. `react-native.config.cjs` autolinks `TileflowNativeAdmissionPackage`, which registers the private admission, document, configuration and surface modules. The library depends on the autolinked `:maplibre_maplibre-react-native` project and rejects conflicting MapLibre Native versions rather than selecting another version silently.
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ $MLRN.post_install(installer)
|
|
|
17
17
|
tileflow_native_admission_post_install(installer)
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The helper requires the MapLibre distribution reference with `exactVersion` 6.
|
|
20
|
+
The helper requires the MapLibre distribution reference with `exactVersion` 6.31.0 and reuses that product for the Tileflow pod/test targets. It does not add another SDK or change the pin.
|
|
21
21
|
|
|
22
22
|
## Installation ownership
|
|
23
23
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
def tileflow_native_admission_post_install(installer)
|
|
5
5
|
project = installer.pods_project
|
|
6
6
|
url = 'https://github.com/maplibre/maplibre-gl-native-distribution'
|
|
7
|
-
version = '6.
|
|
7
|
+
version = '6.31.0'
|
|
8
8
|
refs = project.root_object.package_references.select do |reference|
|
|
9
9
|
reference.respond_to?(:repositoryURL) && reference.repositoryURL == url
|
|
10
10
|
end
|
|
@@ -12,7 +12,7 @@ def tileflow_native_admission_post_install(installer)
|
|
|
12
12
|
reference = refs.first
|
|
13
13
|
requirement = reference.requirement.transform_keys(&:to_s)
|
|
14
14
|
unless requirement == { 'kind' => 'exactVersion', 'version' => version }
|
|
15
|
-
raise 'Tileflow native admission requires the exact MapLibre Native 6.
|
|
15
|
+
raise 'Tileflow native admission requires the exact MapLibre Native 6.31.0 SPM product'
|
|
16
16
|
end
|
|
17
17
|
if defined?($MLRN_NATIVE_VERSION) && $MLRN_NATIVE_VERSION.to_s != version
|
|
18
18
|
raise 'Conflicting MapLibre Native version for Tileflow native admission'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/react-native",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Tileflow maps, camera control and semantic interactions for React Native.",
|
|
6
6
|
"type": "module",
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@tileflow/core": ">=0.1.0-alpha.
|
|
40
|
-
"@tileflow/interactions": ">=0.1.0-alpha.
|
|
39
|
+
"@tileflow/core": ">=0.1.0-alpha.38 <0.1.0-beta.0",
|
|
40
|
+
"@tileflow/interactions": ">=0.1.0-alpha.6 <0.1.0-beta.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@maplibre/maplibre-react-native": "11.
|
|
43
|
+
"@maplibre/maplibre-react-native": "11.5.0",
|
|
44
44
|
"react": "19.2.0",
|
|
45
45
|
"react-native": "0.83.10"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@maplibre/maplibre-react-native": "11.
|
|
48
|
+
"@maplibre/maplibre-react-native": "11.5.0",
|
|
49
49
|
"@types/react": "^19.2.17",
|
|
50
50
|
"react": "19.2.0",
|
|
51
51
|
"react-native": "0.83.10"
|