@expo/ui 56.0.8 → 56.0.9

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 (168) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +38 -1
  4. package/android/src/main/java/expo/modules/ui/LoadingView.kt +80 -0
  5. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +31 -3
  6. package/android/src/main/java/expo/modules/ui/SnackbarView.kt +126 -0
  7. package/android/src/main/java/expo/modules/ui/state/ObservableState.kt +10 -0
  8. package/assets/keyboard_arrow_down.xml +10 -0
  9. package/build/State/useNativeState.d.ts +32 -3
  10. package/build/State/useNativeState.d.ts.map +1 -1
  11. package/build/community/bottom-sheet/BottomSheet.ios.d.ts.map +1 -1
  12. package/build/jetpack-compose/LoadingIndicator/index.d.ts +41 -0
  13. package/build/jetpack-compose/LoadingIndicator/index.d.ts.map +1 -0
  14. package/build/jetpack-compose/Snackbar/index.d.ts +94 -0
  15. package/build/jetpack-compose/Snackbar/index.d.ts.map +1 -0
  16. package/build/jetpack-compose/index.d.ts +2 -0
  17. package/build/jetpack-compose/index.d.ts.map +1 -1
  18. package/build/jetpack-compose/modifiers/index.d.ts +6 -2
  19. package/build/jetpack-compose/modifiers/index.d.ts.map +1 -1
  20. package/build/swift-ui/BottomSheet/index.d.ts +5 -1
  21. package/build/swift-ui/BottomSheet/index.d.ts.map +1 -1
  22. package/build/swift-ui/index.d.ts +1 -0
  23. package/build/swift-ui/index.d.ts.map +1 -1
  24. package/build/swift-ui/withAnimation.d.ts +26 -0
  25. package/build/swift-ui/withAnimation.d.ts.map +1 -0
  26. package/build/universal/BottomSheet/index.android.d.ts +1 -1
  27. package/build/universal/BottomSheet/index.android.d.ts.map +1 -1
  28. package/build/universal/BottomSheet/index.d.ts +1 -1
  29. package/build/universal/BottomSheet/index.d.ts.map +1 -1
  30. package/build/universal/BottomSheet/index.ios.d.ts +1 -1
  31. package/build/universal/BottomSheet/index.ios.d.ts.map +1 -1
  32. package/build/universal/BottomSheet/types.d.ts +27 -0
  33. package/build/universal/BottomSheet/types.d.ts.map +1 -1
  34. package/build/universal/Collapsible/index.android.d.ts +8 -0
  35. package/build/universal/Collapsible/index.android.d.ts.map +1 -0
  36. package/build/universal/Collapsible/index.d.ts +8 -0
  37. package/build/universal/Collapsible/index.d.ts.map +1 -0
  38. package/build/universal/Collapsible/index.ios.d.ts +7 -0
  39. package/build/universal/Collapsible/index.ios.d.ts.map +1 -0
  40. package/build/universal/Collapsible/types.d.ts +23 -0
  41. package/build/universal/Collapsible/types.d.ts.map +1 -0
  42. package/build/universal/Column/index.d.ts.map +1 -1
  43. package/build/universal/Host/index.d.ts +5 -18
  44. package/build/universal/Host/index.d.ts.map +1 -1
  45. package/build/universal/Host/types.d.ts +72 -0
  46. package/build/universal/Host/types.d.ts.map +1 -0
  47. package/build/universal/List/index.android.d.ts +9 -0
  48. package/build/universal/List/index.android.d.ts.map +1 -0
  49. package/build/universal/List/index.d.ts +8 -0
  50. package/build/universal/List/index.d.ts.map +1 -0
  51. package/build/universal/List/index.ios.d.ts +8 -0
  52. package/build/universal/List/index.ios.d.ts.map +1 -0
  53. package/build/universal/List/types.d.ts +26 -0
  54. package/build/universal/List/types.d.ts.map +1 -0
  55. package/build/universal/ListItem/ListItem.android.d.ts +8 -0
  56. package/build/universal/ListItem/ListItem.android.d.ts.map +1 -0
  57. package/build/universal/ListItem/ListItem.d.ts +9 -0
  58. package/build/universal/ListItem/ListItem.d.ts.map +1 -0
  59. package/build/universal/ListItem/ListItem.ios.d.ts +8 -0
  60. package/build/universal/ListItem/ListItem.ios.d.ts.map +1 -0
  61. package/build/universal/ListItem/ListItemSlots.d.ts +21 -0
  62. package/build/universal/ListItem/ListItemSlots.d.ts.map +1 -0
  63. package/build/universal/ListItem/index.d.ts +10 -0
  64. package/build/universal/ListItem/index.d.ts.map +1 -0
  65. package/build/universal/ListItem/types.d.ts +59 -0
  66. package/build/universal/ListItem/types.d.ts.map +1 -0
  67. package/build/universal/Picker/Picker.android.d.ts +9 -0
  68. package/build/universal/Picker/Picker.android.d.ts.map +1 -0
  69. package/build/universal/Picker/Picker.d.ts +8 -0
  70. package/build/universal/Picker/Picker.d.ts.map +1 -0
  71. package/build/universal/Picker/Picker.ios.d.ts +9 -0
  72. package/build/universal/Picker/Picker.ios.d.ts.map +1 -0
  73. package/build/universal/Picker/PickerItem.d.ts +9 -0
  74. package/build/universal/Picker/PickerItem.d.ts.map +1 -0
  75. package/build/universal/Picker/index.d.ts +8 -0
  76. package/build/universal/Picker/index.d.ts.map +1 -0
  77. package/build/universal/Picker/types.d.ts +69 -0
  78. package/build/universal/Picker/types.d.ts.map +1 -0
  79. package/build/universal/index.d.ts +4 -0
  80. package/build/universal/index.d.ts.map +1 -1
  81. package/expo-module.config.json +1 -1
  82. package/ios/BottomSheetView.swift +4 -1
  83. package/ios/ExpoUIModule.swift +41 -1
  84. package/ios/Modifiers/AnimationConfig.swift +109 -0
  85. package/ios/Modifiers/ViewModifierRegistry.swift +1 -112
  86. package/ios/State/ObservableState.swift +12 -1
  87. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.8/expo.modules.ui-56.0.8-sources.jar → 56.0.9/expo.modules.ui-56.0.9-sources.jar} +0 -0
  88. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9-sources.jar.md5 +1 -0
  89. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9-sources.jar.sha1 +1 -0
  90. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9-sources.jar.sha256 +1 -0
  91. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9-sources.jar.sha512 +1 -0
  92. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.aar +0 -0
  93. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.aar.md5 +1 -0
  94. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.aar.sha1 +1 -0
  95. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.aar.sha256 +1 -0
  96. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.aar.sha512 +1 -0
  97. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.8/expo.modules.ui-56.0.8.module → 56.0.9/expo.modules.ui-56.0.9.module} +22 -22
  98. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.module.md5 +1 -0
  99. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.module.sha1 +1 -0
  100. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.module.sha256 +1 -0
  101. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.module.sha512 +1 -0
  102. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.8/expo.modules.ui-56.0.8.pom → 56.0.9/expo.modules.ui-56.0.9.pom} +1 -1
  103. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.pom.md5 +1 -0
  104. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.pom.sha1 +1 -0
  105. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.pom.sha256 +1 -0
  106. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.9/expo.modules.ui-56.0.9.pom.sha512 +1 -0
  107. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
  108. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
  109. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
  110. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
  111. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
  112. package/package.json +3 -3
  113. package/src/State/useNativeState.ts +70 -10
  114. package/src/community/bottom-sheet/BottomSheet.ios.tsx +0 -17
  115. package/src/jetpack-compose/LoadingIndicator/index.tsx +92 -0
  116. package/src/jetpack-compose/Snackbar/index.tsx +135 -0
  117. package/src/jetpack-compose/index.ts +2 -0
  118. package/src/jetpack-compose/modifiers/index.ts +5 -2
  119. package/src/swift-ui/BottomSheet/index.tsx +32 -15
  120. package/src/swift-ui/index.tsx +1 -0
  121. package/src/swift-ui/withAnimation.ts +71 -0
  122. package/src/ts-declarations/react-native-web.d.ts +7 -0
  123. package/src/universal/BottomSheet/index.android.tsx +27 -3
  124. package/src/universal/BottomSheet/index.ios.tsx +30 -12
  125. package/src/universal/BottomSheet/index.tsx +46 -4
  126. package/src/universal/BottomSheet/types.ts +25 -0
  127. package/src/universal/Collapsible/index.android.tsx +72 -0
  128. package/src/universal/Collapsible/index.ios.tsx +16 -0
  129. package/src/universal/Collapsible/index.tsx +58 -0
  130. package/src/universal/Collapsible/types.ts +25 -0
  131. package/src/universal/Column/index.tsx +3 -1
  132. package/src/universal/Host/index.tsx +9 -10
  133. package/src/universal/Host/types.ts +70 -0
  134. package/src/universal/List/index.android.tsx +44 -0
  135. package/src/universal/List/index.ios.tsx +19 -0
  136. package/src/universal/List/index.tsx +26 -0
  137. package/src/universal/List/types.ts +28 -0
  138. package/src/universal/ListItem/ListItem.android.tsx +52 -0
  139. package/src/universal/ListItem/ListItem.ios.tsx +58 -0
  140. package/src/universal/ListItem/ListItem.tsx +72 -0
  141. package/src/universal/ListItem/ListItemSlots.tsx +66 -0
  142. package/src/universal/ListItem/index.ts +15 -0
  143. package/src/universal/ListItem/types.ts +67 -0
  144. package/src/universal/Picker/Picker.android.tsx +69 -0
  145. package/src/universal/Picker/Picker.ios.tsx +45 -0
  146. package/src/universal/Picker/Picker.tsx +52 -0
  147. package/src/universal/Picker/PickerItem.tsx +27 -0
  148. package/src/universal/Picker/index.ts +11 -0
  149. package/src/universal/Picker/types.ts +79 -0
  150. package/src/universal/index.ts +4 -0
  151. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8-sources.jar.md5 +0 -1
  152. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8-sources.jar.sha1 +0 -1
  153. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8-sources.jar.sha256 +0 -1
  154. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8-sources.jar.sha512 +0 -1
  155. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.aar +0 -0
  156. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.aar.md5 +0 -1
  157. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.aar.sha1 +0 -1
  158. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.aar.sha256 +0 -1
  159. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.aar.sha512 +0 -1
  160. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.module.md5 +0 -1
  161. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.module.sha1 +0 -1
  162. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.module.sha256 +0 -1
  163. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.module.sha512 +0 -1
  164. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.pom.md5 +0 -1
  165. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.pom.sha1 +0 -1
  166. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.pom.sha256 +0 -1
  167. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.8/expo.modules.ui-56.0.8.pom.sha512 +0 -1
  168. package/src/community/bottom-sheet/CLAUDE.md +0 -55
