@expo/ui 56.0.2 → 56.0.4
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 +11 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +6 -0
- package/android/src/main/java/expo/modules/ui/MaskView.kt +56 -0
- package/build/community/masked-view/MaskedView.android.d.ts +8 -0
- package/build/community/masked-view/MaskedView.android.d.ts.map +1 -0
- package/build/community/masked-view/MaskedView.d.ts +10 -0
- package/build/community/masked-view/MaskedView.d.ts.map +1 -0
- package/build/community/masked-view/MaskedView.ios.d.ts +8 -0
- package/build/community/masked-view/MaskedView.ios.d.ts.map +1 -0
- package/build/community/masked-view/index.d.ts +4 -0
- package/build/community/masked-view/index.d.ts.map +1 -0
- package/build/community/masked-view/types.d.ts +19 -0
- package/build/community/masked-view/types.d.ts.map +1 -0
- package/build/community/picker/Picker.android.d.ts +10 -2
- package/build/community/picker/Picker.android.d.ts.map +1 -1
- package/build/community/picker/Picker.d.ts +10 -2
- package/build/community/picker/Picker.d.ts.map +1 -1
- package/build/community/picker/Picker.ios.d.ts +10 -2
- package/build/community/picker/Picker.ios.d.ts.map +1 -1
- package/build/community/picker/types.d.ts +12 -10
- package/build/community/picker/types.d.ts.map +1 -1
- package/build/jetpack-compose/modifiers/index.d.ts +1 -1
- package/build/universal/Button/index.d.ts.map +1 -1
- package/build/universal/Checkbox/index.d.ts.map +1 -1
- package/build/universal/Column/index.d.ts.map +1 -1
- package/build/universal/FieldGroup/FieldGroup.d.ts.map +1 -1
- package/build/universal/FieldGroup/FieldSection.d.ts.map +1 -1
- package/build/universal/Row/index.d.ts.map +1 -1
- package/build/universal/ScrollView/index.d.ts.map +1 -1
- package/build/universal/Slider/index.d.ts.map +1 -1
- package/build/universal/Spacer/index.d.ts.map +1 -1
- package/build/universal/Switch/index.d.ts.map +1 -1
- package/build/universal/Text/index.d.ts.map +1 -1
- package/expo-module.config.json +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.2/expo.modules.ui-56.0.2-sources.jar → 56.0.4/expo.modules.ui-56.0.4-sources.jar} +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4-sources.jar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4-sources.jar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4-sources.jar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4-sources.jar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.aar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.aar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.aar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.aar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.2/expo.modules.ui-56.0.2.module → 56.0.4/expo.modules.ui-56.0.4.module} +23 -23
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.module.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.module.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.module.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.module.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.2/expo.modules.ui-56.0.2.pom → 56.0.4/expo.modules.ui-56.0.4.pom} +2 -2
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.pom.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.pom.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.pom.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.4/expo.modules.ui-56.0.4.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 +8 -4
- package/src/community/masked-view/MaskedView.android.tsx +40 -0
- package/src/community/masked-view/MaskedView.ios.tsx +32 -0
- package/src/community/masked-view/MaskedView.tsx +34 -0
- package/src/community/masked-view/index.tsx +3 -0
- package/src/community/masked-view/types.ts +19 -0
- package/src/community/picker/Picker.android.tsx +12 -5
- package/src/community/picker/Picker.ios.tsx +9 -6
- package/src/community/picker/Picker.tsx +3 -4
- package/src/community/picker/types.tsx +24 -18
- package/src/jetpack-compose/modifiers/index.ts +1 -1
- package/src/ts-declarations/react-native-web.d.ts +112 -0
- package/src/universal/Button/index.tsx +37 -50
- package/src/universal/Checkbox/index.tsx +31 -18
- package/src/universal/Column/index.tsx +29 -18
- package/src/universal/FieldGroup/FieldGroup.tsx +24 -28
- package/src/universal/FieldGroup/FieldSection.tsx +62 -80
- package/src/universal/Row/index.tsx +37 -24
- package/src/universal/ScrollView/index.tsx +26 -15
- package/src/universal/Slider/index.tsx +21 -16
- package/src/universal/Spacer/index.tsx +18 -10
- package/src/universal/Switch/index.tsx +15 -10
- package/src/universal/Text/index.tsx +18 -37
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2-sources.jar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2-sources.jar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2-sources.jar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2-sources.jar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.aar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.aar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.aar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.aar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.module.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.module.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.module.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.module.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.pom.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.pom.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.pom.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.2/expo.modules.ui-56.0.2.pom.sha512 +0 -1
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import { Pressable, View, type ViewStyle } from 'react-native';
|
|
1
|
+
import { Pressable, StyleSheet, View, type ViewStyle } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { ColumnProps } from './types';
|
|
4
4
|
import { useUniversalLifecycle } from '../hooks';
|
|
5
5
|
import type { UniversalAlignment } from '../types';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
column: { flexDirection: 'column' },
|
|
9
|
+
hidden: { display: 'none' },
|
|
10
|
+
disabled: {
|
|
11
|
+
opacity: 0.5,
|
|
12
|
+
pointerEvents: 'none',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const alignmentStyles = StyleSheet.create({
|
|
17
|
+
start: { alignItems: 'flex-start' },
|
|
18
|
+
center: { alignItems: 'center' },
|
|
19
|
+
end: { alignItems: 'flex-end' },
|
|
20
|
+
} satisfies Record<UniversalAlignment, ViewStyle>);
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
23
|
* A vertical layout container that arranges its children from top to bottom.
|
|
@@ -21,25 +30,27 @@ export function Column({
|
|
|
21
30
|
onPress,
|
|
22
31
|
onAppear,
|
|
23
32
|
onDisappear,
|
|
24
|
-
disabled,
|
|
25
|
-
hidden,
|
|
33
|
+
disabled = false,
|
|
34
|
+
hidden = false,
|
|
26
35
|
testID,
|
|
27
36
|
}: ColumnProps) {
|
|
28
37
|
useUniversalLifecycle(onAppear, onDisappear);
|
|
29
38
|
|
|
30
|
-
const viewStyle: ViewStyle = {
|
|
31
|
-
flexDirection: 'column',
|
|
32
|
-
alignItems: alignmentMap[alignment],
|
|
33
|
-
gap: spacing,
|
|
34
|
-
...style,
|
|
35
|
-
...(hidden ? { display: 'none' } : undefined),
|
|
36
|
-
...(disabled ? { opacity: 0.5, pointerEvents: 'none' } : undefined),
|
|
37
|
-
};
|
|
38
|
-
|
|
39
39
|
const Container = onPress ? Pressable : View;
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
|
-
<Container
|
|
42
|
+
<Container
|
|
43
|
+
onPress={onPress}
|
|
44
|
+
disabled={disabled}
|
|
45
|
+
testID={testID}
|
|
46
|
+
style={[
|
|
47
|
+
styles.column,
|
|
48
|
+
alignmentStyles[alignment],
|
|
49
|
+
spacing != null && { gap: spacing },
|
|
50
|
+
style,
|
|
51
|
+
hidden && styles.hidden,
|
|
52
|
+
disabled && styles.disabled,
|
|
53
|
+
]}>
|
|
43
54
|
{children}
|
|
44
55
|
</Container>
|
|
45
56
|
);
|
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
import { ScrollView,
|
|
1
|
+
import { ScrollView, StyleSheet, useColorScheme } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import { groupFieldGroupChildren } from './groupChildren';
|
|
4
4
|
import type { FieldGroupProps } from './types';
|
|
5
5
|
import { useUniversalLifecycle } from '../hooks';
|
|
6
6
|
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
container: {
|
|
9
|
+
backgroundColor: '#f2f2f7',
|
|
10
|
+
flex: 1,
|
|
11
|
+
},
|
|
12
|
+
containerDark: {
|
|
13
|
+
backgroundColor: '#000000',
|
|
14
|
+
},
|
|
15
|
+
hidden: {
|
|
16
|
+
display: 'none',
|
|
17
|
+
},
|
|
18
|
+
contentContainer: {
|
|
19
|
+
paddingHorizontal: 16,
|
|
20
|
+
paddingVertical: 16,
|
|
21
|
+
gap: 24,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
7
25
|
/**
|
|
8
26
|
* A scrollable container for grouped settings-style rows, mirroring the look
|
|
9
27
|
* of an iOS Settings screen. Render one or more
|
|
@@ -16,7 +34,7 @@ export function FieldGroup({
|
|
|
16
34
|
style,
|
|
17
35
|
onAppear,
|
|
18
36
|
onDisappear,
|
|
19
|
-
hidden,
|
|
37
|
+
hidden = false,
|
|
20
38
|
testID,
|
|
21
39
|
}: FieldGroupProps) {
|
|
22
40
|
useUniversalLifecycle(onAppear, onDisappear);
|
|
@@ -26,36 +44,14 @@ export function FieldGroup({
|
|
|
26
44
|
return (
|
|
27
45
|
<ScrollView
|
|
28
46
|
style={[
|
|
29
|
-
|
|
30
|
-
isDarkScheme
|
|
47
|
+
styles.container,
|
|
48
|
+
isDarkScheme && styles.containerDark,
|
|
31
49
|
style,
|
|
32
|
-
hidden
|
|
50
|
+
hidden && styles.hidden,
|
|
33
51
|
]}
|
|
34
|
-
contentContainerStyle={
|
|
52
|
+
contentContainerStyle={styles.contentContainer}
|
|
35
53
|
testID={testID}>
|
|
36
54
|
{groupFieldGroupChildren(children)}
|
|
37
55
|
</ScrollView>
|
|
38
56
|
);
|
|
39
57
|
}
|
|
40
|
-
|
|
41
|
-
const containerBaseStyle: ViewStyle = {
|
|
42
|
-
flex: 1,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const containerLightStyle: ViewStyle = {
|
|
46
|
-
backgroundColor: '#f2f2f7',
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const containerDarkStyle: ViewStyle = {
|
|
50
|
-
backgroundColor: '#000000',
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const hiddenStyle: ViewStyle = {
|
|
54
|
-
display: 'none',
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const contentContainerStyle: ViewStyle = {
|
|
58
|
-
paddingHorizontal: 16,
|
|
59
|
-
paddingVertical: 16,
|
|
60
|
-
gap: 24,
|
|
61
|
-
};
|
|
@@ -1,10 +1,62 @@
|
|
|
1
1
|
import { Fragment } from 'react';
|
|
2
|
-
import { Text, useColorScheme, View
|
|
2
|
+
import { StyleSheet, Text, useColorScheme, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { extractFieldSectionSlots } from './FieldSectionSlots';
|
|
5
5
|
import type { FieldSectionProps } from './types';
|
|
6
6
|
import { useUniversalLifecycle } from '../hooks';
|
|
7
7
|
|
|
8
|
+
const styles = StyleSheet.create({
|
|
9
|
+
hidden: {
|
|
10
|
+
display: 'none',
|
|
11
|
+
},
|
|
12
|
+
headerContainer: {
|
|
13
|
+
paddingHorizontal: 16,
|
|
14
|
+
paddingBottom: 8,
|
|
15
|
+
},
|
|
16
|
+
headerText: {
|
|
17
|
+
color: '#6c6c70',
|
|
18
|
+
fontSize: 14,
|
|
19
|
+
fontWeight: '500',
|
|
20
|
+
},
|
|
21
|
+
headerTextDark: {
|
|
22
|
+
color: '#98989e',
|
|
23
|
+
},
|
|
24
|
+
headerTextUppercase: {
|
|
25
|
+
textTransform: 'uppercase',
|
|
26
|
+
letterSpacing: 0.5,
|
|
27
|
+
fontSize: 13,
|
|
28
|
+
},
|
|
29
|
+
card: {
|
|
30
|
+
backgroundColor: '#ffffff',
|
|
31
|
+
borderRadius: 12,
|
|
32
|
+
overflow: 'hidden',
|
|
33
|
+
},
|
|
34
|
+
cardDark: {
|
|
35
|
+
backgroundColor: '#1c1c1e',
|
|
36
|
+
},
|
|
37
|
+
// Gives each row the same minimum height SwiftUI `Form` uses for single-line
|
|
38
|
+
// rows on iOS, so a text-only row doesn't collapse to its text intrinsic
|
|
39
|
+
// size. Taller content (e.g. a Switch) grows the row naturally. Horizontal
|
|
40
|
+
// padding matches SwiftUI `Form`'s built-in row leading/trailing inset.
|
|
41
|
+
rowWrapper: {
|
|
42
|
+
minHeight: 44,
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
paddingHorizontal: 16,
|
|
45
|
+
},
|
|
46
|
+
divider: {
|
|
47
|
+
backgroundColor: '#e5e5ea',
|
|
48
|
+
height: 1,
|
|
49
|
+
marginLeft: 16,
|
|
50
|
+
},
|
|
51
|
+
dividerDark: {
|
|
52
|
+
backgroundColor: '#38383a',
|
|
53
|
+
},
|
|
54
|
+
footerContainer: {
|
|
55
|
+
paddingHorizontal: 16,
|
|
56
|
+
paddingTop: 8,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
8
60
|
/**
|
|
9
61
|
* A grouped list of rows within a [`FieldGroup`](#fieldgroup). Each direct
|
|
10
62
|
* child is rendered as a single row. Use `title` for a simple caption header,
|
|
@@ -27,105 +79,35 @@ export function FieldSection({
|
|
|
27
79
|
|
|
28
80
|
const { header, footer, rows } = extractFieldSectionSlots(children);
|
|
29
81
|
|
|
30
|
-
const containerStyle: ViewStyle = {
|
|
31
|
-
...style,
|
|
32
|
-
...(hidden ? { display: 'none' } : undefined),
|
|
33
|
-
};
|
|
34
|
-
|
|
35
82
|
const headerNode =
|
|
36
83
|
header ??
|
|
37
84
|
(title ? (
|
|
38
85
|
<Text
|
|
39
86
|
style={[
|
|
40
|
-
|
|
41
|
-
isDarkScheme
|
|
42
|
-
titleUppercase
|
|
87
|
+
styles.headerText,
|
|
88
|
+
isDarkScheme && styles.headerTextDark,
|
|
89
|
+
titleUppercase && styles.headerTextUppercase,
|
|
43
90
|
]}>
|
|
44
91
|
{title}
|
|
45
92
|
</Text>
|
|
46
93
|
) : null);
|
|
47
94
|
|
|
48
95
|
return (
|
|
49
|
-
<View style={
|
|
50
|
-
{headerNode ? <View style={
|
|
96
|
+
<View style={[style, hidden && styles.hidden]} testID={testID}>
|
|
97
|
+
{headerNode ? <View style={styles.headerContainer}>{headerNode}</View> : null}
|
|
51
98
|
{rows.length > 0 ? (
|
|
52
|
-
<View style={[
|
|
99
|
+
<View style={[styles.card, isDarkScheme && styles.cardDark]}>
|
|
53
100
|
{rows.map((child, index) => (
|
|
54
101
|
<Fragment key={index}>
|
|
55
|
-
<View style={
|
|
102
|
+
<View style={styles.rowWrapper}>{child}</View>
|
|
56
103
|
{index < rows.length - 1 ? (
|
|
57
|
-
<View style={[
|
|
104
|
+
<View style={[styles.divider, isDarkScheme && styles.dividerDark]} />
|
|
58
105
|
) : null}
|
|
59
106
|
</Fragment>
|
|
60
107
|
))}
|
|
61
108
|
</View>
|
|
62
109
|
) : null}
|
|
63
|
-
{footer ? <View style={
|
|
110
|
+
{footer ? <View style={styles.footerContainer}>{footer}</View> : null}
|
|
64
111
|
</View>
|
|
65
112
|
);
|
|
66
113
|
}
|
|
67
|
-
|
|
68
|
-
const headerContainerStyle: ViewStyle = {
|
|
69
|
-
paddingHorizontal: 16,
|
|
70
|
-
paddingBottom: 8,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const headerTextStyle: TextStyle = {
|
|
74
|
-
fontSize: 14,
|
|
75
|
-
fontWeight: '500',
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const headerTextLightStyle: TextStyle = {
|
|
79
|
-
color: '#6c6c70',
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const headerTextDarkStyle: TextStyle = {
|
|
83
|
-
color: '#98989e',
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const headerTextUppercaseStyle: TextStyle = {
|
|
87
|
-
textTransform: 'uppercase',
|
|
88
|
-
letterSpacing: 0.5,
|
|
89
|
-
fontSize: 13,
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const cardBaseStyle: ViewStyle = {
|
|
93
|
-
borderRadius: 12,
|
|
94
|
-
overflow: 'hidden',
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const cardLightStyle: ViewStyle = {
|
|
98
|
-
backgroundColor: '#ffffff',
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const cardDarkStyle: ViewStyle = {
|
|
102
|
-
backgroundColor: '#1c1c1e',
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Gives each row the same minimum height SwiftUI `Form` uses for single-line
|
|
106
|
-
// rows on iOS, so a text-only row doesn't collapse to its text intrinsic
|
|
107
|
-
// size. Taller content (e.g. a Switch) grows the row naturally. Horizontal
|
|
108
|
-
// padding matches SwiftUI `Form`'s built-in row leading/trailing inset.
|
|
109
|
-
const rowWrapperStyle: ViewStyle = {
|
|
110
|
-
minHeight: 44,
|
|
111
|
-
justifyContent: 'center',
|
|
112
|
-
paddingHorizontal: 16,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const dividerStyle: ViewStyle = {
|
|
116
|
-
height: 1,
|
|
117
|
-
marginLeft: 16,
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const dividerLightStyle: ViewStyle = {
|
|
121
|
-
backgroundColor: '#e5e5ea',
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const dividerDarkStyle: ViewStyle = {
|
|
125
|
-
backgroundColor: '#38383a',
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const footerContainerStyle: ViewStyle = {
|
|
129
|
-
paddingHorizontal: 16,
|
|
130
|
-
paddingTop: 8,
|
|
131
|
-
};
|
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
import { Pressable, View, type ViewStyle } from 'react-native';
|
|
1
|
+
import { Pressable, StyleSheet, View, type ViewStyle } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { RowProps } from './types';
|
|
4
4
|
import { useUniversalLifecycle } from '../hooks';
|
|
5
5
|
import type { UniversalAlignment } from '../types';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
row: {
|
|
9
|
+
// Fill the parent's cross-axis by default so a `<Spacer flexible />`
|
|
10
|
+
// child has room to grow. Without this, a Row placed inside a `Column`
|
|
11
|
+
// with alignment other than 'stretch' is content-sized on web, which
|
|
12
|
+
// leaves flex children with no leftover space. SwiftUI and Compose
|
|
13
|
+
// achieve the same effect via their own layout phases.
|
|
14
|
+
alignSelf: 'stretch',
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
},
|
|
17
|
+
hidden: { display: 'none' },
|
|
18
|
+
disabled: {
|
|
19
|
+
opacity: 0.5,
|
|
20
|
+
pointerEvents: 'none',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const alignmentStyles = StyleSheet.create({
|
|
25
|
+
start: { alignItems: 'flex-start' },
|
|
26
|
+
center: { alignItems: 'center' },
|
|
27
|
+
end: { alignItems: 'flex-end' },
|
|
28
|
+
} satisfies Record<UniversalAlignment, ViewStyle>);
|
|
12
29
|
|
|
13
30
|
/**
|
|
14
31
|
* A horizontal layout container that arranges its children from start to end.
|
|
@@ -21,31 +38,27 @@ export function Row({
|
|
|
21
38
|
onPress,
|
|
22
39
|
onAppear,
|
|
23
40
|
onDisappear,
|
|
24
|
-
disabled,
|
|
25
|
-
hidden,
|
|
41
|
+
disabled = false,
|
|
42
|
+
hidden = false,
|
|
26
43
|
testID,
|
|
27
44
|
}: RowProps) {
|
|
28
45
|
useUniversalLifecycle(onAppear, onDisappear);
|
|
29
46
|
|
|
30
|
-
const viewStyle: ViewStyle = {
|
|
31
|
-
// Fill the parent's cross-axis by default so a `<Spacer flexible />`
|
|
32
|
-
// child has room to grow. Without this, a Row placed inside a `Column`
|
|
33
|
-
// with alignment other than 'stretch' is content-sized on web, which
|
|
34
|
-
// leaves flex children with no leftover space. SwiftUI and Compose
|
|
35
|
-
// achieve the same effect via their own layout phases.
|
|
36
|
-
alignSelf: 'stretch',
|
|
37
|
-
flexDirection: 'row',
|
|
38
|
-
alignItems: alignmentMap[alignment],
|
|
39
|
-
gap: spacing,
|
|
40
|
-
...style,
|
|
41
|
-
...(hidden ? { display: 'none' } : undefined),
|
|
42
|
-
...(disabled ? { opacity: 0.5, pointerEvents: 'none' } : undefined),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
47
|
const Container = onPress ? Pressable : View;
|
|
46
48
|
|
|
47
49
|
return (
|
|
48
|
-
<Container
|
|
50
|
+
<Container
|
|
51
|
+
onPress={onPress}
|
|
52
|
+
disabled={disabled}
|
|
53
|
+
testID={testID}
|
|
54
|
+
style={[
|
|
55
|
+
styles.row,
|
|
56
|
+
alignmentStyles[alignment],
|
|
57
|
+
spacing != null && { gap: spacing },
|
|
58
|
+
style,
|
|
59
|
+
hidden && styles.hidden,
|
|
60
|
+
disabled && styles.disabled,
|
|
61
|
+
]}>
|
|
49
62
|
{children}
|
|
50
63
|
</Container>
|
|
51
64
|
);
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import { ScrollView as RNScrollView,
|
|
1
|
+
import { ScrollView as RNScrollView, StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { ScrollViewProps } from './types';
|
|
4
4
|
import { useUniversalLifecycle } from '../hooks';
|
|
5
5
|
|
|
6
|
+
const styles = StyleSheet.create({
|
|
7
|
+
container: {
|
|
8
|
+
// Constrain to viewport width so horizontal content overflows and scrolls
|
|
9
|
+
// instead of expanding the parent layout.
|
|
10
|
+
// @ts-expect-error
|
|
11
|
+
maxWidth: '100vw',
|
|
12
|
+
},
|
|
13
|
+
noGrow: { flexGrow: 0 },
|
|
14
|
+
hidden: { display: 'none' },
|
|
15
|
+
disabled: {
|
|
16
|
+
opacity: 0.5,
|
|
17
|
+
pointerEvents: 'none',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
6
21
|
/**
|
|
7
22
|
* A scrollable container that supports vertical or horizontal scrolling.
|
|
8
23
|
*/
|
|
@@ -15,24 +30,14 @@ export function ScrollView({
|
|
|
15
30
|
// API compatibility but silently ignored (RN ScrollView has no press handler).
|
|
16
31
|
onAppear,
|
|
17
32
|
onDisappear,
|
|
18
|
-
disabled,
|
|
19
|
-
hidden,
|
|
33
|
+
disabled = false,
|
|
34
|
+
hidden = false,
|
|
20
35
|
testID,
|
|
21
36
|
}: ScrollViewProps) {
|
|
22
37
|
useUniversalLifecycle(onAppear, onDisappear);
|
|
23
38
|
|
|
24
39
|
const isHorizontal = direction === 'horizontal';
|
|
25
40
|
|
|
26
|
-
const containerStyle: ViewStyle = {
|
|
27
|
-
// Constrain to viewport width so horizontal content overflows and scrolls
|
|
28
|
-
// instead of expanding the parent layout.
|
|
29
|
-
maxWidth: '100vw' as any,
|
|
30
|
-
...style,
|
|
31
|
-
...(style?.height != null ? { flexGrow: 0 } : undefined),
|
|
32
|
-
...(hidden ? { display: 'none' } : undefined),
|
|
33
|
-
...(disabled ? { opacity: 0.5, pointerEvents: 'none' } : undefined),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
41
|
// react-native-web does not support separate vertical and horizontal indicator props,
|
|
37
42
|
// so we map both to its single `showsIndicators` prop.
|
|
38
43
|
const showVerticalIndicator = showsIndicators;
|
|
@@ -43,9 +48,15 @@ export function ScrollView({
|
|
|
43
48
|
horizontal={isHorizontal}
|
|
44
49
|
showsVerticalScrollIndicator={showVerticalIndicator}
|
|
45
50
|
showsHorizontalScrollIndicator={showHorizontalIndicator}
|
|
46
|
-
style={containerStyle}
|
|
47
51
|
nestedScrollEnabled
|
|
48
|
-
testID={testID}
|
|
52
|
+
testID={testID}
|
|
53
|
+
style={[
|
|
54
|
+
styles.container,
|
|
55
|
+
style,
|
|
56
|
+
style?.height != null && styles.noGrow,
|
|
57
|
+
hidden && styles.hidden,
|
|
58
|
+
disabled && styles.disabled,
|
|
59
|
+
]}>
|
|
49
60
|
{children}
|
|
50
61
|
</RNScrollView>
|
|
51
62
|
);
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import { StyleSheet, unstable_createElement, View, type ViewProps } from 'react-native';
|
|
2
3
|
|
|
3
4
|
import type { SliderProps } from './types';
|
|
4
5
|
|
|
6
|
+
const styles = StyleSheet.create({
|
|
7
|
+
view: {
|
|
8
|
+
alignSelf: 'stretch',
|
|
9
|
+
justifyContent: 'center',
|
|
10
|
+
},
|
|
11
|
+
input: {
|
|
12
|
+
width: '100%',
|
|
13
|
+
cursor: 'pointer',
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const NativeSlider = (
|
|
18
|
+
props: Omit<ComponentProps<'input'>, 'style' | 'type'> & { style?: ViewProps['style'] }
|
|
19
|
+
) => unstable_createElement('input', { ...props, type: 'range' });
|
|
20
|
+
|
|
5
21
|
/**
|
|
6
22
|
* A control for selecting a value from a continuous or stepped range.
|
|
7
23
|
*/
|
|
@@ -11,13 +27,12 @@ export function Slider({
|
|
|
11
27
|
min = 0,
|
|
12
28
|
max = 1,
|
|
13
29
|
step,
|
|
14
|
-
disabled,
|
|
30
|
+
disabled = false,
|
|
15
31
|
testID,
|
|
16
32
|
}: SliderProps) {
|
|
17
33
|
return (
|
|
18
|
-
<View style={
|
|
19
|
-
<
|
|
20
|
-
type="range"
|
|
34
|
+
<View style={styles.view}>
|
|
35
|
+
<NativeSlider
|
|
21
36
|
value={value}
|
|
22
37
|
min={min}
|
|
23
38
|
max={max}
|
|
@@ -25,20 +40,10 @@ export function Slider({
|
|
|
25
40
|
disabled={disabled}
|
|
26
41
|
onChange={(e) => onValueChange(parseFloat(e.target.value))}
|
|
27
42
|
data-testid={testID}
|
|
28
|
-
style={
|
|
43
|
+
style={styles.input}
|
|
29
44
|
/>
|
|
30
45
|
</View>
|
|
31
46
|
);
|
|
32
47
|
}
|
|
33
48
|
|
|
34
|
-
const containerStyle: ViewStyle = {
|
|
35
|
-
alignSelf: 'stretch',
|
|
36
|
-
justifyContent: 'center',
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const inputStyle: React.CSSProperties = {
|
|
40
|
-
width: '100%',
|
|
41
|
-
cursor: 'pointer',
|
|
42
|
-
};
|
|
43
|
-
|
|
44
49
|
export * from './types';
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StyleSheet, View } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { SpacerProps } from './types';
|
|
4
4
|
import { useUniversalLifecycle } from '../hooks';
|
|
5
5
|
|
|
6
|
+
const styles = StyleSheet.create({
|
|
7
|
+
flexible: { flex: 1 },
|
|
8
|
+
hidden: { display: 'none' },
|
|
9
|
+
});
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
12
|
* A layout spacer that produces empty space between siblings in a
|
|
8
13
|
* `Row` or `Column`.
|
|
@@ -13,19 +18,22 @@ export function Spacer({
|
|
|
13
18
|
style,
|
|
14
19
|
onAppear,
|
|
15
20
|
onDisappear,
|
|
16
|
-
hidden,
|
|
21
|
+
hidden = false,
|
|
17
22
|
testID,
|
|
18
23
|
}: SpacerProps) {
|
|
19
24
|
useUniversalLifecycle(onAppear, onDisappear);
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
return (
|
|
27
|
+
<View
|
|
28
|
+
testID={testID}
|
|
29
|
+
style={[
|
|
30
|
+
flexible && styles.flexible,
|
|
31
|
+
size != null && { width: size, height: size },
|
|
32
|
+
style,
|
|
33
|
+
hidden && styles.hidden,
|
|
34
|
+
]}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
export * from './types';
|
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
import { Switch as RNSwitch, View, Text } from 'react-native';
|
|
1
|
+
import { Switch as RNSwitch, View, Text, StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import type { SwitchProps } from './types';
|
|
4
4
|
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
view: {
|
|
7
|
+
flexDirection: 'row',
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
justifyContent: 'space-between',
|
|
10
|
+
gap: 8,
|
|
11
|
+
},
|
|
12
|
+
disabled: {
|
|
13
|
+
opacity: 0.5,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
5
17
|
/**
|
|
6
18
|
* A toggle control that switches between on and off states.
|
|
7
19
|
*/
|
|
8
|
-
export function Switch({ value, onValueChange, label, disabled, testID }: SwitchProps) {
|
|
20
|
+
export function Switch({ value, onValueChange, label, disabled = false, testID }: SwitchProps) {
|
|
9
21
|
if (label) {
|
|
10
22
|
return (
|
|
11
|
-
<View
|
|
12
|
-
style={{
|
|
13
|
-
flexDirection: 'row',
|
|
14
|
-
alignItems: 'center',
|
|
15
|
-
justifyContent: 'space-between',
|
|
16
|
-
gap: 8,
|
|
17
|
-
opacity: disabled ? 0.5 : 1,
|
|
18
|
-
}}>
|
|
23
|
+
<View style={[styles.view, disabled && styles.disabled]}>
|
|
19
24
|
<Text>{label}</Text>
|
|
20
25
|
<RNSwitch value={value} onValueChange={onValueChange} disabled={disabled} testID={testID} />
|
|
21
26
|
</View>
|