ReviewOS

stacks/stx

feat(native): craft renders `Map`, but stx has no `Map` type, so no template can reach it

#2072
Closed glennmichael123 opened this 8 days ago ·
8 days ago

craft-native@0.0.174 renders a native map. Nothing in stx can emit one, so from a template the feature does not exist — <Map> compiles to nothing.

This is the other half of craft-native/craft#340, which shipped the renderer and closed. The compiler side was never added.

What exists downstream

Verified in the published 0.0.174 tarball, not from the close comment:

  • iOS: MKMapView in CraftNativeScreen.swift
  • Android: CraftNativeMapView over com.google.android.gms.maps, dispatched at MainActivityNative.kt.template:3928 on the node type "Map"
  • both hosts: MapPolyline, MapMarker, fitToBounds, marker tap carrying the marker id, and in-place overlay reconciliation

The wire shape is therefore already fixed and already covered by craft's renderer contract. This is a compiler-side addition against a known target.

What is missing here

On origin/main at 084f501:

  • native/compiler/component-mapping.ts has no map entry. The same commit range added sidebar, splitview, checkbox, icon, pressable and textinput
  • the STXComponentType union in native/compiler/ir.ts gained Sidebar, SplitView and Checkbox, and has no Map, MapPolyline or MapMarker
  • native/primitives/ has no Map.stx

Repro

<script>
const route = signal([47.0, 11.0, 47.1, 11.2])
</script>

<View>
  <Map fitToBounds="true" style="height: 240">
    <MapPolyline :geometry="route()" stroke="#111" />
    <MapMarker id="start" :geometry="[47.0, 11.0]" @press="() => {}" />
  </Map>
</View>

Through compileNativeBundle({ screens: { MapProbe: 'MapProbe.stx' }, root }):

Map: 0
MapPolyline: 0
MapMarker: 0
fitToBounds: 0

Not one node reaches the bundle. <Map> falls through to the component resolver, which hunts for a file:

[stx] component <map> could not be resolved used in .../MapProbe.stx,
so it rendered as nothing.
  searched:
    - .../components/map.stx
    - .../components/Map.stx
    - .../dist/native/primitives/map.stx
    - .../dist/native/primitives/Map.stx
    ... 20 more

The fix, in the shape main already uses

Checkbox landed on main this way and is the template to copy:

  1. native/primitives/Map.stx, MapPolyline.stx, MapMarker.stx — each the five-line component emitting <div data-native="Map">, as Checkbox.stx does
  2. map: 'Map', mappolyline: 'MapPolyline', mapmarker: 'MapMarker' in component-mapping.ts
  3. the three types in the STXComponentType union
  4. coordinate arrays recomputed on a bound attribute the way shape geometry is. MapPolyline's geometry is a flat numeric array exactly like the SVG opcode list, so a signal holding a route should re-draw through affectsGeometry's existing path rather than a second mechanism

Second, smaller ask: this failure is invisible to a build

The resolver does warn, but it warns on stdout from the component plugin. The compile's own diagnostics array came back with one unrelated entry:

diagnostics: [{"level":"warning","message":"dropped-subtree: script"}]

So a capitalized tag that matches no primitive and no component produces a screen that renders nothing, and a build or a CI gate reading diagnostics sees a clean compile. That is how this went unnoticed while the renderer shipped — the same failure mode as #2067, where the thing that was wrong looked fine from every angle a test could check. An unresolved tag inside a native screen should be a diagnostic, and arguably an error.

Why it matters

Eight wildloop screens are built around a trail — /trails, /record, territory/[id] among them — and they are the ones that make the app feel native rather than a web view in a shell. They were blocked on craft#340, which is now shipped, and they remain blocked on this.

8 days ago

Implemented on main in 06685d0 (Map IR types), 968a6e4 (Map primitives), and 1bb9d58 (Map screen compilation coverage). The native compiler now resolves Map as a supported primitive and emits the expected native node contract. CI is running on the current main tip. This is included in the next patch release, not v0.2.519.

Sign in to comment on this issue.