@expo/ui 1.0.0-canary-20250306-d9d3e02 → 1.0.0-canary-20250331-817737a
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 +7 -0
- package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +4 -0
- package/android/src/main/java/expo/modules/ui/PickerView.kt +3 -0
- package/android/src/main/java/expo/modules/ui/TextInputView.kt +75 -0
- package/android/src/main/java/expo/modules/ui/menu/ContextMenu.kt +7 -3
- package/build/components/BottomSheet/index.d.ts +9 -0
- package/build/components/BottomSheet/index.d.ts.map +1 -0
- package/build/components/BottomSheet/index.ios.d.ts +11 -0
- package/build/components/BottomSheet/index.ios.d.ts.map +1 -0
- package/build/components/Button/index.d.ts +1 -1
- package/build/components/ContextMenu/index.android.d.ts +23 -0
- package/build/components/ContextMenu/index.android.d.ts.map +1 -0
- package/build/components/ContextMenu/index.d.ts +54 -20
- package/build/components/ContextMenu/index.d.ts.map +1 -1
- package/build/components/DatePicker/index.d.ts +6 -6
- package/build/components/Label/index.d.ts +28 -0
- package/build/components/Label/index.d.ts.map +1 -0
- package/build/components/Label/index.ios.d.ts +10 -0
- package/build/components/Label/index.ios.d.ts.map +1 -0
- package/build/components/List/index.d.ts +87 -0
- package/build/components/List/index.d.ts.map +1 -0
- package/build/components/List/index.ios.d.ts +9 -0
- package/build/components/List/index.ios.d.ts.map +1 -0
- package/build/components/Picker/index.d.ts +8 -5
- package/build/components/Picker/index.d.ts.map +1 -1
- package/build/components/Progress/index.d.ts +1 -1
- package/build/components/Section/index.d.ts +10 -2
- package/build/components/Section/index.d.ts.map +1 -1
- package/build/components/Slider/index.d.ts +5 -2
- package/build/components/Slider/index.d.ts.map +1 -1
- package/build/components/Switch/index.d.ts +18 -36
- package/build/components/Switch/index.d.ts.map +1 -1
- package/build/components/TextInput/index.d.ts +24 -1
- package/build/components/TextInput/index.d.ts.map +1 -1
- package/build/src/types.d.ts +4 -2
- package/build/src/types.d.ts.map +1 -1
- package/components/BottomSheet/index.ios.tsx +34 -0
- package/components/BottomSheet/index.tsx +12 -0
- package/components/Button/index.tsx +1 -1
- package/components/ContextMenu/index.android.tsx +72 -0
- package/components/ContextMenu/index.tsx +67 -33
- package/components/DatePicker/index.tsx +6 -6
- package/components/Label/index.ios.tsx +16 -0
- package/components/Label/index.tsx +34 -0
- package/components/List/index.ios.tsx +35 -0
- package/components/List/index.tsx +99 -0
- package/components/Picker/index.tsx +8 -5
- package/components/Progress/index.tsx +1 -1
- package/components/Section/index.tsx +10 -2
- package/components/Slider/index.tsx +5 -2
- package/components/Switch/index.tsx +37 -54
- package/components/TextInput/index.tsx +30 -3
- package/ios/BottomSheetView.swift +82 -0
- package/ios/ContextMenu/ContextMenu.swift +65 -2
- package/ios/ContextMenu/ContextMenuRecords.swift +6 -0
- package/ios/ExpoUIModule.swift +5 -0
- package/ios/Label.swift +24 -0
- package/ios/List.swift +122 -0
- package/ios/PickerView.swift +32 -27
- package/ios/SectionView.swift +1 -1
- package/package.json +3 -4
- package/src/types.ts +4 -2
package/ios/List.swift
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
class ListProps: ExpoSwiftUI.ViewProps {
|
|
7
|
+
@Field var listStyle: String = "automatic"
|
|
8
|
+
@Field var moveEnabled: Bool = false
|
|
9
|
+
@Field var deleteEnabled: Bool = false
|
|
10
|
+
@Field var selectEnabled: Bool = true
|
|
11
|
+
@Field var scrollEnabled: Bool = false
|
|
12
|
+
@Field var editModeEnabled: Bool = false
|
|
13
|
+
var onDeleteItem = EventDispatcher()
|
|
14
|
+
var onMoveItem = EventDispatcher()
|
|
15
|
+
var onSelectionChange = EventDispatcher()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct ListView: ExpoSwiftUI.View {
|
|
19
|
+
@EnvironmentObject var props: ListProps
|
|
20
|
+
@State private var selection: Set<Int> = []
|
|
21
|
+
@State var editModeEnabled: EditMode = .inactive
|
|
22
|
+
@State var search: String = ""
|
|
23
|
+
var body: some View {
|
|
24
|
+
let list = List(selection: props.selectEnabled ? $selection : nil) {
|
|
25
|
+
UnwrappedChildren { child, isHostingView in
|
|
26
|
+
child
|
|
27
|
+
.if(!isHostingView) {
|
|
28
|
+
$0.offset(
|
|
29
|
+
x: UIDevice.current.userInterfaceIdiom == .pad
|
|
30
|
+
? IPAD_OFFSET : IPHONE_OFFSET)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
.onDelete(perform: handleDelete)
|
|
34
|
+
.onMove(perform: handleMove)
|
|
35
|
+
.deleteDisabled(!props.deleteEnabled)
|
|
36
|
+
.moveDisabled(!props.moveEnabled)
|
|
37
|
+
}
|
|
38
|
+
.modifier(ListStyleModifer(style: props.listStyle))
|
|
39
|
+
.onAppear {
|
|
40
|
+
editModeEnabled = props.editModeEnabled ? .active : .inactive
|
|
41
|
+
}
|
|
42
|
+
.onChange(of: props.editModeEnabled) { newValue in
|
|
43
|
+
withAnimation {
|
|
44
|
+
editModeEnabled = newValue ? .active : .inactive
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
.onChange(of: selection) { selection in
|
|
48
|
+
print(selection)
|
|
49
|
+
handleSelectionChange(selection: selection)
|
|
50
|
+
}
|
|
51
|
+
.modifier(ScrollDisabledModifier(scrollEnabled: props.selectEnabled))
|
|
52
|
+
.environment(\.editMode, $editModeEnabled)
|
|
53
|
+
if #available(iOS 16.0, tvOS 16.0, *) {
|
|
54
|
+
list.scrollDisabled(!props.scrollEnabled)
|
|
55
|
+
} else {
|
|
56
|
+
list
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
func handleDelete(at offsets: IndexSet) {
|
|
60
|
+
for offset in offsets {
|
|
61
|
+
props.onDeleteItem([
|
|
62
|
+
"index": offset
|
|
63
|
+
])
|
|
64
|
+
selection.remove(offset)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
func handleMove(from sources: IndexSet, to destination: Int) {
|
|
68
|
+
for source in sources {
|
|
69
|
+
props.onMoveItem([
|
|
70
|
+
"from": source,
|
|
71
|
+
"to": destination
|
|
72
|
+
])
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
func handleSelectionChange(selection: Set<Int>) {
|
|
76
|
+
let selectionArray = Array(selection)
|
|
77
|
+
let jsonDict: [String: Any] = [
|
|
78
|
+
"selection": selectionArray
|
|
79
|
+
]
|
|
80
|
+
props.onSelectionChange(jsonDict)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
struct ListStyleModifer: ViewModifier {
|
|
85
|
+
var style: String
|
|
86
|
+
@ViewBuilder func body(content: Content) -> some View {
|
|
87
|
+
switch style {
|
|
88
|
+
case "grouped":
|
|
89
|
+
content.listStyle(.grouped)
|
|
90
|
+
case "insetGrouped":
|
|
91
|
+
#if !os(tvOS)
|
|
92
|
+
content.listStyle(.insetGrouped)
|
|
93
|
+
#endif
|
|
94
|
+
case "inset":
|
|
95
|
+
#if !os(tvOS)
|
|
96
|
+
content.listStyle(.inset)
|
|
97
|
+
#endif
|
|
98
|
+
case "plain":
|
|
99
|
+
content.listStyle(.plain)
|
|
100
|
+
case "sidebar":
|
|
101
|
+
#if !os(tvOS)
|
|
102
|
+
content.listStyle(.sidebar)
|
|
103
|
+
#endif
|
|
104
|
+
case "automatic":
|
|
105
|
+
content.listStyle(.automatic)
|
|
106
|
+
default:
|
|
107
|
+
content
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
struct ScrollDisabledModifier: ViewModifier {
|
|
113
|
+
let scrollEnabled: Bool
|
|
114
|
+
|
|
115
|
+
func body(content: Content) -> some View {
|
|
116
|
+
if #available(iOS 16.0, tvOS 16.0, *) {
|
|
117
|
+
content.scrollDisabled(!scrollEnabled)
|
|
118
|
+
} else {
|
|
119
|
+
content
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/ios/PickerView.swift
CHANGED
|
@@ -13,40 +13,45 @@ class PickerProps: ExpoSwiftUI.ViewProps {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
struct PickerView: ExpoSwiftUI.View {
|
|
16
|
-
@State var selection: Int
|
|
16
|
+
@State var selection: Int = 0
|
|
17
17
|
@State var prevSelectedIndex: Int?
|
|
18
18
|
@EnvironmentObject var props: PickerProps
|
|
19
|
+
@EnvironmentObject var shadowNodeProxy: ExpoSwiftUI.ShadowNodeProxy
|
|
19
20
|
|
|
20
21
|
var body: some View {
|
|
21
22
|
if #available(iOS 17.0, tvOS 17.0, *) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
ExpoSwiftUI.AutoSizingStack(shadowNodeProxy: shadowNodeProxy) {
|
|
24
|
+
Picker(props.label ?? "", selection: $selection) {
|
|
25
|
+
ForEach(Array(props.options.enumerated()), id: \.0) { index, option in
|
|
26
|
+
Text(option).tag(index)
|
|
27
|
+
}
|
|
25
28
|
}
|
|
29
|
+
.tint(props.color)
|
|
30
|
+
#if !os(tvOS)
|
|
31
|
+
.if(props.variant == "wheel", { $0.pickerStyle(.wheel) })
|
|
32
|
+
.if(props.variant == "palette", { $0.pickerStyle(.palette) })
|
|
33
|
+
#endif
|
|
34
|
+
.if(props.variant == "segmented", { $0.pickerStyle(.segmented) })
|
|
35
|
+
.if(props.variant == "inline", { $0.pickerStyle(.inline) })
|
|
36
|
+
.if(props.variant == "menu", { $0.pickerStyle(.menu) })
|
|
37
|
+
.onChange(of: selection, perform: { newValue in
|
|
38
|
+
if props.selectedIndex == newValue {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
let payload = [
|
|
42
|
+
"index": newValue,
|
|
43
|
+
"label": props.options[newValue]
|
|
44
|
+
]
|
|
45
|
+
props.onOptionSelected(payload)
|
|
46
|
+
})
|
|
47
|
+
.onReceive(props.selectedIndex.publisher, perform: { newValue in
|
|
48
|
+
if prevSelectedIndex == newValue {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
selection = newValue
|
|
52
|
+
prevSelectedIndex = newValue
|
|
53
|
+
})
|
|
26
54
|
}
|
|
27
|
-
.tint(props.color)
|
|
28
|
-
#if !os(tvOS)
|
|
29
|
-
.if(props.variant == "wheel", { $0.pickerStyle(.wheel) })
|
|
30
|
-
#endif
|
|
31
|
-
.if(props.variant == "segmented", { $0.pickerStyle(.segmented) })
|
|
32
|
-
.if(props.variant == "menu", { $0.pickerStyle(.menu) })
|
|
33
|
-
.onChange(of: selection, perform: { newValue in
|
|
34
|
-
if props.selectedIndex == newValue {
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
let payload = [
|
|
38
|
-
"index": newValue ?? 0,
|
|
39
|
-
"label": props.options[newValue ?? 0]
|
|
40
|
-
]
|
|
41
|
-
props.onOptionSelected(payload)
|
|
42
|
-
})
|
|
43
|
-
.onReceive(props.selectedIndex.publisher, perform: { newValue in
|
|
44
|
-
if prevSelectedIndex == newValue {
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
selection = newValue
|
|
48
|
-
prevSelectedIndex = newValue
|
|
49
|
-
})
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
}
|
package/ios/SectionView.swift
CHANGED
|
@@ -15,7 +15,7 @@ struct SectionView: ExpoSwiftUI.View {
|
|
|
15
15
|
|
|
16
16
|
var body: some View {
|
|
17
17
|
let form = Form {
|
|
18
|
-
Section(header: Text(props.title ?? "")) {
|
|
18
|
+
Section(header: Text(props.title ?? "").textCase(nil)) {
|
|
19
19
|
UnwrappedChildren { child, isHostingView in
|
|
20
20
|
child
|
|
21
21
|
.if(!isHostingView) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/ui",
|
|
3
|
-
"version": "1.0.0-canary-
|
|
3
|
+
"version": "1.0.0-canary-20250331-817737a",
|
|
4
4
|
"description": "A collection of UI components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "expo-module build",
|
|
@@ -27,12 +27,11 @@
|
|
|
27
27
|
"dependencies": {},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/react": "~19.0.10",
|
|
30
|
-
"expo-module-scripts": "4.0.5-canary-
|
|
30
|
+
"expo-module-scripts": "4.0.5-canary-20250331-817737a"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"expo": "*",
|
|
34
34
|
"react": "*",
|
|
35
35
|
"react-native": "*"
|
|
36
|
-
}
|
|
37
|
-
"gitHead": "d9d3e024d8742099c307754673f17117a20c1dea"
|
|
36
|
+
}
|
|
38
37
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
export type * from '../components/Switch';
|
|
2
|
-
export type * from '../components/Picker';
|
|
3
1
|
export type * from '../components/Button';
|
|
4
2
|
export type * from '../components/ContextMenu';
|
|
3
|
+
export type * from '../components/Picker';
|
|
5
4
|
export type * from '../components/Section';
|
|
6
5
|
export type * from '../components/Slider';
|
|
6
|
+
export type * from '../components/Switch';
|
|
7
|
+
export type * from '../components/Label';
|
|
8
|
+
export type * from '../components/List';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* @hidden
|