react-native-screens 4.25.0-beta.1 → 4.25.0-beta.2
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/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/StackHeaderAppBarLayout.kt +6 -14
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/StackHeaderAppBarLayoutBehavior.kt +29 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/StackHeaderCoordinator.kt +56 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/config/StackHeaderConfig.kt +11 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/config/StackHeaderConfigProviding.kt +5 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/config/StackHeaderConfigViewManager.kt +35 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/subview/StackHeaderSubview.kt +3 -7
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsActionOrigin.kt +26 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsContainer.kt +227 -151
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsNavigationState.kt +60 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/{TabsContainerDelegate.kt → TabsNavigationStateObserver.kt} +19 -14
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsNavigationStateObserverRegistry.kt +88 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/TabsHost.kt +40 -24
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/TabsHostEventEmitter.kt +11 -9
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/TabsHostViewManager.kt +19 -7
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/event/TabsHostTabSelectedEvent.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/event/TabsHostTabSelectionPreventedEvent.kt +3 -3
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/host/event/TabsHostTabSelectionRejectedEvent.kt +11 -10
- package/ios/conversion/RNSConversions-Tabs.mm +19 -0
- package/ios/conversion/RNSConversions.h +3 -0
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryHelper.mm +34 -5
- package/ios/tabs/host/RNSTabBarController.h +152 -99
- package/ios/tabs/host/RNSTabBarController.mm +137 -113
- package/ios/tabs/host/RNSTabsHostComponentView.h +7 -8
- package/ios/tabs/host/RNSTabsHostComponentView.mm +37 -33
- package/ios/tabs/host/RNSTabsHostEventEmitter.h +4 -4
- package/ios/tabs/host/RNSTabsHostEventEmitter.mm +5 -3
- package/ios/tabs/host/RNSTabsNavigationState.h +142 -27
- package/ios/tabs/host/RNSTabsNavigationState.mm +35 -2
- package/ios/tabs/host/RNSTabsNavigationStateObserverRegistry.h +62 -0
- package/ios/tabs/host/RNSTabsNavigationStateObserverRegistry.mm +104 -0
- package/lib/commonjs/components/gamma/stack/header/StackHeaderConfig.android.js +46 -1
- package/lib/commonjs/components/gamma/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/commonjs/components/safe-area/SafeAreaView.web.js +2 -3
- package/lib/commonjs/components/safe-area/SafeAreaView.web.js.map +1 -1
- package/lib/commonjs/components/tabs/host/TabsHost.android.js +2 -2
- package/lib/commonjs/components/tabs/host/TabsHost.android.js.map +1 -1
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js +2 -2
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/commonjs/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/commonjs/flags.js +1 -0
- package/lib/commonjs/flags.js.map +1 -1
- package/lib/module/components/gamma/stack/header/StackHeaderConfig.android.js +46 -1
- package/lib/module/components/gamma/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/module/components/safe-area/SafeAreaView.web.js +1 -1
- package/lib/module/components/safe-area/SafeAreaView.web.js.map +1 -1
- package/lib/module/components/tabs/host/TabsHost.android.js +2 -2
- package/lib/module/components/tabs/host/TabsHost.android.js.map +1 -1
- package/lib/module/components/tabs/host/TabsHost.ios.js +2 -2
- package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/module/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/module/flags.js +1 -0
- package/lib/module/flags.js.map +1 -1
- package/lib/typescript/components/gamma/split/SplitHost.types.d.ts +1 -1
- package/lib/typescript/components/gamma/split/SplitHost.types.d.ts.map +1 -1
- package/lib/typescript/components/gamma/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
- package/lib/typescript/components/gamma/stack/header/StackHeaderConfig.android.types.d.ts +183 -8
- package/lib/typescript/components/gamma/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
- package/lib/typescript/components/gamma/stack/header/StackHeaderConfig.types.d.ts +37 -0
- package/lib/typescript/components/gamma/stack/header/StackHeaderConfig.types.d.ts.map +1 -1
- package/lib/typescript/components/gamma/stack/header/android/StackHeaderSubview.android.types.d.ts +1 -1
- package/lib/typescript/components/gamma/stack/header/android/StackHeaderSubview.android.types.d.ts.map +1 -1
- package/lib/typescript/components/gamma/stack/host/StackHost.types.d.ts +1 -1
- package/lib/typescript/components/gamma/stack/host/StackHost.types.d.ts.map +1 -1
- package/lib/typescript/components/safe-area/SafeAreaView.web.d.ts +1 -1
- package/lib/typescript/components/safe-area/SafeAreaView.web.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +27 -17
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
- package/lib/typescript/components/tabs/index.d.ts +1 -1
- package/lib/typescript/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.d.ts +5 -0
- package/lib/typescript/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/tabs/TabsHostAndroidNativeComponent.d.ts +4 -4
- package/lib/typescript/fabric/tabs/TabsHostAndroidNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +4 -4
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
- package/lib/typescript/flags.d.ts +1 -0
- package/lib/typescript/flags.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/gamma/split/SplitHost.types.ts +1 -1
- package/src/components/gamma/stack/header/StackHeaderConfig.android.tsx +72 -2
- package/src/components/gamma/stack/header/StackHeaderConfig.android.types.ts +183 -8
- package/src/components/gamma/stack/header/StackHeaderConfig.types.ts +37 -0
- package/src/components/gamma/stack/header/android/StackHeaderSubview.android.types.ts +1 -1
- package/src/components/gamma/stack/host/StackHost.types.ts +1 -1
- package/src/components/safe-area/SafeAreaView.web.tsx +1 -1
- package/src/components/tabs/host/TabsHost.android.tsx +2 -2
- package/src/components/tabs/host/TabsHost.ios.tsx +2 -2
- package/src/components/tabs/host/TabsHost.types.ts +27 -17
- package/src/components/tabs/index.ts +1 -1
- package/src/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.ts +6 -0
- package/src/fabric/tabs/TabsHostAndroidNativeComponent.ts +4 -4
- package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +4 -4
- package/src/flags.ts +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsContainerOps.kt +0 -7
- package/android/src/main/java/com/swmansion/rnscreens/gamma/tabs/container/TabsNavState.kt +0 -43
|
@@ -4,7 +4,10 @@ import type { StackHeaderConfigProps } from './StackHeaderConfig.types';
|
|
|
4
4
|
import StackHeaderConfigAndroidNativeComponent from '../../../../fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent';
|
|
5
5
|
import type { NativeProps as StackHeaderConfigAndroidNativeComponentProps } from '../../../../fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent';
|
|
6
6
|
import StackHeaderSubview from './android/StackHeaderSubview.android';
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
StackHeaderConfigPropsAndroid,
|
|
9
|
+
StackHeaderTypeAndroid,
|
|
10
|
+
} from './StackHeaderConfig.android.types';
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* EXPERIMENTAL API, MIGHT CHANGE W/O ANY NOTICE
|
|
@@ -20,10 +23,22 @@ function StackHeaderConfig(props: StackHeaderConfigProps) {
|
|
|
20
23
|
centerSubview,
|
|
21
24
|
trailingSubview,
|
|
22
25
|
backButtonIcon,
|
|
26
|
+
scrollFlagScroll,
|
|
27
|
+
scrollFlagEnterAlways,
|
|
28
|
+
scrollFlagEnterAlwaysCollapsed,
|
|
29
|
+
scrollFlagExitUntilCollapsed,
|
|
30
|
+
scrollFlagSnap,
|
|
23
31
|
...filteredAndroidProps
|
|
24
32
|
} = android ?? {};
|
|
25
33
|
|
|
26
34
|
const backButtonIconProps = parseBackButtonIconToNativeProps(backButtonIcon);
|
|
35
|
+
const scrollFlagProps = resolveScrollFlags(filteredAndroidProps.type, {
|
|
36
|
+
scrollFlagScroll,
|
|
37
|
+
scrollFlagEnterAlways,
|
|
38
|
+
scrollFlagEnterAlwaysCollapsed,
|
|
39
|
+
scrollFlagExitUntilCollapsed,
|
|
40
|
+
scrollFlagSnap,
|
|
41
|
+
});
|
|
27
42
|
|
|
28
43
|
return (
|
|
29
44
|
<StackHeaderConfigAndroidNativeComponent
|
|
@@ -31,7 +46,8 @@ function StackHeaderConfig(props: StackHeaderConfigProps) {
|
|
|
31
46
|
style={StyleSheet.absoluteFill}
|
|
32
47
|
{...baseProps}
|
|
33
48
|
{...filteredAndroidProps}
|
|
34
|
-
{...backButtonIconProps}
|
|
49
|
+
{...backButtonIconProps}
|
|
50
|
+
{...scrollFlagProps}>
|
|
35
51
|
{/*
|
|
36
52
|
Please note that the order of the subviews MUST match
|
|
37
53
|
the order in native StackHeaderConfig.getConfigSubviewAt.
|
|
@@ -93,4 +109,58 @@ function parseBackButtonIconToNativeProps(
|
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
111
|
|
|
112
|
+
type ScrollFlagFields = {
|
|
113
|
+
scrollFlagScroll: boolean;
|
|
114
|
+
scrollFlagEnterAlways: boolean;
|
|
115
|
+
scrollFlagEnterAlwaysCollapsed: boolean;
|
|
116
|
+
scrollFlagExitUntilCollapsed: boolean;
|
|
117
|
+
scrollFlagSnap: boolean;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const SCROLL_FLAG_DEFAULTS_BY_TYPE: Record<
|
|
121
|
+
StackHeaderTypeAndroid,
|
|
122
|
+
ScrollFlagFields
|
|
123
|
+
> = {
|
|
124
|
+
small: {
|
|
125
|
+
scrollFlagScroll: false,
|
|
126
|
+
scrollFlagEnterAlways: false,
|
|
127
|
+
scrollFlagEnterAlwaysCollapsed: false,
|
|
128
|
+
scrollFlagExitUntilCollapsed: false,
|
|
129
|
+
scrollFlagSnap: false,
|
|
130
|
+
},
|
|
131
|
+
medium: {
|
|
132
|
+
scrollFlagScroll: true,
|
|
133
|
+
scrollFlagEnterAlways: false,
|
|
134
|
+
scrollFlagEnterAlwaysCollapsed: false,
|
|
135
|
+
scrollFlagExitUntilCollapsed: true,
|
|
136
|
+
scrollFlagSnap: true,
|
|
137
|
+
},
|
|
138
|
+
large: {
|
|
139
|
+
scrollFlagScroll: true,
|
|
140
|
+
scrollFlagEnterAlways: false,
|
|
141
|
+
scrollFlagEnterAlwaysCollapsed: false,
|
|
142
|
+
scrollFlagExitUntilCollapsed: true,
|
|
143
|
+
scrollFlagSnap: true,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
function resolveScrollFlags(
|
|
148
|
+
type: StackHeaderTypeAndroid | undefined,
|
|
149
|
+
overrides: Pick<StackHeaderConfigPropsAndroid, keyof ScrollFlagFields>,
|
|
150
|
+
): ScrollFlagFields {
|
|
151
|
+
const defaults = SCROLL_FLAG_DEFAULTS_BY_TYPE[type ?? 'small'];
|
|
152
|
+
return {
|
|
153
|
+
scrollFlagScroll: overrides.scrollFlagScroll ?? defaults.scrollFlagScroll,
|
|
154
|
+
scrollFlagEnterAlways:
|
|
155
|
+
overrides.scrollFlagEnterAlways ?? defaults.scrollFlagEnterAlways,
|
|
156
|
+
scrollFlagEnterAlwaysCollapsed:
|
|
157
|
+
overrides.scrollFlagEnterAlwaysCollapsed ??
|
|
158
|
+
defaults.scrollFlagEnterAlwaysCollapsed,
|
|
159
|
+
scrollFlagExitUntilCollapsed:
|
|
160
|
+
overrides.scrollFlagExitUntilCollapsed ??
|
|
161
|
+
defaults.scrollFlagExitUntilCollapsed,
|
|
162
|
+
scrollFlagSnap: overrides.scrollFlagSnap ?? defaults.scrollFlagSnap,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
96
166
|
export default StackHeaderConfig;
|
|
@@ -9,30 +9,205 @@ export type StackHeaderBackgroundSubviewCollapseModeAndroid =
|
|
|
9
9
|
StackHeaderSubviewCollapseModeAndroid;
|
|
10
10
|
|
|
11
11
|
export interface StackHeaderToolbarSubviewAndroid {
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @summary The React component rendered in this toolbar slot.
|
|
14
|
+
*
|
|
15
|
+
* The subview is sized by React Native's layout engine but positioned by the
|
|
16
|
+
* platform native layout. Each subview is placed independently — subviews do
|
|
17
|
+
* not participate in a shared flex layout and cannot influence each other's
|
|
18
|
+
* sizing.
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Intrinsic sizing and explicit dimensions work as expected. Avoid
|
|
23
|
+
* parent-relative sizing (e.g. `flex: 1`) on the root element — it will
|
|
24
|
+
* produce incorrect dimensions. Flex layout within a root that has a known
|
|
25
|
+
* size works as expected.
|
|
26
|
+
*
|
|
27
|
+
* @platform android
|
|
28
|
+
*/
|
|
29
|
+
Component: NonNullable<ReactNode>;
|
|
13
30
|
}
|
|
14
31
|
|
|
15
32
|
export interface StackHeaderBackgroundSubviewAndroid {
|
|
33
|
+
/**
|
|
34
|
+
* @summary Controls how the background subview behaves when the app bar
|
|
35
|
+
* collapses.
|
|
36
|
+
*
|
|
37
|
+
* The following values are available:
|
|
38
|
+
* - `off` - the subview scrolls away with the app bar,
|
|
39
|
+
* - `parallax` - the subview scrolls at a slower rate, creating a parallax
|
|
40
|
+
* effect.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* `pin` is not currently supported because the background subview is
|
|
44
|
+
* stretched to match the entire `AppBarLayout`, which causes pinned content
|
|
45
|
+
* to move immediately rather than staying fixed. Support for `pin` collapse
|
|
46
|
+
* mode might be added in the future.
|
|
47
|
+
*
|
|
48
|
+
* @default off
|
|
49
|
+
*
|
|
50
|
+
* @platform android
|
|
51
|
+
*/
|
|
16
52
|
collapseMode?: StackHeaderSubviewCollapseModeAndroid | undefined;
|
|
17
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @summary The React component rendered as the header background.
|
|
55
|
+
*
|
|
56
|
+
* The subview is stretched to match the header (`AppBarLayout`) dimensions,
|
|
57
|
+
* so parent-relative sizing (e.g. `flex: 1`) works correctly.
|
|
58
|
+
*
|
|
59
|
+
* @platform android
|
|
60
|
+
*/
|
|
61
|
+
Component: NonNullable<ReactNode>;
|
|
18
62
|
}
|
|
19
63
|
|
|
20
64
|
export interface StackHeaderConfigPropsAndroid {
|
|
65
|
+
/**
|
|
66
|
+
* @summary Specifies the type of the Material 3 app bar.
|
|
67
|
+
*
|
|
68
|
+
* The following values are available:
|
|
69
|
+
* - `small` - small app bar with fixed title,
|
|
70
|
+
* - `medium` - medium app bar with collapsing title,
|
|
71
|
+
* - `large` - large app bar with collapsing title.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* M3 Expressive headers aren't currently supported (there is no stable
|
|
75
|
+
* `MDC-Android` version yet).
|
|
76
|
+
*
|
|
77
|
+
* @see {@link https://m3.material.io/components/app-bars/overview|Material Design 3: App bars}
|
|
78
|
+
*
|
|
79
|
+
* @default small
|
|
80
|
+
*
|
|
81
|
+
* @platform android
|
|
82
|
+
*/
|
|
21
83
|
type?: StackHeaderTypeAndroid | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* @summary Custom view rendered behind the header content.
|
|
86
|
+
*
|
|
87
|
+
* @platform android
|
|
88
|
+
*/
|
|
22
89
|
backgroundSubview?: StackHeaderBackgroundSubviewAndroid | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* @summary Custom view placed in the leading (start) slot of the toolbar.
|
|
92
|
+
*
|
|
93
|
+
* @platform android
|
|
94
|
+
*/
|
|
23
95
|
leadingSubview?: StackHeaderToolbarSubviewAndroid | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* @summary Custom view placed in the center slot of the toolbar.
|
|
98
|
+
*
|
|
99
|
+
* @platform android
|
|
100
|
+
*/
|
|
24
101
|
centerSubview?: StackHeaderToolbarSubviewAndroid | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* @summary Custom view placed in the trailing (end) slot of the toolbar.
|
|
104
|
+
*
|
|
105
|
+
* @platform android
|
|
106
|
+
*/
|
|
25
107
|
trailingSubview?: StackHeaderToolbarSubviewAndroid | undefined;
|
|
26
108
|
/**
|
|
27
|
-
* Tint color
|
|
28
|
-
*
|
|
29
|
-
*
|
|
109
|
+
* @summary Tint color applied to the back button icon.
|
|
110
|
+
*
|
|
111
|
+
* When `undefined`, the default tint color is used. This applies to the
|
|
112
|
+
* native back arrow and `drawableResource` icons that have an associated
|
|
113
|
+
* tint. For `imageSource` icons, no tint is applied by default.
|
|
114
|
+
*
|
|
115
|
+
* @platform android
|
|
30
116
|
*/
|
|
31
117
|
backButtonTintColor?: ColorValue | undefined;
|
|
32
118
|
/**
|
|
33
|
-
* Custom icon for the back button.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
119
|
+
* @summary Custom icon for the back button.
|
|
120
|
+
*
|
|
121
|
+
* When `undefined`, the native back arrow (`homeAsUpIndicator`) is used.
|
|
122
|
+
*
|
|
123
|
+
* Supported values:
|
|
124
|
+
* - `{ type: 'imageSource', imageSource }`
|
|
125
|
+
* Uses an image from the provided resource.
|
|
126
|
+
*
|
|
127
|
+
* Remarks: `imageSource` type doesn't support SVGs on Android.
|
|
128
|
+
* For loading SVGs use `drawableResource` type.
|
|
129
|
+
*
|
|
130
|
+
* - `{ type: 'drawableResource', name }`
|
|
131
|
+
* Uses a drawable resource with the given name.
|
|
132
|
+
*
|
|
133
|
+
* Remarks: Requires passing a drawable to resources via Android Studio.
|
|
134
|
+
*
|
|
135
|
+
* @platform android
|
|
36
136
|
*/
|
|
37
137
|
backButtonIcon?: PlatformIconAndroid | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* @summary Whether the header reacts to nested scroll. Required for any
|
|
140
|
+
* other `scrollFlag*` prop to take effect.
|
|
141
|
+
*
|
|
142
|
+
* When `undefined`, falls back to the type-specific default:
|
|
143
|
+
* - `small` -> `false`
|
|
144
|
+
* - `medium` / `large` -> `true`
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* Changing any `scrollFlag*` at runtime forces the header back to
|
|
148
|
+
* its fully expanded state, which produces a visible snap. Treat these
|
|
149
|
+
* props as a static configuration.
|
|
150
|
+
*
|
|
151
|
+
* @platform android
|
|
152
|
+
*/
|
|
153
|
+
scrollFlagScroll?: boolean | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* @summary When enabled, the header re-expands as soon as the user scrolls
|
|
156
|
+
* back toward the top of the content, regardless of the ScrollView's current
|
|
157
|
+
* scroll position. Without this flag, the header only begins expanding once
|
|
158
|
+
* the list has reached the top of its content. Requires `scrollFlagScroll`.
|
|
159
|
+
*
|
|
160
|
+
* When `undefined`, falls back to the type-specific default (`false` for
|
|
161
|
+
* all types).
|
|
162
|
+
*
|
|
163
|
+
* @platform android
|
|
164
|
+
*/
|
|
165
|
+
scrollFlagEnterAlways?: boolean | undefined;
|
|
166
|
+
/**
|
|
167
|
+
* @summary Modifies `scrollFlagEnterAlways` so that the initial re-entry
|
|
168
|
+
* stops at the header's collapsed height (the toolbar); the remainder
|
|
169
|
+
* expands only after the ScrollView reaches the top of its content. Requires
|
|
170
|
+
* `scrollFlagEnterAlways`.
|
|
171
|
+
*
|
|
172
|
+
* When `undefined`, falls back to the type-specific default (`false` for
|
|
173
|
+
* all types).
|
|
174
|
+
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* This flag does not have any effect for `small` header.
|
|
177
|
+
*
|
|
178
|
+
* @platform android
|
|
179
|
+
*/
|
|
180
|
+
scrollFlagEnterAlwaysCollapsed?: boolean | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* @summary When enabled, the header collapses only until its minimum height
|
|
183
|
+
* (the toolbar) remains pinned at the top. Without this flag, the entire
|
|
184
|
+
* header scrolls off the screen. Requires `scrollFlagScroll`.
|
|
185
|
+
*
|
|
186
|
+
* When `undefined`, falls back to the type-specific default:
|
|
187
|
+
* - `small` -> `false`
|
|
188
|
+
* - `medium` / `large` -> `true`
|
|
189
|
+
*
|
|
190
|
+
* @remarks
|
|
191
|
+
* Setting this flag for `small` header is equivalent to disabling
|
|
192
|
+
* `scrollFlagScroll`.
|
|
193
|
+
*
|
|
194
|
+
* Even when this flag is disabled, a strip with the height of the system top
|
|
195
|
+
* inset (status bar and display cutout) remains visible at the top.
|
|
196
|
+
*
|
|
197
|
+
* @platform android
|
|
198
|
+
*/
|
|
199
|
+
scrollFlagExitUntilCollapsed?: boolean | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* @summary When enabled, the header snaps to its nearest edge (fully
|
|
202
|
+
* expanded, or fully collapsed as defined by `scrollFlagExitUntilCollapsed`)
|
|
203
|
+
* after a scroll gesture ends, instead of resting partway. Requires
|
|
204
|
+
* `scrollFlagScroll`.
|
|
205
|
+
*
|
|
206
|
+
* When `undefined`, falls back to the type-specific default:
|
|
207
|
+
* - `small` -> `false`
|
|
208
|
+
* - `medium` / `large` -> `true`
|
|
209
|
+
*
|
|
210
|
+
* @platform android
|
|
211
|
+
*/
|
|
212
|
+
scrollFlagSnap?: boolean | undefined;
|
|
38
213
|
}
|
|
@@ -2,9 +2,46 @@ import { StackHeaderConfigPropsAndroid } from './StackHeaderConfig.android.types
|
|
|
2
2
|
import { StackHeaderConfigPropsIOS } from './StackHeaderConfig.ios.types';
|
|
3
3
|
|
|
4
4
|
export interface StackHeaderConfigPropsBase {
|
|
5
|
+
/**
|
|
6
|
+
* @summary Title displayed in the header.
|
|
7
|
+
*
|
|
8
|
+
* @platform android, ios
|
|
9
|
+
*/
|
|
5
10
|
title?: string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* @summary Specifies if the header should be hidden.
|
|
13
|
+
*
|
|
14
|
+
* @default false
|
|
15
|
+
*
|
|
16
|
+
* @platform android, ios
|
|
17
|
+
*/
|
|
6
18
|
hidden?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* @summary Specifies if the content should be rendered behind the header.
|
|
21
|
+
*
|
|
22
|
+
* When `true`, content is rendered behind the header instead of starting
|
|
23
|
+
* below it.
|
|
24
|
+
*
|
|
25
|
+
* On Android:
|
|
26
|
+
* - The header background color is not affected by this prop.
|
|
27
|
+
* - Setting this prop to `true` is not supported when header scrolling is
|
|
28
|
+
* enabled.
|
|
29
|
+
*
|
|
30
|
+
* @default false
|
|
31
|
+
*
|
|
32
|
+
* @platform android, ios
|
|
33
|
+
*/
|
|
7
34
|
transparent?: boolean | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* @summary Specifies if the back button should be hidden.
|
|
37
|
+
*
|
|
38
|
+
* This prop does not apply to the root screen of the stack for which the back
|
|
39
|
+
* button is always hidden.
|
|
40
|
+
*
|
|
41
|
+
* @default false
|
|
42
|
+
*
|
|
43
|
+
* @platform android, ios
|
|
44
|
+
*/
|
|
8
45
|
backButtonHidden?: boolean | undefined;
|
|
9
46
|
}
|
|
10
47
|
|
|
@@ -9,7 +9,7 @@ export type StackHeaderSubviewTypeAndroid =
|
|
|
9
9
|
export type StackHeaderSubviewCollapseModeAndroid = 'off' | 'parallax';
|
|
10
10
|
|
|
11
11
|
export type StackHeaderSubviewProps = {
|
|
12
|
-
children
|
|
12
|
+
children: NonNullable<ViewProps['children']>;
|
|
13
13
|
|
|
14
14
|
type?: StackHeaderSubviewTypeAndroid | undefined;
|
|
15
15
|
collapseMode?: StackHeaderSubviewCollapseModeAndroid | undefined;
|
|
@@ -3,7 +3,7 @@ import type { ReactNativeElement, ViewProps } from 'react-native';
|
|
|
3
3
|
import { type NativeProps } from '../../../../fabric/gamma/stack/StackHostNativeComponent';
|
|
4
4
|
|
|
5
5
|
export type StackHostProps = {
|
|
6
|
-
children: ViewProps['children']
|
|
6
|
+
children: NonNullable<ViewProps['children']>;
|
|
7
7
|
// TODO: Work on these types
|
|
8
8
|
ref?:
|
|
9
9
|
| React.RefObject<
|
|
@@ -25,7 +25,7 @@ function TabsHost(props: TabsHostProps) {
|
|
|
25
25
|
direction,
|
|
26
26
|
nativeContainerStyle,
|
|
27
27
|
onTabSelected,
|
|
28
|
-
|
|
28
|
+
navStateRequest,
|
|
29
29
|
...filteredBaseProps
|
|
30
30
|
} = baseProps;
|
|
31
31
|
|
|
@@ -41,7 +41,7 @@ function TabsHost(props: TabsHostProps) {
|
|
|
41
41
|
return (
|
|
42
42
|
<TabsHostAndroidNativeComponent
|
|
43
43
|
style={[styles.fillParent, { direction }]}
|
|
44
|
-
|
|
44
|
+
navStateRequest={navStateRequest}
|
|
45
45
|
onTabSelected={onTabSelectedCallback}
|
|
46
46
|
nativeContainerBackgroundColor={nativeContainerStyle?.backgroundColor}
|
|
47
47
|
// @ts-ignore suppress ref - debug only
|
|
@@ -28,7 +28,7 @@ function TabsHost(props: TabsHostProps) {
|
|
|
28
28
|
direction,
|
|
29
29
|
nativeContainerStyle,
|
|
30
30
|
onTabSelected,
|
|
31
|
-
|
|
31
|
+
navStateRequest,
|
|
32
32
|
...filteredBaseProps
|
|
33
33
|
} = baseProps;
|
|
34
34
|
|
|
@@ -47,7 +47,7 @@ function TabsHost(props: TabsHostProps) {
|
|
|
47
47
|
return (
|
|
48
48
|
<TabsHostIOSNativeComponent
|
|
49
49
|
style={styles.fillParent}
|
|
50
|
-
|
|
50
|
+
navStateRequest={navStateRequest}
|
|
51
51
|
onTabSelected={onTabSelectedCallback}
|
|
52
52
|
nativeContainerBackgroundColor={nativeContainerStyle?.backgroundColor}
|
|
53
53
|
// @ts-ignore suppress ref - debug only
|
|
@@ -5,7 +5,7 @@ import type { ColorScheme, Direction } from '../../shared/types';
|
|
|
5
5
|
|
|
6
6
|
// #region Control
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type TabsHostNavStateRequest = {
|
|
9
9
|
/**
|
|
10
10
|
* @summary Valid screen key.
|
|
11
11
|
*
|
|
@@ -14,13 +14,12 @@ export type TabsHostNavState = {
|
|
|
14
14
|
*/
|
|
15
15
|
selectedScreenKey: string;
|
|
16
16
|
/**
|
|
17
|
-
* @summary
|
|
17
|
+
* @summary Provenance of the navigation state this request is derived from.
|
|
18
18
|
*
|
|
19
19
|
* @description
|
|
20
20
|
* The provenance value establishes a relationship between different navigation state instances
|
|
21
|
-
* held by given state holder. The assumption
|
|
22
|
-
*
|
|
23
|
-
* This creates a relationship where we can say that:
|
|
21
|
+
* held by given state holder. The assumption is that when the navigation state is progressed
|
|
22
|
+
* (modified), the provenance number is incremented. This creates a relationship where we can say:
|
|
24
23
|
*
|
|
25
24
|
* 1. State with provenance = n + 1 has been derived from state with provenance = n.
|
|
26
25
|
* 2. For two given navigation states A and B, we can say that A *is stale* iff
|
|
@@ -31,12 +30,15 @@ export type TabsHostNavState = {
|
|
|
31
30
|
*
|
|
32
31
|
* Currently, the native implementation of TabsHost is the state holder.
|
|
33
32
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
33
|
+
* Pass here THE PROVENANCE OF THE LAST ACKNOWLEDGED state you received from native side
|
|
34
|
+
* via {@link TabsHostPropsBase#onTabSelected}. In other words this should be the provenance
|
|
35
|
+
* number of last confirmed state you base your update request on.
|
|
36
|
+
*
|
|
37
|
+
* It is named `baseProvenance` (rather than `provenance`) to disambiguate it from the
|
|
38
|
+
* `provenance` field on the {@link TabSelectedEvent} payload, which carries the provenance
|
|
39
|
+
* of the state *resulting* from a transition.
|
|
38
40
|
*/
|
|
39
|
-
|
|
41
|
+
baseProvenance: number;
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
// #endregion Control
|
|
@@ -60,10 +62,18 @@ export type TabSelectedEvent = {
|
|
|
60
62
|
/** Whether the selection triggered a special effect (e.g. scroll-to-top on repeated selection). */
|
|
61
63
|
hasTriggeredSpecialEffect: boolean;
|
|
62
64
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
+
* @summary Origin (actor) that requested this tab transition.
|
|
66
|
+
*
|
|
67
|
+
* @description
|
|
68
|
+
* - `user` — direct native UI interaction (e.g. tab bar tap, iOS tab drag-and-drop).
|
|
69
|
+
* - `programmatic-js` — JS-initiated request delivered via the `navStateRequest` prop.
|
|
70
|
+
* - `programmatic-native` — request initiated from the native side by an actor
|
|
71
|
+
* integrating directly against the native container.
|
|
72
|
+
* - `implicit` — platform side effect not attributable to an explicit actor
|
|
73
|
+
* (e.g. UIKit reshuffling the selection during a horizontal size-class transition on iPad).
|
|
74
|
+
* Currently only emitted on iOS.
|
|
65
75
|
*/
|
|
66
|
-
|
|
76
|
+
actionOrigin: 'user' | 'programmatic-js' | 'programmatic-native' | 'implicit';
|
|
67
77
|
};
|
|
68
78
|
|
|
69
79
|
/**
|
|
@@ -140,15 +150,15 @@ export interface TabsHostPropsBase {
|
|
|
140
150
|
* the update might get accepted or rejected.
|
|
141
151
|
*
|
|
142
152
|
* @see {@link TabsHostPropsBase#rejectStaleNavStateUpdates}
|
|
143
|
-
* @see {@link
|
|
153
|
+
* @see {@link TabsHostNavStateRequest} for description of the type model & accepted values.
|
|
144
154
|
*/
|
|
145
|
-
|
|
155
|
+
navStateRequest: TabsHostNavStateRequest;
|
|
146
156
|
/**
|
|
147
157
|
* @summary If true, the native side will reject any navigation state updates coming from JS
|
|
148
158
|
* if they are stale.
|
|
149
159
|
*
|
|
150
160
|
* @description A navigation state update is considered stale if it is based of an stale state
|
|
151
|
-
* (@
|
|
161
|
+
* ({@link TabsHostNavStateRequest#baseProvenance} indicates the base state).
|
|
152
162
|
* A state is stale, when at the time of executing update, there already had been accepted a newer state
|
|
153
163
|
* of different origin.
|
|
154
164
|
*
|
|
@@ -167,7 +177,7 @@ export interface TabsHostPropsBase {
|
|
|
167
177
|
rejectStaleNavStateUpdates?: boolean | undefined;
|
|
168
178
|
|
|
169
179
|
// General
|
|
170
|
-
children
|
|
180
|
+
children: NonNullable<ViewProps['children']>;
|
|
171
181
|
/**
|
|
172
182
|
* @summary Hides the tab bar.
|
|
173
183
|
*
|
|
@@ -22,6 +22,12 @@ export interface NativeProps extends ViewProps {
|
|
|
22
22
|
backButtonTintColor?: ColorValue | undefined;
|
|
23
23
|
backButtonDrawableIconResourceName?: string | undefined;
|
|
24
24
|
backButtonImageIconResource?: ImageSource | undefined;
|
|
25
|
+
|
|
26
|
+
scrollFlagScroll?: CT.WithDefault<boolean, false>;
|
|
27
|
+
scrollFlagEnterAlways?: CT.WithDefault<boolean, false>;
|
|
28
|
+
scrollFlagEnterAlwaysCollapsed?: CT.WithDefault<boolean, false>;
|
|
29
|
+
scrollFlagExitUntilCollapsed?: CT.WithDefault<boolean, false>;
|
|
30
|
+
scrollFlagSnap?: CT.WithDefault<boolean, false>;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
export default codegenNativeComponent<NativeProps>(
|
|
@@ -10,12 +10,12 @@ type TabSelectedEvent = {
|
|
|
10
10
|
provenance: CT.Int32;
|
|
11
11
|
isRepeated: boolean;
|
|
12
12
|
hasTriggeredSpecialEffect: boolean;
|
|
13
|
-
|
|
13
|
+
actionOrigin: 'user' | 'programmatic-js' | 'programmatic-native' | 'implicit';
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
type
|
|
16
|
+
type NavigationStateRequest = {
|
|
17
17
|
selectedScreenKey: string;
|
|
18
|
-
|
|
18
|
+
baseProvenance: CT.Int32;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
type TabSelectionRejectedEvent = Readonly<{
|
|
@@ -42,7 +42,7 @@ type TabsHostColorScheme = 'inherit' | 'light' | 'dark';
|
|
|
42
42
|
|
|
43
43
|
export interface NativeProps extends ViewProps {
|
|
44
44
|
// Control
|
|
45
|
-
|
|
45
|
+
navStateRequest: NavigationStateRequest;
|
|
46
46
|
rejectStaleNavStateUpdates?: CT.WithDefault<boolean, false>;
|
|
47
47
|
|
|
48
48
|
// Events
|
|
@@ -10,12 +10,12 @@ type TabSelectedEvent = Readonly<{
|
|
|
10
10
|
provenance: CT.Int32;
|
|
11
11
|
isRepeated: boolean;
|
|
12
12
|
hasTriggeredSpecialEffect: boolean;
|
|
13
|
-
|
|
13
|
+
actionOrigin: 'user' | 'programmatic-js' | 'programmatic-native' | 'implicit';
|
|
14
14
|
}>;
|
|
15
15
|
|
|
16
|
-
type
|
|
16
|
+
type NavigationStateRequest = Readonly<{
|
|
17
17
|
selectedScreenKey: string;
|
|
18
|
-
|
|
18
|
+
baseProvenance: CT.Int32;
|
|
19
19
|
}>;
|
|
20
20
|
|
|
21
21
|
type TabSelectionRejectedEvent = Readonly<{
|
|
@@ -57,7 +57,7 @@ type TabBarControllerMode = 'automatic' | 'tabBar' | 'tabSidebar';
|
|
|
57
57
|
|
|
58
58
|
export interface NativeProps extends ViewProps {
|
|
59
59
|
// Control
|
|
60
|
-
|
|
60
|
+
navStateRequest: NavigationStateRequest;
|
|
61
61
|
rejectStaleNavStateUpdates?: CT.WithDefault<boolean, false>;
|
|
62
62
|
|
|
63
63
|
// Events
|
package/src/flags.ts
CHANGED
|
@@ -65,6 +65,7 @@ export const compatibilityFlags = {
|
|
|
65
65
|
* * https://github.com/software-mansion/react-native-screens/pull/3863
|
|
66
66
|
* * https://github.com/software-mansion/react-native-screens/pull/3875
|
|
67
67
|
* * https://github.com/software-mansion/react-native-screens/pull/3895
|
|
68
|
+
* * https://github.com/software-mansion/react-native-screens/pull/3918
|
|
68
69
|
*/
|
|
69
70
|
usesStableTabsApi: true,
|
|
70
71
|
} as const;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
package com.swmansion.rnscreens.gamma.tabs.container
|
|
2
|
-
|
|
3
|
-
import com.swmansion.rnscreens.gamma.tabs.container.TabsNavStateUpdateRejectionReason.REPEATED
|
|
4
|
-
import com.swmansion.rnscreens.gamma.tabs.container.TabsNavStateUpdateRejectionReason.STALE
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Describes navigation state of a tabs container.
|
|
8
|
-
*
|
|
9
|
-
* @property selectedKey Screen key of the currently selected tab.
|
|
10
|
-
* @property provenance Monotonically increasing number describing the history (generation) of the state.
|
|
11
|
-
* State with provenance `N + 1` is derived from state with provenance `N`.
|
|
12
|
-
* This allows detecting stale updates.
|
|
13
|
-
*/
|
|
14
|
-
data class TabsNavState(
|
|
15
|
-
val selectedKey: String,
|
|
16
|
-
val provenance: Int,
|
|
17
|
-
) {
|
|
18
|
-
internal fun isEmpty(): Boolean = this === EMPTY
|
|
19
|
-
|
|
20
|
-
internal fun isNotEmpty(): Boolean = !this.isEmpty()
|
|
21
|
-
|
|
22
|
-
companion object {
|
|
23
|
-
val EMPTY = TabsNavState("", Int.MIN_VALUE)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Reason why a navigation state update was rejected by the container.
|
|
29
|
-
*
|
|
30
|
-
* - [STALE] — the update's provenance indicates that it is based on a stale state.
|
|
31
|
-
* - [REPEATED] — the requested tab is already selected.
|
|
32
|
-
*/
|
|
33
|
-
enum class TabsNavStateUpdateRejectionReason {
|
|
34
|
-
STALE,
|
|
35
|
-
REPEATED,
|
|
36
|
-
;
|
|
37
|
-
|
|
38
|
-
override fun toString(): String =
|
|
39
|
-
when (this) {
|
|
40
|
-
STALE -> "stale"
|
|
41
|
-
REPEATED -> "repeated"
|
|
42
|
-
}
|
|
43
|
-
}
|