@expo/ui 57.0.21 → 57.0.23
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.
- package/CHANGELOG.md +39 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ui/DatePickerView.kt +36 -2
- package/android/src/main/java/expo/modules/ui/DateRangePickerView.kt +35 -2
- package/android/src/main/java/expo/modules/ui/HostView.kt +28 -1
- package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +23 -2
- package/android/src/main/java/expo/modules/ui/RNHostView.kt +124 -17
- package/build/community/bottom-sheet/BottomSheet.ios.d.ts.map +1 -1
- package/build/community/datetime-picker/DateTimePicker.android.d.ts.map +1 -1
- package/build/community/datetime-picker/utils.d.ts +11 -0
- package/build/community/datetime-picker/utils.d.ts.map +1 -0
- package/build/community/picker/Picker.android.d.ts.map +1 -1
- package/build/jetpack-compose/DatePicker/index.d.ts +38 -0
- package/build/jetpack-compose/DatePicker/index.d.ts.map +1 -1
- package/build/jetpack-compose/RNHostView/index.d.ts +6 -1
- package/build/jetpack-compose/RNHostView/index.d.ts.map +1 -1
- package/build/jetpack-compose/modifiers/index.d.ts +18 -3
- package/build/jetpack-compose/modifiers/index.d.ts.map +1 -1
- package/build/swift-ui/ArrangementView/index.d.ts +49 -0
- package/build/swift-ui/ArrangementView/index.d.ts.map +1 -0
- package/build/swift-ui/Chart/index.d.ts +10 -0
- package/build/swift-ui/Chart/index.d.ts.map +1 -1
- package/build/swift-ui/RNHostView.d.ts +7 -2
- package/build/swift-ui/RNHostView.d.ts.map +1 -1
- package/build/swift-ui/index.d.ts +1 -0
- package/build/swift-ui/index.d.ts.map +1 -1
- package/build/swift-ui/modifiers/animation/index.d.ts +6 -1
- package/build/swift-ui/modifiers/animation/index.d.ts.map +1 -1
- package/build/swift-ui/modifiers/animation/types.d.ts +15 -1
- package/build/swift-ui/modifiers/animation/types.d.ts.map +1 -1
- package/build/swift-ui/modifiers/arrangementModifiers.d.ts +110 -0
- package/build/swift-ui/modifiers/arrangementModifiers.d.ts.map +1 -0
- package/build/swift-ui/modifiers/containerBackground.d.ts +2 -2
- package/build/swift-ui/modifiers/index.d.ts +41 -2
- package/build/swift-ui/modifiers/index.d.ts.map +1 -1
- package/build/swift-ui/modifiers/presentationModifiers.d.ts +17 -1
- package/build/swift-ui/modifiers/presentationModifiers.d.ts.map +1 -1
- package/build/swift-ui/modifiers/searchable.d.ts +84 -0
- package/build/swift-ui/modifiers/searchable.d.ts.map +1 -0
- package/build/universal/RNHostView/index.d.ts.map +1 -1
- package/build/universal/RNHostView/types.d.ts +9 -4
- package/build/universal/RNHostView/types.d.ts.map +1 -1
- package/build/universal/Switch/index.android.d.ts.map +1 -1
- package/build/utils/matchContents.d.ts +11 -0
- package/build/utils/matchContents.d.ts.map +1 -0
- package/expo-module.config.json +1 -1
- package/ios/ArrangementViewView.swift +40 -0
- package/ios/ChartView.swift +15 -10
- package/ios/ExpoUIModule.swift +1 -1
- package/ios/Modifiers/AnimationConfig.swift +20 -0
- package/ios/Modifiers/ArrangementModifiers.swift +157 -0
- package/ios/Modifiers/ContainerBackgroundModifier.swift +26 -13
- package/ios/Modifiers/PreferredColorSchemeModifier.swift +12 -0
- package/ios/Modifiers/PresentationModifiers.swift +20 -4
- package/ios/Modifiers/SearchToolbarBehaviorModifier.swift +35 -0
- package/ios/Modifiers/SearchableModifier.swift +94 -0
- package/ios/Modifiers/View+ModifierArray.swift +3 -3
- package/ios/Modifiers/ViewModifierRegistry.swift +124 -9
- package/ios/Modifiers/WidgetKitModifiers.swift +13 -0
- package/ios/Picker/PickerView.swift +9 -7
- package/ios/RNHostView.swift +55 -9
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.21/expo.modules.ui-57.0.21-sources.jar → 57.0.23/expo.modules.ui-57.0.23-sources.jar} +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23-sources.jar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23-sources.jar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23-sources.jar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23-sources.jar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.21/expo.modules.ui-57.0.21.module → 57.0.23/expo.modules.ui-57.0.23.module} +22 -22
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.module.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.module.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.module.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.module.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.21/expo.modules.ui-57.0.21.pom → 57.0.23/expo.modules.ui-57.0.23.pom} +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.pom.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.pom.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.pom.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.pom.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
- package/package.json +4 -4
- package/src/community/bottom-sheet/BottomSheet.ios.tsx +7 -6
- package/src/community/datetime-picker/DateTimePicker.android.tsx +18 -4
- package/src/community/datetime-picker/utils.ts +21 -0
- package/src/community/picker/Picker.android.tsx +5 -0
- package/src/jetpack-compose/DatePicker/index.tsx +38 -0
- package/src/jetpack-compose/RNHostView/index.tsx +17 -6
- package/src/jetpack-compose/modifiers/index.ts +17 -3
- package/src/swift-ui/ArrangementView/index.tsx +70 -0
- package/src/swift-ui/Chart/index.tsx +10 -0
- package/src/swift-ui/RNHostView.tsx +11 -4
- package/src/swift-ui/index.tsx +1 -0
- package/src/swift-ui/modifiers/animation/index.ts +24 -11
- package/src/swift-ui/modifiers/animation/types.ts +18 -0
- package/src/swift-ui/modifiers/arrangementModifiers.ts +142 -0
- package/src/swift-ui/modifiers/containerBackground.ts +2 -2
- package/src/swift-ui/modifiers/index.ts +52 -1
- package/src/swift-ui/modifiers/presentationModifiers.ts +18 -2
- package/src/swift-ui/modifiers/searchable.ts +107 -0
- package/src/universal/RNHostView/index.tsx +9 -4
- package/src/universal/RNHostView/types.ts +6 -4
- package/src/universal/Switch/index.android.tsx +11 -2
- package/src/utils/matchContents.ts +14 -0
- package/ios/AccessoryWidgetBackgroundView.swift +0 -27
- package/ios/Modifiers/WidgetModifiers.swift +0 -70
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21-sources.jar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21-sources.jar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21-sources.jar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21-sources.jar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.aar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.aar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.aar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.aar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.module.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.module.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.module.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.module.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.pom.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.pom.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.pom.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.21/expo.modules.ui-57.0.21.pom.sha512 +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,45 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 57.0.23 — 2026-10-12
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- [Android] Add `showTitle` and `showHeadline` to the Jetpack Compose `DateTimePicker`, `DatePickerDialog`, `DateRangePicker`, and `DateRangePickerDialog` to hide Material 3's title and headline. The community `DateTimePicker` with `presentation="inline"` now hides both on Android, matching iOS. To keep the title and headline, use `DateTimePicker` from `@expo/ui/jetpack-compose` instead. ([#51274](https://github.com/expo/expo/pull/51274) by [@IGx89](https://github.com/IGx89))
|
|
18
|
+
- [iOS] Add `searchable` and `searchToolbarBehavior` SwiftUI modifiers. ([#50369](https://github.com/expo/expo/pull/50369) by [@expo-bot](https://github.com/expo-bot))
|
|
19
|
+
- [iOS][Android] `RNHostView` `matchContents` accepts `{ horizontal, vertical }`, so hosted content can take its width from the parent and its height from the content. ([#50674](https://github.com/expo/expo/pull/50674) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
20
|
+
- [iOS] Add `cornerRadius` and `opacity` to `Chart`'s `pieStyle`. Pie slices could not have rounded corners, and their opacity was fixed at 0.8, so a chart drawn in solid colors always looked washed out. Both default to the previous behavior. Rounded corners let a single-slice donut work as a progress ring with rounded ends. ([#51351](https://github.com/expo/expo/pull/51351) by [@jsg2021](https://github.com/jsg2021))
|
|
21
|
+
|
|
22
|
+
### 🐛 Bug fixes
|
|
23
|
+
|
|
24
|
+
- [Android] Fix a `Pressable` (or any JS responder) being cancelled when a `MaskedView`, or any other component that renders a `Host`, is laid over it. Once React Native grants the JS responder, the responder's view intercepts the touch stream and sends `ACTION_CANCEL` to its native children, including that `Host`. The `Host` reported this cancel as Compose claiming the gesture, which cancelled the press it belonged to. Holds longer than about 30 ms never fired `onPress`. ([#51163](https://github.com/expo/expo/pull/51163) by [@1kuko3](https://github.com/1kuko3))
|
|
25
|
+
- [iOS] Fix `Picker` not reporting a selection that equals the last `selection` prop when the user changes it again before the prop updates. ([#51196](https://github.com/expo/expo/pull/51196) by [@expo-bot](https://github.com/expo-bot))
|
|
26
|
+
- [iOS] Fix `Chart` ignoring `lineStyle.width` on line charts. The line mark applied `.lineStyle` twice (once for the dash pattern, once for the width), and the first one wins, so lines always rendered at 1 pt. The width and the dash pattern are now set in one `StrokeStyle`. ([#51283](https://github.com/expo/expo/pull/51283) by [@brentvatne](https://github.com/brentvatne))
|
|
27
|
+
- [Android] Fix a numeric `width()` modifier crashing the app on launch with `FieldCastException: Cannot cast value for field 'width'` since the `IntrinsicSize` support added in 57.0.22 / 58.0.9. JS numbers reach the modifier record as `Double`, which matched neither branch of `Either<Int, IntrinsicSizeType>`; the field is now `Either<Double, IntrinsicSizeType>`, so numeric widths convert again and `width(IntrinsicSize.Min|Max)` keeps working. ([#51322](https://github.com/expo/expo/pull/51322) by [@expo-bot](https://github.com/expo-bot))
|
|
28
|
+
- [iOS] Fix the community `BottomSheet` clipping its content when the sheet is narrower than the window, as on iPhone Duo. When the sheet sized itself to its content, the content was pinned to the window width and centered in the sheet, so its leading edge was cut off. The content now takes its width from the sheet and its height from the content. `presentationSizing` takes a `fitted` option (`{ horizontal, vertical }`) to fit a sheet to its content on one axis only. ([#51319](https://github.com/expo/expo/pull/51319) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
29
|
+
- [Android] Fix an `RNHostView` that ignores touches when a Compose button with a ripple in the same `Host` was pressed earlier. The ripple container that Compose adds was found first during React Native's touch-target search, so the touch went to the `Host` instead of the hosted view. ([#51237](https://github.com/expo/expo/pull/51237) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
30
|
+
|
|
31
|
+
## 57.0.22 — 2026-10-06
|
|
32
|
+
|
|
33
|
+
### 🎉 New features
|
|
34
|
+
|
|
35
|
+
- [android] Added `IntrinsicSize` support to the `width` modifier. ([#50693](https://github.com/expo/expo/pull/50693) by [@janicduplessis](https://github.com/janicduplessis))
|
|
36
|
+
- [iOS] Added the `preferredColorScheme` modifier, which sets the color scheme of a presentation such as `BottomSheet`, including its background. ([#50851](https://github.com/expo/expo/pull/50851) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
37
|
+
- [iOS] Added the `navigationBarTitleDisplayMode` and `toolbarTitleDisplayMode` modifiers for controlling navigation and toolbar title presentation. ([#50687](https://github.com/expo/expo/pull/50687) by [@0x5bfa](https://github.com/0x5bfa))
|
|
38
|
+
- [iOS] Added the `smooth`, `snappy`, and `bouncy` spring presets to `Animation`. Like their SwiftUI counterparts, they take an optional `duration` and `extraBounce`. ([#50984](https://github.com/expo/expo/pull/50984) by [@Den1Marshall](https://github.com/Den1Marshall))
|
|
39
|
+
- [iOS] Add `ArrangementView` component and `arrangementViewStyle`, `splitArrangementLayoutRatio`, `splitArrangementLayoutSize`, `splitArrangementFixedLayoutSize`, and `overlayArrangementEdge` modifiers. ([#50893](https://github.com/expo/expo/pull/50893) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
40
|
+
|
|
41
|
+
### 🐛 Bug fixes
|
|
42
|
+
|
|
43
|
+
- [Android] Fix the community `DateTimePicker` reading `value` as a UTC day while `minimumDate`/`maximumDate` use the device-local day. In non-UTC timezones the picker could select and return the wrong day — one before `minimumDate`. `value`'s local calendar day is now sent to Material3 as a UTC day, and the picked day is returned as a local date that keeps `value`'s time of day. ([#50941](https://github.com/expo/expo/pull/50941) by [@expo-bot](https://github.com/expo-bot))
|
|
44
|
+
- [Android] Fix `TimePickerDialog` ignoring `elementColors.containerColor`. ([#51116](https://github.com/expo/expo/pull/51116) by [@expo-bot](https://github.com/expo-bot))
|
|
45
|
+
- [Android] Fix an intermittent `performMeasureAndLayout called during measure layout` crash that tore down the ReactHost when a `Host` with `matchContents` was measured while react-native-reanimated was active. The `onLayoutContent` event is now posted after the measure pass instead of emitted inside it. ([#49933](https://github.com/expo/expo/pull/49933) by [@expo-bot](https://github.com/expo-bot))
|
|
46
|
+
- [android] Fix `Switch` label rendering one letter per line inside a `Host` with `matchContents`. ([#50693](https://github.com/expo/expo/pull/50693) by [@janicduplessis](https://github.com/janicduplessis))
|
|
47
|
+
- [android] Fix `community/picker` `Picker` not updating its displayed label after a selection or a `selectedValue` change. ([#50801](https://github.com/expo/expo/pull/50801) by [@RaddishIoW](https://github.com/RaddishIoW))
|
|
48
|
+
- [iOS] Fixed `delay()` and `repeat()` modifying the animation they are called on. Chaining from a shared animation, such as `Animation.default` or one stored in a constant, no longer changes that animation everywhere else it is used. ([#50927](https://github.com/expo/expo/pull/50927) by [@Den1Marshall](https://github.com/Den1Marshall))
|
|
49
|
+
- [iOS] Stop linking WidgetKit into apps that use `@expo/ui` without widgets. The `widgetURL`, `activityBackgroundTint`, `widgetAccentedRenderingMode`, and `containerBackground` (`widget` placement) modifiers and the `AccessoryWidgetBackground` view now take effect only inside `expo-widgets` widgets and Live Activities. ([#50786](https://github.com/expo/expo/pull/50786) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
50
|
+
- [iOS][tvOS] Fix the tvOS build failing to compile with `'inlineLarge' is unavailable in tvOS` when `@expo/ui` is linked. `ToolbarTitleDisplayMode.inlineLarge` is unavailable on tvOS, but the `inlineLarge` case of the `toolbarTitleDisplayMode` modifier was only gated behind an OS version check that listed `tvOS 18.0`, so it was compiled into the tvOS slice. It is now guarded by platform and returns `nil` on tvOS. The same check also required iOS 18.0 / macOS 15.0, so `inlineLarge` silently fell back to `automatic` on iOS 17 and macOS 14 even though it is available there; it now applies on those versions. ([#51007](https://github.com/expo/expo/pull/51007) by [@gabrieldonadel](https://github.com/gabrieldonadel))
|
|
51
|
+
|
|
13
52
|
## 57.0.21 — 2026-09-29
|
|
14
53
|
|
|
15
54
|
### 🎉 New features
|
package/android/build.gradle
CHANGED
|
@@ -12,13 +12,13 @@ apply plugin: 'expo-module-gradle-plugin'
|
|
|
12
12
|
apply plugin: 'org.jetbrains.kotlin.plugin.compose'
|
|
13
13
|
|
|
14
14
|
group = 'expo.modules.ui'
|
|
15
|
-
version = '57.0.
|
|
15
|
+
version = '57.0.23'
|
|
16
16
|
|
|
17
17
|
android {
|
|
18
18
|
namespace "expo.modules.ui"
|
|
19
19
|
defaultConfig {
|
|
20
20
|
versionCode 1
|
|
21
|
-
versionName "57.0.
|
|
21
|
+
versionName "57.0.23"
|
|
22
22
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
23
23
|
}
|
|
24
24
|
buildFeatures {
|
|
@@ -4,6 +4,7 @@ import androidx.compose.material3.AlertDialog
|
|
|
4
4
|
import androidx.compose.ui.res.stringResource
|
|
5
5
|
import androidx.compose.material3.ButtonDefaults
|
|
6
6
|
import androidx.compose.material3.DatePicker
|
|
7
|
+
import androidx.compose.material3.DatePickerColors
|
|
7
8
|
import androidx.compose.material3.DatePickerDefaults
|
|
8
9
|
import androidx.compose.material3.DatePickerDialog
|
|
9
10
|
import androidx.compose.material3.DatePickerState
|
|
@@ -158,6 +159,8 @@ data class DateTimePickerProps(
|
|
|
158
159
|
val variant: Variant = Variant.PICKER,
|
|
159
160
|
val displayedComponents: DisplayedComponents = DisplayedComponents.DATE,
|
|
160
161
|
val showVariantToggle: Boolean = true,
|
|
162
|
+
val showTitle: Boolean = true,
|
|
163
|
+
val showHeadline: Boolean = true,
|
|
161
164
|
val is24Hour: Boolean = true,
|
|
162
165
|
val color: AndroidColor? = null,
|
|
163
166
|
val elementColors: DateTimePickerColorOverrides = DateTimePickerColorOverrides(),
|
|
@@ -170,6 +173,8 @@ data class DatePickerDialogProps(
|
|
|
170
173
|
val initialDate: Long? = null,
|
|
171
174
|
val variant: Variant = Variant.PICKER,
|
|
172
175
|
val showVariantToggle: Boolean = true,
|
|
176
|
+
val showTitle: Boolean = true,
|
|
177
|
+
val showHeadline: Boolean = true,
|
|
173
178
|
val confirmButtonLabel: String? = null,
|
|
174
179
|
val dismissButtonLabel: String? = null,
|
|
175
180
|
val color: AndroidColor? = null,
|
|
@@ -388,7 +393,7 @@ fun ExpoDatePickerDialogContent(props: DatePickerDialogProps, onDateSelected: (D
|
|
|
388
393
|
// Material3's year-selector chevron tints from the ambient LocalContentColor (which defaults to
|
|
389
394
|
// black), not `navigationContentColor`; bind the local so the chevron honors the navigation color.
|
|
390
395
|
CompositionLocalProvider(LocalContentColor provides colors.navigationContentColor) {
|
|
391
|
-
|
|
396
|
+
MaterialDatePicker(
|
|
392
397
|
modifier = if (displayMode == DisplayMode.Picker) {
|
|
393
398
|
Modifier.wrapContentHeight(align = Alignment.Top, unbounded = true)
|
|
394
399
|
} else {
|
|
@@ -396,6 +401,8 @@ fun ExpoDatePickerDialogContent(props: DatePickerDialogProps, onDateSelected: (D
|
|
|
396
401
|
},
|
|
397
402
|
state = state,
|
|
398
403
|
showModeToggle = props.showVariantToggle,
|
|
404
|
+
showTitle = props.showTitle,
|
|
405
|
+
showHeadline = props.showHeadline,
|
|
399
406
|
colors = colors
|
|
400
407
|
)
|
|
401
408
|
}
|
|
@@ -443,6 +450,7 @@ fun ExpoTimePickerDialogContent(props: TimePickerDialogProps, onDateSelected: (D
|
|
|
443
450
|
Text(props.dismissButtonLabel ?: stringResource(android.R.string.cancel))
|
|
444
451
|
}
|
|
445
452
|
},
|
|
453
|
+
containerColor = timePickerColors.containerColor,
|
|
446
454
|
text = {
|
|
447
455
|
TimePicker(
|
|
448
456
|
state = state,
|
|
@@ -498,15 +506,41 @@ fun ExpoDatePicker(modifier: Modifier = Modifier, props: DateTimePickerProps, on
|
|
|
498
506
|
// Material3's year-selector chevron tints from the ambient LocalContentColor (which defaults to
|
|
499
507
|
// black), not `navigationContentColor`; bind the local so the chevron honors the navigation color.
|
|
500
508
|
CompositionLocalProvider(LocalContentColor provides colors.navigationContentColor) {
|
|
501
|
-
|
|
509
|
+
MaterialDatePicker(
|
|
502
510
|
modifier = modifier,
|
|
503
511
|
state = state,
|
|
504
512
|
showModeToggle = props.showVariantToggle,
|
|
513
|
+
showTitle = props.showTitle,
|
|
514
|
+
showHeadline = props.showHeadline,
|
|
505
515
|
colors = colors
|
|
506
516
|
)
|
|
507
517
|
}
|
|
508
518
|
}
|
|
509
519
|
|
|
520
|
+
// Material 3 hides the title or headline when its slot is `null`. Its default slots pad themselves
|
|
521
|
+
// with private constants, so branch on the call instead of copying them, keeping the defaults exact.
|
|
522
|
+
@OptIn(ExperimentalMaterial3Api::class)
|
|
523
|
+
@Composable
|
|
524
|
+
private fun MaterialDatePicker(
|
|
525
|
+
modifier: Modifier = Modifier,
|
|
526
|
+
state: DatePickerState,
|
|
527
|
+
showModeToggle: Boolean,
|
|
528
|
+
showTitle: Boolean,
|
|
529
|
+
showHeadline: Boolean,
|
|
530
|
+
colors: DatePickerColors
|
|
531
|
+
) {
|
|
532
|
+
when {
|
|
533
|
+
showTitle && showHeadline ->
|
|
534
|
+
DatePicker(state = state, modifier = modifier, colors = colors, showModeToggle = showModeToggle)
|
|
535
|
+
showTitle ->
|
|
536
|
+
DatePicker(state = state, modifier = modifier, colors = colors, headline = null, showModeToggle = showModeToggle)
|
|
537
|
+
showHeadline ->
|
|
538
|
+
DatePicker(state = state, modifier = modifier, colors = colors, title = null, showModeToggle = showModeToggle)
|
|
539
|
+
else ->
|
|
540
|
+
DatePicker(state = state, modifier = modifier, colors = colors, title = null, headline = null, showModeToggle = showModeToggle)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
510
544
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
511
545
|
@Composable
|
|
512
546
|
fun ExpoTimePicker(modifier: Modifier = Modifier, props: DateTimePickerProps, onDateSelected: (DatePickerResult) -> Unit) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package expo.modules.ui
|
|
2
2
|
|
|
3
3
|
import androidx.compose.material3.ButtonDefaults
|
|
4
|
+
import androidx.compose.material3.DatePickerColors
|
|
4
5
|
import androidx.compose.material3.DatePickerDefaults
|
|
5
6
|
import androidx.compose.material3.DatePickerDialog
|
|
6
7
|
import androidx.compose.material3.DateRangePicker
|
|
@@ -13,6 +14,7 @@ import androidx.compose.runtime.Composable
|
|
|
13
14
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
14
15
|
import androidx.compose.runtime.LaunchedEffect
|
|
15
16
|
import androidx.compose.runtime.remember
|
|
17
|
+
import androidx.compose.ui.Modifier
|
|
16
18
|
import androidx.compose.ui.platform.LocalConfiguration
|
|
17
19
|
import androidx.compose.ui.res.stringResource
|
|
18
20
|
import expo.modules.kotlin.records.Field
|
|
@@ -38,6 +40,8 @@ data class DateRangePickerProps(
|
|
|
38
40
|
val initialEndDate: Long? = null,
|
|
39
41
|
val variant: Variant = Variant.PICKER,
|
|
40
42
|
val showVariantToggle: Boolean = true,
|
|
43
|
+
val showTitle: Boolean = true,
|
|
44
|
+
val showHeadline: Boolean = true,
|
|
41
45
|
val color: AndroidColor? = null,
|
|
42
46
|
val elementColors: DateTimePickerColorOverrides = DateTimePickerColorOverrides(),
|
|
43
47
|
val selectableDates: SelectableDatesRecord? = null,
|
|
@@ -50,6 +54,8 @@ data class DateRangePickerDialogProps(
|
|
|
50
54
|
val initialEndDate: Long? = null,
|
|
51
55
|
val variant: Variant = Variant.PICKER,
|
|
52
56
|
val showVariantToggle: Boolean = true,
|
|
57
|
+
val showTitle: Boolean = true,
|
|
58
|
+
val showHeadline: Boolean = true,
|
|
53
59
|
val confirmButtonLabel: String? = null,
|
|
54
60
|
val dismissButtonLabel: String? = null,
|
|
55
61
|
val color: AndroidColor? = null,
|
|
@@ -147,9 +153,11 @@ fun ExpoDateRangePickerDialogContent(
|
|
|
147
153
|
ApplyDatePickerDialogKeyboardBehavior(displayMode)
|
|
148
154
|
|
|
149
155
|
CompositionLocalProvider(LocalContentColor provides colors.navigationContentColor) {
|
|
150
|
-
|
|
156
|
+
MaterialDateRangePicker(
|
|
151
157
|
state = state,
|
|
152
158
|
showModeToggle = props.showVariantToggle,
|
|
159
|
+
showTitle = props.showTitle,
|
|
160
|
+
showHeadline = props.showHeadline,
|
|
153
161
|
colors = colors
|
|
154
162
|
)
|
|
155
163
|
}
|
|
@@ -181,11 +189,36 @@ fun FunctionalComposableScope.DateRangePickerContent(
|
|
|
181
189
|
|
|
182
190
|
val colors = buildDatePickerColors(props.elementColors, props.color.composeOrNull)
|
|
183
191
|
CompositionLocalProvider(LocalContentColor provides colors.navigationContentColor) {
|
|
184
|
-
|
|
192
|
+
MaterialDateRangePicker(
|
|
185
193
|
modifier = modifier,
|
|
186
194
|
state = state,
|
|
187
195
|
showModeToggle = props.showVariantToggle,
|
|
196
|
+
showTitle = props.showTitle,
|
|
197
|
+
showHeadline = props.showHeadline,
|
|
188
198
|
colors = colors
|
|
189
199
|
)
|
|
190
200
|
}
|
|
191
201
|
}
|
|
202
|
+
|
|
203
|
+
// See MaterialDatePicker: branching keeps Material 3's own default title and headline slots.
|
|
204
|
+
@OptIn(ExperimentalMaterial3Api::class)
|
|
205
|
+
@Composable
|
|
206
|
+
private fun MaterialDateRangePicker(
|
|
207
|
+
modifier: Modifier = Modifier,
|
|
208
|
+
state: DateRangePickerState,
|
|
209
|
+
showModeToggle: Boolean,
|
|
210
|
+
showTitle: Boolean,
|
|
211
|
+
showHeadline: Boolean,
|
|
212
|
+
colors: DatePickerColors
|
|
213
|
+
) {
|
|
214
|
+
when {
|
|
215
|
+
showTitle && showHeadline ->
|
|
216
|
+
DateRangePicker(state = state, modifier = modifier, colors = colors, showModeToggle = showModeToggle)
|
|
217
|
+
showTitle ->
|
|
218
|
+
DateRangePicker(state = state, modifier = modifier, colors = colors, headline = null, showModeToggle = showModeToggle)
|
|
219
|
+
showHeadline ->
|
|
220
|
+
DateRangePicker(state = state, modifier = modifier, colors = colors, title = null, showModeToggle = showModeToggle)
|
|
221
|
+
else ->
|
|
222
|
+
DateRangePicker(state = state, modifier = modifier, colors = colors, title = null, headline = null, showModeToggle = showModeToggle)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -4,6 +4,7 @@ package expo.modules.ui
|
|
|
4
4
|
|
|
5
5
|
import android.annotation.SuppressLint
|
|
6
6
|
import android.content.Context
|
|
7
|
+
import android.view.MotionEvent
|
|
7
8
|
import androidx.compose.foundation.isSystemInDarkTheme
|
|
8
9
|
import androidx.compose.foundation.layout.WindowInsets
|
|
9
10
|
import androidx.compose.foundation.layout.displayCutout
|
|
@@ -104,6 +105,26 @@ internal class HostView(context: Context, appContext: AppContext) :
|
|
|
104
105
|
private val onLayoutContent by EventDispatcher<LayoutContentEvent>()
|
|
105
106
|
private var lastDispatchedContentSize: IntSize? = null
|
|
106
107
|
|
|
108
|
+
/**
|
|
109
|
+
* True while this view passes down an `ACTION_CANCEL` that came from its React Native parent,
|
|
110
|
+
* not from a Compose gesture detector. React Native already owns that gesture: the usual cause is
|
|
111
|
+
* the JS responder's view intercepting the stream, which cancels its native children.
|
|
112
|
+
*/
|
|
113
|
+
internal var isDispatchingCancelFromParent = false
|
|
114
|
+
private set
|
|
115
|
+
|
|
116
|
+
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
|
117
|
+
if (ev.actionMasked != MotionEvent.ACTION_CANCEL) {
|
|
118
|
+
return super.dispatchTouchEvent(ev)
|
|
119
|
+
}
|
|
120
|
+
isDispatchingCancelFromParent = true
|
|
121
|
+
try {
|
|
122
|
+
return super.dispatchTouchEvent(ev)
|
|
123
|
+
} finally {
|
|
124
|
+
isDispatchingCancelFromParent = false
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
107
128
|
@Composable
|
|
108
129
|
override fun ComposableScope.Content() {
|
|
109
130
|
val context = LocalContext.current
|
|
@@ -232,7 +253,13 @@ internal class HostView(context: Context, appContext: AppContext) :
|
|
|
232
253
|
shadowNodeProxy.setStyleSize(styleWidth?.toDouble(), styleHeight?.toDouble())
|
|
233
254
|
}
|
|
234
255
|
|
|
235
|
-
|
|
256
|
+
// `onSizeChanged` runs inside the Compose measure pass. Emitting the event here reaches
|
|
257
|
+
// Fabric event listeners synchronously (e.g. reanimated's `onEventDispatch` hook), which
|
|
258
|
+
// can flush mount items and re-enter `onMeasure` of a view that is mid-measure — Compose
|
|
259
|
+
// then throws "performMeasureAndLayout called during measure layout" and takes down the
|
|
260
|
+
// ReactHost. Post the dispatch so it runs after the measure pass completes.
|
|
261
|
+
// See https://github.com/expo/expo/issues/47625.
|
|
262
|
+
post { onLayoutContent(LayoutContentEvent(width.toDouble(), height.toDouble())) }
|
|
236
263
|
}
|
|
237
264
|
}
|
|
238
265
|
|
|
@@ -19,6 +19,7 @@ import androidx.compose.foundation.combinedClickable
|
|
|
19
19
|
import androidx.compose.foundation.horizontalScroll
|
|
20
20
|
import androidx.compose.foundation.rememberScrollState
|
|
21
21
|
import androidx.compose.foundation.verticalScroll
|
|
22
|
+
import androidx.compose.foundation.layout.IntrinsicSize
|
|
22
23
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
23
24
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
24
25
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@@ -73,6 +74,7 @@ import expo.modules.kotlin.AppContext
|
|
|
73
74
|
import expo.modules.kotlin.records.Field
|
|
74
75
|
import expo.modules.kotlin.records.Record
|
|
75
76
|
import expo.modules.kotlin.records.recordFromMap
|
|
77
|
+
import expo.modules.kotlin.types.Either
|
|
76
78
|
import expo.modules.kotlin.types.Enumerable
|
|
77
79
|
import expo.modules.kotlin.views.ComposableScope
|
|
78
80
|
import expo.modules.ui.convertibles.AlignmentType
|
|
@@ -127,6 +129,21 @@ internal data class WidthParams(
|
|
|
127
129
|
@Field val width: Int = 0
|
|
128
130
|
) : Record
|
|
129
131
|
|
|
132
|
+
internal enum class IntrinsicSizeType(val value: String) : Enumerable {
|
|
133
|
+
MIN("min"),
|
|
134
|
+
MAX("max");
|
|
135
|
+
|
|
136
|
+
fun toComposeIntrinsicSize(): IntrinsicSize = when (this) {
|
|
137
|
+
MIN -> IntrinsicSize.Min
|
|
138
|
+
MAX -> IntrinsicSize.Max
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@OptimizedRecord
|
|
143
|
+
internal data class ComposeWidthParams(
|
|
144
|
+
@Field val width: Either<Double, IntrinsicSizeType>? = null
|
|
145
|
+
) : Record
|
|
146
|
+
|
|
130
147
|
@OptimizedRecord
|
|
131
148
|
internal data class HeightParams(
|
|
132
149
|
@Field val height: Int = 0
|
|
@@ -453,8 +470,12 @@ object ModifierRegistry {
|
|
|
453
470
|
}
|
|
454
471
|
|
|
455
472
|
register("width") { map, _, _, _ ->
|
|
456
|
-
val
|
|
457
|
-
|
|
473
|
+
val width = recordFromMap<ComposeWidthParams>(map).width
|
|
474
|
+
if (width?.`is`(IntrinsicSizeType::class) == true) {
|
|
475
|
+
Modifier.width(width.second().toComposeIntrinsicSize())
|
|
476
|
+
} else {
|
|
477
|
+
Modifier.width((width?.first() ?: 0.0).dp)
|
|
478
|
+
}
|
|
458
479
|
}
|
|
459
480
|
|
|
460
481
|
register("height") { map, _, _, _ ->
|
|
@@ -8,15 +8,23 @@ import android.view.View
|
|
|
8
8
|
import android.view.ViewGroup
|
|
9
9
|
import android.view.ViewParent
|
|
10
10
|
import android.widget.FrameLayout
|
|
11
|
+
import androidx.compose.foundation.layout.fillMaxHeight
|
|
11
12
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
13
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
14
|
+
import androidx.compose.foundation.layout.requiredHeight
|
|
12
15
|
import androidx.compose.foundation.layout.requiredSize
|
|
16
|
+
import androidx.compose.foundation.layout.requiredWidth
|
|
17
|
+
import androidx.compose.foundation.layout.wrapContentHeight
|
|
18
|
+
import androidx.compose.foundation.layout.wrapContentWidth
|
|
13
19
|
import androidx.compose.runtime.Composable
|
|
14
20
|
import androidx.compose.runtime.MutableState
|
|
15
21
|
import androidx.compose.runtime.mutableStateOf
|
|
22
|
+
import androidx.compose.ui.Alignment
|
|
16
23
|
import androidx.compose.ui.Modifier
|
|
17
24
|
import androidx.compose.ui.layout.onGloballyPositioned
|
|
18
25
|
import androidx.compose.ui.layout.onSizeChanged
|
|
19
26
|
import androidx.compose.ui.layout.positionInRoot
|
|
27
|
+
import androidx.compose.ui.platform.AbstractComposeView
|
|
20
28
|
import androidx.compose.ui.platform.LocalDensity
|
|
21
29
|
import androidx.compose.ui.unit.IntSize
|
|
22
30
|
import androidx.compose.ui.viewinterop.AndroidView
|
|
@@ -40,7 +48,8 @@ import expo.modules.kotlin.views.OptimizedComposeProps
|
|
|
40
48
|
|
|
41
49
|
@OptimizedComposeProps
|
|
42
50
|
internal data class RNHostViewProps(
|
|
43
|
-
val
|
|
51
|
+
val matchContentsHorizontal: MutableState<Boolean?> = mutableStateOf(null),
|
|
52
|
+
val matchContentsVertical: MutableState<Boolean?> = mutableStateOf(null),
|
|
44
53
|
// Adds LeafNode and MeasurableYogaNode trait in Shadow node
|
|
45
54
|
val expoInternalSizeFromChildren: MutableState<Boolean?> = mutableStateOf(null),
|
|
46
55
|
val modifiers: ModifierList = emptyList()
|
|
@@ -144,22 +153,33 @@ internal class RNHostView(context: Context, appContext: AppContext) :
|
|
|
144
153
|
|
|
145
154
|
@Composable
|
|
146
155
|
override fun ComposableScope.Content() {
|
|
147
|
-
val
|
|
156
|
+
val matchContentsHorizontal = props.matchContentsHorizontal.value ?: false
|
|
157
|
+
val matchContentsVertical = props.matchContentsVertical.value ?: false
|
|
148
158
|
val scope: ComposableScope = this
|
|
149
159
|
|
|
150
160
|
wrapperState.value?.let { wrapper ->
|
|
151
161
|
childViewState.value ?: return@let
|
|
152
|
-
val sizingModifier =
|
|
153
|
-
applySizeFromYogaNodeModifier()
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
val sizingModifier = when {
|
|
163
|
+
matchContentsHorizontal && matchContentsVertical -> applySizeFromYogaNodeModifier()
|
|
164
|
+
matchContentsVertical ->
|
|
165
|
+
Modifier
|
|
166
|
+
.fillMaxWidth()
|
|
167
|
+
.then(reportSizeToYogaNodeModifier(reportHeight = false))
|
|
168
|
+
.then(applyHeightFromYogaNodeModifier())
|
|
169
|
+
matchContentsHorizontal ->
|
|
170
|
+
Modifier
|
|
171
|
+
.fillMaxHeight()
|
|
172
|
+
.then(reportSizeToYogaNodeModifier(reportWidth = false))
|
|
173
|
+
.then(applyWidthFromYogaNodeModifier())
|
|
174
|
+
else ->
|
|
175
|
+
Modifier
|
|
176
|
+
.fillMaxSize()
|
|
177
|
+
.then(reportSizeToYogaNodeModifier())
|
|
158
178
|
}
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
val modifiers =
|
|
162
|
-
.then(
|
|
179
|
+
// A chain applies outside-in. Caller modifiers go first so a `padding` or `border` shrinks the
|
|
180
|
+
// box before its size is reported and its origin is read.
|
|
181
|
+
val modifiers = ModifierRegistry.applyModifiers(props.modifiers, appContext, scope, globalEventDispatcher)
|
|
182
|
+
.then(sizingModifier)
|
|
163
183
|
.then(publishContentOriginModifier())
|
|
164
184
|
|
|
165
185
|
AndroidView(
|
|
@@ -190,6 +210,28 @@ internal class RNHostView(context: Context, appContext: AppContext) :
|
|
|
190
210
|
}
|
|
191
211
|
}
|
|
192
212
|
|
|
213
|
+
@Composable
|
|
214
|
+
private fun applyHeightFromYogaNodeModifier(): Modifier {
|
|
215
|
+
val height = childSizeState.value.height
|
|
216
|
+
if (height <= 0) {
|
|
217
|
+
return Modifier
|
|
218
|
+
}
|
|
219
|
+
return Modifier
|
|
220
|
+
.wrapContentHeight(Alignment.Top, unbounded = true)
|
|
221
|
+
.requiredHeight(with(LocalDensity.current) { height.toDp() })
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@Composable
|
|
225
|
+
private fun applyWidthFromYogaNodeModifier(): Modifier {
|
|
226
|
+
val width = childSizeState.value.width
|
|
227
|
+
if (width <= 0) {
|
|
228
|
+
return Modifier
|
|
229
|
+
}
|
|
230
|
+
return Modifier
|
|
231
|
+
.wrapContentWidth(Alignment.CenterHorizontally, unbounded = true)
|
|
232
|
+
.requiredWidth(with(LocalDensity.current) { width.toDp() })
|
|
233
|
+
}
|
|
234
|
+
|
|
193
235
|
/**
|
|
194
236
|
* Publishes where Compose placed this view inside its `Host`, which Yoga has no way to know:
|
|
195
237
|
* Yoga puts the box at the `Host`'s origin while Compose may draw it anywhere inside. Without
|
|
@@ -219,13 +261,21 @@ internal class RNHostView(context: Context, appContext: AppContext) :
|
|
|
219
261
|
// Sets Yoga node size from Compose view size
|
|
220
262
|
// Listens Compose view size changes and updates the Yoga node size
|
|
221
263
|
@Composable
|
|
222
|
-
private fun reportSizeToYogaNodeModifier(): Modifier {
|
|
264
|
+
private fun reportSizeToYogaNodeModifier(reportWidth: Boolean = true, reportHeight: Boolean = true): Modifier {
|
|
223
265
|
val density = LocalDensity.current
|
|
224
266
|
return Modifier.onSizeChanged { size ->
|
|
225
267
|
with(density) {
|
|
226
268
|
shadowNodeProxy.setViewSize(
|
|
227
|
-
|
|
228
|
-
|
|
269
|
+
if (reportWidth) {
|
|
270
|
+
size.width.toDp().value.toDouble()
|
|
271
|
+
} else {
|
|
272
|
+
Double.NaN
|
|
273
|
+
},
|
|
274
|
+
if (reportHeight) {
|
|
275
|
+
size.height.toDp().value.toDouble()
|
|
276
|
+
} else {
|
|
277
|
+
Double.NaN
|
|
278
|
+
}
|
|
229
279
|
)
|
|
230
280
|
}
|
|
231
281
|
}
|
|
@@ -247,6 +297,28 @@ internal fun detachForReuse(wrapper: View) {
|
|
|
247
297
|
wrapper.layout(0, 0, 0, 0)
|
|
248
298
|
}
|
|
249
299
|
|
|
300
|
+
/**
|
|
301
|
+
* React Native looks for touch targets from the last child to the first, and Compose appends helper
|
|
302
|
+
* views such as ripple containers to its owner view after the hosted views. Those helpers have no
|
|
303
|
+
* React tag, so a touch on them goes to the `Host` instead of the hosted view.
|
|
304
|
+
* This is a workaround: React Native has no way to let the `Host` choose the touch target.
|
|
305
|
+
* This causes https://github.com/expo/expo/issues/51159
|
|
306
|
+
*/
|
|
307
|
+
internal fun keepLastForTouchTargeting(composeOwnerView: ViewGroup, hostedViewsContainer: View) {
|
|
308
|
+
if (composeOwnerView.indexOfChild(hostedViewsContainer) != composeOwnerView.childCount - 1) {
|
|
309
|
+
composeOwnerView.bringChildToFront(hostedViewsContainer)
|
|
310
|
+
}
|
|
311
|
+
composeOwnerView.setOnHierarchyChangeListener(object : ViewGroup.OnHierarchyChangeListener {
|
|
312
|
+
override fun onChildViewAdded(parent: View, child: View) {
|
|
313
|
+
if (child !== hostedViewsContainer) {
|
|
314
|
+
composeOwnerView.bringChildToFront(hostedViewsContainer)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
override fun onChildViewRemoved(parent: View, child: View) = Unit
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
|
|
250
322
|
/**
|
|
251
323
|
* A thin FrameLayout that intercepts touch events and dispatches them to JS via
|
|
252
324
|
* JSTouchDispatcher/JSPointerDispatcher, replicating the pattern from React Native's
|
|
@@ -304,7 +376,8 @@ private class TouchDispatchingRootViewGroup(
|
|
|
304
376
|
|
|
305
377
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
306
378
|
// Always gets called with EXACTLY mode
|
|
307
|
-
// because parent has
|
|
379
|
+
// because parent has fillMaxSize (matchContents = false), requiredSize (matchContents = true), or a
|
|
380
|
+
// fillMax* + required* pair (one matched axis) modifiers
|
|
308
381
|
setMeasuredDimension(
|
|
309
382
|
MeasureSpec.getSize(widthMeasureSpec),
|
|
310
383
|
MeasureSpec.getSize(heightMeasureSpec)
|
|
@@ -316,8 +389,25 @@ private class TouchDispatchingRootViewGroup(
|
|
|
316
389
|
// and we must not override those values.
|
|
317
390
|
}
|
|
318
391
|
|
|
392
|
+
override fun onAttachedToWindow() {
|
|
393
|
+
super.onAttachedToWindow()
|
|
394
|
+
// Walk up until the parent is the ComposeView. That ancestor is the Compose owner view, and the
|
|
395
|
+
// child we came from is the container that Compose keeps all hosted views in.
|
|
396
|
+
var hostedViewsContainer: View = this
|
|
397
|
+
var composeOwnerView = parent as? ViewGroup
|
|
398
|
+
while (composeOwnerView != null && composeOwnerView.parent !is AbstractComposeView) {
|
|
399
|
+
hostedViewsContainer = composeOwnerView
|
|
400
|
+
composeOwnerView = composeOwnerView.parent as? ViewGroup
|
|
401
|
+
}
|
|
402
|
+
composeOwnerView?.let { keepLastForTouchTargeting(it, hostedViewsContainer) }
|
|
403
|
+
}
|
|
404
|
+
|
|
319
405
|
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
|
320
|
-
if (
|
|
406
|
+
if (
|
|
407
|
+
ev.actionMasked == MotionEvent.ACTION_CANCEL &&
|
|
408
|
+
!dispatchesTouchesToJS &&
|
|
409
|
+
!isCancelFromReactNative()
|
|
410
|
+
) {
|
|
321
411
|
// Compose cancels this subtree when a gesture detector above it claims the gesture. The
|
|
322
412
|
// ancestor root, which dispatches this subtree's touches, keeps streaming moves, so a
|
|
323
413
|
// `Pressable` still fires on release. Tell it a native child took over.
|
|
@@ -371,6 +461,23 @@ private class TouchDispatchingRootViewGroup(
|
|
|
371
461
|
return handled
|
|
372
462
|
}
|
|
373
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Whether this cancel reached the `Host` from React Native rather than from Compose. The JS
|
|
466
|
+
* responder's view intercepts the stream once it's granted, which cancels its native children,
|
|
467
|
+
* including the `Host` of a `MaskedView` laid over a `Pressable`. JS still owns that gesture, so
|
|
468
|
+
* reporting it as a native one would cancel the press it belongs to.
|
|
469
|
+
*/
|
|
470
|
+
private fun isCancelFromReactNative(): Boolean {
|
|
471
|
+
var current: ViewParent? = parent
|
|
472
|
+
while (current != null) {
|
|
473
|
+
if (current is HostView) {
|
|
474
|
+
return current.isDispatchingCancelFromParent
|
|
475
|
+
}
|
|
476
|
+
current = current.parent
|
|
477
|
+
}
|
|
478
|
+
return false
|
|
479
|
+
}
|
|
480
|
+
|
|
374
481
|
private inline fun notifyAncestorRootViews(block: (RootView) -> Unit) {
|
|
375
482
|
var current: ViewParent? = parent
|
|
376
483
|
while (current != null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.ios.d.ts","sourceRoot":"","sources":["../../../src/community/bottom-sheet/BottomSheet.ios.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAepE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAwD3C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"BottomSheet.ios.d.ts","sourceRoot":"","sources":["../../../src/community/bottom-sheet/BottomSheet.ios.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAepE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAwD3C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CA6KlD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimePicker.android.d.ts","sourceRoot":"","sources":["../../../src/community/datetime-picker/DateTimePicker.android.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"DateTimePicker.android.d.ts","sourceRoot":"","sources":["../../../src/community/datetime-picker/DateTimePicker.android.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAoCjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAuGxD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the ISO string of the UTC midnight of `value`'s local calendar day, so Material3 shows
|
|
3
|
+
* the same day the user sees locally.
|
|
4
|
+
*/
|
|
5
|
+
export declare function localDateToUtcDayISOString(value: Date): string;
|
|
6
|
+
/**
|
|
7
|
+
* Converts the UTC-midnight day reported by Material3 back into a local date, keeping the time of
|
|
8
|
+
* day from `timeOfDay`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function utcDayToLocalDate(utcDay: Date, timeOfDay: Date): Date;
|
|
11
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/community/datetime-picker/utils.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,CAIrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Picker.android.d.ts","sourceRoot":"","sources":["../../../src/community/picker/Picker.android.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,SAAS,CAAC;AAYjB;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"Picker.android.d.ts","sourceRoot":"","sources":["../../../src/community/picker/Picker.android.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,SAAS,CAAC;AAYjB;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,2CAmDtE;yBAnDe,MAAM"}
|
|
@@ -122,6 +122,20 @@ export interface DateTimePickerProps {
|
|
|
122
122
|
* @default true
|
|
123
123
|
*/
|
|
124
124
|
showVariantToggle?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
127
|
+
* `null` to Material 3's `title` slot. This prop has no effect when `displayedComponents` is
|
|
128
|
+
* `'hourAndMinute'`.
|
|
129
|
+
* @default true
|
|
130
|
+
*/
|
|
131
|
+
showTitle?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
134
|
+
* the picker passes `null` to Material 3's `headline` slot. This prop has no effect when
|
|
135
|
+
* `displayedComponents` is `'hourAndMinute'`.
|
|
136
|
+
* @default true
|
|
137
|
+
*/
|
|
138
|
+
showHeadline?: boolean;
|
|
125
139
|
/**
|
|
126
140
|
* The components that the picker should display.
|
|
127
141
|
* On Android, you can have a picker that selects just the date or just the time.
|
|
@@ -191,6 +205,18 @@ export interface DateRangePickerProps {
|
|
|
191
205
|
* @default true
|
|
192
206
|
*/
|
|
193
207
|
showVariantToggle?: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
210
|
+
* `null` to Material 3's `title` slot.
|
|
211
|
+
* @default true
|
|
212
|
+
*/
|
|
213
|
+
showTitle?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
216
|
+
* the picker passes `null` to Material 3's `headline` slot.
|
|
217
|
+
* @default true
|
|
218
|
+
*/
|
|
219
|
+
showHeadline?: boolean;
|
|
194
220
|
/**
|
|
195
221
|
* The tint color to use on the picker elements.
|
|
196
222
|
*/
|
|
@@ -224,6 +250,18 @@ export interface DatePickerDialogProps {
|
|
|
224
250
|
initialDate?: string | null;
|
|
225
251
|
variant?: AndroidVariant;
|
|
226
252
|
showVariantToggle?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
255
|
+
* `null` to Material 3's `title` slot.
|
|
256
|
+
* @default true
|
|
257
|
+
*/
|
|
258
|
+
showTitle?: boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
261
|
+
* the picker passes `null` to Material 3's `headline` slot.
|
|
262
|
+
* @default true
|
|
263
|
+
*/
|
|
264
|
+
showHeadline?: boolean;
|
|
227
265
|
confirmButtonLabel?: string;
|
|
228
266
|
dismissButtonLabel?: string;
|
|
229
267
|
color?: ColorValue;
|