@expo/ui 58.0.8 → 58.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/CHANGELOG.md +14 -5
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/AnimatedVisibilityView.kt +40 -8
  4. package/android/src/main/java/expo/modules/ui/ComposeViews.kt +21 -3
  5. package/android/src/main/java/expo/modules/ui/DatePickerView.kt +12 -4
  6. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +5 -1
  7. package/android/src/main/java/expo/modules/ui/HorizontalPagerView.kt +3 -1
  8. package/android/src/main/java/expo/modules/ui/HostView.kt +64 -12
  9. package/android/src/main/java/expo/modules/ui/LazyItemsView.kt +14 -2
  10. package/android/src/main/java/expo/modules/ui/ModalBottomSheetView.kt +5 -1
  11. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +29 -4
  12. package/android/src/main/java/expo/modules/ui/RNHostView.kt +68 -17
  13. package/android/src/main/java/expo/modules/ui/ShapeView.kt +3 -1
  14. package/android/src/main/java/expo/modules/ui/SlotView.kt +3 -1
  15. package/android/src/main/java/expo/modules/ui/SnackbarView.kt +5 -1
  16. package/android/src/main/java/expo/modules/ui/TextView.kt +3 -1
  17. package/android/src/main/java/expo/modules/ui/Utils.kt +3 -1
  18. package/android/src/main/java/expo/modules/ui/colors/MaterialColors.kt +5 -1
  19. package/android/src/main/java/expo/modules/ui/convertibles/AnimationSpecParams.kt +3 -1
  20. package/android/src/main/java/expo/modules/ui/graphics/ImageLoader.kt +6 -2
  21. package/android/src/main/java/expo/modules/ui/icon/IconView.kt +5 -1
  22. package/android/src/main/java/expo/modules/ui/state/ObservableState.kt +3 -1
  23. package/android/src/main/java/expo/modules/ui/textfield/BasicTextField.kt +10 -2
  24. package/android/src/main/java/expo/modules/ui/textfield/TextField.kt +20 -4
  25. package/android/src/main/java/expo/modules/ui/textfield/TextFieldShared.kt +3 -1
  26. package/build/community/picker/Picker.android.js +7 -0
  27. package/build/community/picker/Picker.android.js.map +1 -1
  28. package/build/jetpack-compose/LazyColumn/index.d.ts +2 -1
  29. package/build/jetpack-compose/LazyColumn/index.js +1 -0
  30. package/build/jetpack-compose/LazyColumn/index.js.map +1 -1
  31. package/build/jetpack-compose/LazyItems/index.d.ts +19 -18
  32. package/build/jetpack-compose/LazyItems/index.js +1 -2
  33. package/build/jetpack-compose/LazyItems/index.js.map +1 -1
  34. package/build/jetpack-compose/LazyRow/index.d.ts +2 -1
  35. package/build/jetpack-compose/LazyRow/index.js +1 -0
  36. package/build/jetpack-compose/LazyRow/index.js.map +1 -1
  37. package/build/jetpack-compose/RNHostView/index.d.ts +6 -1
  38. package/build/jetpack-compose/RNHostView/index.js +9 -4
  39. package/build/jetpack-compose/RNHostView/index.js.map +1 -1
  40. package/build/jetpack-compose/index.d.ts +0 -1
  41. package/build/jetpack-compose/index.js.map +1 -1
  42. package/build/jetpack-compose/modifiers/index.d.ts +18 -3
  43. package/build/jetpack-compose/modifiers/index.js +15 -2
  44. package/build/jetpack-compose/modifiers/index.js.map +1 -1
  45. package/build/swift-ui/LazyHStack/index.d.ts +45 -0
  46. package/build/swift-ui/LazyHStack/index.js +9 -0
  47. package/build/swift-ui/LazyHStack/index.js.map +1 -1
  48. package/build/swift-ui/LazyStackForEach/index.d.ts +44 -0
  49. package/build/swift-ui/LazyStackForEach/index.js +54 -0
  50. package/build/swift-ui/LazyStackForEach/index.js.map +1 -0
  51. package/build/swift-ui/LazyVStack/index.d.ts +45 -0
  52. package/build/swift-ui/LazyVStack/index.js +9 -0
  53. package/build/swift-ui/LazyVStack/index.js.map +1 -1
  54. package/build/swift-ui/List/DataListForEach.d.ts +6 -7
  55. package/build/swift-ui/List/DataListForEach.js.map +1 -1
  56. package/build/swift-ui/List/ListForEach.d.ts +7 -1
  57. package/build/swift-ui/List/ListForEach.js +1 -5
  58. package/build/swift-ui/List/ListForEach.js.map +1 -1
  59. package/build/swift-ui/RNHostView.d.ts +7 -2
  60. package/build/swift-ui/RNHostView.js +7 -3
  61. package/build/swift-ui/RNHostView.js.map +1 -1
  62. package/build/swift-ui/index.d.ts +1 -0
  63. package/build/swift-ui/index.js.map +1 -1
  64. package/build/swift-ui/modifiers/containerBackground.d.ts +2 -2
  65. package/build/swift-ui/modifiers/containerBackground.js +2 -2
  66. package/build/swift-ui/modifiers/index.d.ts +9 -1
  67. package/build/swift-ui/modifiers/index.js +9 -0
  68. package/build/swift-ui/modifiers/index.js.map +1 -1
  69. package/build/universal/ListItem/ListItem.js +11 -2
  70. package/build/universal/ListItem/ListItem.js.map +1 -1
  71. package/build/universal/RNHostView/index.js +12 -5
  72. package/build/universal/RNHostView/index.js.map +1 -1
  73. package/build/universal/RNHostView/types.d.ts +9 -4
  74. package/build/universal/RNHostView/types.js.map +1 -1
  75. package/build/universal/Switch/index.android.js +5 -1
  76. package/build/universal/Switch/index.android.js.map +1 -1
  77. package/build/utils/matchContents.d.ts +10 -0
  78. package/build/utils/matchContents.js +16 -0
  79. package/build/utils/matchContents.js.map +1 -0
  80. package/expo-module.config.json +0 -1
  81. package/ios/DataListForEachView.swift +65 -28
  82. package/ios/ExpoUIModule.swift +0 -1
  83. package/ios/LazyHStackView.swift +3 -0
  84. package/ios/LazyVStackView.swift +3 -0
  85. package/ios/ListView.swift +8 -0
  86. package/ios/Modifiers/ContainerBackgroundModifier.swift +23 -16
  87. package/ios/Modifiers/PreferredColorSchemeModifier.swift +12 -0
  88. package/ios/Modifiers/View+ModifierArray.swift +3 -3
  89. package/ios/Modifiers/ViewModifierRegistry.swift +11 -9
  90. package/ios/Modifiers/WidgetKitModifiers.swift +13 -0
  91. package/ios/RNHostView.swift +55 -9
  92. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10-sources.jar +0 -0
  93. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10-sources.jar.md5 +1 -0
  94. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10-sources.jar.sha1 +1 -0
  95. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10-sources.jar.sha256 +1 -0
  96. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10-sources.jar.sha512 +1 -0
  97. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.aar +0 -0
  98. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.aar.md5 +1 -0
  99. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.aar.sha1 +1 -0
  100. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.aar.sha256 +1 -0
  101. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.aar.sha512 +1 -0
  102. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.8/expo.modules.ui-58.0.8.module → 58.0.10/expo.modules.ui-58.0.10.module} +22 -22
  103. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.module.md5 +1 -0
  104. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.module.sha1 +1 -0
  105. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.module.sha256 +1 -0
  106. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.module.sha512 +1 -0
  107. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.8/expo.modules.ui-58.0.8.pom → 58.0.10/expo.modules.ui-58.0.10.pom} +1 -1
  108. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.pom.md5 +1 -0
  109. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.pom.sha1 +1 -0
  110. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.pom.sha256 +1 -0
  111. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.10/expo.modules.ui-58.0.10.pom.sha512 +1 -0
  112. package/package.json +3 -3
  113. package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
  114. package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
  115. package/src/community/picker/Picker.android.tsx +5 -0
  116. package/src/jetpack-compose/LazyColumn/index.tsx +2 -0
  117. package/src/jetpack-compose/LazyItems/index.tsx +18 -21
  118. package/src/jetpack-compose/LazyRow/index.tsx +2 -0
  119. package/src/jetpack-compose/RNHostView/index.tsx +17 -6
  120. package/src/jetpack-compose/index.ts +0 -1
  121. package/src/jetpack-compose/modifiers/index.ts +16 -3
  122. package/src/swift-ui/LazyHStack/index.tsx +45 -0
  123. package/src/swift-ui/LazyStackForEach/index.tsx +110 -0
  124. package/src/swift-ui/LazyVStack/index.tsx +45 -0
  125. package/src/swift-ui/List/DataListForEach.tsx +7 -8
  126. package/src/swift-ui/List/ListForEach.tsx +10 -3
  127. package/src/swift-ui/RNHostView.tsx +11 -4
  128. package/src/swift-ui/index.tsx +1 -0
  129. package/src/swift-ui/modifiers/containerBackground.ts +2 -2
  130. package/src/swift-ui/modifiers/index.ts +11 -0
  131. package/src/universal/ListItem/ListItem.tsx +10 -1
  132. package/src/universal/RNHostView/index.tsx +8 -3
  133. package/src/universal/RNHostView/types.ts +6 -4
  134. package/src/universal/Switch/index.android.tsx +11 -2
  135. package/src/utils/matchContents.ts +14 -0
  136. package/ios/AccessoryWidgetBackgroundView.swift +0 -27
  137. package/ios/Modifiers/WidgetModifiers.swift +0 -70
  138. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8-sources.jar +0 -0
  139. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8-sources.jar.md5 +0 -1
  140. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8-sources.jar.sha1 +0 -1
  141. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8-sources.jar.sha256 +0 -1
  142. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8-sources.jar.sha512 +0 -1
  143. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.aar +0 -0
  144. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.aar.md5 +0 -1
  145. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.aar.sha1 +0 -1
  146. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.aar.sha256 +0 -1
  147. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.aar.sha512 +0 -1
  148. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.module.md5 +0 -1
  149. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.module.sha1 +0 -1
  150. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.module.sha256 +0 -1
  151. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.module.sha512 +0 -1
  152. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.pom.md5 +0 -1
  153. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.pom.sha1 +0 -1
  154. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.pom.sha256 +0 -1
  155. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.8/expo.modules.ui-58.0.8.pom.sha512 +0 -1
  156. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +0 -13
  157. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +0 -1
  158. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +0 -1
  159. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +0 -1
  160. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +0 -1