@@ -0,0 +1,59 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * Props for the [`ListItem.Leading`](#listitemleading) slot marker.
4
+ */
5
+ export interface ListItemLeadingProps {
6
+ /** Content rendered in the leading (start) slot. */
7
+ children?: ReactNode;
8
+ }
9
+ /**
10
+ * Props for the [`ListItem.Trailing`](#listitemtrailing) slot marker.
11
+ */
12
+ export interface ListItemTrailingProps {
13
+ /** Content rendered in the trailing (end) slot. */
14
+ children?: ReactNode;
15
+ }
16
+ /**
17
+ * Props for the [`ListItem.Supporting`](#listitemsupporting) slot marker.
18
+ */
19
+ export interface ListItemSupportingProps {
20
+ /** Content rendered below the headline. */
21
+ children?: ReactNode;
22
+ }
23
+ /**
24
+ * Props for the [`ListItem`](#listitem) component.
25
+ * A tappable row in a list.
26
+ */
27
+ export interface ListItemProps {
28
+ /**
29
+ * Headline content of the row.
30
+ * The remaining (non-slot) children are rendered in the headline area.
31
+ */
32
+ children?: ReactNode;
33
+ /**
34
+ * Tap handler.
35
+ * Activates over the entire row rectangle, including the empty gap between leading/headline/trailing.
36
+ */
37
+ onPress?: () => void;
38
+ /**
39
+ * Shorthand for the leading slot.
40
+ * Overridden by `<ListItem.Leading>` if both are provided.
41
+ */
42
+ leading?: ReactNode;
43
+ /**
44
+ * Shorthand for the trailing slot.
45
+ * Overridden by `<ListItem.Trailing>` if both are provided.
46
+ */
47
+ trailing?: ReactNode;
48
+ /**
49
+ * Shorthand for the supporting (sub-)text slot.
50
+ * Strings are rendered with platform-appropriate secondary styling; pass a `ReactNode` for richer content.
51
+ * Overridden by `<ListItem.Supporting>` if both are provided.
52
+ */
53
+ supportingText?: string | ReactNode;
54
+ /**
55
+ * Identifier used to locate the component in end-to-end tests.
56
+ */
57
+ testID?: string;
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/universal/ListItem/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEpC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,9 @@
1
+ import type { PickerItemValue, PickerProps } from './types';
2
+ /**
3
+ * Android implementation of `Picker`.
4
+ * Renders a Material 3 `ExposedDropdownMenuBox`.
5
+ * `appearance` is accepted for API parity but ignored — Material 3 has no wheel-style picker.
6
+ */
7
+ export declare function Picker<T extends PickerItemValue>({ selectedValue, onValueChange, enabled, children, }: PickerProps<T>): import("react/jsx-runtime").JSX.Element;
8
+ export * from './types';
9
+ //# sourceMappingURL=Picker.android.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Picker.android.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/Picker.android.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAU5D;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,EAChD,aAAa,EACb,aAAa,EACb,OAAc,EACd,QAAQ,GACT,EAAE,WAAW,CAAC,CAAC,CAAC,2CA2ChB;AAED,cAAc,SAAS,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { PickerItemValue, PickerProps } from './types';
2
+ /**
3
+ * A single-selection input.
4
+ * Declare options via `<Picker.Item label value />` children.
5
+ */
6
+ export declare function Picker<T extends PickerItemValue>({ selectedValue, onValueChange, enabled, children, testID, }: PickerProps<T>): import("react/jsx-runtime").JSX.Element;
7
+ export * from './types';
8
+ //# sourceMappingURL=Picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Picker.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/Picker.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAK5D;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,EAChD,aAAa,EACb,aAAa,EACb,OAAc,EACd,QAAQ,EACR,MAAM,GACP,EAAE,WAAW,CAAC,CAAC,CAAC,2CAqBhB;AAWD,cAAc,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PickerItemValue, PickerProps } from './types';
2
+ /**
3
+ * iOS implementation of `Picker`.
4
+ * Wraps SwiftUI's `Picker` and applies the matching `.pickerStyle` for the requested `appearance`.
5
+ * Embed inside a parent `<Host>` (same as `Column` / `Row`).
6
+ */
7
+ export declare function Picker<T extends PickerItemValue>({ selectedValue, onValueChange, appearance, enabled, children, testID, }: PickerProps<T>): import("react/jsx-runtime").JSX.Element;
8
+ export * from './types';
9
+ //# sourceMappingURL=Picker.ios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Picker.ios.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/Picker.ios.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,EAChD,aAAa,EACb,aAAa,EACb,UAAmB,EACnB,OAAc,EACd,QAAQ,EACR,MAAM,GACP,EAAE,WAAW,CAAC,CAAC,CAAC,2CAmBhB;AAED,cAAc,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { ExtractedPickerItem, PickerItemProps, PickerItemValue } from './types';
3
+ /**
4
+ * Data-only option marker for [`Picker`](#picker).
5
+ * Used via the compound API: `<Picker.Item label="…" value={…} />`.
6
+ */
7
+ export declare function PickerItem<T extends PickerItemValue>(_props: PickerItemProps<T>): null;
8
+ export declare function extractPickerItems<T extends PickerItemValue>(children: ReactNode): ExtractedPickerItem<T>[];
9
+ //# sourceMappingURL=PickerItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PickerItem.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/PickerItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAErF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,IAAI,CAEtF;AAID,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,eAAe,EAC1D,QAAQ,EAAE,SAAS,GAClB,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAU1B"}
@@ -0,0 +1,8 @@
1
+ import { Picker as PickerBase } from './Picker';
2
+ import type { PickerItemProps, PickerItemValue } from './types';
3
+ declare const Picker: typeof PickerBase & {
4
+ Item: <T extends PickerItemValue>(props: PickerItemProps<T>) => null;
5
+ };
6
+ export { Picker };
7
+ export * from './types';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEhE,QAAA,MAAM,MAAM,EAAiB,OAAO,UAAU,GAAG;IAC/C,IAAI,EAAE,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CACtE,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * The type of values a [`Picker.Item`](#pickeritem) can carry.
4
+ */
5
+ export type PickerItemValue = string | number;
6
+ /**
7
+ * Visual appearance of the picker.
8
+ *
9
+ * - `'menu'` — Compact button that opens a popup/dropdown on tap.
10
+ * Cross-platform default.
11
+ * - `'wheel'` — Scrollable rotor UI that's always visible inline.
12
+ * iOS only; on Android and web this falls back to the platform's default dropdown.
13
+ */
14
+ export type PickerAppearance = 'wheel' | 'menu';
15
+ /**
16
+ * Props for the [`Picker.Item`](#pickeritem) component.
17
+ * A data-only marker used to declare options inside a [`Picker`](#picker).
18
+ */
19
+ export interface PickerItemProps<T extends PickerItemValue = PickerItemValue> {
20
+ /**
21
+ * Display text for this option.
22
+ */
23
+ label: string;
24
+ /**
25
+ * Value passed to `onValueChange` when this option is selected.
26
+ */
27
+ value: T;
28
+ }
29
+ /**
30
+ * Props for the [`Picker`](#picker) component, a single-selection input.
31
+ */
32
+ export interface PickerProps<T extends PickerItemValue = PickerItemValue> {
33
+ /**
34
+ * The currently selected value.
35
+ * Must match the `value` of one of the `<Picker.Item>` children.
36
+ */
37
+ selectedValue: T;
38
+ /**
39
+ * Called when the user selects an option.
40
+ */
41
+ onValueChange: (value: T) => void;
42
+ /**
43
+ * Visual appearance of the picker.
44
+ * See [`PickerAppearance`](#pickerappearance).
45
+ * @default 'menu'
46
+ */
47
+ appearance?: PickerAppearance;
48
+ /**
49
+ * Whether the picker accepts input.
50
+ * @default true
51
+ */
52
+ enabled?: boolean;
53
+ /**
54
+ * `<Picker.Item>` children that declare the available options.
55
+ */
56
+ children?: ReactNode;
57
+ /**
58
+ * Identifier used to locate the component in end-to-end tests.
59
+ */
60
+ testID?: string;
61
+ }
62
+ /**
63
+ * Internal: extracted item data from `<Picker.Item>` children.
64
+ */
65
+ export interface ExtractedPickerItem<T extends PickerItemValue = PickerItemValue> {
66
+ label: string;
67
+ value: T;
68
+ }
69
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/universal/Picker/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe;IAC1E;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC;CACV;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe;IACtE;;;OAGG;IACH,aAAa,EAAE,CAAC,CAAC;IAEjB;;OAEG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAElC;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACV"}
@@ -8,8 +8,12 @@ export * from './Switch';
8
8
  export * from './Slider';
9
9
  export * from './Checkbox';
10
10
  export * from './BottomSheet';
11
+ export * from './Collapsible';
11
12
  export * from './FieldGroup';
12
13
  export * from './Icon';
14
+ export * from './List';
15
+ export * from './ListItem';
16
+ export * from './Picker';
13
17
  export * from './Spacer';
14
18
  export * from './State';
15
19
  export { TextInput, type TextInputProps, type TextInputRef } from './TextInput';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/universal/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhF,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/universal/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhF,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
@@ -10,7 +10,7 @@
10
10
  "publication": {
11
11
  "groupId": "expo.modules.ui",
12
12
  "artifactId": "expo.modules.ui",
13
- "version": "56.0.8",
13
+ "version": "56.0.9",
14
14
  "repository": "local-maven-repo"
15
15
  }
16
16
  }
@@ -7,6 +7,7 @@ final class BottomSheetProps: UIBaseViewProps {
7
7
  @Field var isPresented: Bool = false
8
8
  @Field var fitToContents: Bool = false
9
9
  var onIsPresentedChange = EventDispatcher()
10
+ var onDismiss = EventDispatcher()
10
11
  }
11
12
 
12
13
  struct SizePreferenceKey: PreferenceKey {
@@ -86,7 +87,9 @@ struct BottomSheetView: ExpoSwiftUI.View {
86
87
 
87
88
  var body: some View {
88
89
  Rectangle().hidden()
89
- .sheet(isPresented: $isPresented) {
90
+ .sheet(isPresented: $isPresented, onDismiss: {
91
+ props.onDismiss()
92
+ }) {
90
93
  sheetContent
91
94
  }
92
95
  .onChange(of: isPresented, perform: { newIsPresented in
@@ -1,6 +1,7 @@
1
1
  // Copyright 2025-present 650 Industries. All rights reserved.
2
2
 
3
3
  import ExpoModulesCore
4
+ import SwiftUI
4
5
 
5
6
  public final class ExpoUIModule: Module {
6
7
  public func definition() -> ModuleDefinition {
@@ -28,7 +29,19 @@ public final class ExpoUIModule: Module {
28
29
  }
29
30
 
30
31
  Function("setValue") { (state: ObservableState, wrapper: [String: Any]) in
31
- state.value = wrapper["value"]
32
+ let newValue = wrapper["value"]
33
+ // Update state on the UI thread
34
+ if Thread.isMainThread {
35
+ state.value = newValue
36
+ } else {
37
+ DispatchQueue.main.async {
38
+ state.value = newValue
39
+ }
40
+ }
41
+ }
42
+
43
+ Function("setOnChange") { (state: ObservableState, callback: WorkletCallback?) in
44
+ state.onChange = callback
32
45
  }
33
46
  }
34
47
 
@@ -38,6 +51,33 @@ public final class ExpoUIModule: Module {
38
51
  RefreshableManager.shared.completeRefresh(id: id)
39
52
  }
40
53
 
54
+ AsyncFunction("withAnimation") { (
55
+ animation: AnimationConfig?,
56
+ body: WorkletCallback,
57
+ completion: WorkletCallback?,
58
+ completionCriteria: AnimationCompletionCriteriaType?
59
+ ) in
60
+ let swiftUIAnimation = animation?.toSwiftUIAnimation()
61
+
62
+ if let completion {
63
+ if #available(iOS 17.0, tvOS 17.0, *) {
64
+ let criteria: SwiftUI.AnimationCompletionCriteria =
65
+ completionCriteria == .removed ? .removed : .logicallyComplete
66
+ withAnimation(swiftUIAnimation, completionCriteria: criteria) {
67
+ body.invoke()
68
+ } completion: {
69
+ completion.invoke()
70
+ }
71
+ return
72
+ }
73
+ }
74
+
75
+ withAnimation(swiftUIAnimation) {
76
+ body.invoke()
77
+ }
78
+ }
79
+ .runOnQueue(.main)
80
+
41
81
  // MARK: - Expo UI Views with AsyncFunctions
42
82
 
43
83
  ExpoUIView(SecureFieldView.self) {
@@ -0,0 +1,109 @@
1
+ // Copyright 2025-present 650 Industries. All rights reserved.
2
+
3
+ import ExpoModulesCore
4
+ import SwiftUI
5
+
6
+ internal enum AnimationType: String, Enumerable {
7
+ case easeInOut
8
+ case easeIn
9
+ case easeOut
10
+ case linear
11
+ case spring
12
+ case interpolatingSpring
13
+ case `default`
14
+ }
15
+
16
+ internal enum AnimationCompletionCriteriaType: String, Enumerable {
17
+ case logicallyComplete
18
+ case removed
19
+ }
20
+
21
+ /**
22
+ Describes a SwiftUI `Animation` value over the JS bridge. Consumed by both
23
+ the `animation(_:value:)` view modifier and the `withAnimation(_:_:)`
24
+ function so they accept the same JS shape.
25
+ */
26
+ internal struct AnimationConfig: Record {
27
+ // Shared fallbacks used when the JS side omits a parameter. Mirrors
28
+ // SwiftUI's own defaults so each animation variant resolves the same way.
29
+ private static let defaultDuration: Double = 0.5
30
+ private static let defaultResponse: Double = 0.5
31
+ private static let defaultDampingFraction: Double = 0.825
32
+ private static let defaultBlendDuration: Double = 0.0
33
+ private static let defaultBounce: Double = 0.0
34
+
35
+ @Field var type: AnimationType = .default
36
+ @Field var duration: Double?
37
+ @Field var response: Double?
38
+ @Field var dampingFraction: Double?
39
+ @Field var blendDuration: Double?
40
+ @Field var bounce: Double?
41
+ @Field var mass: Double = 1.0
42
+ @Field var stiffness: Double?
43
+ @Field var damping: Double?
44
+ @Field var initialVelocity: Double = 0.0
45
+ @Field var delay: Double?
46
+ @Field var repeatCount: Int?
47
+ @Field var autoreverses: Bool = true
48
+
49
+ func toSwiftUIAnimation() -> Animation {
50
+ var animation: Animation
51
+
52
+ switch type {
53
+ case .easeIn:
54
+ animation = duration.map { Animation.easeIn(duration: $0) } ?? .easeIn
55
+ case .easeOut:
56
+ animation = duration.map { Animation.easeOut(duration: $0) } ?? .easeOut
57
+ case .linear:
58
+ animation = duration.map { Animation.linear(duration: $0) } ?? .linear
59
+ case .easeInOut:
60
+ animation = duration.map { Animation.easeInOut(duration: $0) } ?? .easeInOut
61
+ case .spring:
62
+ if response != nil || dampingFraction != nil {
63
+ animation = .spring(
64
+ response: response ?? Self.defaultResponse,
65
+ dampingFraction: dampingFraction ?? Self.defaultDampingFraction,
66
+ blendDuration: blendDuration ?? Self.defaultBlendDuration
67
+ )
68
+ } else if duration != nil || bounce != nil {
69
+ animation = .spring(
70
+ duration: duration ?? Self.defaultDuration,
71
+ bounce: bounce ?? Self.defaultBounce,
72
+ blendDuration: blendDuration ?? Self.defaultBlendDuration
73
+ )
74
+ } else if let blendDuration {
75
+ animation = .spring(blendDuration: blendDuration)
76
+ } else {
77
+ animation = .spring
78
+ }
79
+ case .interpolatingSpring:
80
+ if duration != nil || bounce != nil {
81
+ animation = .interpolatingSpring(
82
+ duration: duration ?? Self.defaultDuration,
83
+ bounce: bounce ?? Self.defaultBounce,
84
+ initialVelocity: initialVelocity
85
+ )
86
+ } else if let stiffness, let damping {
87
+ animation = .interpolatingSpring(
88
+ mass: mass,
89
+ stiffness: stiffness,
90
+ damping: damping,
91
+ initialVelocity: initialVelocity
92
+ )
93
+ } else {
94
+ animation = .interpolatingSpring
95
+ }
96
+ default:
97
+ animation = .default
98
+ }
99
+
100
+ if let delay {
101
+ animation = animation.delay(delay)
102
+ }
103
+ if let repeatCount {
104
+ animation = animation.repeatCount(repeatCount, autoreverses: autoreverses)
105
+ }
106
+
107
+ return animation
108
+ }
109
+ }
@@ -621,38 +621,12 @@ internal struct AnyViewModifier: ViewModifier {
621
621
  }
622
622
  }
623
623
 
624
- internal enum AnimationType: String, Enumerable {
625
- case easeInOut
626
- case easeIn
627
- case easeOut
628
- case linear
629
- case spring
630
- case interpolatingSpring
631
- case `default`
632
- }
633
-
634
- internal struct AnimationConfig: Record {
635
- @Field var type: AnimationType = .default
636
- @Field var duration: Double?
637
- @Field var response: Double?
638
- @Field var dampingFraction: Double?
639
- @Field var blendDuration: Double?
640
- @Field var bounce: Double?
641
- @Field var mass: Double?
642
- @Field var stiffness: Double?
643
- @Field var damping: Double?
644
- @Field var initialVelocity: Double?
645
- @Field var delay: Double?
646
- @Field var repeatCount: Int?
647
- @Field var autoreverses: Bool?
648
- }
649
-
650
624
  internal struct AnimationModifier: ViewModifier, Record {
651
625
  @Field var animation: AnimationConfig
652
626
  @Field var animatedValue: Either<Double, Bool>?
653
627
 
654
628
  func body(content: Content) -> some View {
655
- let animationValue = parseAnimation(animation)
629
+ let animationValue = animation.toSwiftUIAnimation()
656
630
  if let value: Bool = animatedValue?.get() {
657
631
  content.animation(animationValue, value: value)
658
632
  } else if let value: Double = animatedValue?.get() {
@@ -661,91 +635,6 @@ internal struct AnimationModifier: ViewModifier, Record {
661
635
  content
662
636
  }
663
637
  }
664
-
665
- private func parseAnimation(_ config: AnimationConfig) -> Animation {
666
- let type = config.type
667
-
668
- var animation: Animation
669
-
670
- switch type {
671
- case .easeIn:
672
- if let duration = config.duration {
673
- animation = .easeIn(duration: duration)
674
- } else {
675
- animation = .easeIn
676
- }
677
-
678
- case .easeOut:
679
- if let duration = config.duration {
680
- animation = .easeOut(duration: duration)
681
- } else {
682
- animation = .easeOut
683
- }
684
-
685
- case .linear:
686
- if let duration = config.duration {
687
- animation = .linear(duration: duration)
688
- } else {
689
- animation = .linear
690
- }
691
-
692
- case .easeInOut:
693
- if let duration = config.duration {
694
- animation = .easeInOut(duration: duration)
695
- } else {
696
- animation = .easeInOut
697
- }
698
-
699
- case .spring:
700
- let duration = config.duration
701
- let bounce = config.bounce
702
- let response = config.response
703
- let dampingFraction = config.dampingFraction
704
- let blendDuration = config.blendDuration
705
-
706
- if response != nil || dampingFraction != nil {
707
- // default values are 0.5, 0.825, 0.0
708
- animation = .spring(response: response ?? 0.5, dampingFraction: dampingFraction ?? 0.825, blendDuration: blendDuration ?? 0.0)
709
- } else if duration != nil || bounce != nil {
710
- // default values are 0.5, 0.0, 0.0
711
- animation = .spring(duration: duration ?? 0.5, bounce: bounce ?? 0.0, blendDuration: blendDuration ?? 0.0)
712
- } else if let blendDuration = blendDuration {
713
- animation = .spring(blendDuration: blendDuration)
714
- } else {
715
- animation = .spring
716
- }
717
-
718
- case .interpolatingSpring:
719
- let duration = config.duration
720
- let bounce = config.bounce
721
- let mass = config.mass
722
- let stiffness = config.stiffness
723
- let damping = config.damping
724
- let initialVelocity = config.initialVelocity
725
-
726
- if duration != nil || bounce != nil {
727
- animation = .interpolatingSpring(duration: duration ?? 0.5, bounce: bounce ?? 0.0, initialVelocity: initialVelocity ?? 0.0)
728
- } else if let stiffness, let damping {
729
- animation = .interpolatingSpring(mass: mass ?? 1.0, stiffness: stiffness, damping: damping, initialVelocity: initialVelocity ?? 0.0)
730
- } else {
731
- animation = .interpolatingSpring
732
- }
733
-
734
- default:
735
- animation = .default
736
- }
737
-
738
- if let delay = config.delay {
739
- animation = animation.delay(delay)
740
- }
741
-
742
- if let repeatCount = config.repeatCount {
743
- let autoreverses = config.autoreverses ?? false
744
- animation = animation.repeatCount(repeatCount, autoreverses: autoreverses)
745
- }
746
-
747
- return animation
748
- }
749
638
  }
750
639
 
751
640
  internal enum ScrollContentBackgroundTypes: String, Enumerable {
@@ -13,7 +13,18 @@ import SwiftUI
13
13
  * Toggle(label, isOn: state.binding(false))
14
14
  */
15
15
  internal class ObservableState: SharedObject, ObservableObject {
16
- @Published var value: Any?
16
+ var onChange: WorkletCallback?
17
+ private var isNotifying = false
18
+
19
+ @Published var value: Any? {
20
+ didSet {
21
+ // Skip re-invoking onChange if state.value was written from inside onChange.
22
+ guard !isNotifying else { return }
23
+ isNotifying = true
24
+ defer { isNotifying = false }
25
+ onChange?.invoke(arguments: [value ?? NSNull()])
26
+ }
27
+ }
17
28
 
18
29
  init(value: Any?) {
19
30
  self.value = value
@@ -0,0 +1 @@
1
+ b68d51962848180ac90fcb20a9766fabd72327ad
@@ -0,0 +1 @@
1
+ e068f417d7a302f7d37e1d8648b7f61d2da46d215aede6ad991e35f780e794ea
@@ -0,0 +1 @@
1
+ 408e70adeb3b30e509e418a2a6edbd5afb888a27f8fcd5c04032a1089ef32c4483e542854cd1621a74aa2763094cd2e6ba98b30e99e213dd06734167e6d4083c
@@ -0,0 +1 @@
1
+ 4631f8e63a9536ef63c03c7666fbaa0e5a4f60a1
@@ -0,0 +1 @@
1
+ 7f2175675f65b6caaf5ce6580cdd24a10f208ae6d80b894e4460796fe2f0dc05
@@ -0,0 +1 @@
1
+ ba0dfa2c02b2ad1f248bfe43a5a922a95dbb83c493eb23cd8d3b98f3e790d9be19133002ac2ab408f3a9268af3c5718072f0646c2e13b0ce2d01b8198ae8ccc6