@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
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import ExpoModulesCore
|
|
4
4
|
import SwiftUI
|
|
5
|
-
#if !os(tvOS)
|
|
6
|
-
import WidgetKit
|
|
7
|
-
#endif
|
|
8
5
|
|
|
9
6
|
internal enum ContainerBackgroundPlacementOptions: String, Enumerable {
|
|
10
7
|
case widget
|
|
11
8
|
case navigation
|
|
12
9
|
case navigationSplitView
|
|
13
10
|
|
|
14
|
-
#if !os(tvOS)
|
|
11
|
+
#if !os(tvOS) && !os(macOS)
|
|
12
|
+
// `widget` is declared in WidgetKit, so expo-widgets applies it through `ViewModifierRegistry.widgetKit`.
|
|
15
13
|
@available(iOS 18.0, *)
|
|
16
|
-
var toContainerBackgroundPlacement: ContainerBackgroundPlacement {
|
|
14
|
+
var toContainerBackgroundPlacement: ContainerBackgroundPlacement? {
|
|
17
15
|
switch self {
|
|
18
|
-
case .widget: return
|
|
16
|
+
case .widget: return nil
|
|
19
17
|
case .navigation: return .navigation
|
|
20
18
|
case .navigationSplitView: return .navigationSplitView
|
|
21
19
|
}
|
|
@@ -28,20 +26,35 @@ internal struct ContainerBackgroundModifier: ViewModifier, Record {
|
|
|
28
26
|
@Field var container: ContainerBackgroundPlacementOptions?
|
|
29
27
|
|
|
30
28
|
func body(content: Content) -> some View {
|
|
31
|
-
#if
|
|
29
|
+
#if os(tvOS) || os(macOS)
|
|
30
|
+
content
|
|
31
|
+
#else
|
|
32
32
|
if let shapeStyle = style?.toAnyShapeStyle(), let container {
|
|
33
|
-
if
|
|
34
|
-
|
|
35
|
-
} else if #available(iOS
|
|
36
|
-
content.containerBackground(shapeStyle, for:
|
|
33
|
+
if container == .widget, let widgetKit = ViewModifierRegistry.widgetKit {
|
|
34
|
+
widgetKit.containerBackground(AnyView(content), style: shapeStyle)
|
|
35
|
+
} else if #available(iOS 18.0, *), let placement = container.toContainerBackgroundPlacement {
|
|
36
|
+
content.containerBackground(shapeStyle, for: placement)
|
|
37
|
+
} else if let widgetKit = ViewModifierRegistry.widgetKit {
|
|
38
|
+
// On iOS 17, the other placements fall back to `widget`.
|
|
39
|
+
widgetKit.containerBackground(AnyView(content), style: shapeStyle)
|
|
37
40
|
} else {
|
|
38
41
|
content
|
|
39
42
|
}
|
|
40
43
|
} else {
|
|
41
44
|
content
|
|
42
45
|
}
|
|
43
|
-
#else
|
|
44
|
-
content
|
|
45
46
|
#endif
|
|
46
47
|
}
|
|
48
|
+
|
|
49
|
+
#if DEBUG
|
|
50
|
+
private static var didWarnAboutWidgetPlacement = false
|
|
51
|
+
|
|
52
|
+
func warnIfWidgetPlacementIsUnavailable() {
|
|
53
|
+
guard container == .widget, ViewModifierRegistry.widgetKit == nil, !Self.didWarnAboutWidgetPlacement else {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
Self.didWarnAboutWidgetPlacement = true
|
|
57
|
+
log.warn("containerBackground with the 'widget' placement has no effect here, because it only applies inside widgets rendered by expo-widgets. Use the 'navigation' or 'navigationSplitView' placement in app screens.")
|
|
58
|
+
}
|
|
59
|
+
#endif
|
|
47
60
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
internal struct PreferredColorSchemeModifier: ViewModifier, Record {
|
|
7
|
+
@Field var colorScheme: ColorSchemeType?
|
|
8
|
+
|
|
9
|
+
func body(content: Content) -> some View {
|
|
10
|
+
content.preferredColorScheme(colorScheme?.toNativeColorScheme())
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -238,23 +238,39 @@ internal enum PresentationSizingOption: String, Enumerable {
|
|
|
238
238
|
case page
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
internal struct PresentationSizingFittedAxes: Record {
|
|
242
|
+
@Field var horizontal: Bool = false
|
|
243
|
+
@Field var vertical: Bool = false
|
|
244
|
+
}
|
|
245
|
+
|
|
241
246
|
internal struct PresentationSizingModifier: ViewModifier, Record {
|
|
242
247
|
@Field var sizing: PresentationSizingOption = .automatic
|
|
248
|
+
@Field var fitted: PresentationSizingFittedAxes?
|
|
243
249
|
|
|
244
250
|
func body(content: Content) -> some View {
|
|
245
251
|
if #available(iOS 18.0, tvOS 18.0, macOS 15.0, *) {
|
|
246
252
|
switch sizing {
|
|
247
253
|
case .automatic:
|
|
248
|
-
content.
|
|
254
|
+
applySizing(content, .automatic)
|
|
249
255
|
case .fitted:
|
|
250
|
-
content.
|
|
256
|
+
applySizing(content, .fitted)
|
|
251
257
|
case .form:
|
|
252
|
-
content.
|
|
258
|
+
applySizing(content, .form)
|
|
253
259
|
case .page:
|
|
254
|
-
content.
|
|
260
|
+
applySizing(content, .page)
|
|
255
261
|
}
|
|
256
262
|
} else {
|
|
257
263
|
content
|
|
258
264
|
}
|
|
259
265
|
}
|
|
266
|
+
|
|
267
|
+
@available(iOS 18.0, tvOS 18.0, macOS 15.0, *)
|
|
268
|
+
@ViewBuilder
|
|
269
|
+
private func applySizing(_ content: Content, _ sizing: some PresentationSizing) -> some View {
|
|
270
|
+
if let fitted {
|
|
271
|
+
content.presentationSizing(sizing.fitted(horizontal: fitted.horizontal, vertical: fitted.vertical))
|
|
272
|
+
} else {
|
|
273
|
+
content.presentationSizing(sizing)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
260
276
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright 2026-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
internal enum SearchToolbarBehaviorType: String, Enumerable {
|
|
7
|
+
case automatic
|
|
8
|
+
case minimize
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
internal struct SearchToolbarBehaviorModifier: ViewModifier, Record {
|
|
12
|
+
@Field var behavior: SearchToolbarBehaviorType = .automatic
|
|
13
|
+
|
|
14
|
+
@ViewBuilder
|
|
15
|
+
func body(content: Content) -> some View {
|
|
16
|
+
if #available(iOS 26.0, macOS 26.0, tvOS 26.0, *) {
|
|
17
|
+
#if compiler(>=6.2) // Xcode 26
|
|
18
|
+
switch behavior {
|
|
19
|
+
case .automatic:
|
|
20
|
+
content.searchToolbarBehavior(.automatic)
|
|
21
|
+
case .minimize:
|
|
22
|
+
#if os(macOS) || os(tvOS)
|
|
23
|
+
content.searchToolbarBehavior(.automatic)
|
|
24
|
+
#else
|
|
25
|
+
content.searchToolbarBehavior(.minimize)
|
|
26
|
+
#endif
|
|
27
|
+
}
|
|
28
|
+
#else
|
|
29
|
+
content
|
|
30
|
+
#endif
|
|
31
|
+
} else {
|
|
32
|
+
content
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -67,10 +67,10 @@ internal extension Image {
|
|
|
67
67
|
)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
if
|
|
70
|
+
if let widgetKit = ViewModifierRegistry.widgetKit,
|
|
71
71
|
let modifierConfig = modifiers.first(where: { $0["$type"] as? String == "widgetAccentedRenderingMode" }),
|
|
72
|
-
let
|
|
73
|
-
|
|
72
|
+
let view = widgetKit.widgetAccentedRenderingMode(image, params: modifierConfig, appContext: appContext) {
|
|
73
|
+
view
|
|
74
74
|
} else {
|
|
75
75
|
image
|
|
76
76
|
}
|
|
@@ -1529,6 +1529,8 @@ public class ViewModifierRegistry {
|
|
|
1529
1529
|
public typealias ModifierFactory = ([String: Any], AppContext, EventDispatcher) throws -> any ViewModifier
|
|
1530
1530
|
private(set) internal var modifierFactories: [String: ModifierFactory] = [:]
|
|
1531
1531
|
|
|
1532
|
+
public static var widgetKit: WidgetKitModifiers?
|
|
1533
|
+
|
|
1532
1534
|
private init() {
|
|
1533
1535
|
registerBuiltInModifiers()
|
|
1534
1536
|
}
|
|
@@ -1813,6 +1815,83 @@ internal struct NavigationTitleModifier: ViewModifier, Record {
|
|
|
1813
1815
|
}
|
|
1814
1816
|
}
|
|
1815
1817
|
|
|
1818
|
+
internal enum NavigationBarTitleDisplayMode: String, Enumerable {
|
|
1819
|
+
case automatic
|
|
1820
|
+
case inline
|
|
1821
|
+
case large
|
|
1822
|
+
|
|
1823
|
+
#if os(iOS)
|
|
1824
|
+
var value: NavigationBarItem.TitleDisplayMode {
|
|
1825
|
+
switch self {
|
|
1826
|
+
case .automatic:
|
|
1827
|
+
return .automatic
|
|
1828
|
+
case .inline:
|
|
1829
|
+
return .inline
|
|
1830
|
+
case .large:
|
|
1831
|
+
return .large
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
#endif
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
internal struct NavigationBarTitleDisplayModeModifier: ViewModifier, Record {
|
|
1838
|
+
@Field var displayMode: NavigationBarTitleDisplayMode = .automatic
|
|
1839
|
+
|
|
1840
|
+
func body(content: Content) -> some View {
|
|
1841
|
+
#if os(iOS)
|
|
1842
|
+
content.navigationBarTitleDisplayMode(displayMode.value)
|
|
1843
|
+
#else
|
|
1844
|
+
content
|
|
1845
|
+
#endif
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
internal enum ToolbarTitleDisplayModeType: String, Enumerable {
|
|
1850
|
+
case automatic
|
|
1851
|
+
case inline
|
|
1852
|
+
case inlineLarge
|
|
1853
|
+
case large
|
|
1854
|
+
|
|
1855
|
+
@available(iOS 17.0, tvOS 17.0, macOS 14.0, *)
|
|
1856
|
+
var value: SwiftUI.ToolbarTitleDisplayMode? {
|
|
1857
|
+
switch self {
|
|
1858
|
+
case .automatic:
|
|
1859
|
+
return .automatic
|
|
1860
|
+
case .inline:
|
|
1861
|
+
return .inline
|
|
1862
|
+
case .inlineLarge:
|
|
1863
|
+
#if os(tvOS)
|
|
1864
|
+
return nil
|
|
1865
|
+
#else
|
|
1866
|
+
return .inlineLarge
|
|
1867
|
+
#endif
|
|
1868
|
+
case .large:
|
|
1869
|
+
#if os(iOS)
|
|
1870
|
+
return .large
|
|
1871
|
+
#else
|
|
1872
|
+
return nil
|
|
1873
|
+
#endif
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
internal struct ToolbarTitleDisplayModeModifier: ViewModifier, Record {
|
|
1879
|
+
@Field var mode: ToolbarTitleDisplayModeType = .automatic
|
|
1880
|
+
|
|
1881
|
+
@ViewBuilder
|
|
1882
|
+
func body(content: Content) -> some View {
|
|
1883
|
+
if #available(iOS 17.0, tvOS 17.0, macOS 14.0, *) {
|
|
1884
|
+
if let value = mode.value {
|
|
1885
|
+
content.toolbarTitleDisplayMode(value)
|
|
1886
|
+
} else {
|
|
1887
|
+
content
|
|
1888
|
+
}
|
|
1889
|
+
} else {
|
|
1890
|
+
content
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1816
1895
|
// MARK: - Built-in Modifier Registration
|
|
1817
1896
|
|
|
1818
1897
|
// swiftlint:disable:next no_grouping_extension
|
|
@@ -1989,6 +2068,14 @@ extension ViewModifierRegistry {
|
|
|
1989
2068
|
return try NavigationTitleModifier(from: params, appContext: appContext)
|
|
1990
2069
|
}
|
|
1991
2070
|
|
|
2071
|
+
register("navigationBarTitleDisplayMode") { params, appContext, _ in
|
|
2072
|
+
return try NavigationBarTitleDisplayModeModifier(from: params, appContext: appContext)
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
register("toolbarTitleDisplayMode") { params, appContext, _ in
|
|
2076
|
+
return try ToolbarTitleDisplayModeModifier(from: params, appContext: appContext)
|
|
2077
|
+
}
|
|
2078
|
+
|
|
1992
2079
|
register("navigationSplitViewStyle") { params, appContext, _ in
|
|
1993
2080
|
return try NavigationSplitViewStyleModifier(from: params, appContext: appContext)
|
|
1994
2081
|
}
|
|
@@ -1997,6 +2084,26 @@ extension ViewModifierRegistry {
|
|
|
1997
2084
|
return try NavigationSplitViewColumnWidthModifier(from: params, appContext: appContext)
|
|
1998
2085
|
}
|
|
1999
2086
|
|
|
2087
|
+
register("arrangementViewStyle") { params, appContext, _ in
|
|
2088
|
+
return try ArrangementViewStyleModifier(from: params, appContext: appContext)
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
register("splitArrangementLayoutRatio") { params, appContext, _ in
|
|
2092
|
+
return try SplitArrangementLayoutRatioModifier(from: params, appContext: appContext)
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
register("splitArrangementLayoutSize") { params, appContext, _ in
|
|
2096
|
+
return try SplitArrangementLayoutSizeModifier(from: params, appContext: appContext)
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
register("splitArrangementFixedLayoutSize") { params, appContext, _ in
|
|
2100
|
+
return try SplitArrangementFixedLayoutSizeModifier(from: params, appContext: appContext)
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
register("overlayArrangementEdge") { params, appContext, _ in
|
|
2104
|
+
return try OverlayArrangementEdgeModifier(from: params, appContext: appContext)
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2000
2107
|
register("accessibilityLabel") { params, appContext, _ in
|
|
2001
2108
|
return try AccessibilityLabelModifier(from: params, appContext: appContext)
|
|
2002
2109
|
}
|
|
@@ -2269,6 +2376,14 @@ extension ViewModifierRegistry {
|
|
|
2269
2376
|
return try ScrollPositionModifier(from: params, appContext: appContext, eventDispatcher: eventDispatcher)
|
|
2270
2377
|
}
|
|
2271
2378
|
|
|
2379
|
+
register("searchable") { params, appContext, eventDispatcher in
|
|
2380
|
+
return try SearchableModifier(from: params, appContext: appContext, eventDispatcher: eventDispatcher)
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
register("searchToolbarBehavior") { params, appContext, _ in
|
|
2384
|
+
return try SearchToolbarBehaviorModifier(from: params, appContext: appContext)
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2272
2387
|
register("pickerStyle") { params, appContext, _ in
|
|
2273
2388
|
return try PickerStyleModifier(from: params, appContext: appContext)
|
|
2274
2389
|
}
|
|
@@ -2305,6 +2420,10 @@ extension ViewModifierRegistry {
|
|
|
2305
2420
|
return try ScrollDisabledModifier(from: params, appContext: appContext)
|
|
2306
2421
|
}
|
|
2307
2422
|
|
|
2423
|
+
register("preferredColorScheme") { params, appContext, _ in
|
|
2424
|
+
return try PreferredColorSchemeModifier(from: params, appContext: appContext)
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2308
2427
|
register("scrollClipDisabled") { params, appContext, _ in
|
|
2309
2428
|
return try ScrollClipDisabledModifier(from: params, appContext: appContext)
|
|
2310
2429
|
}
|
|
@@ -2389,14 +2508,6 @@ extension ViewModifierRegistry {
|
|
|
2389
2508
|
return try ContentTransitionModifier(from: params, appContext: appContext)
|
|
2390
2509
|
}
|
|
2391
2510
|
|
|
2392
|
-
register("widgetURL") { params, appContext, _ in
|
|
2393
|
-
return try WidgetURLModifier(from: params, appContext: appContext)
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2396
|
-
register("activityBackgroundTint") { params, appContext, _ in
|
|
2397
|
-
return try ActivityBackgroundTintModifier(from: params, appContext: appContext)
|
|
2398
|
-
}
|
|
2399
|
-
|
|
2400
2511
|
register("keyboardType") { params, appContext, _ in
|
|
2401
2512
|
return try KeyboardTypeModifier(from: params, appContext: appContext)
|
|
2402
2513
|
}
|
|
@@ -2410,7 +2521,11 @@ extension ViewModifierRegistry {
|
|
|
2410
2521
|
}
|
|
2411
2522
|
|
|
2412
2523
|
register("containerBackground") { params, appContext, _ in
|
|
2413
|
-
|
|
2524
|
+
let modifier = try ContainerBackgroundModifier(from: params, appContext: appContext)
|
|
2525
|
+
#if DEBUG
|
|
2526
|
+
modifier.warnIfWidgetPlacementIsUnavailable()
|
|
2527
|
+
#endif
|
|
2528
|
+
return modifier
|
|
2414
2529
|
}
|
|
2415
2530
|
|
|
2416
2531
|
register("symbolEffect") { params, appContext, _ in
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright 2026-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The parts of SwiftUI that are declared in WidgetKit. expo-widgets sets
|
|
8
|
+
* `ViewModifierRegistry.widgetKit`, so ExpoUI does not link WidgetKit.
|
|
9
|
+
*/
|
|
10
|
+
public protocol WidgetKitModifiers {
|
|
11
|
+
func containerBackground(_ view: AnyView, style: AnyShapeStyle) -> AnyView
|
|
12
|
+
func widgetAccentedRenderingMode(_ image: Image, params: [String: Any], appContext: AppContext) -> AnyView?
|
|
13
|
+
}
|
|
@@ -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
|
@@ -4,7 +4,8 @@ import SwiftUI
|
|
|
4
4
|
import ExpoModulesCore
|
|
5
5
|
|
|
6
6
|
internal final class RNHostViewProps: ExpoSwiftUI.ViewProps {
|
|
7
|
-
@Field var
|
|
7
|
+
@Field var matchContentsHorizontal: Bool = false
|
|
8
|
+
@Field var matchContentsVertical: Bool = false
|
|
8
9
|
/**
|
|
9
10
|
Adds LeafNode and MeasurableYogaNode trait in Shadow node
|
|
10
11
|
*/
|
|
@@ -50,8 +51,13 @@ struct RNHostView: ExpoSwiftUI.View {
|
|
|
50
51
|
|
|
51
52
|
@ViewBuilder
|
|
52
53
|
private var hostedContent: some View {
|
|
53
|
-
if
|
|
54
|
-
ApplySizeFromYogaNode(
|
|
54
|
+
if matchesContents, let childUIView = firstChildUIView {
|
|
55
|
+
ApplySizeFromYogaNode(
|
|
56
|
+
childUIView: childUIView,
|
|
57
|
+
horizontal: props.matchContentsHorizontal,
|
|
58
|
+
vertical: props.matchContentsVertical,
|
|
59
|
+
shadowNodeProxy: props.shadowNodeProxy
|
|
60
|
+
) {
|
|
55
61
|
Children()
|
|
56
62
|
}
|
|
57
63
|
.onAppear {
|
|
@@ -62,7 +68,7 @@ struct RNHostView: ExpoSwiftUI.View {
|
|
|
62
68
|
.onDisappear {
|
|
63
69
|
touchHandler.detach()
|
|
64
70
|
}
|
|
65
|
-
} else if
|
|
71
|
+
} else if matchesContents {
|
|
66
72
|
// No hosted UIView (a pure SwiftUI child, e.g. Text/Image). Render it at its
|
|
67
73
|
// natural size instead of falling into the fill branch below, which would
|
|
68
74
|
// stretch a self-sizing SwiftUI view to fill its container.
|
|
@@ -87,6 +93,10 @@ struct RNHostView: ExpoSwiftUI.View {
|
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
private var matchesContents: Bool {
|
|
97
|
+
props.matchContentsHorizontal || props.matchContentsVertical
|
|
98
|
+
}
|
|
99
|
+
|
|
90
100
|
private var firstChildUIView: UIView? {
|
|
91
101
|
props.children?.first?.uiView
|
|
92
102
|
}
|
|
@@ -143,20 +153,52 @@ private final class RNHostTouchHandler: ObservableObject {
|
|
|
143
153
|
}
|
|
144
154
|
}
|
|
145
155
|
|
|
146
|
-
// Sets SwiftUI view size from Yoga node size
|
|
156
|
+
// Sets SwiftUI view size from Yoga node size on the matched axes
|
|
147
157
|
// Listens to Yoga node size changes and updates the SwiftUI view size
|
|
158
|
+
// An axis that is not matched fills the parent and reports its size to the Yoga node instead
|
|
148
159
|
private struct ApplySizeFromYogaNode<Content: SwiftUI.View>: SwiftUI.View {
|
|
149
160
|
@StateObject private var observer: Observer
|
|
161
|
+
let horizontal: Bool
|
|
162
|
+
let vertical: Bool
|
|
163
|
+
let shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
|
|
150
164
|
let content: Content
|
|
151
165
|
|
|
152
|
-
init(
|
|
166
|
+
init(
|
|
167
|
+
childUIView: UIView,
|
|
168
|
+
horizontal: Bool,
|
|
169
|
+
vertical: Bool,
|
|
170
|
+
shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy,
|
|
171
|
+
@ViewBuilder content: () -> Content
|
|
172
|
+
) {
|
|
153
173
|
_observer = StateObject(wrappedValue: Observer(view: childUIView))
|
|
174
|
+
self.horizontal = horizontal
|
|
175
|
+
self.vertical = vertical
|
|
176
|
+
self.shadowNodeProxy = shadowNodeProxy
|
|
154
177
|
self.content = content()
|
|
155
178
|
}
|
|
156
179
|
|
|
157
180
|
var body: some SwiftUI.View {
|
|
158
|
-
|
|
159
|
-
|
|
181
|
+
if horizontal && vertical {
|
|
182
|
+
content
|
|
183
|
+
.frame(width: observer.size.width, height: observer.size.height)
|
|
184
|
+
} else {
|
|
185
|
+
content
|
|
186
|
+
.frame(
|
|
187
|
+
width: horizontal ? observer.size.width : nil,
|
|
188
|
+
height: vertical ? observer.size.height : nil
|
|
189
|
+
)
|
|
190
|
+
.frame(
|
|
191
|
+
maxWidth: horizontal ? nil : .infinity,
|
|
192
|
+
maxHeight: vertical ? nil : .infinity
|
|
193
|
+
)
|
|
194
|
+
.modifier(
|
|
195
|
+
ReportSizeToYogaNodeModifier(
|
|
196
|
+
shadowNodeProxy: shadowNodeProxy,
|
|
197
|
+
reportWidth: !horizontal,
|
|
198
|
+
reportHeight: !vertical
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
}
|
|
160
202
|
}
|
|
161
203
|
|
|
162
204
|
@MainActor
|
|
@@ -183,9 +225,13 @@ private struct ApplySizeFromYogaNode<Content: SwiftUI.View>: SwiftUI.View {
|
|
|
183
225
|
// Listens to SwiftUI view size changes and updates the Yoga node size
|
|
184
226
|
private struct ReportSizeToYogaNodeModifier: ViewModifier {
|
|
185
227
|
let shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
|
|
228
|
+
var reportWidth = true
|
|
229
|
+
var reportHeight = true
|
|
186
230
|
|
|
187
231
|
private func handleSizeChange(_ size: CGSize) {
|
|
188
|
-
shadowNodeProxy.setViewSize?(
|
|
232
|
+
shadowNodeProxy.setViewSize?(
|
|
233
|
+
CGSize(width: reportWidth ? size.width : .nan, height: reportHeight ? size.height : .nan)
|
|
234
|
+
)
|
|
189
235
|
}
|
|
190
236
|
|
|
191
237
|
func body(content: Content) -> some View {
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9e119ee5a1c2c38e6d69d4f866341e7a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
04332c3498b6b2a56dfb4cbefe592c11f4a8f36a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
5f4063182b296fa0028d945a2621f9d8a86eb5219b0ad88492a18dfe4d737978
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0a89146da34d837d01eb682540df3405b70f6b1d18c50bedc2ecc1d0dee3188df777de03a5b629100950a0f6d3c2d9f89f52416641cb22d8f3a715c8e841ff18
|
|
Binary file
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.md5
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
53230bb5c7cc2bcc0d717bc544974f6c
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha1
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bc99884c9e5f484800ffb10156cc8b50fa4d31c8
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha256
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
45594b39ac8f0c6eb37b663d40160b8e93b6d5f56b985a739c8a03c6780d910f
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.23/expo.modules.ui-57.0.23.aar.sha512
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
7ba6b0ca0e41c0aeaea90cfc7d49664bb88531a251ba79b1124009eba0b724b48ba1c306744111a40871213cdf5767638b931803dc2229c4ba1850b6cc87ca15
|