@@ -1,13 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { StyleSheet, View } from 'react-native';
3
+ import { resolveMatchContents } from '../../utils/matchContents';
3
4
  import { useUniversalLifecycle } from '../hooks';
4
5
  const styles = StyleSheet.create({
5
- fillParent: {
6
- width: '100%',
6
+ fillWidth: {
7
+ width: '100%'
8
+ },
9
+ fillHeight: {
7
10
  height: '100%'
8
11
  },
9
- matchContents: {
10
- width: 'fit-content',
12
+ fitWidth: {
13
+ width: 'fit-content'
14
+ },
15
+ fitHeight: {
11
16
  height: 'fit-content'
12
17
  },
13
18
  hidden: {
@@ -18,11 +23,13 @@ const styles = StyleSheet.create({
18
23
  * Hosts React Native views inside Jetpack Compose or SwiftUI views.
19
24
  */ export function RNHostView({ children, style, onAppear, onDisappear, hidden = false, testID, matchContents = false, onLayout }) {
20
25
  useUniversalLifecycle(onAppear, onDisappear);
26
+ const { horizontal, vertical } = resolveMatchContents(matchContents);
21
27
  return /*#__PURE__*/ _jsx(View, {
22
28
  testID: testID,
23
29
  onLayout: onLayout,
24
30
  style: [
25
- matchContents ? styles.matchContents : styles.fillParent,
31
+ horizontal ? styles.fitWidth : styles.fillWidth,
32
+ vertical ? styles.fitHeight : styles.fillHeight,
26
33
  style,
27
34
  hidden && styles.hidden
28
35
  ],
@@ -1 +1 @@
1
- {"version":3,"sources":["universal/RNHostView/index.tsx"],"sourcesContent":[null],"names":["StyleSheet","View","useUniversalLifecycle","styles","create","fillParent","width","height","matchContents","hidden","display","RNHostView","children","style","onAppear","onDisappear","testID","onLayout"],"mappings":";AAAA,SAASA,UAAU,EAAEC,IAAI,QAAQ,eAAe;AAEhD,SAASC,qBAAqB,QAAQ,WAAW;AAGjD,MAAMC,SAASH,WAAWI,MAAM,CAAC;IAC/BC,YAAY;QAAEC,OAAO;QAAQC,QAAQ;IAAO;IAC5CC,eAAe;QAAEF,OAAO;QAAeC,QAAQ;IAAc;IAC7DE,QAAQ;QAAEC,SAAS;IAAO;AAC5B;AAEA;;CAEC,GACD,OAAO,SAASC,WAAW,EACzBC,QAAQ,EACRC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXN,SAAS,KAAK,EACdO,MAAM,EACNR,gBAAgB,KAAK,EACrBS,QAAQ,EACQ;IAChBf,sBAAsBY,UAAUC;IAEhC,qBACE,KAACd;QACCe,QAAQA;QACRC,UAAUA;QACVJ,OAAO;YACLL,gBAAgBL,OAAOK,aAAa,GAAGL,OAAOE,UAAU;YACxDQ;YACAJ,UAAUN,OAAOM,MAAM;SACxB;kBACAG;;AAGP;AAEA,cAAc,UAAU"}
1
+ {"version":3,"sources":["universal/RNHostView/index.tsx"],"sourcesContent":[null],"names":["StyleSheet","View","resolveMatchContents","useUniversalLifecycle","styles","create","fillWidth","width","fillHeight","height","fitWidth","fitHeight","hidden","display","RNHostView","children","style","onAppear","onDisappear","testID","matchContents","onLayout","horizontal","vertical"],"mappings":";AAAA,SAASA,UAAU,EAAEC,IAAI,QAAQ,eAAe;AAEhD,SAASC,oBAAoB,QAAQ,4BAA4B;AACjE,SAASC,qBAAqB,QAAQ,WAAW;AAGjD,MAAMC,SAASJ,WAAWK,MAAM,CAAC;IAC/BC,WAAW;QAAEC,OAAO;IAAO;IAC3BC,YAAY;QAAEC,QAAQ;IAAO;IAC7BC,UAAU;QAAEH,OAAO;IAAc;IACjCI,WAAW;QAAEF,QAAQ;IAAc;IACnCG,QAAQ;QAAEC,SAAS;IAAO;AAC5B;AAEA;;CAEC,GACD,OAAO,SAASC,WAAW,EACzBC,QAAQ,EACRC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXN,SAAS,KAAK,EACdO,MAAM,EACNC,gBAAgB,KAAK,EACrBC,QAAQ,EACQ;IAChBlB,sBAAsBc,UAAUC;IAChC,MAAM,EAAEI,UAAU,EAAEC,QAAQ,EAAE,GAAGrB,qBAAqBkB;IAEtD,qBACE,KAACnB;QACCkB,QAAQA;QACRE,UAAUA;QACVL,OAAO;YACLM,aAAalB,OAAOM,QAAQ,GAAGN,OAAOE,SAAS;YAC/CiB,WAAWnB,OAAOO,SAAS,GAAGP,OAAOI,UAAU;YAC/CQ;YACAJ,UAAUR,OAAOQ,MAAM;SACxB;kBACAG;;AAGP;AAEA,cAAc,UAAU"}
@@ -6,16 +6,21 @@ import type { UniversalBaseProps } from '../types';
6
6
  */
7
7
  export interface RNHostViewProps extends UniversalBaseProps {
8
8
  /**
9
- * When `true`, the host updates its size in the native view tree to match
10
- * the children's size. When `false`, the host uses the size of the parent
11
- * native view.
9
+ * When `true`, the host updates its size in the SwiftUI or Compose view tree to
10
+ * match the children's size. When `false`, the host uses the size of the parent
11
+ * SwiftUI or Compose view. Pass an object to choose per axis. For example,
12
+ * `{ vertical: true }` takes the width from the parent and the height from the
13
+ * children, so text wraps and grows vertically.
12
14
  *
13
15
  * Can only be set once on mount; changing it remounts the component.
14
16
  * @default false
15
17
  * @platform android
16
18
  * @platform ios
17
19
  */
18
- matchContents?: boolean;
20
+ matchContents?: boolean | {
21
+ vertical?: boolean;
22
+ horizontal?: boolean;
23
+ };
19
24
  onLayout?: (event: LayoutChangeEvent) => void;
20
25
  /**
21
26
  * The React Native view to host.
@@ -1 +1 @@
1
- {"version":3,"sources":["universal/RNHostView/types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAKA;;CAEC,GACD,WAmBC"}
1
+ {"version":3,"sources":["universal/RNHostView/types.ts"],"sourcesContent":[null],"names":[],"mappings":"AAKA;;CAEC,GACD,WAqBC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Row, Switch as ComposeSwitch, Text } from '@expo/ui/jetpack-compose';
3
- import { testID as testIDModifier, weight } from '@expo/ui/jetpack-compose/modifiers';
3
+ import { fillMaxWidth, IntrinsicSize, testID as testIDModifier, weight, width } from '@expo/ui/jetpack-compose/modifiers';
4
4
  export function Switch({ value, onValueChange, label, disabled, testID, modifiers }) {
5
5
  const toggle = /*#__PURE__*/ _jsx(ComposeSwitch, {
6
6
  value: value,
@@ -19,6 +19,10 @@ export function Switch({ value, onValueChange, label, disabled, testID, modifier
19
19
  horizontalArrangement: {
20
20
  spacedBy: 8
21
21
  },
22
+ modifiers: [
23
+ fillMaxWidth(),
24
+ width(IntrinsicSize.Max)
25
+ ],
22
26
  children: [
23
27
  /*#__PURE__*/ _jsx(Text, {
24
28
  modifiers: [
@@ -1 +1 @@
1
- {"version":3,"sources":["universal/Switch/index.android.tsx"],"sourcesContent":[null],"names":["Row","Switch","ComposeSwitch","Text","testID","testIDModifier","weight","value","onValueChange","label","disabled","modifiers","toggle","onCheckedChange","undefined","enabled","verticalAlignment","horizontalArrangement","spacedBy"],"mappings":";AAAA,SAASA,GAAG,EAAEC,UAAUC,aAAa,EAAEC,IAAI,QAAQ,2BAA2B;AAC9E,SAASC,UAAUC,cAAc,EAAEC,MAAM,QAAQ,qCAAqC;AAItF,OAAO,SAASL,OAAO,EAAEM,KAAK,EAAEC,aAAa,EAAEC,KAAK,EAAEC,QAAQ,EAAEN,MAAM,EAAEO,SAAS,EAAe;IAC9F,MAAMC,uBACJ,KAACV;QACCK,OAAOA;QACPM,iBAAiBH,WAAWI,YAAYN;QACxCO,SAAS,CAACL;QACVC,WAAW;eAAKA,aAAa,EAAE;eAAOP,SAAS;gBAACC,eAAeD;aAAQ,GAAG,EAAE;SAAE;;IAIlF,IAAIK,SAAS,MAAM,OAAOG;IAE1B,qBACE,MAACZ;QAAIgB,mBAAkB;QAASC,uBAAuB;YAAEC,UAAU;QAAE;;0BACnE,KAACf;gBAAKQ,WAAW;oBAACL,OAAO;iBAAG;0BAAGG;;YAC9BG;;;AAGP;AAEA,cAAc,UAAU"}
1
+ {"version":3,"sources":["universal/Switch/index.android.tsx"],"sourcesContent":[null],"names":["Row","Switch","ComposeSwitch","Text","fillMaxWidth","IntrinsicSize","testID","testIDModifier","weight","width","value","onValueChange","label","disabled","modifiers","toggle","onCheckedChange","undefined","enabled","verticalAlignment","horizontalArrangement","spacedBy","Max"],"mappings":";AAAA,SAASA,GAAG,EAAEC,UAAUC,aAAa,EAAEC,IAAI,QAAQ,2BAA2B;AAC9E,SACEC,YAAY,EACZC,aAAa,EACbC,UAAUC,cAAc,EACxBC,MAAM,EACNC,KAAK,QACA,qCAAqC;AAI5C,OAAO,SAASR,OAAO,EAAES,KAAK,EAAEC,aAAa,EAAEC,KAAK,EAAEC,QAAQ,EAAEP,MAAM,EAAEQ,SAAS,EAAe;IAC9F,MAAMC,uBACJ,KAACb;QACCQ,OAAOA;QACPM,iBAAiBH,WAAWI,YAAYN;QACxCO,SAAS,CAACL;QACVC,WAAW;eAAKA,aAAa,EAAE;eAAOR,SAAS;gBAACC,eAAeD;aAAQ,GAAG,EAAE;SAAE;;IAIlF,IAAIM,SAAS,MAAM,OAAOG;IAE1B,qBACE,MAACf;QACCmB,mBAAkB;QAClBC,uBAAuB;YAAEC,UAAU;QAAE;QACrCP,WAAW;YAACV;YAAgBK,MAAMJ,cAAciB,GAAG;SAAE;;0BACrD,KAACnB;gBAAKW,WAAW;oBAACN,OAAO;iBAAG;0BAAGI;;YAC9BG;;;AAGP;AAEA,cAAc,UAAU"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Resolves `RNHostView`'s `matchContents` prop to one flag per axis.
3
+ */
4
+ export declare function resolveMatchContents(matchContents: boolean | {
5
+ vertical?: boolean;
6
+ horizontal?: boolean;
7
+ } | null | undefined): {
8
+ horizontal: boolean;
9
+ vertical: boolean;
10
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Resolves `RNHostView`'s `matchContents` prop to one flag per axis.
3
+ */ export function resolveMatchContents(matchContents) {
4
+ if (matchContents != null && typeof matchContents === 'object') {
5
+ return {
6
+ horizontal: matchContents.horizontal ?? false,
7
+ vertical: matchContents.vertical ?? false
8
+ };
9
+ }
10
+ return {
11
+ horizontal: matchContents ?? false,
12
+ vertical: matchContents ?? false
13
+ };
14
+ }
15
+
16
+ //# sourceMappingURL=matchContents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["utils/matchContents.ts"],"sourcesContent":[null],"names":["resolveMatchContents","matchContents","horizontal","vertical"],"mappings":"AAAA;;CAEC,GACD,OAAO,SAASA,qBACdC,aAAwF;IAExF,IAAIA,iBAAiB,QAAQ,OAAOA,kBAAkB,UAAU;QAC9D,OAAO;YACLC,YAAYD,cAAcC,UAAU,IAAI;YACxCC,UAAUF,cAAcE,QAAQ,IAAI;QACtC;IACF;IACA,OAAO;QAAED,YAAYD,iBAAiB;QAAOE,UAAUF,iBAAiB;IAAM;AAChF"}
@@ -10,7 +10,6 @@
10
10
  "publication": {
11
11
  "groupId": "expo.modules.ui",
12
12
  "artifactId": "expo.modules.ui",
13
- "version": "58.0.8",
14
13
  "repository": "local-maven-repo"
15
14
  }
16
15
  }
@@ -3,7 +3,26 @@
3
3
  import ExpoModulesCore
4
4
  import SwiftUI
5
5
 
6
+ // The axis the rows scroll along: vertical in `List` and `LazyVStack`, horizontal in `LazyHStack`.
7
+ enum DataListForEachAxis: String, Enumerable {
8
+ case vertical
9
+ case horizontal
10
+ }
11
+
12
+ private struct ContainerCrossAxisSizeKey: EnvironmentKey {
13
+ static let defaultValue: CGFloat = 0
14
+ }
15
+
16
+ extension EnvironmentValues {
17
+ // Set by `ListView`, `LazyVStackView` and `LazyHStackView`, so recycled rows reset their cached sizes when it changes.
18
+ var containerCrossAxisSize: CGFloat {
19
+ get { self[ContainerCrossAxisSizeKey.self] }
20
+ set { self[ContainerCrossAxisSizeKey.self] = newValue }
21
+ }
22
+ }
23
+
6
24
  final class DataListForEachProps: UIBaseViewProps {
25
+ @Field var axis: DataListForEachAxis = .vertical
7
26
  @Field var itemKeys: [String] = []
8
27
  @Field var revision: Int = 0
9
28
  @Field var estimatedItemSize: Double = 64
@@ -79,6 +98,7 @@ private struct DataListForEachRow: View {
79
98
  @ObservedObject var listProps: DataListForEachProps
80
99
  @ObservedObject var poolProps: DataListForEachPoolProps
81
100
  let window: DataListForEachWindow
101
+ @Environment(\.containerCrossAxisSize) private var crossAxisSize
82
102
  @State private var appeared = false
83
103
  @State private var visibilityID = UUID()
84
104
 
@@ -99,27 +119,27 @@ private struct DataListForEachRow: View {
99
119
  itemKey: itemKey,
100
120
  index: index,
101
121
  revision: listProps.revision,
102
- estimatedHeight: CGFloat(listProps.estimatedItemSize),
122
+ estimatedSize: CGFloat(listProps.estimatedItemSize),
123
+ axis: listProps.axis,
103
124
  window: window
104
125
  )
105
126
  } else {
106
- Color.clear
107
- .frame(height: window.height(for: itemKey, fallback: listProps.estimatedItemSize))
108
- .accessibilityHidden(true)
127
+ DataListForEachPlaceholder(
128
+ size: window.size(for: itemKey, fallback: listProps.estimatedItemSize),
129
+ axis: listProps.axis
130
+ )
109
131
  }
110
132
  }
111
- .frame(maxWidth: .infinity, alignment: .leading)
112
133
  .onAppear {
113
134
  appeared = true
135
+ window.updateCrossAxisSize(crossAxisSize)
114
136
  window.appear(itemKey, index: index, token: visibilityID, props: listProps)
115
137
  }
138
+ .onChange(of: crossAxisSize) { window.updateCrossAxisSize($0) }
116
139
  .onChange(of: listProps.revision) { _ in
117
140
  window.reset(listProps)
118
141
  if appeared { window.appear(itemKey, index: index, token: visibilityID, props: listProps) }
119
142
  }
120
- .onGeometryChange(for: CGFloat.self, of: { $0.size.width }, action: { width in
121
- window.updateWidth(width)
122
- })
123
143
  .onDisappear {
124
144
  appeared = false
125
145
  window.disappear(itemKey, token: visibilityID)
@@ -127,12 +147,25 @@ private struct DataListForEachRow: View {
127
147
  }
128
148
  }
129
149
 
150
+ private struct DataListForEachPlaceholder: View {
151
+ let size: CGFloat
152
+ let axis: DataListForEachAxis
153
+
154
+ // Sized along the scroll axis only, so it never stretches a lazy stack across it.
155
+ var body: some View {
156
+ Color.clear
157
+ .frame(width: axis == .horizontal ? size : 0, height: axis == .horizontal ? 0 : size)
158
+ .accessibilityHidden(true)
159
+ }
160
+ }
161
+
130
162
  private struct DataListForEachSlotContent: View {
131
163
  @ObservedObject var props: DataListForEachItemProps
132
164
  let itemKey: String
133
165
  let index: Int
134
166
  let revision: Int
135
- let estimatedHeight: CGFloat
167
+ let estimatedSize: CGFloat
168
+ let axis: DataListForEachAxis
136
169
  let window: DataListForEachWindow
137
170
  // we use this state so swiftui re-layouts when the slot is reused for a different item
138
171
  @State private var showsContent = false
@@ -146,14 +179,17 @@ private struct DataListForEachSlotContent: View {
146
179
  if showsContent {
147
180
  DataListForEachItemView(props: props)
148
181
  .id(itemKey)
149
- .onGeometryChange(for: CGFloat.self, of: { $0.size.height }, action: { height in
150
- window.measure(height, for: itemKey, revision: revision)
151
- })
182
+ .onGeometryChange(
183
+ for: CGFloat.self,
184
+ of: { axis == .horizontal ? $0.size.width : $0.size.height },
185
+ action: { size in window.measure(size, for: itemKey, revision: revision) }
186
+ )
152
187
  } else {
153
188
  // Hide the previous item while JS updates this slot.
154
- Color.clear
155
- .frame(height: window.height(for: itemKey, fallback: Double(estimatedHeight)))
156
- .accessibilityHidden(true)
189
+ DataListForEachPlaceholder(
190
+ size: window.size(for: itemKey, fallback: Double(estimatedSize)),
191
+ axis: axis
192
+ )
157
193
  }
158
194
  }
159
195
  .onAppear { showsContent = matches }
@@ -166,8 +202,9 @@ private final class DataListForEachWindow: ObservableObject {
166
202
  private weak var props: DataListForEachProps?
167
203
  private var appeared: [String: Int] = [:]
168
204
  private var visibilityTokens: [String: UUID] = [:]
169
- private var heights: [String: CGFloat] = [:]
170
- private var width: CGFloat = 0
205
+ // Row sizes along the scroll axis.
206
+ private var sizes: [String: CGFloat] = [:]
207
+ private var crossAxisSize: CGFloat = 0
171
208
  private var revision = -1
172
209
  private var pending: DispatchWorkItem?
173
210
  private var lastSent: [Int] = []
@@ -182,7 +219,7 @@ private final class DataListForEachWindow: ObservableObject {
182
219
  return
183
220
  }
184
221
  revision = props.revision
185
- heights.removeAll()
222
+ sizes.removeAll()
186
223
  let positions = Dictionary(uniqueKeysWithValues: props.itemKeys.enumerated().map { ($0.element, $0.offset) })
187
224
  appeared = positions.filter { appeared[$0.key] != nil }
188
225
  visibilityTokens = visibilityTokens.filter { positions[$0.key] != nil }
@@ -190,12 +227,12 @@ private final class DataListForEachWindow: ObservableObject {
190
227
  schedule()
191
228
  }
192
229
 
193
- func updateWidth(_ newWidth: CGFloat) {
194
- if width != newWidth {
195
- if width > 0 {
196
- heights.removeAll()
230
+ func updateCrossAxisSize(_ newSize: CGFloat) {
231
+ if crossAxisSize != newSize {
232
+ if crossAxisSize > 0 {
233
+ sizes.removeAll()
197
234
  }
198
- width = newWidth
235
+ crossAxisSize = newSize
199
236
  }
200
237
  }
201
238
 
@@ -220,15 +257,15 @@ private final class DataListForEachWindow: ObservableObject {
220
257
  schedule()
221
258
  }
222
259
 
223
- func height(for key: String, fallback: Double) -> CGFloat {
224
- heights[key] ?? CGFloat(fallback)
260
+ func size(for key: String, fallback: Double) -> CGFloat {
261
+ sizes[key] ?? CGFloat(fallback)
225
262
  }
226
263
 
227
- func measure(_ height: CGFloat, for key: String, revision: Int) {
228
- guard revision == self.revision, height.isFinite, height > 0 else {
264
+ func measure(_ size: CGFloat, for key: String, revision: Int) {
265
+ guard revision == self.revision, size.isFinite, size > 0 else {
229
266
  return
230
267
  }
231
- heights[key] = height
268
+ sizes[key] = size
232
269
  }
233
270
 
234
271
  private func schedule() {
@@ -204,7 +204,6 @@ public final class ExpoUIModule: Module {
204
204
  ExpoUIView(BackgroundView.self)
205
205
  ExpoUIView(MaskView.self)
206
206
  ExpoUIView(GridView.self)
207
- ExpoUIView(AccessoryWidgetBackgroundView.self)
208
207
  ExpoUIView(LinkView.self)
209
208
  ExpoUIView(TabView.self)
210
209
  ExpoUIView(Tab.self)
@@ -10,6 +10,7 @@ public final class LazyHStackViewProps: UIBaseViewProps {
10
10
 
11
11
  public struct LazyHStackView: ExpoSwiftUI.View {
12
12
  @ObservedObject public var props: LazyHStackViewProps
13
+ @State private var crossAxisSize: CGFloat = 0
13
14
 
14
15
  public init(props: LazyHStackViewProps) {
15
16
  self.props = props
@@ -21,5 +22,7 @@ public struct LazyHStackView: ExpoSwiftUI.View {
21
22
  spacing: props.spacing.map { CGFloat($0) }) {
22
23
  Children()
23
24
  }
25
+ .onGeometryChange(for: CGFloat.self, of: { $0.size.height }, action: { crossAxisSize = $0 })
26
+ .environment(\.containerCrossAxisSize, crossAxisSize)
24
27
  }
25
28
  }
@@ -10,6 +10,7 @@ public final class LazyVStackViewProps: UIBaseViewProps {
10
10
 
11
11
  public struct LazyVStackView: ExpoSwiftUI.View {
12
12
  @ObservedObject public var props: LazyVStackViewProps
13
+ @State private var crossAxisSize: CGFloat = 0
13
14
 
14
15
  public init(props: LazyVStackViewProps) {
15
16
  self.props = props
@@ -21,5 +22,7 @@ public struct LazyVStackView: ExpoSwiftUI.View {
21
22
  spacing: props.spacing.map { CGFloat($0) }) {
22
23
  Children()
23
24
  }
25
+ .onGeometryChange(for: CGFloat.self, of: { $0.size.width }, action: { crossAxisSize = $0 })
26
+ .environment(\.containerCrossAxisSize, crossAxisSize)
24
27
  }
25
28
  }
@@ -11,8 +11,16 @@ final class ListProps: UIBaseViewProps {
11
11
  struct ListView: ExpoSwiftUI.View {
12
12
  @ObservedObject var props: ListProps
13
13
  @State private var selection = Set<AnyHashable>()
14
+ @State private var crossAxisSize: CGFloat = 0
14
15
 
15
16
  var body: some View {
17
+ list
18
+ .onGeometryChange(for: CGFloat.self, of: { $0.size.width }, action: { crossAxisSize = $0 })
19
+ .environment(\.containerCrossAxisSize, crossAxisSize)
20
+ }
21
+
22
+ @ViewBuilder
23
+ private var list: some View {
16
24
  if props.selection != nil {
17
25
  List(selection: $selection) {
18
26
  Children()
@@ -2,9 +2,6 @@
2
2
 
3
3
  import ExpoModulesCore
4
4
  import SwiftUI
5
- #if !os(tvOS)
6
- import WidgetKit
7
- #endif
8
5
 
9
6
  internal enum ContainerBackgroundPlacementOptions: String, Enumerable {
10
7
  case widget
@@ -12,10 +9,11 @@ internal enum ContainerBackgroundPlacementOptions: String, Enumerable {
12
9
  case navigationSplitView
13
10
 
14
11
  #if !os(tvOS) && !os(macOS)
12
+ // `widget` is declared in WidgetKit, so expo-widgets applies it through `ViewModifierRegistry.widgetKit`.
15
13
  @available(iOS 18.0, *)
16
- var toContainerBackgroundPlacement: ContainerBackgroundPlacement {
14
+ var toContainerBackgroundPlacement: ContainerBackgroundPlacement? {
17
15
  switch self {
18
- case .widget: return .widget
16
+ case .widget: return nil
19
17
  case .navigation: return .navigation
20
18
  case .navigationSplitView: return .navigationSplitView
21
19
  }
@@ -28,20 +26,17 @@ internal struct ContainerBackgroundModifier: ViewModifier, Record {
28
26
  @Field var container: ContainerBackgroundPlacementOptions?
29
27
 
30
28
  func body(content: Content) -> some View {
31
- #if os(tvOS)
29
+ #if os(tvOS) || os(macOS)
32
30
  content
33
- #elseif os(macOS)
34
- if let shapeStyle = style?.toAnyShapeStyle(), container == .widget {
35
- content.containerBackground(shapeStyle, for: .widget)
36
- } else {
37
- content
38
- }
39
31
  #else
40
32
  if let shapeStyle = style?.toAnyShapeStyle(), let container {
41
- if #available(iOS 18.0, *) {
42
- content.containerBackground(shapeStyle, for: container.toContainerBackgroundPlacement)
43
- } else if #available(iOS 17.0, *) {
44
- content.containerBackground(shapeStyle, for: .widget)
33
+ if container == .widget, let widgetKit = ViewModifierRegistry.widgetKit {
34
+ widgetKit.containerBackground(AnyView(content), style: shapeStyle)
35
+ } else if #available(iOS 18.0, *), let placement = container.toContainerBackgroundPlacement {
36
+ content.containerBackground(shapeStyle, for: placement)
37
+ } else if let widgetKit = ViewModifierRegistry.widgetKit {
38
+ // On iOS 17, the other placements fall back to `widget`.
39
+ widgetKit.containerBackground(AnyView(content), style: shapeStyle)
45
40
  } else {
46
41
  content
47
42
  }
@@ -50,4 +45,16 @@ internal struct ContainerBackgroundModifier: ViewModifier, Record {
50
45
  }
51
46
  #endif
52
47
  }
48
+
49
+ #if DEBUG
50
+ private static var didWarnAboutWidgetPlacement = false
51
+
52
+ func warnIfWidgetPlacementIsUnavailable() {
53
+ guard container == .widget, ViewModifierRegistry.widgetKit == nil, !Self.didWarnAboutWidgetPlacement else {
54
+ return
55
+ }
56
+ Self.didWarnAboutWidgetPlacement = true
57
+ log.warn("containerBackground with the 'widget' placement has no effect here, because it only applies inside widgets rendered by expo-widgets. Use the 'navigation' or 'navigationSplitView' placement in app screens.")
58
+ }
59
+ #endif
53
60
  }
@@ -0,0 +1,12 @@
1
+ // Copyright 2025-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesCore
4
+ import SwiftUI
5
+
6
+ internal struct PreferredColorSchemeModifier: ViewModifier, Record {
7
+ @Field var colorScheme: ColorSchemeType?
8
+
9
+ func body(content: Content) -> some View {
10
+ content.preferredColorScheme(colorScheme?.toNativeColorScheme())
11
+ }
12
+ }
@@ -67,10 +67,10 @@ internal extension Image {
67
67
  )
68
68
  }
69
69
 
70
- if #available(iOS 18.0, macOS 15.0, *),
70
+ if let widgetKit = ViewModifierRegistry.widgetKit,
71
71
  let modifierConfig = modifiers.first(where: { $0["$type"] as? String == "widgetAccentedRenderingMode" }),
72
- let modifier = try? WidgetAccentedRenderingModeModifier(from: modifierConfig, appContext: appContext) {
73
- modifier.apply(to: image)
72
+ let view = widgetKit.widgetAccentedRenderingMode(image, params: modifierConfig, appContext: appContext) {
73
+ view
74
74
  } else {
75
75
  image
76
76
  }
@@ -1533,6 +1533,8 @@ public class ViewModifierRegistry {
1533
1533
  public typealias ModifierFactory = ([String: Any], AppContext, EventDispatcher) throws -> any ViewModifier
1534
1534
  private(set) internal var modifierFactories: [String: ModifierFactory] = [:]
1535
1535
 
1536
+ public static var widgetKit: WidgetKitModifiers?
1537
+
1536
1538
  private init() {
1537
1539
  registerBuiltInModifiers()
1538
1540
  }
@@ -2309,6 +2311,10 @@ extension ViewModifierRegistry {
2309
2311
  return try ScrollDisabledModifier(from: params, appContext: appContext)
2310
2312
  }
2311
2313
 
2314
+ register("preferredColorScheme") { params, appContext, _ in
2315
+ return try PreferredColorSchemeModifier(from: params, appContext: appContext)
2316
+ }
2317
+
2312
2318
  register("scrollClipDisabled") { params, appContext, _ in
2313
2319
  return try ScrollClipDisabledModifier(from: params, appContext: appContext)
2314
2320
  }
@@ -2393,14 +2399,6 @@ extension ViewModifierRegistry {
2393
2399
  return try ContentTransitionModifier(from: params, appContext: appContext)
2394
2400
  }
2395
2401
 
2396
- register("widgetURL") { params, appContext, _ in
2397
- return try WidgetURLModifier(from: params, appContext: appContext)
2398
- }
2399
-
2400
- register("activityBackgroundTint") { params, appContext, _ in
2401
- return try ActivityBackgroundTintModifier(from: params, appContext: appContext)
2402
- }
2403
-
2404
2402
  register("keyboardType") { params, appContext, _ in
2405
2403
  return try KeyboardTypeModifier(from: params, appContext: appContext)
2406
2404
  }
@@ -2414,7 +2412,11 @@ extension ViewModifierRegistry {
2414
2412
  }
2415
2413
 
2416
2414
  register("containerBackground") { params, appContext, _ in
2417
- return try ContainerBackgroundModifier(from: params, appContext: appContext)
2415
+ let modifier = try ContainerBackgroundModifier(from: params, appContext: appContext)
2416
+ #if DEBUG
2417
+ modifier.warnIfWidgetPlacementIsUnavailable()
2418
+ #endif
2419
+ return modifier
2418
2420
  }
2419
2421
 
2420
2422
  register("symbolEffect") { params, appContext, _ in
@@ -0,0 +1,13 @@
1
+ // Copyright 2026-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesCore
4
+ import SwiftUI
5
+
6
+ /**
7
+ * The parts of SwiftUI that are declared in WidgetKit. expo-widgets sets
8
+ * `ViewModifierRegistry.widgetKit`, so ExpoUI does not link WidgetKit.
9
+ */
10
+ public protocol WidgetKitModifiers {
11
+ func containerBackground(_ view: AnyView, style: AnyShapeStyle) -> AnyView
12
+ func widgetAccentedRenderingMode(_ image: Image, params: [String: Any], appContext: AppContext) -> AnyView?
13
+ }
@@ -4,7 +4,8 @@ import SwiftUI
4
4
  import ExpoModulesCore
5
5
 
6
6
  internal final class RNHostViewProps: ExpoSwiftUI.ViewProps {
7
- @Field var matchContents: Bool = false
7
+ @Field var matchContentsHorizontal: Bool = false
8
+ @Field var matchContentsVertical: Bool = false
8
9
  /**
9
10
  Adds LeafNode and MeasurableYogaNode trait in Shadow node
10
11
  */
@@ -50,8 +51,13 @@ struct RNHostView: ExpoSwiftUI.View {
50
51
 
51
52
  @ViewBuilder
52
53
  private var hostedContent: some View {
53
- if props.matchContents, let childUIView = firstChildUIView {
54
- ApplySizeFromYogaNode(childUIView: childUIView) {
54
+ if matchesContents, let childUIView = firstChildUIView {
55
+ ApplySizeFromYogaNode(
56
+ childUIView: childUIView,
57
+ horizontal: props.matchContentsHorizontal,
58
+ vertical: props.matchContentsVertical,
59
+ shadowNodeProxy: props.shadowNodeProxy
60
+ ) {
55
61
  Children()
56
62
  }
57
63
  .onAppear {
@@ -62,7 +68,7 @@ struct RNHostView: ExpoSwiftUI.View {
62
68
  .onDisappear {
63
69
  touchHandler.detach()
64
70
  }
65
- } else if props.matchContents {
71
+ } else if matchesContents {
66
72
  // No hosted UIView (a pure SwiftUI child, e.g. Text/Image). Render it at its
67
73
  // natural size instead of falling into the fill branch below, which would
68
74
  // stretch a self-sizing SwiftUI view to fill its container.
@@ -87,6 +93,10 @@ struct RNHostView: ExpoSwiftUI.View {
87
93
  }
88
94
  }
89
95
 
96
+ private var matchesContents: Bool {
97
+ props.matchContentsHorizontal || props.matchContentsVertical
98
+ }
99
+
90
100
  private var firstChildUIView: UIView? {
91
101
  props.children?.first?.uiView
92
102
  }
@@ -143,20 +153,52 @@ private final class RNHostTouchHandler: ObservableObject {
143
153
  }
144
154
  }
145
155
 
146
- // Sets SwiftUI view size from Yoga node size
156
+ // Sets SwiftUI view size from Yoga node size on the matched axes
147
157
  // Listens to Yoga node size changes and updates the SwiftUI view size
158
+ // An axis that is not matched fills the parent and reports its size to the Yoga node instead
148
159
  private struct ApplySizeFromYogaNode<Content: SwiftUI.View>: SwiftUI.View {
149
160
  @StateObject private var observer: Observer
161
+ let horizontal: Bool
162
+ let vertical: Bool
163
+ let shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
150
164
  let content: Content
151
165
 
152
- init(childUIView: UIView, @ViewBuilder content: () -> Content) {
166
+ init(
167
+ childUIView: UIView,
168
+ horizontal: Bool,
169
+ vertical: Bool,
170
+ shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy,
171
+ @ViewBuilder content: () -> Content
172
+ ) {
153
173
  _observer = StateObject(wrappedValue: Observer(view: childUIView))
174
+ self.horizontal = horizontal
175
+ self.vertical = vertical
176
+ self.shadowNodeProxy = shadowNodeProxy
154
177
  self.content = content()
155
178
  }
156
179
 
157
180
  var body: some SwiftUI.View {
158
- content
159
- .frame(width: observer.size.width, height: observer.size.height)
181
+ if horizontal && vertical {
182
+ content
183
+ .frame(width: observer.size.width, height: observer.size.height)
184
+ } else {
185
+ content
186
+ .frame(
187
+ width: horizontal ? observer.size.width : nil,
188
+ height: vertical ? observer.size.height : nil
189
+ )
190
+ .frame(
191
+ maxWidth: horizontal ? nil : .infinity,
192
+ maxHeight: vertical ? nil : .infinity
193
+ )
194
+ .modifier(
195
+ ReportSizeToYogaNodeModifier(
196
+ shadowNodeProxy: shadowNodeProxy,
197
+ reportWidth: !horizontal,
198
+ reportHeight: !vertical
199
+ )
200
+ )
201
+ }
160
202
  }
161
203
 
162
204
  @MainActor
@@ -183,9 +225,13 @@ private struct ApplySizeFromYogaNode<Content: SwiftUI.View>: SwiftUI.View {
183
225
  // Listens to SwiftUI view size changes and updates the Yoga node size
184
226
  private struct ReportSizeToYogaNodeModifier: ViewModifier {
185
227
  let shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
228
+ var reportWidth = true
229
+ var reportHeight = true
186
230
 
187
231
  private func handleSizeChange(_ size: CGSize) {
188
- shadowNodeProxy.setViewSize?(size)
232
+ shadowNodeProxy.setViewSize?(
233
+ CGSize(width: reportWidth ? size.width : .nan, height: reportHeight ? size.height : .nan)
234
+ )
189
235
  }
190
236
 
191
237
  func body(content: Content) -> some View {