@expo/ui 58.0.14 → 58.0.16
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 +24 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ui/DatePickerView.kt +35 -2
- package/android/src/main/java/expo/modules/ui/DateRangePickerView.kt +35 -2
- package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +3 -0
- package/android/src/main/java/expo/modules/ui/HostView.kt +21 -0
- package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +2 -2
- package/android/src/main/java/expo/modules/ui/RNHostView.kt +117 -1
- package/android/src/main/java/expo/modules/ui/menu/DropdownMenu.kt +8 -1
- package/android/src/main/java/expo/modules/ui/menu/DropdownMenuRecords.kt +13 -1
- package/build/NativeTreeContext.d.ts +10 -0
- package/build/NativeTreeContext.js +25 -0
- package/build/NativeTreeContext.js.map +1 -0
- package/build/State/useWorkletCallback.d.ts +1 -1
- package/build/community/bottom-sheet/BottomSheet.ios.js +11 -4
- package/build/community/bottom-sheet/BottomSheet.ios.js.map +1 -1
- package/build/community/datetime-picker/DateTimePicker.android.js +4 -0
- package/build/community/datetime-picker/DateTimePicker.android.js.map +1 -1
- package/build/community/menu/MenuView.android.js +6 -0
- package/build/community/menu/MenuView.android.js.map +1 -1
- package/build/jetpack-compose/DatePicker/index.d.ts +38 -0
- package/build/jetpack-compose/DatePicker/index.js.map +1 -1
- package/build/jetpack-compose/DropdownMenu/index.d.ts +8 -1
- package/build/jetpack-compose/DropdownMenu/index.js.map +1 -1
- package/build/jetpack-compose/Host/index.js +8 -2
- package/build/jetpack-compose/Host/index.js.map +1 -1
- package/build/jetpack-compose/RNHostView/index.js +5 -1
- package/build/jetpack-compose/RNHostView/index.js.map +1 -1
- package/build/swift-ui/Chart/index.d.ts +10 -0
- package/build/swift-ui/Chart/index.js.map +1 -1
- package/build/swift-ui/Host/index.js +8 -2
- package/build/swift-ui/Host/index.js.map +1 -1
- package/build/swift-ui/RNHostView.js +5 -1
- package/build/swift-ui/RNHostView.js.map +1 -1
- package/build/swift-ui/Toolbar/index.d.ts +2 -0
- package/build/swift-ui/Toolbar/index.js +2 -0
- package/build/swift-ui/Toolbar/index.js.map +1 -1
- package/build/swift-ui/modifiers/hingeObservation.d.ts +1 -1
- package/build/swift-ui/modifiers/hingeObservation.js +1 -1
- package/build/swift-ui/modifiers/index.d.ts +1 -0
- package/build/swift-ui/modifiers/index.js +1 -0
- package/build/swift-ui/modifiers/index.js.map +1 -1
- package/build/swift-ui/modifiers/presentationModifiers.d.ts +17 -1
- package/build/swift-ui/modifiers/presentationModifiers.js +4 -2
- package/build/swift-ui/modifiers/presentationModifiers.js.map +1 -1
- package/build/swift-ui/modifiers/searchable.d.ts +83 -0
- package/build/swift-ui/modifiers/searchable.js +74 -0
- package/build/swift-ui/modifiers/searchable.js.map +1 -0
- package/build/types.d.ts +27 -0
- package/build/types.js +1 -1
- package/build/types.js.map +1 -1
- package/build/universal/BottomSheet/index.android.js +26 -18
- package/build/universal/BottomSheet/index.android.js.map +1 -1
- package/build/universal/BottomSheet/index.ios.js +20 -12
- package/build/universal/BottomSheet/index.ios.js.map +1 -1
- package/ios/ChartView.swift +15 -10
- package/ios/DataListForEachView.swift +1 -0
- package/ios/GridView.swift +1 -0
- package/ios/HostView.swift +27 -4
- package/ios/Modifiers/PresentationModifiers.swift +20 -4
- package/ios/Modifiers/SearchToolbarBehaviorModifier.swift +35 -0
- package/ios/Modifiers/SearchableModifier.swift +94 -0
- package/ios/Modifiers/ViewModifierRegistry.swift +8 -0
- package/ios/NamespaceView.swift +1 -0
- package/ios/Picker/PickerView.swift +9 -7
- package/ios/RNHostView.swift +19 -4
- package/ios/SlotView.swift +1 -0
- package/ios/TabView/TabView.swift +2 -0
- package/ios/ToolbarView.swift +2 -1
- package/ios/UIBaseView.swift +13 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14-sources.jar → 58.0.16/expo.modules.ui-58.0.16-sources.jar} +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16-sources.jar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14.module → 58.0.16/expo.modules.ui-58.0.16.module} +22 -22
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.14/expo.modules.ui-58.0.14.pom → 58.0.16/expo.modules.ui-58.0.16.pom} +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha512 +1 -0
- package/package.json +2 -2
- package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
- package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
- package/src/NativeTreeContext.tsx +31 -0
- package/src/State/useWorkletCallback.ts +1 -1
- package/src/community/bottom-sheet/BottomSheet.ios.tsx +7 -6
- package/src/community/datetime-picker/DateTimePicker.android.tsx +4 -0
- package/src/community/menu/MenuView.android.tsx +12 -2
- package/src/jetpack-compose/DatePicker/index.tsx +38 -0
- package/src/jetpack-compose/DropdownMenu/index.tsx +12 -1
- package/src/jetpack-compose/Host/index.tsx +6 -2
- package/src/jetpack-compose/RNHostView/index.tsx +3 -1
- package/src/swift-ui/Chart/index.tsx +10 -0
- package/src/swift-ui/Host/index.tsx +6 -2
- package/src/swift-ui/RNHostView.tsx +3 -1
- package/src/swift-ui/Toolbar/index.tsx +2 -0
- package/src/swift-ui/modifiers/hingeObservation.ts +1 -1
- package/src/swift-ui/modifiers/index.ts +1 -0
- package/src/swift-ui/modifiers/presentationModifiers.ts +18 -2
- package/src/swift-ui/modifiers/searchable.ts +107 -0
- package/src/types.ts +28 -0
- package/src/universal/BottomSheet/index.android.tsx +23 -12
- package/src/universal/BottomSheet/index.ios.tsx +20 -9
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14-sources.jar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.aar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.module.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.14/expo.modules.ui-58.0.14.pom.sha512 +0 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Copyright 2026-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
internal enum SearchFieldPlacementType: String, Enumerable {
|
|
7
|
+
case automatic
|
|
8
|
+
case toolbar
|
|
9
|
+
case sidebar
|
|
10
|
+
case navigationBarDrawer
|
|
11
|
+
|
|
12
|
+
var toSearchFieldPlacement: SearchFieldPlacement {
|
|
13
|
+
switch self {
|
|
14
|
+
case .automatic:
|
|
15
|
+
return .automatic
|
|
16
|
+
case .toolbar:
|
|
17
|
+
#if os(tvOS)
|
|
18
|
+
return .automatic
|
|
19
|
+
#else
|
|
20
|
+
return .toolbar
|
|
21
|
+
#endif
|
|
22
|
+
case .sidebar:
|
|
23
|
+
#if os(tvOS)
|
|
24
|
+
return .automatic
|
|
25
|
+
#else
|
|
26
|
+
return .sidebar
|
|
27
|
+
#endif
|
|
28
|
+
case .navigationBarDrawer:
|
|
29
|
+
#if os(iOS)
|
|
30
|
+
return .navigationBarDrawer
|
|
31
|
+
#else
|
|
32
|
+
return .automatic
|
|
33
|
+
#endif
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
internal struct SearchableModifier: ViewModifier, Record {
|
|
39
|
+
@Field var text: ObservableState?
|
|
40
|
+
@Field var placement: SearchFieldPlacementType = .automatic
|
|
41
|
+
@Field var prompt: String?
|
|
42
|
+
var eventDispatcher: EventDispatcher?
|
|
43
|
+
|
|
44
|
+
init() {}
|
|
45
|
+
|
|
46
|
+
init(from params: Dict, appContext: AppContext, eventDispatcher: EventDispatcher) throws {
|
|
47
|
+
try self = .init(from: params, appContext: appContext)
|
|
48
|
+
self.eventDispatcher = eventDispatcher
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ViewBuilder
|
|
52
|
+
func body(content: Content) -> some View {
|
|
53
|
+
if let text {
|
|
54
|
+
SearchableWrapper(
|
|
55
|
+
state: text,
|
|
56
|
+
placement: placement,
|
|
57
|
+
prompt: prompt,
|
|
58
|
+
eventDispatcher: eventDispatcher
|
|
59
|
+
) {
|
|
60
|
+
content
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
content
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private struct SearchableWrapper<C: View>: View {
|
|
69
|
+
@ObservedObject var state: ObservableState
|
|
70
|
+
let placement: SearchFieldPlacementType
|
|
71
|
+
let prompt: String?
|
|
72
|
+
let eventDispatcher: EventDispatcher?
|
|
73
|
+
@ViewBuilder let content: () -> C
|
|
74
|
+
|
|
75
|
+
var body: some View {
|
|
76
|
+
// The search field writes through the binding. Only report edits that come from the field,
|
|
77
|
+
// so a value written from JavaScript does not bounce back as an event.
|
|
78
|
+
let query = Binding<String>(
|
|
79
|
+
get: { state.value as? String ?? "" },
|
|
80
|
+
set: { newValue in
|
|
81
|
+
guard newValue != state.value as? String else {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
state.value = newValue
|
|
85
|
+
eventDispatcher?(["searchable": ["text": newValue]])
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
if let prompt {
|
|
89
|
+
content().searchable(text: query, placement: placement.toSearchFieldPlacement, prompt: prompt)
|
|
90
|
+
} else {
|
|
91
|
+
content().searchable(text: query, placement: placement.toSearchFieldPlacement)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -2380,6 +2380,14 @@ extension ViewModifierRegistry {
|
|
|
2380
2380
|
return try ScrollPositionModifier(from: params, appContext: appContext, eventDispatcher: eventDispatcher)
|
|
2381
2381
|
}
|
|
2382
2382
|
|
|
2383
|
+
register("searchable") { params, appContext, eventDispatcher in
|
|
2384
|
+
return try SearchableModifier(from: params, appContext: appContext, eventDispatcher: eventDispatcher)
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
register("searchToolbarBehavior") { params, appContext, _ in
|
|
2388
|
+
return try SearchToolbarBehaviorModifier(from: params, appContext: appContext)
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2383
2391
|
register("pickerStyle") { params, appContext, _ in
|
|
2384
2392
|
return try PickerStyleModifier(from: params, appContext: appContext)
|
|
2385
2393
|
}
|
package/ios/NamespaceView.swift
CHANGED
|
@@ -21,6 +21,7 @@ internal struct NamespaceView: ExpoSwiftUI.View {
|
|
|
21
21
|
NamespaceRegistry.shared.registerNamespace(namespace, forKey: props.id)
|
|
22
22
|
|
|
23
23
|
return Children()
|
|
24
|
+
.publishZeroContentOrigin(props.shadowNodeProxy)
|
|
24
25
|
.onDisappear {
|
|
25
26
|
NamespaceRegistry.shared.unregisterNamespace(forKey: props.id)
|
|
26
27
|
}
|
|
@@ -12,6 +12,7 @@ internal final class PickerProps: UIBaseViewProps {
|
|
|
12
12
|
|
|
13
13
|
internal struct PickerView: ExpoSwiftUI.View {
|
|
14
14
|
@State var selection: AnyHashable?
|
|
15
|
+
@State private var previousSelection: AnyHashable?
|
|
15
16
|
@ObservedObject var props: PickerProps
|
|
16
17
|
|
|
17
18
|
init(props: PickerProps) {
|
|
@@ -38,11 +39,8 @@ internal struct PickerView: ExpoSwiftUI.View {
|
|
|
38
39
|
|
|
39
40
|
picker
|
|
40
41
|
.onChange(of: selection) { newValue in
|
|
41
|
-
guard let newValue else { return }
|
|
42
|
-
|
|
43
|
-
if currentSelection == newValue {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
42
|
+
guard let newValue, newValue != previousSelection else { return }
|
|
43
|
+
previousSelection = newValue
|
|
46
44
|
let payload: [String: Any]
|
|
47
45
|
if let stringValue = newValue as? String {
|
|
48
46
|
payload = ["selection": stringValue]
|
|
@@ -54,10 +52,14 @@ internal struct PickerView: ExpoSwiftUI.View {
|
|
|
54
52
|
props.onSelectionChange(payload)
|
|
55
53
|
}
|
|
56
54
|
.onChange(of: props.selection) { newValue in
|
|
57
|
-
|
|
55
|
+
let newSelection = Self.getHashableFromEither(newValue)
|
|
56
|
+
previousSelection = newSelection
|
|
57
|
+
selection = newSelection
|
|
58
58
|
}
|
|
59
59
|
.onAppear {
|
|
60
|
-
|
|
60
|
+
let initialSelection = Self.getHashableFromEither(props.selection)
|
|
61
|
+
previousSelection = initialSelection
|
|
62
|
+
selection = initialSelection
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
|
package/ios/RNHostView.swift
CHANGED
|
@@ -107,14 +107,17 @@ struct RNHostView: ExpoSwiftUI.View {
|
|
|
107
107
|
private struct PublishContentOriginModifier: ViewModifier {
|
|
108
108
|
let shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
|
|
109
109
|
let isEnabled: Bool
|
|
110
|
+
@Environment(\.expoHostingView) private var hostingView
|
|
110
111
|
|
|
111
112
|
func body(content: Content) -> some View {
|
|
112
113
|
if isEnabled {
|
|
113
114
|
content
|
|
114
|
-
.onGeometryChange(for:
|
|
115
|
-
proxy
|
|
116
|
-
} action: {
|
|
117
|
-
|
|
115
|
+
.onGeometryChange(for: CGPoint?.self) { proxy in
|
|
116
|
+
originInHost(proxy)
|
|
117
|
+
} action: { origin in
|
|
118
|
+
if let origin {
|
|
119
|
+
shadowNodeProxy.setContentOrigin?(origin)
|
|
120
|
+
}
|
|
118
121
|
}
|
|
119
122
|
.onDisappear {
|
|
120
123
|
shadowNodeProxy.clearContentOrigin?()
|
|
@@ -123,6 +126,18 @@ private struct PublishContentOriginModifier: ViewModifier {
|
|
|
123
126
|
content
|
|
124
127
|
}
|
|
125
128
|
}
|
|
129
|
+
|
|
130
|
+
// Relative to the `Host`'s UIKit view, which Yoga laid out, so a safe-area inset is included.
|
|
131
|
+
private func originInHost(_ proxy: GeometryProxy) -> CGPoint? {
|
|
132
|
+
#if os(macOS)
|
|
133
|
+
return proxy.frame(in: .named(expoHostCoordinateSpace)).origin
|
|
134
|
+
#else
|
|
135
|
+
guard let hostView = hostingView?.view, let window = hostView.window else {
|
|
136
|
+
return nil
|
|
137
|
+
}
|
|
138
|
+
return hostView.convert(proxy.frame(in: .global).origin, from: window)
|
|
139
|
+
#endif
|
|
140
|
+
}
|
|
126
141
|
}
|
|
127
142
|
|
|
128
143
|
// Tracks the `RCTSurfaceTouchHandler` attached to a hosted RN view so it can be detached when the
|
package/ios/SlotView.swift
CHANGED
|
@@ -56,7 +56,9 @@ internal struct TabView: ExpoSwiftUI.View {
|
|
|
56
56
|
systemImage: tab.props.systemImage ?? "",
|
|
57
57
|
value: tab.props.value
|
|
58
58
|
) {
|
|
59
|
+
// The tab's own body does not run here, so publish its zero content origin on its content.
|
|
59
60
|
Self.tabContent(for: tab.props.children ?? [])
|
|
61
|
+
.publishZeroContentOrigin(tab.props.shadowNodeProxy)
|
|
60
62
|
}
|
|
61
63
|
#if !os(tvOS)
|
|
62
64
|
.badge(Self.badgeText(from: tab.props.modifiers))
|
package/ios/ToolbarView.swift
CHANGED
|
@@ -15,7 +15,8 @@ private struct ToolbarContentView: View {
|
|
|
15
15
|
let children = props.children ?? []
|
|
16
16
|
|
|
17
17
|
if children.contains(where: isItem) {
|
|
18
|
-
|
|
18
|
+
// The content slot's own body does not run here, so publish its zero content origin on the base.
|
|
19
|
+
children.reduce(AnyView(base.publishZeroContentOrigin(props.shadowNodeProxy))) { view, child in
|
|
19
20
|
let childView: any View = child.childView
|
|
20
21
|
|
|
21
22
|
guard let slot = child.childView as? SlotView, slot.props.name == "item" else {
|
package/ios/UIBaseView.swift
CHANGED
|
@@ -19,6 +19,19 @@ public struct UIBaseView<Props: UIBaseViewProps, Content: ExpoSwiftUI.View<Props
|
|
|
19
19
|
innerView
|
|
20
20
|
.applyAccessibilityIdentifier(props.testID)
|
|
21
21
|
.applyModifiers(props.modifiers, appContext: props.appContext, globalEventDispatcher: props.globalEventDispatcher)
|
|
22
|
+
.publishZeroContentOrigin(props.shadowNodeProxy)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
extension View {
|
|
27
|
+
/**
|
|
28
|
+
SwiftUI places this view, so `measure()` must skip its Yoga origin. A zero content origin does that,
|
|
29
|
+
and `RNHostView` reports its own position inside the `Host`. Core clears the entry on teardown.
|
|
30
|
+
*/
|
|
31
|
+
func publishZeroContentOrigin(_ shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy) -> some View {
|
|
32
|
+
onAppear {
|
|
33
|
+
shadowNodeProxy.setContentOrigin?(.zero)
|
|
34
|
+
}
|
|
22
35
|
}
|
|
23
36
|
}
|
|
24
37
|
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6b0b0d2a72178b6d25a038ee47271abb
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aef15fcbe60dff9cbb6491595df9269d819f7065
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
101a40d45fc8e73887c9518fbc88c31e2a700ca6e62d2cc96dd65f72459a9d69
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
79141ef63c1b975a30858d8c1ca7bccde8d14a64d337883063b3c1cbe44f977cc40e0fda89d3076fd84b5e47308e86b3659c71744a4fc3cac2b858a0686f38c6
|
|
Binary file
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.md5
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
812db5879217f7bbe3b44b5ffcb0725a
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha1
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
64369f3b1f16363a28412ac36309b53dc2a29752
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha256
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b8e480f4d8449359c2f5686c3614c9aa82ef98af9b7ce0edd4d839d14de7696f
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.aar.sha512
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9e42c8a718971e6d77015353c6747570385fe0c1d901cf388a50509e00c9ee8581a81ba88d0e83a611b7ec5a6d1dff4280ecf81ed92776d2cf7c26f48c0048c5
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"component": {
|
|
4
4
|
"group": "expo.modules.ui",
|
|
5
5
|
"module": "expo.modules.ui",
|
|
6
|
-
"version": "58.0.
|
|
6
|
+
"version": "58.0.16",
|
|
7
7
|
"attributes": {
|
|
8
8
|
"org.gradle.status": "release"
|
|
9
9
|
}
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
{
|
|
27
|
-
"name": "expo.modules.ui-58.0.
|
|
28
|
-
"url": "expo.modules.ui-58.0.
|
|
29
|
-
"size":
|
|
30
|
-
"sha512": "
|
|
31
|
-
"sha256": "
|
|
32
|
-
"sha1": "
|
|
33
|
-
"md5": "
|
|
27
|
+
"name": "expo.modules.ui-58.0.16.aar",
|
|
28
|
+
"url": "expo.modules.ui-58.0.16.aar",
|
|
29
|
+
"size": 1858313,
|
|
30
|
+
"sha512": "9e42c8a718971e6d77015353c6747570385fe0c1d901cf388a50509e00c9ee8581a81ba88d0e83a611b7ec5a6d1dff4280ecf81ed92776d2cf7c26f48c0048c5",
|
|
31
|
+
"sha256": "b8e480f4d8449359c2f5686c3614c9aa82ef98af9b7ce0edd4d839d14de7696f",
|
|
32
|
+
"sha1": "64369f3b1f16363a28412ac36309b53dc2a29752",
|
|
33
|
+
"md5": "812db5879217f7bbe3b44b5ffcb0725a"
|
|
34
34
|
}
|
|
35
35
|
]
|
|
36
36
|
},
|
|
@@ -141,13 +141,13 @@
|
|
|
141
141
|
],
|
|
142
142
|
"files": [
|
|
143
143
|
{
|
|
144
|
-
"name": "expo.modules.ui-58.0.
|
|
145
|
-
"url": "expo.modules.ui-58.0.
|
|
146
|
-
"size":
|
|
147
|
-
"sha512": "
|
|
148
|
-
"sha256": "
|
|
149
|
-
"sha1": "
|
|
150
|
-
"md5": "
|
|
144
|
+
"name": "expo.modules.ui-58.0.16.aar",
|
|
145
|
+
"url": "expo.modules.ui-58.0.16.aar",
|
|
146
|
+
"size": 1858313,
|
|
147
|
+
"sha512": "9e42c8a718971e6d77015353c6747570385fe0c1d901cf388a50509e00c9ee8581a81ba88d0e83a611b7ec5a6d1dff4280ecf81ed92776d2cf7c26f48c0048c5",
|
|
148
|
+
"sha256": "b8e480f4d8449359c2f5686c3614c9aa82ef98af9b7ce0edd4d839d14de7696f",
|
|
149
|
+
"sha1": "64369f3b1f16363a28412ac36309b53dc2a29752",
|
|
150
|
+
"md5": "812db5879217f7bbe3b44b5ffcb0725a"
|
|
151
151
|
}
|
|
152
152
|
]
|
|
153
153
|
},
|
|
@@ -161,13 +161,13 @@
|
|
|
161
161
|
},
|
|
162
162
|
"files": [
|
|
163
163
|
{
|
|
164
|
-
"name": "expo.modules.ui-58.0.
|
|
165
|
-
"url": "expo.modules.ui-58.0.
|
|
166
|
-
"size":
|
|
167
|
-
"sha512": "
|
|
168
|
-
"sha256": "
|
|
169
|
-
"sha1": "
|
|
170
|
-
"md5": "
|
|
164
|
+
"name": "expo.modules.ui-58.0.16-sources.jar",
|
|
165
|
+
"url": "expo.modules.ui-58.0.16-sources.jar",
|
|
166
|
+
"size": 112962,
|
|
167
|
+
"sha512": "79141ef63c1b975a30858d8c1ca7bccde8d14a64d337883063b3c1cbe44f977cc40e0fda89d3076fd84b5e47308e86b3659c71744a4fc3cac2b858a0686f38c6",
|
|
168
|
+
"sha256": "101a40d45fc8e73887c9518fbc88c31e2a700ca6e62d2cc96dd65f72459a9d69",
|
|
169
|
+
"sha1": "aef15fcbe60dff9cbb6491595df9269d819f7065",
|
|
170
|
+
"md5": "6b0b0d2a72178b6d25a038ee47271abb"
|
|
171
171
|
}
|
|
172
172
|
]
|
|
173
173
|
}
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.md5
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d130a88c3e9ea609bae6f4e886ab244d
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.module.sha1
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
81f23fddc089c0a466c08356e6c33881fd08d65c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d57d5ce3086debe5c6c7760679de69409aa264c6871d034bac2140af6245f9f4
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
44da04bba32c6fbb281c187d7382eabf9cf3cf674dc9f469335345dfe7268e2818a725531749822cd788eb96ce8c56ecb3535f30c757da77fb67630c050de4f3
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<modelVersion>4.0.0</modelVersion>
|
|
10
10
|
<groupId>expo.modules.ui</groupId>
|
|
11
11
|
<artifactId>expo.modules.ui</artifactId>
|
|
12
|
-
<version>58.0.
|
|
12
|
+
<version>58.0.16</version>
|
|
13
13
|
<packaging>aar</packaging>
|
|
14
14
|
<name>expo.modules.ui</name>
|
|
15
15
|
<url>https://github.com/expo/expo</url>
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.md5
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22c38dd6d4b789603e333d4c0a25d138
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha1
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
de7f94f1b4c3356f8244f8b620146bb9f37c52b8
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha256
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2bc1691b86aa0689fbf3bd19f3904aed5b40d206a8a152a03bf27c92eb871f28
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.16/expo.modules.ui-58.0.16.pom.sha512
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
528fce22a7b79c091d7dab483702c8e99ae783b76bd79c6b11e2086d9c59308f28a1b77e9379d8dc81f3ce6b3916f100d8c5c873ac165f75f780262ae8f56264
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/ui",
|
|
3
|
-
"version": "58.0.
|
|
3
|
+
"version": "58.0.16",
|
|
4
4
|
"description": "A collection of UI components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Jetpack Compose",
|
|
@@ -141,6 +141,7 @@
|
|
|
141
141
|
},
|
|
142
142
|
"devDependencies": {
|
|
143
143
|
"@babel/core": "^7.26.0",
|
|
144
|
+
"@expo/internal-scripts": "58.0.1",
|
|
144
145
|
"@playwright/test": "^1.59.0",
|
|
145
146
|
"@testing-library/react": "^16.3.0",
|
|
146
147
|
"@testing-library/react-native": "^14.0.1",
|
|
@@ -148,7 +149,6 @@
|
|
|
148
149
|
"@types/jest": "^30.0.0",
|
|
149
150
|
"@types/node": "^22.14.0",
|
|
150
151
|
"@types/react": "~19.3.0",
|
|
151
|
-
"expo-module-scripts": "56.0.8",
|
|
152
152
|
"react-native-reanimated": "4.7.0",
|
|
153
153
|
"react-native-worklets": "0.13.0"
|
|
154
154
|
},
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `true` inside a `Host`, where SwiftUI or Jetpack Compose renders the content. `RNHostView` sets it
|
|
5
|
+
* back to `false`, because its children are React Native views again.
|
|
6
|
+
*/
|
|
7
|
+
export const NativeTreeContext = createContext(false);
|
|
8
|
+
|
|
9
|
+
export function useIsInsideNativeTree(): boolean {
|
|
10
|
+
return useContext(NativeTreeContext);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let warned = false;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Warns once in development when a `Host` renders directly inside another `Host`'s native content.
|
|
17
|
+
*/
|
|
18
|
+
export function useWarnIfNestedHost(layoutSystem: 'SwiftUI' | 'Jetpack Compose'): void {
|
|
19
|
+
const isNested = useIsInsideNativeTree();
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (__DEV__ && isNested && !warned) {
|
|
22
|
+
warned = true;
|
|
23
|
+
console.warn(
|
|
24
|
+
`[@expo/ui] A \`Host\` is rendered directly inside another \`Host\`'s ${layoutSystem} content. ` +
|
|
25
|
+
`${layoutSystem} places it, but React Native can't see where, so its layout and \`measure()\` ` +
|
|
26
|
+
`can be wrong, and a \`Pressable\` inside it can cancel its press. Wrap the nested \`Host\` in ` +
|
|
27
|
+
`\`RNHostView\`, or render its ${layoutSystem} components directly in the outer \`Host\`.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}, [isNested, layoutSystem]);
|
|
31
|
+
}
|
|
@@ -4,7 +4,7 @@ import { worklets } from './optionalWorklets';
|
|
|
4
4
|
import { useWorkletProp } from './useWorkletProp';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* A worklet function wrapped for native code, returned by [`useWorkletCallback`](#
|
|
7
|
+
* A worklet function wrapped for native code, returned by [`useWorkletCallback`](#useworkletcallbackcallback).
|
|
8
8
|
* Pass it to a modifier or prop that accepts worklet callbacks, which then runs it synchronously on
|
|
9
9
|
* the UI thread.
|
|
10
10
|
*/
|
|
@@ -199,8 +199,9 @@ export function BottomSheet(props: BottomSheetProps) {
|
|
|
199
199
|
const bg = extractBackgroundColor(backgroundStyle);
|
|
200
200
|
return [
|
|
201
201
|
...(fitToContents
|
|
202
|
-
? //
|
|
203
|
-
|
|
202
|
+
? // Fits the sheet height to the content (iPad opens near full height otherwise) and lets
|
|
203
|
+
// the system choose the width.
|
|
204
|
+
[presentationSizing('automatic', { fitted: { horizontal: false, vertical: true } })]
|
|
204
205
|
: [
|
|
205
206
|
presentationDetents(detents, {
|
|
206
207
|
selection: selectedDetent,
|
|
@@ -231,16 +232,16 @@ export function BottomSheet(props: BottomSheetProps) {
|
|
|
231
232
|
onDismiss={fireCloseCallbacks}
|
|
232
233
|
fitToContents={fitToContents}>
|
|
233
234
|
<Group modifiers={modifiers}>
|
|
234
|
-
<RNHostView matchContents={fitToContents}>
|
|
235
|
+
<RNHostView matchContents={fitToContents ? { vertical: true } : false}>
|
|
235
236
|
{/* paddingTop compensates for tighter spacing between native drag indicator and content
|
|
236
237
|
compared to gorhom's handle. flexGrow:1 + height:0 (flex-basis 0) fills the snap-point
|
|
237
238
|
height without inheriting the scrollable child's intrinsic content height. With matchContents,
|
|
238
|
-
RNHostView
|
|
239
|
-
|
|
239
|
+
RNHostView takes the width from the sheet, which can be narrower than the window, and
|
|
240
|
+
the height from the content. */}
|
|
240
241
|
<View
|
|
241
242
|
style={
|
|
242
243
|
fitToContents
|
|
243
|
-
? {
|
|
244
|
+
? { paddingTop: handleComponent !== null ? 16 : 0 }
|
|
244
245
|
: { flexGrow: 1, height: 0, paddingTop: handleComponent !== null ? 16 : 0 }
|
|
245
246
|
}>
|
|
246
247
|
<SheetScrollContextReset>{children}</SheetScrollContextReset>
|
|
@@ -129,6 +129,10 @@ export function DateTimePicker(props: DateTimePickerProps) {
|
|
|
129
129
|
color={accentColor}
|
|
130
130
|
onDateSelected={onDateSelected}
|
|
131
131
|
showVariantToggle={false}
|
|
132
|
+
// Match iOS, where the inline picker has no label: hide Material 3's "Select date" title
|
|
133
|
+
// and its selected-date headline.
|
|
134
|
+
showTitle={false}
|
|
135
|
+
showHeadline={false}
|
|
132
136
|
{...(testID ? { testID } : undefined)}
|
|
133
137
|
/>
|
|
134
138
|
</Host>
|
|
@@ -12,8 +12,12 @@ import { Icon } from '../../jetpack-compose/Icon';
|
|
|
12
12
|
import { RNHostView } from '../../jetpack-compose/RNHostView';
|
|
13
13
|
import { Text as ComposeText } from '../../jetpack-compose/Text';
|
|
14
14
|
import { useMaterialColors } from '../../jetpack-compose/colors';
|
|
15
|
+
import type { PopupProperties } from '../../types';
|
|
15
16
|
import type { MenuAction, MenuComponentProps, MenuComponentRef, NativeActionEvent } from './types';
|
|
16
17
|
|
|
18
|
+
// Clipped popups drop the status bar offset, so edge-to-edge menus near the bottom detach from the anchor.
|
|
19
|
+
const POPUP_PROPERTIES: PopupProperties = { clippingEnabled: false };
|
|
20
|
+
|
|
17
21
|
function actionId(action: MenuAction): string {
|
|
18
22
|
return action.id ?? action.title;
|
|
19
23
|
}
|
|
@@ -82,7 +86,10 @@ function MenuActionItem({ action, onPressAction, dismissAll, destructiveColor }:
|
|
|
82
86
|
);
|
|
83
87
|
}
|
|
84
88
|
return (
|
|
85
|
-
<DropdownMenu
|
|
89
|
+
<DropdownMenu
|
|
90
|
+
expanded={submenuExpanded}
|
|
91
|
+
onDismissRequest={() => setSubmenuExpanded(false)}
|
|
92
|
+
properties={POPUP_PROPERTIES}>
|
|
86
93
|
<DropdownMenu.Trigger>
|
|
87
94
|
<DropdownMenuItem
|
|
88
95
|
enabled={!attributes?.disabled}
|
|
@@ -191,7 +198,10 @@ export function MenuView(props: MenuComponentProps & { ref?: React.Ref<MenuCompo
|
|
|
191
198
|
return (
|
|
192
199
|
<View style={style} testID={testID}>
|
|
193
200
|
<Host colorScheme={colorScheme} matchContents>
|
|
194
|
-
<DropdownMenu
|
|
201
|
+
<DropdownMenu
|
|
202
|
+
expanded={expanded}
|
|
203
|
+
onDismissRequest={dismissAll}
|
|
204
|
+
properties={POPUP_PROPERTIES}>
|
|
195
205
|
<DropdownMenu.Trigger>
|
|
196
206
|
<RNHostView matchContents>
|
|
197
207
|
<Pressable
|
|
@@ -131,6 +131,20 @@ export interface DateTimePickerProps {
|
|
|
131
131
|
* @default true
|
|
132
132
|
*/
|
|
133
133
|
showVariantToggle?: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
136
|
+
* `null` to Material 3's `title` slot. This prop has no effect when `displayedComponents` is
|
|
137
|
+
* `'hourAndMinute'`.
|
|
138
|
+
* @default true
|
|
139
|
+
*/
|
|
140
|
+
showTitle?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
143
|
+
* the picker passes `null` to Material 3's `headline` slot. This prop has no effect when
|
|
144
|
+
* `displayedComponents` is `'hourAndMinute'`.
|
|
145
|
+
* @default true
|
|
146
|
+
*/
|
|
147
|
+
showHeadline?: boolean;
|
|
134
148
|
/**
|
|
135
149
|
* The components that the picker should display.
|
|
136
150
|
* On Android, you can have a picker that selects just the date or just the time.
|
|
@@ -252,6 +266,18 @@ export interface DateRangePickerProps {
|
|
|
252
266
|
* @default true
|
|
253
267
|
*/
|
|
254
268
|
showVariantToggle?: boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
271
|
+
* `null` to Material 3's `title` slot.
|
|
272
|
+
* @default true
|
|
273
|
+
*/
|
|
274
|
+
showTitle?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
277
|
+
* the picker passes `null` to Material 3's `headline` slot.
|
|
278
|
+
* @default true
|
|
279
|
+
*/
|
|
280
|
+
showHeadline?: boolean;
|
|
255
281
|
/**
|
|
256
282
|
* The tint color to use on the picker elements.
|
|
257
283
|
*/
|
|
@@ -332,6 +358,18 @@ export interface DatePickerDialogProps {
|
|
|
332
358
|
initialDate?: string | null;
|
|
333
359
|
variant?: AndroidVariant;
|
|
334
360
|
showVariantToggle?: boolean;
|
|
361
|
+
/**
|
|
362
|
+
* Whether the picker shows its title, such as "Select date". When `false`, the picker passes
|
|
363
|
+
* `null` to Material 3's `title` slot.
|
|
364
|
+
* @default true
|
|
365
|
+
*/
|
|
366
|
+
showTitle?: boolean;
|
|
367
|
+
/**
|
|
368
|
+
* Whether the picker shows its headline, which displays the current selection. When `false`,
|
|
369
|
+
* the picker passes `null` to Material 3's `headline` slot.
|
|
370
|
+
* @default true
|
|
371
|
+
*/
|
|
372
|
+
showHeadline?: boolean;
|
|
335
373
|
confirmButtonLabel?: string;
|
|
336
374
|
dismissButtonLabel?: string;
|
|
337
375
|
color?: ColorValue;
|
|
@@ -3,7 +3,7 @@ import type { ReactNode } from 'react';
|
|
|
3
3
|
import type { StyleProp, ViewStyle, ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import { PresentedContent } from '../../PresentedContentContext';
|
|
6
|
-
import type { ModifierConfig } from '../../types';
|
|
6
|
+
import type { ModifierConfig, PopupProperties } from '../../types';
|
|
7
7
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
8
8
|
|
|
9
9
|
const MenuNativeView: React.ComponentType<NativeMenuProps> = requireNativeView(
|
|
@@ -59,6 +59,13 @@ export interface DropdownMenuProps {
|
|
|
59
59
|
*/
|
|
60
60
|
shadowElevation?: number;
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Properties for the popup window of the dropdown menu.
|
|
64
|
+
*
|
|
65
|
+
* @platform android
|
|
66
|
+
*/
|
|
67
|
+
properties?: PopupProperties;
|
|
68
|
+
|
|
62
69
|
/**
|
|
63
70
|
* Optional styles to apply to the `DropdownMenu`.
|
|
64
71
|
*/
|
|
@@ -76,6 +83,7 @@ type NativeMenuProps = {
|
|
|
76
83
|
color?: ColorValue;
|
|
77
84
|
cornerRadius?: number;
|
|
78
85
|
shadowElevation?: number;
|
|
86
|
+
properties?: PopupProperties;
|
|
79
87
|
style?: StyleProp<ViewStyle>;
|
|
80
88
|
modifiers?: ModifierConfig[];
|
|
81
89
|
children?: ReactNode;
|
|
@@ -129,3 +137,6 @@ DropdownMenu.Items = Items;
|
|
|
129
137
|
|
|
130
138
|
export { DropdownMenu };
|
|
131
139
|
export { DropdownMenuItem } from './DropdownMenuItem';
|
|
140
|
+
|
|
141
|
+
// Re-exported so the docs generator includes PopupProperties on the DropdownMenu API page.
|
|
142
|
+
export type { PopupProperties };
|