Skip to content

[ios][ui] Add defaultScrollAnchor modifier#43914

Merged
intergalacticspacehighway merged 1 commit intoexpo:mainfrom
ramonclaudio:feat/expo-ui-default-scroll-anchor
Mar 13, 2026
Merged

[ios][ui] Add defaultScrollAnchor modifier#43914
intergalacticspacehighway merged 1 commit intoexpo:mainfrom
ramonclaudio:feat/expo-ui-default-scroll-anchor

Conversation

@ramonclaudio
Copy link
Copy Markdown
Contributor

Exposes SwiftUI's .defaultScrollAnchor(_:) (iOS 17+) as a modifier. This lets you control where a ScrollView or List starts its scroll position without any geometric transform hacks.

<ScrollView modifiers={[defaultScrollAnchor('bottom')]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>

The scroll view starts at the bottom. Scroll up to see older content. No scaleEffect(y: -1) flip, no reversed data, no inverted scroll indicators.

Reuses the existing UnitPointOptions enum and its toUnitPoint converter. Accepts any UnitPoint preset: top, bottom, center, leading, trailing, topLeading, topTrailing, bottomLeading, bottomTrailing, zero.

Falls back to a no-op on iOS < 17.

Same pattern as scrollDismissesKeyboard, scrollDisabled, scrollContentBackground.

Test plan

  • Built ExpoUI target against iOS 26.2 SDK (Xcode 26, iPhone 17 Pro sim). BUILD SUCCEEDED, zero errors.
  • Added a test screen to native-component-list with a 50-item ScrollView + defaultScrollAnchor('bottom'). Confirmed the view loads scrolled to "Message 50" at the bottom. Scroll indicators point the right way.
  • yarn build passes.
  • yarn lint --fix passes.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 13, 2026

Subscribed to pull request

File Patterns Mentions
docs/** @amandeepmittal
packages/expo-ui/** @Kudo, @behenate, @intergalacticspacehighway

Generated by CodeMention

@expo-bot expo-bot added the bot: passed checks ExpoBot has nothing to complain about label Mar 13, 2026
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-default-scroll-anchor branch from 8779219 to 9e5b0ac Compare March 13, 2026 02:37
Comment thread packages/expo-ui/ios/Modifiers/DefaultScrollAnchorModifier.swift Outdated
Comment thread packages/expo-ui/src/swift-ui/modifiers/index.ts
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-default-scroll-anchor branch from e423048 to 4a6c07d Compare March 13, 2026 03:21
Copy link
Copy Markdown
Contributor

@intergalacticspacehighway intergalacticspacehighway left a comment

Choose a reason for hiding this comment

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

Thanks!

@intergalacticspacehighway intergalacticspacehighway merged commit 073ace8 into expo:main Mar 13, 2026
13 of 14 checks passed
intergalacticspacehighway pushed a commit that referenced this pull request Mar 13, 2026
Exposes SwiftUI's `.defaultScrollAnchor(_:)` (iOS 17+) as a modifier.
This lets you control where a ScrollView or List starts its scroll
position without any geometric transform hacks.

```tsx
<ScrollView modifiers={[defaultScrollAnchor('bottom')]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>
```

The scroll view starts at the bottom. Scroll up to see older content. No
`scaleEffect(y: -1)` flip, no reversed data, no inverted scroll
indicators.

Reuses the existing `UnitPointOptions` enum and its `toUnitPoint`
converter. Accepts any `UnitPoint` preset: `top`, `bottom`, `center`,
`leading`, `trailing`, `topLeading`, `topTrailing`, `bottomLeading`,
`bottomTrailing`, `zero`.

Falls back to a no-op on iOS < 17.

Same pattern as `scrollDismissesKeyboard`, `scrollDisabled`,
`scrollContentBackground`.

## Test plan

- Built ExpoUI target against iOS 26.2 SDK (Xcode 26, iPhone 17 Pro
sim). `BUILD SUCCEEDED`, zero errors.
- Added a test screen to `native-component-list` with a 50-item
`ScrollView` + `defaultScrollAnchor('bottom')`. Confirmed the view loads
scrolled to "Message 50" at the bottom. Scroll indicators point the
right way.
- `yarn build` passes.
- `yarn lint --fix` passes.
intergalacticspacehighway pushed a commit that referenced this pull request Mar 13, 2026
Exposes SwiftUI's `.defaultScrollAnchor(_:for:)` (iOS 18+) as a
modifier. This is the two-parameter overload that lets you set different
scroll anchors for different roles: where the scroll view starts, how it
handles content size changes, and how it aligns content smaller than its
container.

```tsx
<ScrollView modifiers={[
  defaultScrollAnchor('bottom'),
  defaultScrollAnchorForRole('top', 'initialOffset'),
]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>
```

The scroll view anchors to bottom globally, but the `initialOffset` role
override makes it start at the top. Each role can be independently
controlled.

`ScrollAnchorRole` has three cases: `initialOffset` (where to start),
`sizeChanges` (how to reposition on resize), `alignment` (how to align
content smaller than the container). Passing `null` as the anchor opts
out of a specific role.

Also improves `defaultScrollAnchor` from #43914:
- Adds `null` support to match Apple's `UnitPoint?` signature (allows
resetting/opting out)
- Adds `@platform macos 14.0+` to JSDoc (was missing, Swift guard
already covered it)
- Extracts shared `UnitPointValue` type used by both modifiers

Reuses the existing `UnitPointOptions` enum. Adds a new
`ScrollAnchorRoleOptions` enum. Falls back to a no-op on iOS < 18.

Same pattern as `defaultScrollAnchor` from #43914.

## Test plan

- Built and ran on iPhone 17 Pro simulator (iOS 26.2, Xcode 26).
- Tested `defaultScrollAnchor('bottom')` - scroll view starts at bottom.
- Tested `defaultScrollAnchorForRole('top', 'initialOffset')` overriding
`defaultScrollAnchor('bottom')` - scroll view starts at top, confirming
per-role override works.
- Tested `defaultScrollAnchor(null)` - no-op, default top behavior.
- `yarn build` passes.
- `yarn tsc --noEmit` passes.
- `yarn lint --fix` passes.
- `yarn test` passes (30/30).
- Docs regenerated for `unversioned` and `v55.0.0`.
intergalacticspacehighway pushed a commit that referenced this pull request Mar 13, 2026
Exposes SwiftUI's `.defaultScrollAnchor(_:for:)` (iOS 18+) as a
modifier. This is the two-parameter overload that lets you set different
scroll anchors for different roles: where the scroll view starts, how it
handles content size changes, and how it aligns content smaller than its
container.

```tsx
<ScrollView modifiers={[
  defaultScrollAnchor('bottom'),
  defaultScrollAnchorForRole('top', 'initialOffset'),
]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>
```

The scroll view anchors to bottom globally, but the `initialOffset` role
override makes it start at the top. Each role can be independently
controlled.

`ScrollAnchorRole` has three cases: `initialOffset` (where to start),
`sizeChanges` (how to reposition on resize), `alignment` (how to align
content smaller than the container). Passing `null` as the anchor opts
out of a specific role.

Also improves `defaultScrollAnchor` from #43914:
- Adds `null` support to match Apple's `UnitPoint?` signature (allows
resetting/opting out)
- Adds `@platform macos 14.0+` to JSDoc (was missing, Swift guard
already covered it)
- Extracts shared `UnitPointValue` type used by both modifiers

Reuses the existing `UnitPointOptions` enum. Adds a new
`ScrollAnchorRoleOptions` enum. Falls back to a no-op on iOS < 18.

Same pattern as `defaultScrollAnchor` from #43914.

## Test plan

- Built and ran on iPhone 17 Pro simulator (iOS 26.2, Xcode 26).
- Tested `defaultScrollAnchor('bottom')` - scroll view starts at bottom.
- Tested `defaultScrollAnchorForRole('top', 'initialOffset')` overriding
`defaultScrollAnchor('bottom')` - scroll view starts at top, confirming
per-role override works.
- Tested `defaultScrollAnchor(null)` - no-op, default top behavior.
- `yarn build` passes.
- `yarn tsc --noEmit` passes.
- `yarn lint --fix` passes.
- `yarn test` passes (30/30).
- Docs regenerated for `unversioned` and `v55.0.0`.
kristentr added a commit to kristentr/expo that referenced this pull request Mar 19, 2026
* Create swift.yml (#24)

* Create sonarcloud.yml (#25)

* Create codeql.yml

* Potential fix for code scanning alert no. 43: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* [notifications]: handle Keychain unavailability during iOS background launch (expo#43829)

# Why

Fixes expo#43828

When iOS launches an app in the background (e.g. push notification
delivery with the device locked), `getRegistrationInfoAsync` throws an
unhandled promise rejection because:

1. The module-level `.then()` in `DevicePushTokenAutoRegistration.fx.ts`
has no rejection handler
2. Registration info is stored with
`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`, which is inaccessible
when the device is locked

This causes `ERR_NOTIFICATIONS_KEYCHAIN_ACCESS` errors that surface as
unhandled rejections in production (observed via Sentry across multiple
users/devices).

## How

**TypeScript** (`DevicePushTokenAutoRegistration.fx.ts`):
- Add a rejection handler to the startup
`.then(getRegistrationInfoAsync)` call, matching the `console.warn`
pattern used by every other async path in the same file

**Swift** (`ServerRegistrationModule.swift`):
- Change `registrationSetQuery` accessibility from
`kSecAttrAccessibleWhenUnlockedThisDeviceOnly` to
`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`
- This matches what `installationIdSetQuery` already uses (same file,
line 82)
- Registration info is just `{"isEnabled":true}` — non-sensitive data
that Apple recommends storing with `AfterFirstUnlock` for
background-accessible items
- Safe for existing users: the write path already does `SecItemDelete` +
`SecItemAdd`, so the next successful write naturally uses the new
protection class

**Test** (`DevicePushTokenAutoRegistration-test.ts`):
- Add test that mocks `getRegistrationInfoAsync` to reject and verifies
the rejection is handled gracefully (no unhandled rejection,
`console.warn` is called)

## Test Plan

- [x] `yarn test` in `packages/expo-notifications` — all 46 tests pass
- [x] `yarn lint` in `packages/expo-notifications` — clean
- [x] New test verifies the rejection handler fires when
`getRegistrationInfoAsync` rejects with a Keychain error

---------

Co-authored-by: Vojtech Novak <[email protected]>

* [babel-preset-expo] Fix test expectations for Hermes V1 class preservation (expo#43837)

* [metro-config] update isHermesV1 detection (expo#43841)

* [gl] Make msaaSamples and enableExperimentalWorkletSupport optional in GLViewProps (expo#43767)

* [expo-ui][android] add AnimatedVisibility transition API (expo#43632)

# Why

To expose the entry/exit animation configuration to the JS side.

**Note** that with the animations affecting layout (`expand`/`shrink`),
it's better to leave the layout to compose. If `Host` with
`matchesContent` is used, then the layout will jump, as there are no
synchronous events in react native android yet.

# How

This PR adds an API similar to SwiftUI approach:
- builder pattern for both entry and exit animations
- passes them down as an array of configuration objects

# Test Plan


https://github.com/user-attachments/assets/112cf147-6d9e-4ea4-962b-4d30719f59aa

# Checklist

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

- [ ] 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)

* [docs] Update EAS CLI reference for 18.3.0 (expo#43875)

# Why

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

Update EAS CLI reference for 18.3.0.

# How

<!--
How did you build this feature or fix this bug and why?
-->

- Run `yarn run eas-cli-sync` to sync to the latest changes and update
the CLI version
- Add normalization to parse broken external links in the script.
(External Apple developers documentation link was broken after the
sync).

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

See preview.

# Checklist

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

- [ ] 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)

* [docs] Update manual install diffs for React Native 0.83 / SDK 55 (expo#43865)

# Why

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

Fix ENG-18812

# How

- Update `expo-android.diff` to use
`ExpoReactHostFactory.getDefaultReactHost()` instead of the old
`ReactNativeHostWrapper` pattern, matching what
`install-expo-modules@latest` produces for RN 0.83.
- Update `expo-ios.diff` to reflect RN 0.83's new `AppDelegate.swift`
structure: `ExpoAppDelegate`, `ExpoReactNativeFactory`,
`ExpoReactNativeFactoryDelegate`, and `internal import Expo`.
- Bump version reference in `installing-expo-modules.mdx` from RN 0.81
to RN 0.83.
- Update the Expo template GitHub link from `sdk-54` to `sdk-55`.

# Test Plan

- Create a fresh RN 0.83 project with `npx
@react-native-community/cli@latest init myapp --version 0.83.0`.
- Apply the diffs shown on the Install Expo modules page manually and
verify the project builds on both Android and iOS.
- Compare the manual diff output against running `npx
install-expo-modules@latest` on a clean RN 0.83 project to confirm they
match.

For docs changes, see Preview:
https://pr-43865.expo-docs.pages.dev/bare/installing-expo-modules/

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# Checklist

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

- [ ] 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).
- [x] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

* Bump react-native-maps to 1.27.2 (expo#43884)

# Why

Closes expo#42423
 

# How

Bump react-native-maps to 1.27.2

# Test Plan

Run NCL locally 

# Checklist

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

- [ ] 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)

* [expo-ui][android] add `imePadding` modifier (expo#43652)

# Why

In order to show content above keyboard

# How

Expose `imePadding` modifier

# Test Plan

Bare expo


https://github.com/user-attachments/assets/eab7b239-bd06-4cbd-a387-6dd1354046e4

# 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)

* [create-expo-nightly][widgets] fix nightly tests (expo#43849)

* [expo-go] Copy dev menu UI (expo#43686)

# Why
We want expo go to own it's own implementation of the dev menu. This makes it easier to make changes without impacting expo-dev-menu

# How
Copy over dev menus ui and integrate with the kernel

# Test Plan
Expo go

* [expo-go][menu] Remove bridge dependency (expo#43687)

# Why
`currentBridge` is always nil on RN 0.84 so we need to remove references to it

# How
We can get everything we need from the manifest and the react host on the kernel

# Test Plan
Expo go

* [2/n] Upgrade React Native to 0.85.0-rc.1 (expo#43817)

# Why

Align with latest React Native core version

# How

- Update gradle to 9.3.1 + fix `org.jetbrains:annotations` versions
mismatch
- Update package versions
  - `react-native 0.85-rc.0 -> 0.85-rc.1`
  - `@react-native/normalize-colors 0.85-rc.0 -> 0.85-rc.1`
  - `@react-native/babel-preset 0.85-rc.0 -> 0.85-rc.1`
  - `@react-native/dev-middleware 0.85-rc.0 -> 0.85-rc.1`

# Test Plan

- Bare Expo
- Minimal tester

# Checklist

- [ ] 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)

* [expo-go] Add new server discovery (expo#43689)

# Why
Brings the same server discovery from expo-dev-launcher to expo go

# Test Plan
Expo go

* fix(cli): avoid TTY init crash in non-interactive terminals (expo#43796)

* [ui][android] - Match Chip with Compose API (expo#43900)

# Why

Match JS Chip API with Compose API. The old API used a single `Chip`
component with a `variant` prop, which doesn't map cleanly to Material
3's distinct chip types that each have different slots, props, and
behaviors.

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

# How

- Split the single `Chip` component into four separate components:
`AssistChip`, `FilterChip`, `InputChip`, and `SuggestionChip`, matching
M3's chip taxonomy.
- Replaced flat props (`label`, `icon`) with slot-based composition
(`<Chip.Label>`, `<Chip.LeadingIcon>`, `<Chip.TrailingIcon>`,
`<InputChip.Avatar>`).
  - Added `colors`, `elevation`, and `border` props to all chip types 
- Merged the standalone `FilterChip` module into the unified `Chip`
module
  - Renamed `onPress` to `onClick` in the user API
- Updated docs for all three versions with usage examples and chip type
descriptions.


<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

Test Chip examples and docs
<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# Checklist

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

- [ ] 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)

* fix(expo-updates): fix iOS build script failing silently on paths with spaces (expo#43497)

Fixes expo#43500



## Why

When the Xcode project root lives in a path containing **spaces** (e.g.
a USB volume mounted as `/Volumes/My Drive/MyApp`), the iOS build script
`create-updates-resources-ios.sh` silently exits early and never
generates `app.manifest`.

### Root cause

```bash
# Before – unquoted, triggers word-splitting in bash
PROJECT_DIR_BASENAME=$(basename $PROJECT_DIR)
if [ "x$PROJECT_DIR_BASENAME" != "xPods" ]; then
  exit 0     # ← always taken when PROJECT_DIR contains spaces
fi
```

`basename /Volumes/My Drive/App/ios/Pods` splits on the space, producing
a multi-word token (e.g. `Drive/App/ios/Pods` as a separate word). The
`[ … != xPods ]` check then always succeeds, causing the script to `exit
0` before generating any resources.

The result is that `EXUpdates.bundle` is built with only `Info.plist`
and no `app.manifest`. The app then crashes on launch inside
`EmbeddedAppLoader.cachedEmbeddedManifest` with:

```
Assertion failed: The embedded update is invalid …
```

### Fixes

1. **Quote `$PROJECT_DIR`** in the `basename` call so word-splitting
cannot occur:
   ```bash
   PROJECT_DIR_BASENAME=$(basename "$PROJECT_DIR")
   ```

2. **`mkdir -p "$RESOURCE_DEST"`** for the `shallow` bundle format
branch. The `deep` branch already had this; without it a clean build
writes `app.manifest` into a directory that doesn't exist yet, producing
an `ENOENT` from `createUpdatesResources.js`.

## Test plan

- Build an iOS archive with the project root on a volume/directory whose
path contains spaces.
- Verify `EXUpdates.bundle/app.manifest` is present in the built `.app`.
- Confirm the app launches without crashing.

* docs(mcp): update tools table to match current server capabilities

Remove generate_claude_md and generate_agents_md (moved to plugin-based
installation), add read_documentation, testflight_crashes, and
testflight_feedback. Add builds/workflows section to intro examples.

* fix(cli): Remove -quiet flag from Xcode build args (expo#43906)

Revert the previous addition of the -quiet argument to xcodebuild so
build environment variables and full output are always printed. Remove
'-quiet' from getXcodeBuildArgsAsync, update unit tests to no longer
expect the flag, and add a changelog entry noting the revert.

---------

Co-authored-by: Expo Bot <[email protected]>

* [ios][ui] Add defaultScrollAnchor modifier (expo#43914)

Exposes SwiftUI's `.defaultScrollAnchor(_:)` (iOS 17+) as a modifier.
This lets you control where a ScrollView or List starts its scroll
position without any geometric transform hacks.

```tsx
<ScrollView modifiers={[defaultScrollAnchor('bottom')]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>
```

The scroll view starts at the bottom. Scroll up to see older content. No
`scaleEffect(y: -1)` flip, no reversed data, no inverted scroll
indicators.

Reuses the existing `UnitPointOptions` enum and its `toUnitPoint`
converter. Accepts any `UnitPoint` preset: `top`, `bottom`, `center`,
`leading`, `trailing`, `topLeading`, `topTrailing`, `bottomLeading`,
`bottomTrailing`, `zero`.

Falls back to a no-op on iOS < 17.

Same pattern as `scrollDismissesKeyboard`, `scrollDisabled`,
`scrollContentBackground`.

## Test plan

- Built ExpoUI target against iOS 26.2 SDK (Xcode 26, iPhone 17 Pro
sim). `BUILD SUCCEEDED`, zero errors.
- Added a test screen to `native-component-list` with a 50-item
`ScrollView` + `defaultScrollAnchor('bottom')`. Confirmed the view loads
scrolled to "Message 50" at the bottom. Scroll indicators point the
right way.
- `yarn build` passes.
- `yarn lint --fix` passes.

* fix(task-manager): Keep JS timers alive during background task execution on Android (expo#43821)

# Why

On Android, background task JS execution hangs indefinitely when the app
is backgrounded. All async operations (promises, `setTimeout`, etc.)
never resolve, causing background tasks to time out without completing
any work.

This is because React Native's `JavaTimerManager` deliberately stops
processing JS timers when the Activity is paused (`isPaused=true`)
**unless** `HeadlessJsTaskContext` reports active headless tasks
(`isRunningTasks=true`). The guard at
[`JavaTimerManager.kt:291`](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.kt#L291):

```kotlin
if (isPaused.get() && !isRunningTasks.get()) {
    return  // timers never fire
}
```

`expo-task-manager`'s `TaskService` dispatches task events to JS but
never registers with `HeadlessJsTaskContext`. So `isRunningTasks` stays
`false`, and all JS timers (which back promises, `setTimeout`, etc.) are
paused. This affects any package built on `expo-task-manager`, including
`expo-background-task`.

# How

In `TaskService.executeTask()`, when the first event is dispatched for
an `appScopeKey`, we call `HeadlessJsTaskContext.startTask()` to
register an active headless task. This signals to `JavaTimerManager`
that JS timers should keep firing. When the last event for that
`appScopeKey` completes in `notifyTaskFinished()`, we call
`finishTask()` to clean up.

On the JS side, a no-op headless task is registered via
`AppRegistry.registerHeadlessTask('expo-task-manager', ...)` to suppress
the warning that `startHeadlessTask` logs when no JS handler is found.

### Event tracking bug fix

This PR also fixes a pre-existing bug in `TaskService.executeTask()`
where subsequent events for the same `appScopeKey` were not being
tracked in `sEvents`. The original code created a new disconnected
`ArrayList` in the `else` branch without adding it back to the map:

```java
// Before (bug):
} else {
  appEvents = new ArrayList<>();  // new list, never stored in sEvents
  appEvents.add(eventId);         // eventId is lost
}

// After (fix):
} else {
  appEvents = sEvents.get(appScopeKey);  // get the existing tracked list
  appEvents.add(eventId);                 // eventId is properly tracked
}
```

This meant only the first event per `appScopeKey` was tracked, so
`notifyTaskFinished()` could not properly remove subsequent event IDs.
This fix is needed for the headless task lifecycle to work correctly
when multiple tasks run concurrently.

# Test Plan

The background task example app (`native-component-list`) includes timer
tick logs that verify JS timers work while backgrounded. A
`DebugBgTaskReceiver` is included in `bare-expo` to trigger tasks via
ADB.

1. Build bare-expo: `cd apps/bare-expo && npx expo run:android`
2. Open the app, navigate to Background Task screen, tap **Schedule
Background Task**
3. Background the app (press Home)
4. Trigger via ADB:
   ```bash
adb shell am broadcast -a dev.expo.payments.DEBUG_BG_TASK -n
dev.expo.payments/.DebugBgTaskReceiver
   ```
5. Watch logcat:
   ```bash
   adb logcat -s ReactNativeJS DebugBgTaskReceiver TaskService
   ```

**Without fix:** Only `TASK RUNNING` and `tick 1/5` appear (before first
`setTimeout`). Subsequent ticks never fire.

**With fix:** All 5 ticks appear at 2s intervals, followed by `all ticks
completed, saving timestamp`.

# 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)

* [expo-router] fix zoom transition to prefetched routes (expo#43852)

# Why

When screen was preloaded the zoom transition was flaky. The reason for
this is:
1. When screen was preloaded, it was added on the native side, but
`ZoomTransitionEnabler` was not mounted
2. When the navigation happened from JS side, `ZoomTransitionEnabler`
was mounted, but because the screen was preloaded it happened only after
the transition started - no enter zoom transition

This was timing issue and was not happening in all cases.

There is another similar issue regarding timing, when
`ZoomTransitionEnabler` is mounted too late when there is a lot of
processing involved. I want to solve it in the follow-up PR, by
prefetching the zoomed page, before the navigation.

# How

Add `INTERNAL_EXPO_ROUTER_ZOOM_TRANSITION_SCREEN_ID_PARAM_NAME` param in
the `PRELOAD` stack operation similar to navigation operation. This will
mount the `ZoomTransitionEnabler` in case of prefetching as well.

# Test Plan

1. Unit tests
2. Manual testing in link-preview app with prefetch enabled

# Checklist

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

- [ ] 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)

* [ui] add date and time picker dialogs, extra props (expo#43895)

# Why

Add `DatePickerDialog` and `TimePickerDialog` components to `expo-ui` on
Android, and support `selectableDates` to constrain the date range. Also
refactors color-building logic into shared helpers.

# How

- Added `DatePickerDialogView` and `TimePickerDialogView` native Compose
views backed by Material 3 `DatePickerDialog` and `AlertDialog`.
- Introduced `selectableDates` prop (`{ start?: Date; end?: Date }`) for
both inline and dialog pickers.
- Extracted `buildDatePickerColors` / `buildTimePickerColors` helpers to
deduplicate color overrides.
- Exported `DatePickerDialog`, `TimePickerDialog` components and types
from the JS layer with Date-to-timestamp conversion.
- Added NCL examples for both dialogs and selectable dates.

# Test Plan

1. Open the DateTimePicker screen in NCL on Android.
2. Tap "Show Date Dialog" — verify the dialog opens with selectable
dates constrained to -5d…+30d, confirm/dismiss work.
3. Tap "Show Time Dialog" — verify 24h time picker dialog, confirm
returns selected time, dismiss fires alert.
4. Scroll to the "With selectableDates" section — verify dates outside
the range are greyed out.
5. Verify the existing inline date/time pickers still function as
before.

# 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)
- [ ] 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)

* [device][ios] Update Apple devices (expo#43644)

# Why

newer Apple devices were missing, so `Device.modelName` was not behaving
as expected for these models

# How

synced with the latest Xcode 26.3 database

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# Checklist

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

- [ ] 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)

* [widgets] Pass environment to AppIntent (expo#43925)

# Why

It's first step to remove `target` requirement on `Button`.

# How

Pass stringified JSON widget environment to `AppIntent`

# Test Plan

Inspect environment in AppIntent execution.

* [ios][ui] Add defaultScrollAnchorForRole modifier (expo#43923)

Exposes SwiftUI's `.defaultScrollAnchor(_:for:)` (iOS 18+) as a
modifier. This is the two-parameter overload that lets you set different
scroll anchors for different roles: where the scroll view starts, how it
handles content size changes, and how it aligns content smaller than its
container.

```tsx
<ScrollView modifiers={[
  defaultScrollAnchor('bottom'),
  defaultScrollAnchorForRole('top', 'initialOffset'),
]}>
  {messages.map(msg => <Text key={msg.id}>{msg.text}</Text>)}
</ScrollView>
```

The scroll view anchors to bottom globally, but the `initialOffset` role
override makes it start at the top. Each role can be independently
controlled.

`ScrollAnchorRole` has three cases: `initialOffset` (where to start),
`sizeChanges` (how to reposition on resize), `alignment` (how to align
content smaller than the container). Passing `null` as the anchor opts
out of a specific role.

Also improves `defaultScrollAnchor` from expo#43914:
- Adds `null` support to match Apple's `UnitPoint?` signature (allows
resetting/opting out)
- Adds `@platform macos 14.0+` to JSDoc (was missing, Swift guard
already covered it)
- Extracts shared `UnitPointValue` type used by both modifiers

Reuses the existing `UnitPointOptions` enum. Adds a new
`ScrollAnchorRoleOptions` enum. Falls back to a no-op on iOS < 18.

Same pattern as `defaultScrollAnchor` from expo#43914.

## Test plan

- Built and ran on iPhone 17 Pro simulator (iOS 26.2, Xcode 26).
- Tested `defaultScrollAnchor('bottom')` - scroll view starts at bottom.
- Tested `defaultScrollAnchorForRole('top', 'initialOffset')` overriding
`defaultScrollAnchor('bottom')` - scroll view starts at top, confirming
per-role override works.
- Tested `defaultScrollAnchor(null)` - no-op, default top behavior.
- `yarn build` passes.
- `yarn tsc --noEmit` passes.
- `yarn lint --fix` passes.
- `yarn test` passes (30/30).
- Docs regenerated for `unversioned` and `v55.0.0`.

* [docs][config-types] sync xdl schemas (expo#43929)

* [prebuild-config] remove deprecated plugins (expo#43918)

* [web][camera] Fix `isAvailableAsync` on web (expo#43932)

* [ui][android] - Refactor `Button` and `IconButton` (expo#43859)

# Why

Matches Button and IconButton to native APIs. Removes custom props.

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

# How

- Removed `variant` prop and split `Button` and `IconButton` into 5
separate components matching M3 `Button`, `FilledTonalButton`,
`OutlinedButton`, `ElevatedButton`, `TextButton`. Removed `text`,
`leadingIcon`, `trailingIcon`, `color`, `elementColors`, `disabled`
props. Added `onClick`, `enabled`, `colors`, `shape`, `modifiers`.
`Content` is now composed via children instead of string props. Followed
[Compose Button
docs](https://developer.android.com/develop/ui/compose/components/button)
for Expo UI docs.
- Same approach in `IconButton`, split into `IconButton`,
`FilledIconButton`, `FilledTonalIconButton`, `OutlinedIconButton`.
Removed `variant`, `color`, `elementColors`, `disabled`, `onPress`.
Followed [Compose IconButton
docs](https://developer.android.com/develop/ui/compose/components/icon-button)
for Expo UI docs.

<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan
- Updated ButtonScreen.android.tsx NCL example
  - Created `IconButtonScreen.android.tsx` NCL example
  - Updated `button.mdx` and `iconbutton.mdx` docs with usage examples.



https://github.com/user-attachments/assets/c444331a-b57f-4356-a791-9b82cb4e61e3


<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# 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)
- [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)

* Fix capitalization in screens.mdx documentation (expo#43936)

# Why

Fix grammar in docs

* [docs] merge skills plugin into one (expo#43938)

* [config-types] revert update (expo#43940)

* [router] Fix `Stack.Protected` not applying to index routes (expo#43769)

* fix(cli): support files >= 2 GiB in AFC device upload (expo#43755)

Fixes `RangeError [ERR_FS_FILE_TOO_LARGE]` when installing apps that
contain files >= 2 GiB onto physical iOS devices via `npx expo run:ios`.

`AFCClient.uploadFile()` used `fs.readFile()` to read the entire source
file into a `Buffer` before uploading. Node.js `Buffer` has a hard 2 GiB
limit (`kMaxLength`), so any individual file in the `.app` bundle
exceeding this size causes the install to fail with:

```
RangeError [ERR_FS_FILE_TOO_LARGE]: File size (2472937860) is greater than 2 GiB
    at FSReqCallback.readFileAfterStat [as oncomplete] (node:fs:316:11)
```

This is increasingly common with apps bundling on-device ML models (e.g.
LLaMA, Stable Diffusion).

## Fix

Replace `fs.readFile()` with chunked reading via
`fs.openSync`/`fs.readSync` in 8 MiB chunks. Each chunk is written to
the device using the existing `FILE_WRITE` AFC operation. The AFC
protocol already supports multiple sequential writes to an open file
descriptor, so no protocol-level changes are needed.

- Removed unused `promisify` import from `util`
- Added tests for chunked upload behavior, empty files, and error
handling (remote fd cleanup)

---------

Co-authored-by: Cedric van Putten <[email protected]>

* [ui][android] - Match Card with compose API (expo#43896)

* fix(modules-core): serialize PersistentFileLog reads on the dispatch queue (expo#43958)

* fix(autolinking): respect NO_COLOR and handle async errors in CLI entry (expo#43915)

* [expo-router] fix regex for routes with multiple spaces (expo#43935)

# Why

The regex for `getStateForPath` was only covering routes with single
space (e.g. `my route.tsx`). This PR adds support for multiple spaces
(e.g. `my super route.tsx`)

# How

Add `g` to `replace` function

# Test Plan

1. Unit tests
2. Manual testing

**Before**
<img width="1140" height="605" alt="Screenshot 2026-03-16 at 10 16 28"
src="proxy.php?url=https%3A%2F%2Fgithub.com%2F%3Ca+href%3D"https://github.com/user-attachments/assets/4d3bd834-fb27-4f40-8618-2f738dc983c3">https://github.com/user-attachments/assets/4d3bd834-fb27-4f40-8618-2f738dc983c3"
/>



**After**
<img width="1140" height="605" alt="Screenshot 2026-03-16 at 10 16 46"
src="proxy.php?url=https%3A%2F%2Fgithub.com%2F%3Ca+href%3D"https://github.com/user-attachments/assets/b4f11f4f-7bd3-450d-868c-dbec73ff0eec">https://github.com/user-attachments/assets/b4f11f4f-7bd3-450d-868c-dbec73ff0eec"
/>




# 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)

* [ui][android] - Match Progress API with Compose (expo#43907)

# Why

Match Progress Indicator API closely with the native Jetpack Compose
API.

  # How

- Split single `ProgressView` with variant enum into 4 separate native
views: `LinearProgressIndicator`, `CircularProgressIndicator`,
`LinearWavyProgressIndicator`, `CircularWavyProgressIndicator`
- Flattened `elementColors: { trackColor }` → direct `trackColor` prop
to match native
- Added native props: `strokeCap`, `gapSize` (linear/circular),
`strokeWidth` (circular only)
- Merged separate `linearprogress.mdx` and `circularprogress.mdx` docs
into single `progress.mdx`
  - Added redirects from old doc paths
  - Updated NCL example screen to use `LazyColumn` + `Card` layout

  # Test Plan

  Test `ProgressViewScreen.android.tsx` screen in NCL app.

  # 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)

* [expo-router] fix params mutation in getPathDataFromState (expo#43934)

# Why

`getPathDataFromState` was deleting params from the object passed as
argument. Since this function should be pure this could cause unexpected
bugs. The upstream react-navigation function does not mutate the
original object, but rather modifies the shallow copy.

# How

Shallow copy the params object before deleting properties

# Test Plan

1. Unit tests
2. Manual testing

# Checklist

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

- [ ] 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)

* [android][updates] Add correct cancellation handling (expo#43966)

* [expo-navigation-bar] Add style and hidden properties to the config plugin (expo#43978)

* [expo-status-bar] Add config plugin (expo#43968)

* [docs] Document EAS_BUILD_DISABLE_BUNDLE_JAVASCRIPT_STEP env var

* [widgets] Remove unused `Compression` related code (expo#43981)

# Why

Fixes expo#43956

# How

Remove unused code from initial implementation related to `Compression`

# Test Plan

Compile the app and see if it works.

# 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)

* [ui][android] - Match Switch API with native (expo#43887)

# Why

Matches `Switch` to Compose API and adds
[Checkbox](https://composables.com/docs/androidx.compose.material3/material3/components/Checkbox)
and
[TriStateCheckbox](https://composables.com/docs/androidx.compose.material3/material3/components/TriStateCheckbox)
components

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

# How

- Matches prop names to native API
- Split Switch into `Switch` and `Checkbox`
- Added examples
- Added accessibility modifier and example for checkbox.

<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

Added/tested example in NCL and docs.


https://github.com/user-attachments/assets/ac18ec48-9c9b-4100-a9e2-2a52f1ea0345



<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# 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)
- [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)

* [expo-router] fix hash order to be RFC compliant (expo#43933)

# Why

Fixes: expo#43735

# How

Parse `hash` correctly from the url

# Test Plan

1. Unit tests
2. Manual testing

**Before**


https://github.com/user-attachments/assets/0280c9dc-9555-4c89-8605-9992852d7c46

**After**


https://github.com/user-attachments/assets/846ce243-0300-426a-8964-55f65dfdae35

# 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)

* [ui][android] - Match `ToggleButton` with Compose API (expo#43974)

# Why

Match the `ToggleButton` JS component to the native Jetpack Compose API,
following the same pattern used for Button, IconButton, Card, and Chip
refactors.

  # How

- Split the single `ToggleButton` component (with `variant` prop) into
four separate components that map 1:1 to their Material 3 Compose
counterparts: `ToggleButton`, `IconToggleButton`,
`FilledIconToggleButton`, `OutlinedIconToggleButton`.
- Removed `variant`, `text`, `color`, and `disabled` props. Content is
now passed via `children`, and `colors` (with checked/unchecked
variants) replaces `color`. `enabled` replaces `disabled`.
- Updated docs and added a `ToggleButtonScreen` example in
native-component-list.

  # Test Plan

- Open native-component-list → Expo UI → ToggleButton component screen
on Android.
  - Verify all four variants render and toggle correctly.
  - Verify custom colors apply to checked/unchecked states.

  # 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)

* [ui] Add `Link` component (expo#43983)

# Why

It's needed for widgets, but also works in a standalone app

# How

Add `Link` view according to apple documentation
https://developer.apple.com/documentation/swiftui/link

# Test Plan

I've added Link screen to the NCL

* [ui][android] - Picker refactor (expo#43809)

# Why

Removes Picker in order to map JS component API with platform API for
better composition.

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

# How

- Removes custom Picker.
- Adds RadioButton and Segmented Button as separate components.
- Adds recommended accessibility modifiers
- Updates docs with accessibility practices. Took example reference from
https://composables.com/docs/androidx.compose.material3/material3/components/RadioButton


<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

Added/tested examples in NCL

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# 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)
- [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)

* [docs] Add Expo Agent intro video to additional resources (expo#43990)

# Why

The Expo team published a new video, "Introducing Expo Agent (beta)", on
the @ExpoDevelopers YouTube channel on March 10, 2026. It is not yet
listed on the additional resources page.

# How

- Add the "Introducing Expo Agent (beta)" video entry to the top of the
`YOUTUBE_VIDEOS` array in `docs/public/static/talks.ts`.
- Update `modificationDate` in
`docs/pages/additional-resources/index.mdx` to reflect the current date.

<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

<img width="2776" height="844" alt="CleanShot 2026-03-17 at 15 35 11@2x"
src="proxy.php?url=https%3A%2F%2Fgithub.com%2F%3Ca+href%3D"https://github.com/user-attachments/assets/fb4dc5c5-e8d1-4a32-a85e-9d85cd9a3b0b">https://github.com/user-attachments/assets/fb4dc5c5-e8d1-4a32-a85e-9d85cd9a3b0b"
/>


# Checklist

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

- [ ] 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)

* [widgets] Automatically add `target` for `Button` (expo#43977)

# Why

Next step to remove `target` prop requirement on `Button`.
expo#43925

# How

Add a unique `target` prop to every `Button`. If a parent element has a
`key` prop, it will be appended to help uniquely identify each button
(e.g., when rendering buttons inside a `.map()`).

# Test Plan

I've added a few tests that hopefully covers all possible use cases.

* [ios][expo-ui] Add date and timer support to Text component (expo#43552)

* [ui] Add `widgetURL` modifier (expo#43984)

# Why

Widgets

# How

Added widget-specific modifier and moved existing widget-one to separate
file.

# Test Plan

Tested in widgets-tester

* [widgets] Add support for `Link` view from `@expo/ui` (expo#43985)

# Why

Add support for expo#43983

# How

Add case for `Link` view in `DynamicView`

# Test Plan

Tested in widget-tester.

* merge commit update (#40)

* Create objective-c-xcode.yml (#1)

Signed-off-by: Kristen T. Tran <[email protected]>

* Create swift.yml (#24)

* Create sonarcloud.yml (#25)

* Create codeql.yml

---------

Signed-off-by: Kristen T. Tran <[email protected]>

---------

Signed-off-by: Kristen T. Tran <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Jakob Malmo <[email protected]>
Co-authored-by: Vojtech Novak <[email protected]>
Co-authored-by: Kudo Chien <[email protected]>
Co-authored-by: Carlos Roldán <[email protected]>
Co-authored-by: Jakub Tkacz <[email protected]>
Co-authored-by: Aman Mittal <[email protected]>
Co-authored-by: Gabriel Donadel Dall'Agnol <[email protected]>
Co-authored-by: Alan Hughes <[email protected]>
Co-authored-by: Mathieu Acthernoene <[email protected]>
Co-authored-by: Krystof Woldrich <[email protected]>
Co-authored-by: nishan (o^▽^o) <[email protected]>
Co-authored-by: ciospettw <[email protected]>
Co-authored-by: Brent Vatne <[email protected]>
Co-authored-by: Evan Bacon <[email protected]>
Co-authored-by: Expo Bot <[email protected]>
Co-authored-by: Ray <[email protected]>
Co-authored-by: Janic Duplessis <[email protected]>
Co-authored-by: Pavol Rusnak <[email protected]>
Co-authored-by: Jakub Grzywacz <[email protected]>
Co-authored-by: Zachary Ebenfeld <[email protected]>
Co-authored-by: contra <[email protected]>
Co-authored-by: Cedric van Putten <[email protected]>
Co-authored-by: Louis <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot: passed checks ExpoBot has nothing to complain about sdk-55

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants