also looking at this
feat(maps): add key-free native Android maps and shared map controls
#363
28 files
+1857
-481
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -154,7 +154,7 @@ next route. | ||
| 154 | 154 | | `Image` | `UIImageView` | `ImageView` | |
| 155 | 155 | | `ImageBackground` | `CraftNativeImageBackgroundView` | `CraftNativeImageBackgroundView` | |
| 156 | 156 | | `Video` | `CraftNativeVideoView` (`AVPlayerViewController`) | `CraftNativeVideoView` (`VideoView`) | |
| 157 | | `Map` | `CraftNativeMapView` (`MKMapView`) | `CraftNativeMapView` (`GoogleMap`) | | |
| 157 | | `Map` | `CraftNativeMapView` (`MKMapView`) | `CraftNativeMapView` (native MapLibre or Google Maps) | | |
| 158 | 158 | | `MapPolyline`, `MapMarker` | overlays inside `CraftNativeMapView` | overlays inside `CraftNativeMapView` | |
| 159 | 159 | | `Svg` | `CraftNativeSvgView` | `CraftNativeSvgView` | |
| 160 | 160 | | `G`, `SvgText` | drawn inside `CraftNativeSvgView` | drawn inside `CraftNativeSvgView` | |
| @@ -228,12 +228,21 @@ or `fitToBounds`, which recenters only when its overlay geometry changes. Explic | ||
| 228 | 228 | authored camera bounds on both hosts; only `fitToBounds` adds framing padding. A marker's `onPress` or |
| 229 | 229 | `onMarkerPress` receives `nativeEvent.id`; a marker's own handler wins, and the map-level handler is |
| 230 | 230 | used as a fallback when the marker has no non-empty handler. |
| 231 | It is backed by MapKit on iOS and the Google Maps SDK on | |
| 232 | Android; the Android template adds that dependency only for screens that opt | |
| 233 | into the native map host. The shared `mapType` values are `standard`, | |
| 231 | It is backed by MapKit on iOS and the configured native provider on Android. | |
| 232 | Set the Craft Android config's `mapProvider` to `maplibre` for a key-free native | |
| 233 | GL view; `google` preserves the existing Google Maps host. Only the selected | |
| 234 | provider's SDK is included in the generated Android project. These STX map | |
| 235 | components do not use the DOM-based `@craft-native/ts-maps` adapter. | |
| 236 | The shared `mapType` values are `standard`, | |
| 234 | 237 | `satellite`, and `hybrid`; Android's terrain-only style is intentionally not |
| 235 | part of the cross-platform contract. Tile styling, clustering, directions, and | |
| 236 | offline tiles remain outside this contract. Set `showsUserLocation` to opt into the | |
| 238 | part of the cross-platform contract. `tileOverlay` accepts an HTTPS raster URL | |
| 239 | template and its visible provider attribution. `edgePadding` reserves logical | |
| 240 | points around a fitted route for floating controls. `pitchEnabled` controls | |
| 241 | tilt gestures; `cameraPitch` and `cameraHeading` set the camera explicitly. | |
| 242 | Markers accept `pinColor` for trailheads and inspected profile positions, or | |
| 243 | `bearing` for a contrasting route-direction sign. Clustering, turn-by-turn | |
| 244 | directions, and offline tile downloads remain outside this view contract. | |
| 245 | Set `showsUserLocation` to opt into the | |
| 237 | 246 | platform location dot; the host only enables it when the app's existing |
| 238 | 247 | location permission is already granted, and never prompts from a renderer |
| 239 | 248 | pass. Android also forwards `MapView` start/stop lifecycle callbacks as map |
| @@ -140,18 +140,28 @@ craft android build --native-bundle ../native-screen.js | ||
| 140 | 140 | Native mode maps STX `View`, `SafeAreaView`, `KeyboardAvoidingView`, `StatusBar`, |
| 141 | 141 | `RefreshControl`, `Text`, `Button`, `Link`, `Icon`, |
| 142 | 142 | `Pressable`, `TouchableOpacity`, `TouchableHighlight`, `Checkbox`, `TextInput`, `Picker`, `DatePicker`, `Modal`, `Switch`, `Slider`, `ActivityIndicator`, `Image`, `ImageBackground`, `Video`, `Svg`, `G`, `SvgText`, `ScrollView`, |
| 143 | `Map`, `SectionList`, and `FlatList` to Android views. `Map` uses the Google | |
| 144 | Maps SDK for trail polylines and marker taps; its overlays carry flat | |
| 143 | `Map`, `SectionList`, and `FlatList` to Android views. `Map` uses the configured | |
| 144 | native map provider for trail polylines and marker taps; its overlays carry flat | |
| 145 | 145 | latitude/longitude `geometry` arrays, `strokeWidth` is expressed in logical |
| 146 | 146 | points, and the camera supports controlled `region`, one-time `initialRegion`, |
| 147 | and `fitToBounds`. Set `mapsApiKey` in the Android config to emit the SDK manifest key; | |
| 147 | and `fitToBounds`. Select `mapProvider: 'maplibre'` for the key-free native | |
| 148 | MapLibre renderer. It uses native GL views and needs neither a Google map SDK | |
| 149 | dependency nor a Google map key. `mapProvider: 'google'` retains the existing | |
| 150 | Google Maps host and uses `mapsApiKey` for its SDK manifest key; Google remains | |
| 151 | the default for compatibility with existing projects. | |
| 152 | ||
| 148 | 153 | Coordinates must be JSON numbers (numeric strings are not coerced), are |
| 149 | 154 | range-checked at the native boundary, and invalid points or pole-crossing |
| 150 | 155 | regions are ignored. `fitToBounds` waits for the map viewport to |
| 151 | 156 | be measured before caching a successful camera fit, so an early map callback |
| 152 | 157 | does not lose the initial route framing. |
| 153 | without it, the native map remains an explicit opt-in integration that needs | |
| 154 | the app's own Maps credentials. `SectionList` uses the same | |
| 158 | The shared controls include `showsCompass`, `showsScale`, `pitchEnabled`, | |
| 159 | `cameraPitch`, `cameraHeading`, and floating-control `edgePadding`. Markers | |
| 160 | accept `pinColor` and route-direction `bearing`. The builder's | |
| 161 | `nativeMapProviders` export advertises the providers it actually implements, | |
| 162 | so a build orchestrator can refuse an unsupported explicit choice. | |
| 163 | ||
| 164 | `SectionList` uses the same | |
| 155 | 165 | native scroll host for ordinary `.stx` slot children; grouped section data |
| 156 | 166 | should use `FlatList` until the section-data protocol is available. The |
| 157 | 167 | generated host routes both list names through `CraftNativeScrollView` for this |
| @@ -2,7 +2,14 @@ | ||
| 2 | 2 | |
| 3 | 3 | Craft SDK bindings for the [ts-maps](https://github.com/stacksjs/ts-maps) interactive map runtime. |
| 4 | 4 | |
| 5 | This package is the TypeScript side of `MapProvider.ts_maps` in Craft's Zig core. It ships a `MapView` component you can drop into any Craft app (desktop, mobile, WebView) to get a cross-platform interactive map with zero API keys. | |
| 5 | This package is the TypeScript side of `MapProvider.ts_maps` in Craft's Zig core. | |
| 6 | Its `MapView` owns a DOM container and renders ts-maps inside a browser or | |
| 7 | WebView, with zero API keys. It is not the STX native `Map` component. | |
| 8 | ||
| 9 | For a fully native STX screen, use `Map`, `MapMarker`, and `MapPolyline`. | |
| 10 | Craft renders them with MapKit on iOS and the configured native Android map | |
| 11 | provider. Android's `mapProvider: 'maplibre'` selects a key-free native GL view; | |
| 12 | it does not mount this package's DOM adapter. | |
| 6 | 13 | |
| 7 | 14 | ## Install |
| 8 | 15 | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /** |
| 2 | * `MapView` — Craft-native interactive map component backed by the | |
| 3 | * ts-maps runtime. Instances are WebView-hosted; in native Craft apps | |
| 2 | * `MapView` — Craft WebView map component backed by the | |
| 3 | * ts-maps runtime. Instances own a DOM container; in Craft apps | |
| 4 | 4 | * the Zig core drives them via the `ts_maps` bridge namespace. |
| 5 | 5 | * |
| 6 | 6 | * @module @craft-native/ts-maps/MapView |