@expo/ui 57.0.12 → 57.0.14
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 +33 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +17 -3
- package/android/src/main/java/expo/modules/ui/ModalBottomSheetView.kt +50 -0
- package/android/src/main/java/expo/modules/ui/ProgressView.kt +31 -0
- package/android/src/main/java/expo/modules/ui/RNHostView.kt +141 -11
- package/build/PresentedContentContext.d.ts +18 -0
- package/build/PresentedContentContext.d.ts.map +1 -0
- package/build/community/pager-view/PagerView.android.d.ts.map +1 -1
- package/build/jetpack-compose/AlertDialog/index.d.ts.map +1 -1
- package/build/jetpack-compose/BasicAlertDialog/index.d.ts.map +1 -1
- package/build/jetpack-compose/DropdownMenu/index.d.ts.map +1 -1
- package/build/jetpack-compose/ExposedDropdownMenuBox/ExposedDropdownMenu.d.ts.map +1 -1
- package/build/jetpack-compose/Host/index.d.ts +3 -0
- package/build/jetpack-compose/Host/index.d.ts.map +1 -1
- package/build/jetpack-compose/ModalBottomSheet/index.d.ts.map +1 -1
- package/build/jetpack-compose/Progress/index.d.ts +25 -2
- package/build/jetpack-compose/Progress/index.d.ts.map +1 -1
- package/build/jetpack-compose/RNHostView/index.d.ts +0 -6
- package/build/jetpack-compose/RNHostView/index.d.ts.map +1 -1
- package/build/jetpack-compose/TextField/shared.d.ts +2 -1
- package/build/jetpack-compose/TextField/shared.d.ts.map +1 -1
- package/build/jetpack-compose/Tooltip/index.d.ts.map +1 -1
- package/build/keyboard/index.d.ts +43 -0
- package/build/keyboard/index.d.ts.map +1 -0
- package/build/keyboard/interop.d.ts +16 -0
- package/build/keyboard/interop.d.ts.map +1 -0
- package/build/keyboard/textInputState.d.ts +2 -0
- package/build/keyboard/textInputState.d.ts.map +1 -0
- package/build/keyboard/textInputState.web.d.ts +11 -0
- package/build/keyboard/textInputState.web.d.ts.map +1 -0
- package/build/swift-ui/Background/index.d.ts +18 -0
- package/build/swift-ui/Background/index.d.ts.map +1 -0
- package/build/swift-ui/BottomSheet/index.d.ts.map +1 -1
- package/build/swift-ui/Host/index.d.ts +3 -0
- package/build/swift-ui/Host/index.d.ts.map +1 -1
- package/build/swift-ui/Popover/index.d.ts.map +1 -1
- package/build/swift-ui/RNHostView.d.ts +2 -1
- package/build/swift-ui/RNHostView.d.ts.map +1 -1
- package/build/swift-ui/SecureField/index.d.ts.map +1 -1
- package/build/swift-ui/TextField/index.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/index.d.ts +21 -1
- package/build/swift-ui/modifiers/index.d.ts.map +1 -1
- package/build/universal/BottomSheet/index.android.d.ts +1 -1
- package/build/universal/BottomSheet/index.android.d.ts.map +1 -1
- package/build/universal/BottomSheet/types.d.ts +14 -0
- package/build/universal/BottomSheet/types.d.ts.map +1 -1
- package/build/utils/useMergeRefs.d.ts +12 -0
- package/build/utils/useMergeRefs.d.ts.map +1 -0
- package/expo-module.config.json +1 -1
- package/ios/BackgroundView.swift +34 -0
- package/ios/ColorPickerView.swift +1 -1
- package/ios/ExpoUIModule.swift +4 -0
- package/ios/HostView.swift +7 -0
- package/ios/Modifiers/ViewModifierRegistry.swift +48 -0
- package/ios/RNHostView.swift +65 -4
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.12/expo.modules.ui-57.0.12-sources.jar → 57.0.14/expo.modules.ui-57.0.14-sources.jar} +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14-sources.jar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14-sources.jar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14-sources.jar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14-sources.jar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.aar.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.aar.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.aar.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.aar.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.12/expo.modules.ui-57.0.12.module → 57.0.14/expo.modules.ui-57.0.14.module} +22 -22
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.module.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.module.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.module.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.module.sha512 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/{57.0.12/expo.modules.ui-57.0.12.pom → 57.0.14/expo.modules.ui-57.0.14.pom} +1 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.pom.md5 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.pom.sha1 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.pom.sha256 +1 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.14/expo.modules.ui-57.0.14.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/PresentedContentContext.tsx +22 -0
- package/src/community/pager-view/PagerView.android.tsx +1 -7
- package/src/jetpack-compose/AlertDialog/index.tsx +6 -1
- package/src/jetpack-compose/BasicAlertDialog/index.tsx +7 -1
- package/src/jetpack-compose/DropdownMenu/index.tsx +7 -1
- package/src/jetpack-compose/ExposedDropdownMenuBox/ExposedDropdownMenu.tsx +3 -1
- package/src/jetpack-compose/Host/index.tsx +28 -17
- package/src/jetpack-compose/ModalBottomSheet/index.tsx +8 -1
- package/src/jetpack-compose/Progress/index.tsx +32 -2
- package/src/jetpack-compose/RNHostView/index.tsx +16 -13
- package/src/jetpack-compose/TextField/shared.ts +7 -1
- package/src/jetpack-compose/Tooltip/index.tsx +2 -1
- package/src/keyboard/index.tsx +243 -0
- package/src/keyboard/interop.ts +99 -0
- package/src/keyboard/textInputState.ts +2 -0
- package/src/keyboard/textInputState.web.ts +16 -0
- package/src/swift-ui/Background/index.tsx +38 -0
- package/src/swift-ui/BottomSheet/index.tsx +4 -1
- package/src/swift-ui/Host/index.tsx +33 -18
- package/src/swift-ui/Popover/index.tsx +7 -1
- package/src/swift-ui/RNHostView.tsx +17 -3
- package/src/swift-ui/SecureField/index.tsx +8 -2
- package/src/swift-ui/TextField/index.tsx +8 -1
- package/src/swift-ui/index.tsx +1 -0
- package/src/swift-ui/modifiers/index.ts +25 -0
- package/src/ts-declarations/react-native-text-input-state.d.ts +26 -0
- package/src/universal/BottomSheet/index.android.tsx +4 -1
- package/src/universal/BottomSheet/types.ts +17 -0
- package/src/utils/useMergeRefs.ts +47 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12-sources.jar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12-sources.jar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12-sources.jar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12-sources.jar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar +0 -0
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.sha512 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.md5 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha1 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha256 +0 -1
- package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha512 +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { requireNativeView } from 'expo';
|
|
2
|
+
|
|
3
|
+
import { Slot } from '../SlotView';
|
|
4
|
+
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
5
|
+
import { type Alignment, type CommonViewModifierProps } from '../types';
|
|
6
|
+
|
|
7
|
+
export interface BackgroundProps extends CommonViewModifierProps {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* The alignment of the background content relative to the base content.
|
|
11
|
+
* @default 'center'
|
|
12
|
+
*/
|
|
13
|
+
alignment?: Alignment;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const BackgroundNativeView: React.ComponentType<BackgroundProps> = requireNativeView(
|
|
17
|
+
'ExpoUI',
|
|
18
|
+
'BackgroundView'
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function BackgroundContent(props: { children: React.ReactNode }) {
|
|
22
|
+
return <Slot name="content">{props.children}</Slot>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Background.Content = BackgroundContent;
|
|
26
|
+
|
|
27
|
+
export function Background(props: BackgroundProps) {
|
|
28
|
+
const { modifiers, children, ...restProps } = props;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<BackgroundNativeView
|
|
32
|
+
{...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
|
|
33
|
+
modifiers={modifiers}
|
|
34
|
+
{...restProps}>
|
|
35
|
+
{children}
|
|
36
|
+
</BackgroundNativeView>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -2,6 +2,7 @@ import { requireNativeView } from 'expo';
|
|
|
2
2
|
import { useState, type ComponentType, type ReactNode } from 'react';
|
|
3
3
|
import { type NativeSyntheticEvent } from 'react-native';
|
|
4
4
|
|
|
5
|
+
import { PresentedContent } from '../../PresentedContentContext';
|
|
5
6
|
import { Slot } from '../SlotView';
|
|
6
7
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
7
8
|
import { type CommonViewModifierProps } from '../types';
|
|
@@ -76,7 +77,9 @@ function BottomSheet(props: BottomSheetProps) {
|
|
|
76
77
|
onDismiss?.();
|
|
77
78
|
}}>
|
|
78
79
|
{anchor != null ? <Slot name="anchor">{anchor}</Slot> : null}
|
|
79
|
-
{
|
|
80
|
+
{/* Only the sheet's content is presented in its own view controller. The anchor renders in
|
|
81
|
+
place, in the React Native surface, so it stays outside `PresentedContent`. */}
|
|
82
|
+
{isMounted ? <PresentedContent>{children}</PresentedContent> : null}
|
|
80
83
|
</BottomSheetNativeView>
|
|
81
84
|
);
|
|
82
85
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { requireNativeView } from 'expo';
|
|
2
|
+
import type { Ref } from 'react';
|
|
2
3
|
import { I18nManager, type ColorValue, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
4
|
|
|
5
|
+
import { TextInputHostProvider, useTextInputHostRef } from '../../keyboard';
|
|
6
|
+
import { useMergeRefs } from '../../utils/useMergeRefs';
|
|
4
7
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
5
8
|
import { type CommonViewModifierProps } from '../types';
|
|
6
9
|
|
|
@@ -54,10 +57,16 @@ export interface HostProps extends CommonViewModifierProps {
|
|
|
54
57
|
children: React.ReactNode;
|
|
55
58
|
style?: StyleProp<ViewStyle>;
|
|
56
59
|
pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto';
|
|
60
|
+
/** @hidden */
|
|
61
|
+
ref?: Ref<any>;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
const HostNativeView: React.ComponentType<
|
|
60
|
-
HostProps & {
|
|
65
|
+
HostProps & {
|
|
66
|
+
matchContentsVertical?: boolean;
|
|
67
|
+
matchContentsHorizontal?: boolean;
|
|
68
|
+
ref?: Ref<any>;
|
|
69
|
+
}
|
|
61
70
|
> = requireNativeView('ExpoUI', 'HostView');
|
|
62
71
|
|
|
63
72
|
/**
|
|
@@ -71,26 +80,32 @@ export function Host(props: HostProps) {
|
|
|
71
80
|
modifiers,
|
|
72
81
|
layoutDirection,
|
|
73
82
|
seedColor,
|
|
83
|
+
ref,
|
|
74
84
|
...restProps
|
|
75
85
|
} = props;
|
|
86
|
+
const hostRef = useTextInputHostRef();
|
|
87
|
+
const mergedRef = useMergeRefs(ref, hostRef);
|
|
76
88
|
|
|
77
89
|
return (
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
layoutDirection
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
<TextInputHostProvider hostRef={hostRef}>
|
|
91
|
+
<HostNativeView
|
|
92
|
+
modifiers={modifiers}
|
|
93
|
+
{...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
|
|
94
|
+
matchContentsVertical={
|
|
95
|
+
typeof matchContents === 'object' ? matchContents.vertical : matchContents
|
|
96
|
+
}
|
|
97
|
+
matchContentsHorizontal={
|
|
98
|
+
typeof matchContents === 'object' ? matchContents.horizontal : matchContents
|
|
99
|
+
}
|
|
100
|
+
onLayoutContent={onLayoutContent}
|
|
101
|
+
layoutDirection={
|
|
102
|
+
layoutDirection ?? (I18nManager.getConstants().isRTL ? 'rightToLeft' : 'leftToRight')
|
|
103
|
+
}
|
|
104
|
+
ignoreSafeArea={ignoreSafeArea}
|
|
105
|
+
seedColor={seedColor}
|
|
106
|
+
{...restProps}
|
|
107
|
+
ref={mergedRef}
|
|
108
|
+
/>
|
|
109
|
+
</TextInputHostProvider>
|
|
95
110
|
);
|
|
96
111
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { requireNativeView } from 'expo';
|
|
2
2
|
import type { NativeSyntheticEvent } from 'react-native';
|
|
3
3
|
|
|
4
|
+
import { PresentedContent } from '../../PresentedContentContext';
|
|
4
5
|
import { Slot } from '../SlotView';
|
|
5
6
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
6
7
|
import type { CommonViewModifierProps } from '../types';
|
|
@@ -40,7 +41,12 @@ function PopoverTrigger(props: { children: React.ReactNode }) {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function PopoverContent(props: { children: React.ReactNode }) {
|
|
43
|
-
|
|
44
|
+
// Presented in its own view controller; the trigger renders in place, so only this side is wrapped.
|
|
45
|
+
return (
|
|
46
|
+
<Slot name="popover">
|
|
47
|
+
<PresentedContent>{props.children}</PresentedContent>
|
|
48
|
+
</Slot>
|
|
49
|
+
);
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
Popover.Trigger = PopoverTrigger;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { requireNativeView } from 'expo';
|
|
2
2
|
|
|
3
|
+
import { PresentedContentContext, useIsPresentedInOwnWindow } from '../PresentedContentContext';
|
|
4
|
+
|
|
3
5
|
const RNHostNativeView: React.ComponentType<any> = requireNativeView('ExpoUI', 'RNHostView');
|
|
4
6
|
|
|
5
7
|
export interface RNHostViewProps {
|
|
6
8
|
/**
|
|
7
|
-
* When `true`, the RNHost will update its size in the React Native view tree to match the
|
|
9
|
+
* When `true`, the RNHost will update its size in the React Native view tree to match the
|
|
10
|
+
* children's size.
|
|
8
11
|
* When `false`, the RNHost will use the size of the parent SwiftUI View.
|
|
9
12
|
* Can be only set once on mount.
|
|
10
13
|
* @default false
|
|
@@ -17,12 +20,23 @@ export interface RNHostViewProps {
|
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export function RNHostView(props: RNHostViewProps) {
|
|
23
|
+
// A sheet or popover presents its content in its own view controller, where the React Native
|
|
24
|
+
// surface root is not an ancestor and so touch dispatches don't work.
|
|
25
|
+
// Hosted content there owns its touches and is the origin it is measured from; native reads
|
|
26
|
+
// this one prop for both.
|
|
27
|
+
const layoutRoot = useIsPresentedInOwnWindow();
|
|
28
|
+
|
|
20
29
|
return (
|
|
21
30
|
<RNHostNativeView
|
|
22
31
|
{...props}
|
|
32
|
+
layoutRoot={layoutRoot}
|
|
23
33
|
// `matchContents` can only be used once on mount
|
|
24
34
|
// So we force unmount when it changes to prevent unexpected layout
|
|
25
|
-
key={props.matchContents ? 'matchContents' : 'noMatchContents'}
|
|
26
|
-
|
|
35
|
+
key={props.matchContents ? 'matchContents' : 'noMatchContents'}>
|
|
36
|
+
{/* Reset context here so only nearest RNHostView becomes the layout root for its children, and not any other RNHostView above it in the tree. */}
|
|
37
|
+
<PresentedContentContext.Provider value={false}>
|
|
38
|
+
{props.children}
|
|
39
|
+
</PresentedContentContext.Provider>
|
|
40
|
+
</RNHostNativeView>
|
|
27
41
|
);
|
|
28
42
|
}
|
|
@@ -2,6 +2,7 @@ import { requireNativeView } from 'expo';
|
|
|
2
2
|
import type { Ref } from 'react';
|
|
3
3
|
|
|
4
4
|
import { getStateId, type ObservableState, useWorkletProp, worklets } from '../../State';
|
|
5
|
+
import { useHostedTextInput } from '../../keyboard';
|
|
5
6
|
import type { ViewEvent } from '../../types';
|
|
6
7
|
import { Slot } from '../SlotView';
|
|
7
8
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
@@ -74,14 +75,19 @@ function Placeholder({ children }: { children: React.ReactNode }) {
|
|
|
74
75
|
* Renders a SwiftUI `SecureField` for password input.
|
|
75
76
|
*/
|
|
76
77
|
export function SecureField(props: SecureFieldProps) {
|
|
77
|
-
const { text, onTextChange, onFocusChange, modifiers, ...restProps } = props;
|
|
78
|
+
const { text, onTextChange, onFocusChange, modifiers, ref, ...restProps } = props;
|
|
78
79
|
|
|
79
80
|
const isWorklet = !!onTextChange && !!worklets?.isWorkletFunction?.(onTextChange);
|
|
80
81
|
const workletCallback = useWorkletProp(isWorklet ? onTextChange : undefined, 'onTextChange');
|
|
82
|
+
// `blurOnUnmount`: a field left first responder while its row is removed makes UIKit
|
|
83
|
+
// assert ("refused to resign"); native teardown hooks run too late to clear SwiftUI's
|
|
84
|
+
// `@FocusState`. https://github.com/expo/expo/issues/49348
|
|
85
|
+
const hosted = useHostedTextInput<SecureFieldRef>(ref, onFocusChange, { blurOnUnmount: true });
|
|
81
86
|
|
|
82
87
|
return (
|
|
83
88
|
<SecureFieldNativeView
|
|
84
89
|
{...restProps}
|
|
90
|
+
ref={hosted.ref}
|
|
85
91
|
modifiers={modifiers}
|
|
86
92
|
{...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
|
|
87
93
|
text={getStateId(text)}
|
|
@@ -89,7 +95,7 @@ export function SecureField(props: SecureFieldProps) {
|
|
|
89
95
|
onTextChange={
|
|
90
96
|
!isWorklet && onTextChange ? (event) => onTextChange(event.nativeEvent.value) : undefined
|
|
91
97
|
}
|
|
92
|
-
onFocusChange={
|
|
98
|
+
onFocusChange={(event) => hosted.onFocusChange(event.nativeEvent.value)}
|
|
93
99
|
/>
|
|
94
100
|
);
|
|
95
101
|
}
|
|
@@ -2,6 +2,7 @@ import { requireNativeView } from 'expo';
|
|
|
2
2
|
import type { Ref } from 'react';
|
|
3
3
|
|
|
4
4
|
import { getStateId, type ObservableState, useWorkletProp, worklets } from '../../State';
|
|
5
|
+
import { useHostedTextInput } from '../../keyboard';
|
|
5
6
|
import type { ViewEvent } from '../../types';
|
|
6
7
|
import { Slot } from '../SlotView';
|
|
7
8
|
import { createViewModifierEventListener } from '../modifiers/utils';
|
|
@@ -114,15 +115,21 @@ export function TextField(props: TextFieldProps) {
|
|
|
114
115
|
onFocusChange,
|
|
115
116
|
onSelectionChange,
|
|
116
117
|
modifiers,
|
|
118
|
+
ref,
|
|
117
119
|
...restProps
|
|
118
120
|
} = props;
|
|
119
121
|
|
|
120
122
|
const isWorklet = !!onTextChange && !!worklets?.isWorkletFunction?.(onTextChange);
|
|
121
123
|
const workletCallback = useWorkletProp(isWorklet ? onTextChange : undefined, 'onTextChange');
|
|
124
|
+
// `blurOnUnmount`: a field left first responder while its row is removed makes UIKit
|
|
125
|
+
// assert ("refused to resign"); native teardown hooks run too late to clear SwiftUI's
|
|
126
|
+
// `@FocusState`. https://github.com/expo/expo/issues/49348
|
|
127
|
+
const hosted = useHostedTextInput<TextFieldRef>(ref, onFocusChange, { blurOnUnmount: true });
|
|
122
128
|
|
|
123
129
|
return (
|
|
124
130
|
<TextFieldNativeView
|
|
125
131
|
{...restProps}
|
|
132
|
+
ref={hosted.ref}
|
|
126
133
|
modifiers={modifiers}
|
|
127
134
|
{...(modifiers ? createViewModifierEventListener(modifiers) : undefined)}
|
|
128
135
|
text={getStateId(text)}
|
|
@@ -131,7 +138,7 @@ export function TextField(props: TextFieldProps) {
|
|
|
131
138
|
onTextChange={
|
|
132
139
|
!isWorklet && onTextChange ? (event) => onTextChange(event.nativeEvent.value) : undefined
|
|
133
140
|
}
|
|
134
|
-
onFocusChange={
|
|
141
|
+
onFocusChange={(event) => hosted.onFocusChange(event.nativeEvent.value)}
|
|
135
142
|
onSelectionChange={
|
|
136
143
|
onSelectionChange
|
|
137
144
|
? (event) =>
|
package/src/swift-ui/index.tsx
CHANGED
|
@@ -1129,6 +1129,30 @@ export const listRowSeparatorTint = (color?: Color, edges?: 'all' | 'top' | 'bot
|
|
|
1129
1129
|
*/
|
|
1130
1130
|
export const listRowSpacing = (spacing?: number) => createModifier('listRowSpacing', { spacing });
|
|
1131
1131
|
|
|
1132
|
+
/**
|
|
1133
|
+
* Sets the position of a horizontal alignment guide of this view.
|
|
1134
|
+
*
|
|
1135
|
+
* Use the `'listRowSeparatorLeading'` guide to set where the separator of a `List` row starts.
|
|
1136
|
+
* SwiftUI insets a row separator past a leading `Image`, but not past other leading content, so
|
|
1137
|
+
* rows with different leading content get separators that start at different offsets.
|
|
1138
|
+
* @param guide - The horizontal alignment guide to set. `'listRowSeparatorLeading'` and
|
|
1139
|
+
* `'listRowSeparatorTrailing'` do nothing on tvOS, where SwiftUI does not provide them.
|
|
1140
|
+
* @param value - The position of the guide, in points from the leading edge of the view.
|
|
1141
|
+
* @see Official [SwiftUI documentation](https://developer.apple.com/documentation/swiftui/view/alignmentguide(_:computevalue:)-9mdoh).
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* ```tsx
|
|
1145
|
+
* <HStack modifiers={[alignmentGuide('listRowSeparatorLeading', 32)]}>
|
|
1146
|
+
* <Text>A</Text>
|
|
1147
|
+
* <Text>The separator starts 32 points from the leading edge</Text>
|
|
1148
|
+
* </HStack>
|
|
1149
|
+
* ```
|
|
1150
|
+
*/
|
|
1151
|
+
export const alignmentGuide = (
|
|
1152
|
+
guide: 'leading' | 'center' | 'trailing' | 'listRowSeparatorLeading' | 'listRowSeparatorTrailing',
|
|
1153
|
+
value: number
|
|
1154
|
+
) => createModifier('alignmentGuide', { guide, value });
|
|
1155
|
+
|
|
1132
1156
|
/**
|
|
1133
1157
|
* Sets the truncation mode for lines of text that are too long to fit in the available space.
|
|
1134
1158
|
* @param mode - The truncation mode that specifies where to truncate the text within the text view, if needed.
|
|
@@ -1743,6 +1767,7 @@ export type BuiltInModifier =
|
|
|
1743
1767
|
| ReturnType<typeof listRowSeparator>
|
|
1744
1768
|
| ReturnType<typeof listRowSeparatorTint>
|
|
1745
1769
|
| ReturnType<typeof listRowSpacing>
|
|
1770
|
+
| ReturnType<typeof alignmentGuide>
|
|
1746
1771
|
| ReturnType<typeof truncationMode>
|
|
1747
1772
|
| ReturnType<typeof allowsTightening>
|
|
1748
1773
|
| ReturnType<typeof kerning>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
declare module 'react-native/Libraries/Components/TextInput/TextInputState' {
|
|
2
|
+
import type { ReactNativeElement } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* React Native's registry of focusable text inputs. `ScrollView` reads it to
|
|
6
|
+
* decide whether a touch landed on the focused input, and `Keyboard.dismiss()`
|
|
7
|
+
* blurs whatever it points at. `TextInput.State` re-exports only a read-only
|
|
8
|
+
* subset publicly, so participating in the registry requires this module.
|
|
9
|
+
*/
|
|
10
|
+
const TextInputState: {
|
|
11
|
+
currentlyFocusedInput(): ReactNativeElement | null;
|
|
12
|
+
/** Marks an instance as focused. Does not dispatch a native focus command. */
|
|
13
|
+
focusInput(instance: ReactNativeElement | null): void;
|
|
14
|
+
/** Clears the focused instance, but only if it is the one passed in. */
|
|
15
|
+
blurInput(instance: ReactNativeElement | null): void;
|
|
16
|
+
registerInput(instance: ReactNativeElement): void;
|
|
17
|
+
unregisterInput(instance: ReactNativeElement): void;
|
|
18
|
+
isTextInput(instance: ReactNativeElement): boolean;
|
|
19
|
+
/** Marks an instance as focused, then dispatches a native `focus` command. */
|
|
20
|
+
focusTextInput(instance: ReactNativeElement | null): void;
|
|
21
|
+
/** Clears the focused instance, then dispatches a native `blur` command. */
|
|
22
|
+
blurTextInput(instance: ReactNativeElement | null): void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default TextInputState;
|
|
26
|
+
}
|
|
@@ -40,6 +40,8 @@ export function BottomSheet({
|
|
|
40
40
|
testID,
|
|
41
41
|
modifiers,
|
|
42
42
|
shouldDismissOnBackPress = true,
|
|
43
|
+
shouldDismissOnClickOutside = true,
|
|
44
|
+
scrimColor,
|
|
43
45
|
contentPadding,
|
|
44
46
|
}: BottomSheetProps) {
|
|
45
47
|
const sheetRef = useRef<ModalBottomSheetRef>(null);
|
|
@@ -82,7 +84,8 @@ export function BottomSheet({
|
|
|
82
84
|
onDismissRequest={onDismiss}
|
|
83
85
|
showDragHandle={showDragIndicator}
|
|
84
86
|
skipPartiallyExpanded={shouldSkipPartiallyExpanded(snapPoints)}
|
|
85
|
-
properties={{ shouldDismissOnBackPress }}
|
|
87
|
+
properties={{ shouldDismissOnBackPress, shouldDismissOnClickOutside }}
|
|
88
|
+
scrimColor={scrimColor}
|
|
86
89
|
modifiers={modifiers}>
|
|
87
90
|
<Column modifiers={contentModifiers}>{children}</Column>
|
|
88
91
|
</ModalBottomSheet>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ColorValue } from 'react-native';
|
|
2
|
+
|
|
1
3
|
import type { ModifierConfig } from '../../types';
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -88,6 +90,21 @@ export interface BottomSheetProps {
|
|
|
88
90
|
*/
|
|
89
91
|
shouldDismissOnBackPress?: boolean;
|
|
90
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Whether tapping the backdrop (scrim) dismisses the bottom sheet.
|
|
95
|
+
* When `false`, the sheet stays open until the user explicitly closes it (e.g. via a button).
|
|
96
|
+
* @default true
|
|
97
|
+
* @platform android
|
|
98
|
+
*/
|
|
99
|
+
shouldDismissOnClickOutside?: boolean;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The color of the scrim overlay rendered behind the bottom sheet.
|
|
103
|
+
* Pass `'transparent'` to make the backdrop invisible while still blocking touches.
|
|
104
|
+
* @platform android
|
|
105
|
+
*/
|
|
106
|
+
scrimColor?: ColorValue;
|
|
107
|
+
|
|
91
108
|
/**
|
|
92
109
|
* Platform-specific modifier escape hatch. Pass an array of modifier configs
|
|
93
110
|
* from `@expo/ui/swift-ui/modifiers` or `@expo/ui/jetpack-compose/modifiers`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback, useRef, type Ref } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds a ref that forwards its value to each of the given refs, in the order
|
|
5
|
+
* they are given. Handles object refs and callback refs, including a callback
|
|
6
|
+
* ref that returns its own cleanup function.
|
|
7
|
+
*
|
|
8
|
+
* A copy of React Native's `useMergeRefs`, which lives behind a deep internal
|
|
9
|
+
* import: those are deprecated, warn in development, and have no counterpart in
|
|
10
|
+
* React Native for web.
|
|
11
|
+
*/
|
|
12
|
+
export function useMergeRefs<T>(...refs: (Ref<T> | undefined)[]): (instance: T | null) => void {
|
|
13
|
+
const cleanups = useRef<(void | (() => void))[]>([]);
|
|
14
|
+
|
|
15
|
+
return useCallback(
|
|
16
|
+
(instance: T | null) => {
|
|
17
|
+
for (const cleanup of cleanups.current) {
|
|
18
|
+
cleanup?.();
|
|
19
|
+
}
|
|
20
|
+
cleanups.current = [];
|
|
21
|
+
if (instance == null) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
cleanups.current = refs.map((ref) => {
|
|
25
|
+
if (ref == null) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if (typeof ref === 'function') {
|
|
29
|
+
const cleanup = ref(instance);
|
|
30
|
+
return typeof cleanup === 'function' ? cleanup : () => ref(null);
|
|
31
|
+
}
|
|
32
|
+
// React's `RefObject<T>` type does not admit null, but a detached ref has
|
|
33
|
+
// to be cleared, which is what React itself does here.
|
|
34
|
+
const refObject = ref as { current: T | null };
|
|
35
|
+
refObject.current = instance;
|
|
36
|
+
return () => {
|
|
37
|
+
refObject.current = null;
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
// The refs are the dependencies. Changing one has to produce a new ref so that
|
|
42
|
+
// React detaches the old one and attaches the new, which is how React Native's
|
|
43
|
+
// own `useMergeRefs` behaves.
|
|
44
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
+
refs
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
46f030ed2d5faa9fc07df319df125512
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dabe60c8f675eb6123187ef607915dccbeb79789
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3f5266c79c694c7d3ae5a885827d2dfb4ae922a9f66fceca406cd7556b753ac0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
bee3386af6f699916c5f3b09c72510621403743e5e887bf0e60d13142304a97964289f39f1fe79355ca9127cc02dfc88cf2d21bbfa4638ed4b9446de05030856
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar
DELETED
|
Binary file
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4508cfcae86a661e2c66bbf15b5909b0
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2ba19351886430ec818130eab431ce8143a56693
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
cdc531cad279eabcfce2c71e778614be0e16c45c77222fe4fa51fcbd7991e30b
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.aar.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
8feb6c5213343355b543cddfedde01251c5a8a9067aa01efb89fe663b2a0e04f3284ab62ed2c9a2f8e65305691f61dd248ba2fdbc3dc7415c5d09ced6425edd1
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
e5ac93703a61ae630a0dd0c0e6d369f3
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.module.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
64563430ecb895ad72e936b019402ccd7c9e6c89
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a615e1f0a09d6a7e76aba8b907fde6ffae9af29c50e411d880ba36a30908ccdb
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
fab8c1e40a8d6e25b66e77c977f415a05a3c4f6b5dcafb461c3a1be165b8db57f21b6cce4b46446a7855090b367fd38ff678b6d48e807dc22712d5e207cd9336
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a337a557c57ffe7e752768ab50d3a6b5
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dcf4640e9a602afa20af004bae13cdcb182d7cc6
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3f88190776e8ff18c8b42b46ee0b8b4e2a827cf671160966b6a3e1e62301f913
|
package/local-maven-repo/expo/modules/ui/expo.modules.ui/57.0.12/expo.modules.ui-57.0.12.pom.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
62c5c2b27746a876d4db64eef13f596835a2f876c0808457d1a82b38fc93e7e5e667a11a5cbcb603efa58ff10b9001981bb347f99b6bd009e452445c80299689
|