Skip to content

feat: add live JSX markers and custom cluster rendering - #74

Draft
piotr-graczyk-dev wants to merge 11 commits into
mainfrom
codex/custom-marker-views
Draft

feat: add live JSX markers and custom cluster rendering#74
piotr-graczyk-dev wants to merge 11 commits into
mainfrom
codex/custom-marker-views

Conversation

@piotr-graczyk-dev

@piotr-graczyk-dev piotr-graczyk-dev commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Marker children are serialized descriptors, so they cannot host live React Native content. Add MarkerView with fixed bounds, native coordinate projection, and Fabric-owned children for arbitrary JSX, stateful controls, and internal animations. No bitmap snapshots or per-frame JavaScript camera projection are used.

Live markers now share the native clustering engine with descriptor markers. renderCluster supplies arbitrary JSX cluster badges; clustered-away marker subtrees unmount to release their animation/layout work. The existing SDK badge remains the default. The change also handles native gesture ownership, clipping, host/provider lifecycle, generated Fabric child mounting, and optional Google iOS builds.

Validation:

  • 90 Bun tests; lint, package/provider typechecks, library build, and example TypeScript checks.
  • Android Kotlin and arm64 C++/JNI compilation; 21 native tests, including ScrollView ownership, mixed SDK/Fabric rendering, cluster collapse/expansion, and skipped unchanged display updates.
  • iOS Release compilation with the optional Google provider enabled and disabled; the latest press-to-expand correction also passed the simulator Release build. Generated compatibility patch is idempotent across 157 files.
  • Release/MapKit simulator: 24 completed cluster cases at 200/1000 points, validated camera endpoints and active app state. Custom cluster press expanded to individual markers; child Pressable and unmount checks passed. JSX host counts were 48 before each route and 24 after it for both dataset sizes. Simulator timings are excluded from device performance acceptance.
  • Earlier physical iPhone checks verified live JSX interaction and unmount; the corrected pre-clustering benchmark completed 36 primary and 12 ordinary-JSX control cases with validated camera endpoints.

This is a draft because the performance acceptance gate remains open. Pre-clustering iPhone diagnostics show about 119 Hz callbacks for 200 static hosts, 117–120 Hz for transformed hosts, and 51–55 Hz for animated width; ordinary JSX overlays show the same width bottleneck. These callback rates are not presented map FPS, and the surface traces did not reproduce a sustained 120 FPS map baseline. The 24-case cluster workload passed functional checks on an isolated simulator. The final iPhone Release binary is built; a fresh device query still requires a passcode, so the physical cluster run remains pending. No unrestricted 120 FPS guarantee is claimed.

API and clustering contract · Device evidence and limitations · Reproduction

The example-only FrameStats harness is adapted from #66. Earlier duration-error measurements are retained separately and explicitly excluded from moving-camera acceptance.

@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown

React Doctor found 10 issues in 5 files · 2 errors & 8 warnings · score 64 / 100 (Needs work) · full project

Errors

8 warnings

App.tsx

  • ⚠️ L727 Side effect inside a state updater function no-side-effect-in-state-updater-function
  • ⚠️ L732 Side effect inside a state updater function no-side-effect-in-state-updater-function
  • ⚠️ L733 Side effect inside a state updater function no-side-effect-in-state-updater-function

src/components/MapView.tsx

  • ⚠️ L47 React function has high control-flow complexity no-high-complexity-react-function
  • ⚠️ L47 Large component is hard to read and change no-giant-component
  • ⚠️ L147 Chained array iterations js-combine-iterations

src/components/MarkerView.tsx

  • ⚠️ L51 Non-component export in component file only-export-components

src/overlays/__tests__/collectMarkerViews.test.ts

  • ⚠️ L15 Children passed as a prop no-children-prop

Reviewed by React Doctor for commit 2a96412. See inline comments for fixes.

}, [markers, markerViewEntries]);
const visibleMarkerViews = useMemo(() => {
const ids = new Set(markerViewState?.markerViewIds);
return markerViewEntries

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/js-combine-iterations (warning)

This loops over your list twice because .filter().map() makes two passes, so do it in one pass with .reduce() or a for...of loop

Fix → Combine .map().filter() style chains into one pass with .reduce() or a for...of loop, so you only loop over the list once

Docs

);
}

export function validateMarkerViewProps({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/only-export-components (warning)

This file exports non-components, so Fast Refresh can't safely preserve component state.

Fix → Move non-component exports out of component files so Fast Refresh can preserve component state instead of full-reloading.

Docs

coordinate: { latitude: 52, longitude: 21 },
width: 96,
height: 48,
children: null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-children-prop (warning)

A children prop can override or hide nested children, so the component may render different content than the JSX shows.

Fix → Nest children between the tags so the rendered content is visible in JSX and cannot be hidden inside a props object.

Docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant