@tileflow/react-native 0.1.0-alpha.7 → 0.1.0-alpha.9
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 +19 -17
- package/dist/{contract-BaK24QZD.d.ts → contract-BWCbfMOx.d.ts} +19 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +444 -75
- package/dist/internal/camera.d.ts +1 -1
- package/dist/internal/initial-view.d.ts +1 -1
- package/dist/internal/interactions.js +1 -0
- package/dist/internal/native-admission.d.ts +1 -0
- package/dist/internal/native-admission.js +47 -21
- package/dist/internal/native-appearance.d.ts +1 -1
- package/dist/internal/session.d.ts +4 -1
- package/dist/internal/session.js +46 -20
- package/dist/internal/source-state.d.ts +1 -1
- package/package.json +3 -4
- package/docs/native-admission.md +0 -124
- package/docs/native-configuration.md +0 -210
- package/docs/native-interactions.md +0 -161
- package/docs/native-location.md +0 -148
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @tileflow/react-native
|
|
2
2
|
|
|
3
|
-
`@tileflow/react-native` provides a Tileflow `Map` backed by MapLibre Native on iOS and Android. It is pre-release.
|
|
3
|
+
`@tileflow/react-native` provides a Tileflow `Map` backed by MapLibre Native on iOS and Android. It is pre-release. Publication requires the repository’s protected release workflow.
|
|
4
4
|
|
|
5
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
|
|
|
@@ -91,7 +91,7 @@ Add `timeOfDay="dusk"` beside `theme` to select a map's optional `day`, `dawn`,
|
|
|
91
91
|
`night` preset. For Streets, `theme="light"` with this preset selects the existing `dusk` palette.
|
|
92
92
|
Maps without this capability ignore the option; omitting it keeps the selected theme unchanged.
|
|
93
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/
|
|
94
|
+
[authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/REFERENCE.md#style-with-themes-and-semantic-modules).
|
|
95
95
|
|
|
96
96
|
Theme and `timeOfDay` changes cross-fade over 450 ms by default: a snapshot of the drawn map covers it, follows the camera and fades out once the new theme is drawn. Use `themeTransition={{duration: 700}}` to customize the duration, or `duration: 0` for an immediate change. `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:
|
|
97
97
|
|
|
@@ -99,7 +99,7 @@ Theme and `timeOfDay` changes cross-fade over 450 ms by default: a snapshot of t
|
|
|
99
99
|
<Map source={source} themeBlend={{themes: ['night', 'dusk', 'day'], position}} style={{flex: 1}} />
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
The first blend of a set of themes prepares every theme's style and replaces the native style once; moving `position` later changes the map without loading. Removing `themeBlend` returns to `theme`. Both keep the same native Map, context and session, and `ready` events wait for the fade. The device's reduce-motion setting changes at once. See [theme transitions and blends](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/
|
|
102
|
+
The first blend of a set of themes prepares every theme's style and replaces the native style once; moving `position` later changes the map without loading. Removing `themeBlend` returns to `theme`. Both keep the same native Map, context and session, and `ready` events wait for the fade. The device's reduce-motion setting changes at once. See [theme transitions and blends](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) for what follows the position on native maps.
|
|
103
103
|
|
|
104
104
|
## Boundary choropleths
|
|
105
105
|
|
|
@@ -132,8 +132,7 @@ export function UnemploymentMap({
|
|
|
132
132
|
|
|
133
133
|
Values survive theme changes: they are set again once the new style has loaded. `values: null`
|
|
134
134
|
removes them. Rows keyed by codes the polygons do not carry are joined before they reach the app,
|
|
135
|
-
on a server or at build time
|
|
136
|
-
[boundary areas and choropleths](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/boundary-areas-and-choropleths.md#join-by-codes-the-polygons-do-not-carry).
|
|
135
|
+
on a server or at build time.
|
|
137
136
|
|
|
138
137
|
## Camera
|
|
139
138
|
|
|
@@ -178,16 +177,12 @@ Relative URLs are resolved with Core's native URL policy. Protected resources ar
|
|
|
178
177
|
|
|
179
178
|
Glyph templates use a finite set of exact font-stack expansions. A later theme may extend that same template only through an acknowledged append-only finite union; it cannot change the resource scope, origin or identity.
|
|
180
179
|
|
|
181
|
-
See [Private native resource admission](./docs/native-admission.md) for the transport and security boundaries.
|
|
182
|
-
|
|
183
180
|
## Hosted mobile application configuration
|
|
184
181
|
|
|
185
182
|
Hosted native session delivery uses a scoped, revocable, publishable **mobile application credential** configured once in the native application. It authenticates the distributed application, not its end user. The manifest supplies `mapId`, `apiUrl` and `usageMode`; Tileflow requires the manifest API origin to exactly match the configured canonical HTTPS origin before bootstrap.
|
|
186
183
|
|
|
187
184
|
There is intentionally no credential prop, JS setter, Provider, client object, package-name/bundle-ID authentication or attestation path in this version.
|
|
188
185
|
|
|
189
|
-
See [Native application configuration](./docs/native-configuration.md) for the exact Android resource and iOS Info.plist keys, credential grammar, origin normalization, rotation/revocation guidance and threat model.
|
|
190
|
-
|
|
191
186
|
## Map options and presentation
|
|
192
187
|
|
|
193
188
|
The public `mapOptions` object remains a positive allowlist. It includes the currently supported gesture/control options only. Style inputs, request transformation, headers and upstream lifecycle callbacks remain owned by Tileflow. Runtime validation rejects forged extra keys without reflecting their values.
|
|
@@ -208,7 +203,7 @@ The public lifecycle surface remains:
|
|
|
208
203
|
|
|
209
204
|
`getSourceState()` returns only the last safe projected source snapshot. Errors use existing bounded codes/fields/kinds. No URL, response body, native event, credential, grant, session object, native handle or raw cause enters public callbacks, refs or serializable state.
|
|
210
205
|
|
|
211
|
-
`onError` reports `source-error`, `renderer-error` and, for Hosted session delivery, `session-error`. A `session-error` means Tileflow refused the session: the mobile credential was rejected (`NATIVE_SESSION_CREDENTIAL_REJECTED`), it does not authorize the Map (`NATIVE_SESSION_MAP_MISMATCH`), the Map was not found (`NATIVE_SESSION_MAP_NOT_FOUND`)
|
|
206
|
+
`onError` reports `source-error`, `renderer-error` and, for Hosted session delivery, `session-error`. A `session-error` means Tileflow refused the session: the mobile credential was rejected (`NATIVE_SESSION_CREDENTIAL_REJECTED`), it does not authorize the Map (`NATIVE_SESSION_MAP_MISMATCH`), the Map was not found (`NATIVE_SESSION_MAP_NOT_FOUND`), its view or spending limit was reached (`NATIVE_SESSION_QUOTA_EXCEEDED`), or the service refused the session for another reason that trying again cannot change (`NATIVE_SESSION_REJECTED`), such as a Map that does not use session delivery. For `NATIVE_SESSION_REJECTED`, `event.error.reason` is the service's code when it sent one, for example `MOBILE_SESSION_MODE_REQUIRED`; it is a bounded identifier, never a message or response body. A `session-error` can arrive after the first load, when a renewal is refused. The map keeps what it has drawn but loads nothing new until you call `ref.retry()` or change the source:
|
|
212
207
|
|
|
213
208
|
```tsx
|
|
214
209
|
import {Map, type MapRef} from '@tileflow/react-native';
|
|
@@ -226,6 +221,11 @@ export function StoreMap() {
|
|
|
226
221
|
event.error.code === 'NATIVE_SESSION_QUOTA_EXCEEDED'
|
|
227
222
|
) {
|
|
228
223
|
// Show your own notice; call map.current?.retry() once the limit is raised.
|
|
224
|
+
} else if (
|
|
225
|
+
event.type === 'session-error' &&
|
|
226
|
+
event.error.code === 'NATIVE_SESSION_REJECTED'
|
|
227
|
+
) {
|
|
228
|
+
// event.error.reason, such as 'MOBILE_SESSION_MODE_REQUIRED', names the cause.
|
|
229
229
|
}
|
|
230
230
|
}}
|
|
231
231
|
style={{flex: 1}}
|
|
@@ -247,7 +247,7 @@ $MLRN.post_install(installer)
|
|
|
247
247
|
tileflow_native_admission_post_install(installer)
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
Do not add a second MapLibre Native CocoaPod.
|
|
250
|
+
Do not add a second MapLibre Native CocoaPod.
|
|
251
251
|
|
|
252
252
|
## Source-checkout harness
|
|
253
253
|
|
|
@@ -275,9 +275,15 @@ wrapper. A bounded accessible marker is rendered when `renderMarker` is omitted.
|
|
|
275
275
|
remain in native vector or GeoJSON layers and are selected through semantic rendered-feature
|
|
276
276
|
queries rather than thousands of React marker views.
|
|
277
277
|
|
|
278
|
+
`Map` also takes the web adapters' `dataSources`, `dataOverlays` and `annotationClusters`, with
|
|
279
|
+
`geojsonSource()`, `clusterOverlay()` and `heatmapOverlay()` from `@tileflow/core/native`. Tapping a
|
|
280
|
+
cluster zooms in unless the application controls `view`, and reports a `cluster` target through
|
|
281
|
+
`onInteractionEvent`. Compiled clusters and heatmaps are checked by
|
|
282
|
+
`tileflow validate --renderer native`. Polygon drawing with Terra Draw is web-only. See the
|
|
283
|
+
[interactions reference](https://github.com/tileflow/tileflow-sdk/blob/main/packages/interactions/REFERENCE.md).
|
|
284
|
+
|
|
278
285
|
The application owns persistent selection and its presentation. The SDK emits normalized
|
|
279
|
-
annotation or POI targets but no popup, callout, tooltip, sheet, panel or modal renderer.
|
|
280
|
-
[Native interaction contract](./docs/native-interactions.md).
|
|
286
|
+
annotation or POI targets but no popup, callout, tooltip, sheet, panel or modal renderer.
|
|
281
287
|
|
|
282
288
|
## Current boundary
|
|
283
289
|
|
|
@@ -297,7 +303,3 @@ Source and tests describe contracts; they do not establish that a native build,
|
|
|
297
303
|
fix arrives. Applications can compose a validated foreground fix through the existing accessible
|
|
298
304
|
annotation and controlled-camera contracts while keeping permission, provider lifetime, privacy
|
|
299
305
|
policy, status UI and recenter controls outside Tileflow.
|
|
300
|
-
|
|
301
|
-
See [Application-owned foreground location](./docs/native-location.md) for the package-owned
|
|
302
|
-
source-checkout recipe. The recipe is excluded from package exports and packed runtime files and
|
|
303
|
-
imports no concrete location provider.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MapProps as MapProps$1 } from '@maplibre/maplibre-react-native';
|
|
2
2
|
import { ReactElement, ReactNode, Ref } from 'react';
|
|
3
3
|
import { ViewProps } from 'react-native';
|
|
4
|
-
import { TileflowNativeInitialView, TileflowNativeInitialViewOptions, TileflowNativeSource, TileflowNativeSourceOptions, TileflowBoundaryValues, TileflowBoundaryFamily, TileflowNativeSourceState, TileflowNativeSourceError } from '@tileflow/core/native';
|
|
5
|
-
import { TileflowAnnotation, TileflowInteractionBinding, TileflowInteractionEvent, TileflowResolvedAnnotationTarget, TileflowResolvedPoiFeatureTarget, TileflowInteractionDiagnostic, TileflowAnnotationViewContext } from '@tileflow/interactions';
|
|
4
|
+
import { TileflowMapLibreOverlay, TileflowGeoJsonSource, TileflowNativeInitialView, TileflowNativeInitialViewOptions, TileflowNativeSource, TileflowNativeSourceOptions, TileflowBoundaryValues, TileflowBoundaryFamily, TileflowNativeSourceState, TileflowNativeSourceError } from '@tileflow/core/native';
|
|
5
|
+
import { TileflowAnnotation, TileflowAnnotationClusterOptions, TileflowInteractionBinding, TileflowInteractionEvent, TileflowResolvedAnnotationTarget, TileflowResolvedClusterTarget, TileflowResolvedPoiFeatureTarget, TileflowResolvedStyleFeatureTarget, TileflowInteractionDiagnostic, TileflowAnnotationViewContext } from '@tileflow/interactions';
|
|
6
6
|
|
|
7
7
|
/** Marker composition only. Selection presentation and native handles are not part of this context. */
|
|
8
8
|
type MapMarkerRenderContext<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = Readonly<Pick<TileflowAnnotationViewContext<TAnnotation>, 'annotation' | 'target' | 'content' | 'viewName'>>;
|
|
@@ -10,11 +10,17 @@ type MapMarkerRenderContext<TAnnotation extends TileflowAnnotation = TileflowAnn
|
|
|
10
10
|
type MapMarkerRenderer<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = (context: MapMarkerRenderContext<TAnnotation>) => ReactElement;
|
|
11
11
|
/** Mobile reports activation; the application owns any persistent selection. */
|
|
12
12
|
type MapInteractionEvent<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = Readonly<Omit<TileflowInteractionEvent<TAnnotation>, 'target' | 'type'> & {
|
|
13
|
-
target: TileflowResolvedAnnotationTarget<TAnnotation> | TileflowResolvedPoiFeatureTarget;
|
|
13
|
+
target: TileflowResolvedAnnotationTarget<TAnnotation> | TileflowResolvedClusterTarget | TileflowResolvedPoiFeatureTarget | TileflowResolvedStyleFeatureTarget;
|
|
14
14
|
type: 'target:activate';
|
|
15
15
|
}>;
|
|
16
16
|
type MapInteractionProps<TAnnotation extends TileflowAnnotation = TileflowAnnotation> = Readonly<{
|
|
17
|
+
/** Group `annotations` into accessible native cluster buttons. Up to 1,000 annotations. */
|
|
18
|
+
annotationClusters?: TileflowAnnotationClusterOptions;
|
|
17
19
|
annotations?: readonly TAnnotation[];
|
|
20
|
+
/** Overlays drawn over `dataSources` or compiled sources, keyed as in `defineMap`. */
|
|
21
|
+
dataOverlays?: Readonly<Record<string, TileflowMapLibreOverlay>>;
|
|
22
|
+
/** Application GeoJSON, keyed as in `defineMap`. A compiled source of the same key is filled. */
|
|
23
|
+
dataSources?: Readonly<Record<string, TileflowGeoJsonSource>>;
|
|
18
24
|
interactions?: readonly TileflowInteractionBinding[];
|
|
19
25
|
onInteractionEvent?: (event: MapInteractionEvent<TAnnotation>) => void;
|
|
20
26
|
onInteractionDiagnostic?: (diagnostic: TileflowInteractionDiagnostic) => void;
|
|
@@ -110,13 +116,19 @@ type MapSourceState = Readonly<{
|
|
|
110
116
|
error: MapSourceError;
|
|
111
117
|
}>;
|
|
112
118
|
/**
|
|
113
|
-
* The Hosted session stopped: its credential, Map or quota was rejected
|
|
114
|
-
*
|
|
115
|
-
*
|
|
119
|
+
* The Hosted session stopped: its credential, Map or quota was rejected, or Tileflow refused the
|
|
120
|
+
* session for another reason that trying again will not change (`NATIVE_SESSION_REJECTED`). The map
|
|
121
|
+
* keeps what it has drawn and loads nothing new until `ref.retry()` or another source. Service
|
|
122
|
+
* outages and rate limits retry on their own and are not reported.
|
|
116
123
|
*/
|
|
117
124
|
type MapSessionError = Readonly<{
|
|
118
|
-
code: 'NATIVE_SESSION_CREDENTIAL_REJECTED' | 'NATIVE_SESSION_MAP_MISMATCH' | 'NATIVE_SESSION_MAP_NOT_FOUND' | 'NATIVE_SESSION_QUOTA_EXCEEDED' | 'NATIVE_SESSION_INPUT_INVALID';
|
|
125
|
+
code: 'NATIVE_SESSION_CREDENTIAL_REJECTED' | 'NATIVE_SESSION_MAP_MISMATCH' | 'NATIVE_SESSION_MAP_NOT_FOUND' | 'NATIVE_SESSION_QUOTA_EXCEEDED' | 'NATIVE_SESSION_REJECTED' | 'NATIVE_SESSION_INPUT_INVALID';
|
|
119
126
|
kind: 'terminal';
|
|
127
|
+
/**
|
|
128
|
+
* For `NATIVE_SESSION_REJECTED`, the service's code when its answer carried one, such as
|
|
129
|
+
* `MOBILE_SESSION_MODE_REQUIRED`. A bounded identifier, never a message or response body.
|
|
130
|
+
*/
|
|
131
|
+
reason?: string;
|
|
120
132
|
}>;
|
|
121
133
|
type MapRef = Readonly<{
|
|
122
134
|
/** A synchronous read of the last source snapshot. Does not trigger loading or native commands. */
|
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, f as MapBoundaryFeatureState, c as MapCameraProps, g as MapColorScheme, h as MapErrorEvent, i as MapEventHandlers, b as MapInitialViewInputs, j as MapInteractionEvent, k as MapInteractionProps, l as MapLoadEvent, m as MapMarkerRenderContext, n as MapMarkerRenderer, o as MapOptions, p as MapPresentationProps, q as MapReadinessChangeEvent, r as MapRef, s as MapSelection, t as MapSessionError, u as MapSource, v as MapSourceError, w as MapSourceProps, x as MapSourceState, y as MapTheme, z as MapThemeBlend, A as MapThemeChangeEvent, B as MapThemeSelection, C as MapThemeTransition, M as MapView, a as MapViewChangeEvent } from './contract-
|
|
4
|
+
import { d as MapProps } from './contract-BWCbfMOx.js';
|
|
5
|
+
export { e as MapBaseProps, f as MapBoundaryFeatureState, c as MapCameraProps, g as MapColorScheme, h as MapErrorEvent, i as MapEventHandlers, b as MapInitialViewInputs, j as MapInteractionEvent, k as MapInteractionProps, l as MapLoadEvent, m as MapMarkerRenderContext, n as MapMarkerRenderer, o as MapOptions, p as MapPresentationProps, q as MapReadinessChangeEvent, r as MapRef, s as MapSelection, t as MapSessionError, u as MapSource, v as MapSourceError, w as MapSourceProps, x as MapSourceState, y as MapTheme, z as MapThemeBlend, A as MapThemeChangeEvent, B as MapThemeSelection, C as MapThemeTransition, M as MapView, a as MapViewChangeEvent } from './contract-BWCbfMOx.js';
|
|
6
6
|
import '@maplibre/maplibre-react-native';
|
|
7
7
|
import 'react-native';
|
|
8
8
|
import '@tileflow/core/native';
|