Skip to content

[pull] main from expo:main#649

Merged
pull[bot] merged 7 commits intocode:mainfrom
expo:main
Mar 4, 2026
Merged

[pull] main from expo:main#649
pull[bot] merged 7 commits intocode:mainfrom
expo:main

Conversation

@pull
Copy link

@pull pull bot commented Mar 4, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

huextrat and others added 7 commits March 4, 2026 21:22
# Why

This PR adds programmatic selection support for markers in Google Maps,
along with proper event callbacks for user interactions. Currently,
there's no way to:
- Programmatically select a marker from JS (show its info window)
- Control camera movement when selecting (zoom, moveCamera options)

These features are essential for building interactive map experiences
where the UI needs to stay in sync with map selection state.

iOS: #42187

# How

## New Features

### 1. Programmatic Selection (`selectMarker()` ref method)
Added a `selectMarker(id?, options?)` method on the map ref that allows
selecting markers by their ID:
```tsx
const mapRef = useRef<GoogleMaps.MapView>(null);

// Select a marker with camera animation
mapRef.current?.selectMarker('marker-1', { moveCamera: true, zoom: 15 });

// Select without moving camera
mapRef.current?.selectMarker('marker-2', { moveCamera: false });

// Clear selection
mapRef.current?.selectMarker();
```

Options:
- `zoom`: Optional zoom level when animating to the selected marker
- `moveCamera`: Whether to animate the camera to the marker (defaults to
`true`)

## Implementation Details

- `onMarkerClick` fires both for direct clicks and programmatic
selection via ref
- `onMapClick` may be used to be notified that no markers are selected
anymore

# Test Plan

1. Open the Native Component List app on Android
2. Navigate to Maps → Google Maps → Markers
3. Test the following:
- Tap markers on the map → `onMarkerClick` fires, list updates, info
window shows
- Tap items in the horizontal list → marker gets selected via ref, info
window shows
   - Tap elsewhere on the map → `onMapClick` fires, selection clears
- Verify camera animates to marker when selecting (unless `moveCamera:
false`)
4. Test edge cases:
   - Rapidly switching between markers
   - Removing markers while one is selected

# Checklist

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [x] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [X] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
…asyncRoutes` is enabled (#43531)

# Why

Followup to #43446.

When `asyncRoutes: true` is enabled with SSR, each route gets its own
async JavaScript chunk(s). Currently, these chunks are added to the
serialized HTML in the correct order for regular/static routes, but are
reversed for dynamic routes like `[slug]` or `[...rest]`.

| Route | Async chunks order |
|---|---|
| `app/index.tsx` | `_layout-<HASH>.js`, `index-<HASH>.js` |
| `app/slug.tsx` | `[slug]-<HASH>.js`, `_layout.tsx` |

Both the SSG and SSR export pipelines currently exhibit this issue.

# How

Added a `sortMatchedAssetsByEntryPoints()` utility that sorts matched
async assets by the index of their matching entryPoint in the route's
`entryPoints` array (which is always correctly ordered) and applied it
to both the SSG and SSR pipelines.

# Test Plan

- CI
- Manual testing against the blog and E2E fixture

# Checklist

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [x] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
## `rotation3DEffect` modifier 

### Summary
- Add `rotation3DEffect` modifier for 3D rotation transforms (e.g. card
flip animations)

### New: `rotation3DEffect`

Maps to SwiftUI's
[`.rotation3DEffect(_:axis:anchor:anchorZ:perspective:)`](https://developer.apple.com/documentation/swiftui/view/rotation3deffect(_:axis:anchor:anchorz:perspective:)).


**Parameters:**
| Param | Type | Default | Description |
|---|---|---|---|
| `angle` | `number` | required | Rotation angle in degrees |
| `axis` | `{ x?, y?, z? }` | `{ 0, 0, 0 }` | Rotation axis |
| `perspective` | `number` | `1` | Perspective distortion |



### Test plan

```
export default function Rotation3DDemo() {
  const [flipped, setFlipped] = useState(false);

  return (
    <>
      <Stack.Screen options={{ title: 'rotation3DEffect' }} />
      <Host style={{ flex: 1 }}>
        <VStack
          alignment="center"
          modifiers={[
            frame({ maxWidth: 10000, height: 200 }),
            padding({ all: 24 }),
            background('#007AFF'),
            cornerRadius(20),
            rotation3DEffect({ angle: flipped ? 180 : 0, axis: { y: 1 } }),
            animation(Animation.spring({ duration: 0.6 }), flipped),
            onTapGesture(() => setFlipped((p) => !p)),
          ]}>
          <Text modifiers={[font({ size: 32, weight: 'bold' })]}>Tap to flip</Text>
        </VStack>
      </Host>
    </>
  );
}
```

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
…#43618)

## Summary

Fixes `expo run:ios -d` hanging indefinitely at "Connecting to: <device
name>" when launching on physical devices.

The `xcrun devicectl device process launch` command was hanging when the
app was already running on the device. Adding the `--terminate-existing`
flag terminates any running instances before launching, preventing the
hang.

**Root cause:** Without `--terminate-existing`, the devicectl launch
command would wait indefinitely if the app was already running.

**The fix:** Add `--terminate-existing` to the devicectl launch command
arguments.

This only affects the devicectl code path (used for iOS 17+ and
network-connected devices). The usbmuxd path has its own mechanism for
handling already-running apps.

## Test plan

- [x] Run `yarn test
src/start/platforms/ios/__tests__/devicectl.test.ts` - tests pass
- [ ] Run `npx expo run:ios -d` on a physical device with the app
already running
- [ ] Verify app terminates and relaunches successfully
- [ ] Verify launching works when app is not already running

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
@pull pull bot locked and limited conversation to collaborators Mar 4, 2026
@pull pull bot added the ⤵️ pull label Mar 4, 2026
@pull pull bot merged commit fa458e4 into code:main Mar 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants