Skip to content

Conversation

@kimchi-developer
Copy link
Owner

Summary

  • Refactor Android expo-ui leaf components from class-based to DSL pattern
  • Add matchContents prop to Android HostView for proper sizing
  • Remove AutoSizingComposable from individual components (sizing now handled by Host)
  • Convert TextInputView to controlled component pattern

Changes

Kotlin (expo-ui/android)

  • HostView: Add matchContentsHorizontal and matchContentsVertical props with AutoSizingComposable integration
  • SwitchView: Convert to DSL, remove AutoSizingComposable
  • PickerView: Convert to DSL, remove AutoSizingComposable
  • SliderView: Convert to DSL
  • ProgressView: Convert to DSL, remove AutoSizingComposable
  • TextInputView: Convert to DSL with controlled component pattern (value prop), remove setText imperative API
  • ChipView: Convert to DSL
  • DatePickerView: Convert to DSL
  • ShapeView: Convert to DSL
  • AlertDialogView: Convert to DSL

TypeScript (expo-ui/src)

  • Host: Add matchContents prop type (boolean | { vertical?, horizontal? })
  • TextInput: Add value prop for controlled mode, remove TextInputRef and ref prop

Example screens (native-component-list)

  • Add matchContents to Host components where needed
  • Update TextInputScreen to use controlled pattern
  • Fix DateTimePickerScreen Host import (swift-ui → jetpack-compose)

Test plan

  • Test Switch component renders with correct size
  • Test Picker component (segmented, radio variants)
  • Test Slider component
  • Test Progress indicators (circular, linear, wavy variants)
  • Test TextInput controlled and uncontrolled modes
  • Test Chip component (assist, filter, input, suggestion variants)
  • Test DateTimePicker
  • Test AlertDialog
  • Test Shape component

@kimchi-developer kimchi-developer force-pushed the @kimchi-developer/expo-ui-android-dsl-refactor branch 29 times, most recently from 1717e2c to bc0c34e Compare December 20, 2025 13:40
Copilot AI and others added 30 commits January 15, 2026 15:14
…xpo#42177)

