@react-navigation/stack 8.0.0-alpha.30 → 8.0.0-alpha.31
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/lib/module/views/Header/HeaderContainer.js +29 -11
- package/lib/module/views/Header/HeaderContainer.js.map +1 -1
- package/lib/module/views/Stack/CardContainer.js +53 -81
- package/lib/module/views/Stack/CardContainer.js.map +1 -1
- package/lib/module/views/Stack/CardStack.js +95 -49
- package/lib/module/views/Stack/CardStack.js.map +1 -1
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts +6 -2
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardContainer.d.ts +3 -5
- package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardStack.d.ts +3 -2
- package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/views/Header/HeaderContainer.tsx +43 -16
- package/src/views/Stack/CardContainer.tsx +73 -108
- package/src/views/Stack/CardStack.tsx +112 -59
- package/lib/module/views/Stack/CardA11yWrapper.js +0 -42
- package/lib/module/views/Stack/CardA11yWrapper.js.map +0 -1
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +0 -15
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +0 -1
- package/src/views/Stack/CardA11yWrapper.tsx +0 -56
|
@@ -48,13 +48,18 @@ import type {
|
|
|
48
48
|
} from '../../types';
|
|
49
49
|
import { getDistanceForDirection } from '../../utils/getDistanceForDirection';
|
|
50
50
|
import { getModalRouteKeys } from '../../utils/getModalRoutesKeys';
|
|
51
|
-
import type {
|
|
51
|
+
import type {
|
|
52
|
+
HeaderHeight,
|
|
53
|
+
Props as HeaderContainerProps,
|
|
54
|
+
} from '../Header/HeaderContainer';
|
|
52
55
|
import { CardContainer } from './CardContainer';
|
|
53
56
|
|
|
54
57
|
type GestureValues = {
|
|
55
58
|
[key: string]: Animated.Value;
|
|
56
59
|
};
|
|
57
60
|
|
|
61
|
+
type HeaderHeights = Record<string, HeaderHeight>;
|
|
62
|
+
|
|
58
63
|
type Props = {
|
|
59
64
|
direction: LocaleDirection;
|
|
60
65
|
insets: EdgeInsets;
|
|
@@ -89,7 +94,7 @@ type State = {
|
|
|
89
94
|
scenes: Scene[];
|
|
90
95
|
gestures: GestureValues;
|
|
91
96
|
layout: Layout;
|
|
92
|
-
headerHeights:
|
|
97
|
+
headerHeights: HeaderHeights;
|
|
93
98
|
};
|
|
94
99
|
|
|
95
100
|
const NAMED_TRANSITIONS_PRESETS = {
|
|
@@ -110,6 +115,8 @@ const NAMED_TRANSITIONS_PRESETS = {
|
|
|
110
115
|
|
|
111
116
|
const FALLBACK_DESCRIPTOR = Object.freeze({ options: {} });
|
|
112
117
|
|
|
118
|
+
const HIDDEN_HEADER_HEIGHT = { measured: false, value: 0 };
|
|
119
|
+
|
|
113
120
|
const getInterpolationIndex = (scenes: Scene[], index: number) => {
|
|
114
121
|
const { cardStyleInterpolator } = scenes[index].descriptor.options;
|
|
115
122
|
|
|
@@ -162,9 +169,9 @@ const getHeaderHeights = (
|
|
|
162
169
|
isParentHeaderShown: boolean,
|
|
163
170
|
isParentModal: boolean,
|
|
164
171
|
layout: Layout,
|
|
165
|
-
previous:
|
|
172
|
+
previous: HeaderHeights
|
|
166
173
|
) => {
|
|
167
|
-
return scenes.reduce<
|
|
174
|
+
return scenes.reduce<HeaderHeights>((acc, curr, index) => {
|
|
168
175
|
const {
|
|
169
176
|
headerStatusBarHeight = isParentHeaderShown ? 0 : insets.top,
|
|
170
177
|
headerStyle,
|
|
@@ -175,19 +182,34 @@ const getHeaderHeights = (
|
|
|
175
182
|
const height =
|
|
176
183
|
'height' in style && typeof style.height === 'number'
|
|
177
184
|
? style.height
|
|
178
|
-
:
|
|
185
|
+
: undefined;
|
|
179
186
|
|
|
180
187
|
const interpolationIndex = getInterpolationIndex(scenes, index);
|
|
181
188
|
const isModal = getIsModal(curr, interpolationIndex, isParentModal);
|
|
182
189
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
if (typeof height === 'number') {
|
|
191
|
+
acc[curr.route.key] = { measured: true, value: height };
|
|
192
|
+
} else {
|
|
193
|
+
const previousHeight = previous[curr.route.key];
|
|
194
|
+
const defaultHeight = getDefaultHeaderHeight({
|
|
195
|
+
landscape: layout.width > layout.height,
|
|
196
|
+
modalPresentation: isModal,
|
|
197
|
+
topInset: headerStatusBarHeight,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// If we hadn't measured before, use re-computed default height
|
|
201
|
+
if (
|
|
202
|
+
!previousHeight?.measured &&
|
|
203
|
+
defaultHeight !== previousHeight?.value
|
|
204
|
+
) {
|
|
205
|
+
acc[curr.route.key] = {
|
|
206
|
+
measured: false,
|
|
207
|
+
value: defaultHeight,
|
|
208
|
+
};
|
|
209
|
+
} else if (previousHeight) {
|
|
210
|
+
acc[curr.route.key] = previousHeight;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
191
213
|
|
|
192
214
|
return acc;
|
|
193
215
|
}, {});
|
|
@@ -541,14 +563,17 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
541
563
|
this.setState(({ headerHeights }) => {
|
|
542
564
|
const previousHeight = headerHeights[route.key];
|
|
543
565
|
|
|
544
|
-
if (previousHeight === height) {
|
|
566
|
+
if (previousHeight?.value === height) {
|
|
545
567
|
return null;
|
|
546
568
|
}
|
|
547
569
|
|
|
548
570
|
return {
|
|
549
571
|
headerHeights: {
|
|
550
572
|
...headerHeights,
|
|
551
|
-
[route.key]:
|
|
573
|
+
[route.key]: {
|
|
574
|
+
measured: true,
|
|
575
|
+
value: height,
|
|
576
|
+
},
|
|
552
577
|
},
|
|
553
578
|
};
|
|
554
579
|
});
|
|
@@ -622,6 +647,8 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
622
647
|
scenes.findLast((scene) => scene.route.key === focusedRoute.key)
|
|
623
648
|
?.descriptor.options.headerMode === 'float';
|
|
624
649
|
|
|
650
|
+
const focusedHeaderHeight = headerHeights[focusedRoute.key];
|
|
651
|
+
|
|
625
652
|
return (
|
|
626
653
|
<View style={styles.container}>
|
|
627
654
|
{renderHeader({
|
|
@@ -637,7 +664,7 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
637
664
|
// The header title can't be found with maestro without this
|
|
638
665
|
// In some cases, header buttons may not be touchable as well
|
|
639
666
|
isFloatHeaderFocused && {
|
|
640
|
-
height:
|
|
667
|
+
height: focusedHeaderHeight?.value,
|
|
641
668
|
},
|
|
642
669
|
],
|
|
643
670
|
],
|
|
@@ -647,12 +674,12 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
647
674
|
const focused = focusedRoute.key === route.key;
|
|
648
675
|
const gesture = gestures[route.key];
|
|
649
676
|
const scene = scenes[index];
|
|
650
|
-
const isInactive = isInactiveRoute(route, this.props.routes);
|
|
651
677
|
|
|
652
678
|
const {
|
|
653
679
|
inactiveBehavior = 'pause',
|
|
654
680
|
animation,
|
|
655
681
|
headerShown = true,
|
|
682
|
+
headerMode,
|
|
656
683
|
headerTransparent,
|
|
657
684
|
} = scene.descriptor.options;
|
|
658
685
|
|
|
@@ -662,7 +689,9 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
662
689
|
const safeAreaInsetLeft = insets.left;
|
|
663
690
|
|
|
664
691
|
const headerHeight =
|
|
665
|
-
headerShown !== false
|
|
692
|
+
headerShown !== false
|
|
693
|
+
? headerHeights[route.key]
|
|
694
|
+
: HIDDEN_HEADER_HEIGHT;
|
|
666
695
|
|
|
667
696
|
// Start from current card and count backwards the number of cards with same interpolation
|
|
668
697
|
const interpolationIndex = getInterpolationIndex(scenes, index);
|
|
@@ -696,25 +725,36 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
696
725
|
self[index + 1]?.key
|
|
697
726
|
);
|
|
698
727
|
|
|
728
|
+
const isInactive = isInactiveRoute(route, this.props.routes);
|
|
729
|
+
const isRetained = state.retainedRouteKeys?.includes(route.key);
|
|
730
|
+
const isPreloaded = isInactive && !isRetained;
|
|
731
|
+
|
|
732
|
+
const isTopmost = index === routes.length - 1;
|
|
699
733
|
const isBeforeLast = index === routes.length - 2;
|
|
700
734
|
|
|
701
735
|
// Keep animating and the last two rendered routes visible for smoother transitions
|
|
702
736
|
const isVisible =
|
|
703
737
|
focused ||
|
|
704
738
|
isNextScreenTransparent ||
|
|
739
|
+
// React native destroys the view when hidden
|
|
740
|
+
// So we keep retained screens visible
|
|
741
|
+
// This makes sure any videos being played don't stop etc.
|
|
742
|
+
isRetained ||
|
|
705
743
|
// We only need to keep other screens visible when animation is enabled
|
|
706
744
|
(isAnimationEnabled &&
|
|
707
745
|
(isFocusing ||
|
|
708
746
|
isRemoving ||
|
|
709
|
-
// Preloaded
|
|
710
|
-
(!
|
|
747
|
+
// Preloaded screens should stay mounted, but remain hidden until focused
|
|
748
|
+
(!isPreloaded && index >= routes.length - 2)));
|
|
711
749
|
|
|
712
750
|
const activityMode = // Render focused and animating screens normally
|
|
713
751
|
focused || isFocusing
|
|
714
752
|
? 'normal'
|
|
715
753
|
: inactiveBehavior === 'none' ||
|
|
716
754
|
// Unpause preloaded or retained screens so updates are visible
|
|
755
|
+
// Handle retained explicitly as isInactive won't be updated until animation end
|
|
717
756
|
isInactive ||
|
|
757
|
+
isRetained ||
|
|
718
758
|
// Keep the screen before transparent screen active
|
|
719
759
|
// This lets the screen under the transparent screen update and animate
|
|
720
760
|
isNextScreenTransparent ||
|
|
@@ -736,49 +776,62 @@ export class CardStack extends React.Component<Props, State> {
|
|
|
736
776
|
}
|
|
737
777
|
|
|
738
778
|
return (
|
|
739
|
-
<
|
|
779
|
+
<ActivityView
|
|
740
780
|
key={route.key}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
getPreviousScene={this.getPreviousScene}
|
|
762
|
-
getFocusedRoute={this.getFocusedRoute}
|
|
763
|
-
hasAbsoluteFloatHeader={
|
|
764
|
-
isFloatHeaderAbsolute && !headerTransparent
|
|
765
|
-
}
|
|
766
|
-
renderHeader={renderHeader}
|
|
767
|
-
onOpenRoute={onOpenRoute}
|
|
768
|
-
onCloseRoute={onCloseRoute}
|
|
769
|
-
onTransitionStart={onTransitionStart}
|
|
770
|
-
onTransitionEnd={onTransitionEnd}
|
|
771
|
-
isNextScreenTransparent={isNextScreenTransparent}
|
|
772
|
-
preloaded={isInactive}
|
|
781
|
+
mode={activityMode}
|
|
782
|
+
visible={isVisible}
|
|
783
|
+
style={{
|
|
784
|
+
...StyleSheet.absoluteFill,
|
|
785
|
+
// Avoid unfocused larger pages increasing scroll area
|
|
786
|
+
// e.g. when a smaller screen is pushed over a larger one on web
|
|
787
|
+
overflow: isTopmost ? undefined : 'hidden',
|
|
788
|
+
marginTop:
|
|
789
|
+
headerTransparent || headerMode === 'screen'
|
|
790
|
+
? 0
|
|
791
|
+
: // Add offset for non-transparent floating header
|
|
792
|
+
isFloatHeaderAbsolute
|
|
793
|
+
? // If header is absolute, offset the card by the header height
|
|
794
|
+
headerHeight?.value
|
|
795
|
+
: // Otherwise, the in-flow float header already takes the
|
|
796
|
+
// focused header's space, so offset by the difference
|
|
797
|
+
headerHeight && focusedHeaderHeight
|
|
798
|
+
? headerHeight.value - focusedHeaderHeight.value
|
|
799
|
+
: 0,
|
|
800
|
+
}}
|
|
773
801
|
>
|
|
774
|
-
<
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
802
|
+
<CardContainer
|
|
803
|
+
index={index}
|
|
804
|
+
interpolationIndex={interpolationIndex}
|
|
805
|
+
modal={isModal}
|
|
806
|
+
active={isTopmost}
|
|
807
|
+
focused={focused}
|
|
808
|
+
opening={openingRouteKeys.includes(route.key)}
|
|
809
|
+
closing={closingRouteKeys.includes(route.key)}
|
|
810
|
+
layout={layout}
|
|
811
|
+
gesture={gesture}
|
|
812
|
+
scene={scene}
|
|
813
|
+
safeAreaInsetTop={safeAreaInsetTop}
|
|
814
|
+
safeAreaInsetRight={safeAreaInsetRight}
|
|
815
|
+
safeAreaInsetBottom={safeAreaInsetBottom}
|
|
816
|
+
safeAreaInsetLeft={safeAreaInsetLeft}
|
|
817
|
+
onGestureStart={onGestureStart}
|
|
818
|
+
onGestureCancel={onGestureCancel}
|
|
819
|
+
onGestureEnd={onGestureEnd}
|
|
820
|
+
headerHeight={headerHeight}
|
|
821
|
+
isParentHeaderShown={isParentHeaderShown}
|
|
822
|
+
onHeaderHeightChange={this.handleHeaderLayout}
|
|
823
|
+
getPreviousScene={this.getPreviousScene}
|
|
824
|
+
getFocusedRoute={this.getFocusedRoute}
|
|
825
|
+
renderHeader={renderHeader}
|
|
826
|
+
onOpenRoute={onOpenRoute}
|
|
827
|
+
onCloseRoute={onCloseRoute}
|
|
828
|
+
onTransitionStart={onTransitionStart}
|
|
829
|
+
onTransitionEnd={onTransitionEnd}
|
|
830
|
+
preloaded={isInactive}
|
|
778
831
|
>
|
|
779
832
|
{scene.descriptor.render()}
|
|
780
|
-
</
|
|
781
|
-
</
|
|
833
|
+
</CardContainer>
|
|
834
|
+
</ActivityView>
|
|
782
835
|
);
|
|
783
836
|
})}
|
|
784
837
|
</View>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import { Platform, StyleSheet, View } from 'react-native';
|
|
5
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
-
export function CardA11yWrapper({
|
|
7
|
-
focused,
|
|
8
|
-
active,
|
|
9
|
-
animated,
|
|
10
|
-
isNextScreenTransparent,
|
|
11
|
-
children,
|
|
12
|
-
ref
|
|
13
|
-
}) {
|
|
14
|
-
// Manage this in separate component to avoid re-rendering card during gestures
|
|
15
|
-
// Otherwise the gesture animation will be interrupted as state hasn't updated yet
|
|
16
|
-
const [inert, setInert] = React.useState(false);
|
|
17
|
-
React.useImperativeHandle(ref, () => ({
|
|
18
|
-
setInert
|
|
19
|
-
}), []);
|
|
20
|
-
const isHidden = !animated && isNextScreenTransparent === false && !focused;
|
|
21
|
-
return /*#__PURE__*/_jsx(View, {
|
|
22
|
-
"aria-hidden": !focused,
|
|
23
|
-
style: [StyleSheet.absoluteFill, {
|
|
24
|
-
pointerEvents: (animated ? inert : !focused) ? 'none' : 'box-none',
|
|
25
|
-
// This is necessary to avoid unfocused larger pages increasing scroll area
|
|
26
|
-
// The issue can be seen on the web when a smaller screen is pushed over a larger one
|
|
27
|
-
overflow: active ? undefined : 'hidden',
|
|
28
|
-
// We use visibility on web
|
|
29
|
-
display: Platform.OS !== 'web' && isHidden ? 'none' : 'flex',
|
|
30
|
-
// Hide unfocused screens when animation isn't enabled
|
|
31
|
-
// This is also necessary for a11y on web
|
|
32
|
-
// @ts-expect-error visibility is only available on web
|
|
33
|
-
visibility: isHidden ? 'hidden' : 'visible'
|
|
34
|
-
}]
|
|
35
|
-
// Make sure this view is not removed on the new architecture, as it causes focus loss during navigation on Android.
|
|
36
|
-
// This can happen when the view flattening results in different trees - due to `overflow` style changing in a parent.
|
|
37
|
-
,
|
|
38
|
-
collapsable: false,
|
|
39
|
-
children: children
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=CardA11yWrapper.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","Platform","StyleSheet","View","jsx","_jsx","CardA11yWrapper","focused","active","animated","isNextScreenTransparent","children","ref","inert","setInert","useState","useImperativeHandle","isHidden","style","absoluteFill","pointerEvents","overflow","undefined","display","OS","visibility","collapsable"],"sourceRoot":"../../../../src","sources":["views/Stack/CardA11yWrapper.tsx"],"mappings":";;AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,QAAQ,EAAEC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAa1D,OAAO,SAASC,eAAeA,CAAC;EAC9BC,OAAO;EACPC,MAAM;EACNC,QAAQ;EACRC,uBAAuB;EACvBC,QAAQ;EACRC;AACK,CAAC,EAAE;EACR;EACA;EACA,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGd,KAAK,CAACe,QAAQ,CAAC,KAAK,CAAC;EAE/Cf,KAAK,CAACgB,mBAAmB,CAACJ,GAAG,EAAE,OAAO;IAAEE;EAAS,CAAC,CAAC,EAAE,EAAE,CAAC;EAExD,MAAMG,QAAQ,GAAG,CAACR,QAAQ,IAAIC,uBAAuB,KAAK,KAAK,IAAI,CAACH,OAAO;EAE3E,oBACEF,IAAA,CAACF,IAAI;IACH,eAAa,CAACI,OAAQ;IACtBW,KAAK,EAAE,CACLhB,UAAU,CAACiB,YAAY,EACvB;MACEC,aAAa,EAAE,CAACX,QAAQ,GAAGI,KAAK,GAAG,CAACN,OAAO,IAAI,MAAM,GAAG,UAAU;MAClE;MACA;MACAc,QAAQ,EAAEb,MAAM,GAAGc,SAAS,GAAG,QAAQ;MACvC;MACAC,OAAO,EAAEtB,QAAQ,CAACuB,EAAE,KAAK,KAAK,IAAIP,QAAQ,GAAG,MAAM,GAAG,MAAM;MAC5D;MACA;MACA;MACAQ,UAAU,EAAER,QAAQ,GAAG,QAAQ,GAAG;IACpC,CAAC;IAEH;IACA;IAAA;IACAS,WAAW,EAAE,KAAM;IAAAf,QAAA,EAElBA;EAAQ,CACL,CAAC;AAEX","ignoreList":[]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
type Props = {
|
|
3
|
-
focused: boolean;
|
|
4
|
-
active: boolean;
|
|
5
|
-
animated: boolean;
|
|
6
|
-
isNextScreenTransparent: boolean;
|
|
7
|
-
children: React.ReactNode;
|
|
8
|
-
ref?: React.Ref<CardA11yWrapperRef>;
|
|
9
|
-
};
|
|
10
|
-
export type CardA11yWrapperRef = {
|
|
11
|
-
setInert: (value: boolean) => void;
|
|
12
|
-
};
|
|
13
|
-
export declare function CardA11yWrapper({ focused, active, animated, isNextScreenTransparent, children, ref, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=CardA11yWrapper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CardA11yWrapper.d.ts","sourceRoot":"","sources":["../../../../../src/views/Stack/CardA11yWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,KAAK,KAAK,GAAG;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,uBAAuB,EAAE,OAAO,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,CAAC;AAExE,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,MAAM,EACN,QAAQ,EACR,uBAAuB,EACvB,QAAQ,EACR,GAAG,GACJ,EAAE,KAAK,2CAkCP"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Platform, StyleSheet, View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
type Props = {
|
|
5
|
-
focused: boolean;
|
|
6
|
-
active: boolean;
|
|
7
|
-
animated: boolean;
|
|
8
|
-
isNextScreenTransparent: boolean;
|
|
9
|
-
children: React.ReactNode;
|
|
10
|
-
ref?: React.Ref<CardA11yWrapperRef>;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type CardA11yWrapperRef = { setInert: (value: boolean) => void };
|
|
14
|
-
|
|
15
|
-
export function CardA11yWrapper({
|
|
16
|
-
focused,
|
|
17
|
-
active,
|
|
18
|
-
animated,
|
|
19
|
-
isNextScreenTransparent,
|
|
20
|
-
children,
|
|
21
|
-
ref,
|
|
22
|
-
}: Props) {
|
|
23
|
-
// Manage this in separate component to avoid re-rendering card during gestures
|
|
24
|
-
// Otherwise the gesture animation will be interrupted as state hasn't updated yet
|
|
25
|
-
const [inert, setInert] = React.useState(false);
|
|
26
|
-
|
|
27
|
-
React.useImperativeHandle(ref, () => ({ setInert }), []);
|
|
28
|
-
|
|
29
|
-
const isHidden = !animated && isNextScreenTransparent === false && !focused;
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<View
|
|
33
|
-
aria-hidden={!focused}
|
|
34
|
-
style={[
|
|
35
|
-
StyleSheet.absoluteFill,
|
|
36
|
-
{
|
|
37
|
-
pointerEvents: (animated ? inert : !focused) ? 'none' : 'box-none',
|
|
38
|
-
// This is necessary to avoid unfocused larger pages increasing scroll area
|
|
39
|
-
// The issue can be seen on the web when a smaller screen is pushed over a larger one
|
|
40
|
-
overflow: active ? undefined : 'hidden',
|
|
41
|
-
// We use visibility on web
|
|
42
|
-
display: Platform.OS !== 'web' && isHidden ? 'none' : 'flex',
|
|
43
|
-
// Hide unfocused screens when animation isn't enabled
|
|
44
|
-
// This is also necessary for a11y on web
|
|
45
|
-
// @ts-expect-error visibility is only available on web
|
|
46
|
-
visibility: isHidden ? 'hidden' : 'visible',
|
|
47
|
-
},
|
|
48
|
-
]}
|
|
49
|
-
// Make sure this view is not removed on the new architecture, as it causes focus loss during navigation on Android.
|
|
50
|
-
// This can happen when the view flattening results in different trees - due to `overflow` style changing in a parent.
|
|
51
|
-
collapsable={false}
|
|
52
|
-
>
|
|
53
|
-
{children}
|
|
54
|
-
</View>
|
|
55
|
-
);
|
|
56
|
-
}
|