- [x] Review the current Maestro Cloud documentation structure
- [x] Add the Outputs section with all 6 outputs documented
- [x] Verify the formatting matches other pre-packaged jobs
- [x] Request code review - passed with no issues
- [x] Add example showing how to use Maestro Cloud outputs in subsequent jobs
- [x] Update example to use `after` instead of `needs` to notify on both success and failure
- [x] Add note about async mode limitations for outputs
- [x] Complete the task

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> ## Summary
> 
> The `type: maestro-cloud` pre-packaged job in EAS Workflows now has new outputs that were implemented in https://github.com/expo/universe/pull/24049. The documentation needs to be updated to reflect these new outputs.
> 
> ## Changes Needed
> 
> Update the file `docs/pages/eas/workflows/pre-packaged-jobs.mdx` to add an **Outputs** section for the Maestro Cloud job (after the Parameters section).
> 
> The following outputs should be documented:
> 
> | Output | Type | Description |
> | ------ | ---- | ----------- |
> | maestro_cloud_url | string | URL to the Maestro Cloud upload results page. |
> | total_flows_count | number | Total number of flows that were executed. |
> | successful_flows_count | number | Number of flows that completed successfully (status SUCCESS or WARNING). |
> | failed_flows_count | number | Number of flows that failed (status ERROR or STOPPED). |
> | successful_flow_names_json | string | JSON array containing the names of successful flows. |
> | failed_flow_names_json | string | JSON array containing the names of failed flows. |
> 
> ## Location
> 
> The outputs section should be added in the "## Maestro Cloud" section, after the "#### Parameters" table and before the "### Examples" section. The structure should follow the same pattern as other pre-packaged jobs (like Build, Deploy, Fingerprint, etc.) which have an "#### Outputs" subsection with a table.
> 
> ## Reference Implementation
> 
> The outputs are defined in `expo/universe` at `server/www/src/data/entities/workflow/job/WorkflowMaestroCloudJob.ts`:
> 
> ```typescript
> outputs: {
>   maestro_cloud_url: '${{ steps.maestro_cloud.outputs.maestro_cloud_url }}',
>   total_flows_count: '${{ steps.results.outputs.total_flows_count || 0 }}',
>   successful_flows_count: '${{ steps.results.outputs.successful_flows_count || 0 }}',
>   failed_flows_count: '${{ steps.results.outputs.failed_flows_count || 0 }}',
>   successful_flow_names_json: '${{ steps.results.outputs.successful_flow_names_json || "[]" }}',
>   failed_flow_names_json: '${{ steps.results.outputs.failed_flow_names_json || "[]" }}',
> },
> ```


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/expo/expo/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Stanisław Chmiela <sjchmiela@users.noreply.github.com>
… loaders (expo#42147)

# Why

In development, regardless of the `web.output` setting, loaders would
always get a `null` `request` parameter.

# How

- Modified `createRouteHandlerMiddleware()` to respect `web.output`
  - when `web.output: static`, `request` is `undefined`
- when `web.output: server`and `unstable_useServerRendering: true`,
`request` is a `Request`
- Removed `DataLoaderModuleMiddleware` and updated
`createRouteHandlerMiddleware()` to handle loader responses
- Aligned loader function argument to be `Request | undefined` to match
`LoaderFunction` type, SSG was using `Request | null`
- Added a new E2E test fixture and updated the Jest static and server
loader E2E tests

# Test Plan

- CI
- Manual testing

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

Some local e2e tests were failing

# How

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

# Test Plan


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

Resolves
<https://linear.app/expo/issue/ENG-18754/bug-report-heap-corruption>

Expo's TypedArray implementation always returns data pointer with
byteOffset applied
([source](https://github.com/expo/expo/blob/1cf92d61390bd06649d2debb8ab1258bda2e6f4d/packages/expo-modules-core/common/cpp/JSI/TypedArray.cpp#L55)).
So functions like
[`read()`/`write()`](https://github.com/expo/expo/blob/1cf92d61390bd06649d2debb8ab1258bda2e6f4d/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/typedarray/TypedArray.kt#L38-L39)
on Android or
[`rawPointer`](https://github.com/expo/expo/blob/1cf92d61390bd06649d2debb8ab1258bda2e6f4d/packages/expo-modules-core/ios/Core/TypedArrays/TypedArray.swift#L65)
on iOS already return relative offset.
Thus, we shouldn't apply `byteOffset` again on callsites.

# How

- Removed `byteOffset` offsets when writing typed arrays in `digest()`
and `getRandomValues()` (set to 0)
- Added comments in typed array methods to make it more clear about the
offsets.

# Test Plan

Manual tests with custom offsets, including repro from Linear

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

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
# Why

Launching a deep link with the dev launcher currently results in the
creation of two JavaScript threads, which causes the app to crash.

# How

Do not launch previous URL when a deep link is present.

# Test Plan

Build Bare Expo and launch the app by pressing `i` in the terminal.

# 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)
…xpo#42086)

# Why

Small step towards
https://linear.app/expo/issue/ENG-12689/one-copy-uint8array-databytearray-convertible

# How

- Pre-allocated direct buffer in response sink
- Returned native ArrayBuffer, which does not copy when returned to JS

# Test Plan

- Fetch test suite
- Manual testing in [my benchmark
app](https://github.com/barthap/fetch-benchmark)

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

This PR adds support for monograms on Apple Maps markers, as documented
in Apple's MapKit API:
https://developer.apple.com/documentation/mapkit/marker/init(_:monogram:coordinate:)-2ojcy
Monograms allow displaying short text (typically initials like "JD" for
"John Doe") directly on the marker balloon, which is useful for
contact-style markers or location codes without requiring a custom SF
Symbol.

# How

Added a new optional `monogram` property to `AppleMapsMarker`:

- **TypeScript**: Added `monogram?: string` field to the
`AppleMapsMarker` type
- **Swift**: Added `monogram` field to `MapMarker` struct with a
computed `hasMonogram` property
- **iOS17/iOS18 Views**: Updated marker rendering to conditionally use
the `Marker(_:monogram:coordinate:)` initializer when a monogram is
provided and no `systemImage` is set

The `systemImage` property takes precedence over `monogram` if both are
provided, ensuring backward compatibility.

# Test Plan

1. Create markers with the `monogram` property set to initials (e.g.,
"AB", "JD")
2. Verify the marker displays the monogram text on the balloon instead
of a pin icon
3. Test that markers with `systemImage` still display the SF Symbol
correctly
4. Test that markers with both `systemImage` and `monogram` use
`systemImage` (precedence)
5. Test on both iOS 17+ and iOS 18+ devices to ensure both view
implementations work
# Why

There is swiftlint issue in our native ios code

# How

run `swiftlint lint --config [path-to-expo-repo]/.swiftlint.yml --strict
[path-to-expo-repo]/packages/expo-router --fix`

# Test Plan

CI

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

@tomekzaw reported an issue, that in his setup he gets an error:
`'Logger' is ambiguous for type lookup`.

The other type that was found is `os.Logger`. I couldn't reproduce the
issue locally, but the approach used in this PR solves it, by specifying
which `Logger` to use.

# How

Change `Logger` to `ExpoModulesCore.Logger`

# Test Plan

1. Build the router-e2e app

# 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)
…fig plugin (expo#42231)

# Why

Add a comment to make it clear, which library set this plugin to true

# How

<!--
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.
-->

# 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)
# Why
The promises resolve after the test ends. A race condition caused
`writeContactToFileAsync` to throw an exception - contacts were deleted
before the function even started.

# How

Rewrite the test to use async/await properly and to run in isolation
from other tests.

# Test Plan

Tested on bare-expo
…xpo#42203)

# Why
Fixes an issue with adding a contact when a default account is set to
cloud:
`Cannot add contacts to local or SIM accounts when default account is
set to cloud`

The problem seems to occur only on pure Android - I reproduced it on
Google Pixel, while for example on Xiaomi it doesn't happen.
The cause is adding a contact with the account type/name hardcoded to
null, whereas those fields should be overwritten with the system default
type.

# How
Removes unnecessary hardcoded ACCOUNT_TYPE and ACCOUNT_NAME when
creating a contact. When they are not present, the system can create a
contact in its default location.

# Test Plan
Tested on BareExpo on Google Pixel 9 and Xiaomi Poco X3 Pro
…roduction (expo#42166)

# Why

In SSR, we always expect that a loader module is available if
`route.loader` is set. If the loader module is not found, we should
throw an error instead of returning `undefined`.

# How

Throw an error in `expo-server/src/vendor/environment/common.ts` when a
loader module isn't found.

# Test Plan

- CI
- Manual testing (`yarn export:server-loader`, delete any loader from
`_expo/loaders` then run `yarn expo serve`)

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

Copied from expo#41788 as I was not able to
edit that PR.

Adds a 'renderingMode' prop to NativeTabs.Trigger.Icon that controls how
icons are rendered on iOS:

- 'template' (default): Icon uses template rendering, allowing iOS to
apply the selected/unselected tint color
- 'original': Icon preserves its original colors, useful for icons with
gradients, transparency, or multiple colors

This enables developers to use custom colored PNG icons without them
being tinted by the tab bar.

# Why

Complex icon sets with gradients and multiple colors are gaining
popularity and while native UI is what this component is aimed at it
would be great to support custom icons without tinting for unique UI
design. `src` support is not fully usable imo without this change as a
common reason to use them is non-solid icons.

# How

When using PNG's as icons I noticed the tinting was affecting the design
of the sets. There doesn't seem to be any escape hatches via styling
prop (both `null` and `transparent` on tinting do not give the desired
outcome). The feature addition doesn't affect the default functionality
and is a simple change to allow advanced customization.

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

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

---------

Co-authored-by: Byron Polley <byronpolley@live.com>
Co-authored-by: Aman Mittal <amandeepmittal@live.com>
…2149)

# Why

Loader functions should only have access to immutable requests, similar
to middleware functions, to prevent request modification.

# How

- Exported `ImmutableRequest` from `expo-server` to use in `@expo/cli`
- Ensure loaders are invoked with `ImmutableRequest` in both
`expo-server` for production, and `@expo/cli` for development.

# Test Plan

- CI
- Manual testing

# 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)
… render bundles (expo#42245)

# Why

Fixes an SSR rendering issue where visiting a loader endpoint (e.g.,
`/_expo/loaders/request`) before the page request (e.g., `/request`)
causes the page to render with a Suspense fallback instead of the SSR
content.

The underlying issue was a module ID collision between loader bundles
and `render.js`. Both bundles contain the same source file (for example
`app/request.tsx`) but with different exports due to Babel transforms:
  - `render.js`: Contains full component + loader function
  - loader bundle: Contains only the loader function
  
Because Metro module IDs are based on the file path, both bundles would
get the same ID for the route module. If the loader bundle was loaded
first, route components would be missing and thus break SSR.

# How

Modified the `createModuleId()` wrapper in `withExpoSerializers.ts` so
`+loader` is appended to paths for modules with `loaderReference`
metadata, but only when serializing loader bundles.

# Test Plan

- CI
- Manual testing: 
  ```bash
  yarn export:server-loader && yarn expo serve
  curl http://localhost:8081/_expo/loaders/request
  curl http://localhost:8081/request
  ```
On this branch, you should see the second request returns the complete
HTML for `/request`, not the Suspense fallback

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

Overlooked adding changelogs in previous PR

# How

Added the relevant changelogs to `@expo/cli` and `@expo/metro-config`

# Test Plan

Not required

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

# Why

In Expo Widgets, we need to recreate props from dictionary. 
To not make `appContext` setter and `updateRawProps` public, we need this new init. 

# How

Create new `init(rawProps: [String: Any], context: AppContext)`  on `ExpoSwiftUI.ViewProps`

# Test Plan

Bare Expo builds and Widgets works.
# Why

In expo#42237 I commited a seemingly
insignificant change in the comment directly through GitHub, and I
forgot that it would require rebuilding the js.

# How

`yarn build`

# Test Plan

`check-packages` should be green ✅
…42238)

# Why

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

# How

<!--
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.
-->

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

---------

Co-authored-by: Tomasz Sapeta <tsapeta@expo.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.