diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js index 0d2de826d..e2f4c7298 100644 --- a/native/chat/chat-input-bar.react.js +++ b/native/chat/chat-input-bar.react.js @@ -1,988 +1,988 @@ // @flow import invariant from 'invariant'; import _throttle from 'lodash/throttle'; import * as React from 'react'; import { View, TextInput, TouchableOpacity, Platform, Text, ActivityIndicator, TouchableWithoutFeedback, NativeAppEventEmitter, } from 'react-native'; import { TextInputKeyboardMangerIOS } from 'react-native-keyboard-input'; import Animated, { EasingNode } from 'react-native-reanimated'; import Icon from 'react-native-vector-icons/Ionicons'; import { useDispatch } from 'react-redux'; import { joinThreadActionTypes, joinThread, newThreadActionTypes, } from 'lib/actions/thread-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { localIDPrefix, trimMessage } from 'lib/shared/message-utils'; import { threadHasPermission, viewerIsMember, threadFrozenDueToViewerBlock, threadActualMembers, checkIfDefaultMembersAreVoiced, draftKeyFromThreadID, } from 'lib/shared/thread-utils'; import type { CalendarQuery } from 'lib/types/entry-types'; import type { LoadingStatus } from 'lib/types/loading-types'; import type { PhotoPaste } from 'lib/types/media-types'; import { messageTypes } from 'lib/types/message-types'; import type { Dispatch } from 'lib/types/redux-types'; import { type ThreadInfo, threadPermissions, type ClientThreadJoinRequest, type ThreadJoinPayload, } from 'lib/types/thread-types'; import { type UserInfos } from 'lib/types/user-types'; import { type DispatchActionPromise, useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils'; import Button from '../components/button.react'; import ClearableTextInput from '../components/clearable-text-input.react'; import SWMansionIcon from '../components/swmansion-icon.react'; import { type UpdateDraft, type MoveDraft, useDrafts } from '../data/core-data'; import { type InputState, InputStateContext } from '../input/input-state'; import { getKeyboardHeight } from '../keyboard/keyboard'; import KeyboardInputHost from '../keyboard/keyboard-input-host.react'; import { type KeyboardState, KeyboardContext, } from '../keyboard/keyboard-state'; import { nonThreadCalendarQuery, activeThreadSelector, } from '../navigation/nav-selectors'; import { NavContext } from '../navigation/navigation-context'; import { type NavigationRoute, CameraModalRouteName, ImagePasteModalRouteName, } from '../navigation/route-names'; import { useSelector } from '../redux/redux-utils'; import { type Colors, useStyles, useColors } from '../themes/colors'; import type { LayoutEvent } from '../types/react-native'; import { type AnimatedViewStyle, AnimatedView } from '../types/styles'; import { runTiming } from '../utils/animation-utils'; import { ChatContext } from './chat-context'; import type { ChatNavigationProp } from './chat.react'; /* eslint-disable import/no-named-as-default-member */ const { Value, Clock, block, set, cond, neq, sub, interpolateNode, stopClock, } = Animated; /* eslint-enable import/no-named-as-default-member */ const expandoButtonsAnimationConfig = { duration: 150, easing: EasingNode.inOut(EasingNode.ease), }; const sendButtonAnimationConfig = { duration: 150, easing: EasingNode.inOut(EasingNode.ease), }; type BaseProps = { +threadInfo: ThreadInfo, }; type Props = { ...BaseProps, // Redux state +viewerID: ?string, +draft: string, +updateDraft: UpdateDraft, +moveDraft: MoveDraft, +joinThreadLoadingStatus: LoadingStatus, +threadCreationInProgress: boolean, +calendarQuery: () => CalendarQuery, +nextLocalID: number, +userInfos: UserInfos, +colors: Colors, +styles: typeof unboundStyles, +onInputBarLayout?: (event: LayoutEvent) => mixed, +openCamera: () => mixed, // connectNav +isActive: boolean, // withKeyboardState +keyboardState: ?KeyboardState, // Redux dispatch functions +dispatch: Dispatch, +dispatchActionPromise: DispatchActionPromise, // async functions that hit server APIs +joinThread: (request: ClientThreadJoinRequest) => Promise, // withInputState +inputState: ?InputState, }; type State = { +text: string, +textEdited: boolean, +buttonsExpanded: boolean, }; class ChatInputBar extends React.PureComponent { textInput: ?React.ElementRef; clearableTextInput: ?ClearableTextInput; expandoButtonsOpen: Value; targetExpandoButtonsOpen: Value; expandoButtonsStyle: AnimatedViewStyle; cameraRollIconStyle: AnimatedViewStyle; cameraIconStyle: AnimatedViewStyle; expandIconStyle: AnimatedViewStyle; sendButtonContainerOpen: Value; targetSendButtonContainerOpen: Value; sendButtonContainerStyle: AnimatedViewStyle; constructor(props: Props) { super(props); this.state = { text: props.draft, textEdited: false, buttonsExpanded: true, }; this.setUpActionIconAnimations(); this.setUpSendIconAnimations(); } setUpActionIconAnimations() { this.expandoButtonsOpen = new Value(1); this.targetExpandoButtonsOpen = new Value(1); const prevTargetExpandoButtonsOpen = new Value(1); const expandoButtonClock = new Clock(); const expandoButtonsOpen = block([ cond(neq(this.targetExpandoButtonsOpen, prevTargetExpandoButtonsOpen), [ stopClock(expandoButtonClock), set(prevTargetExpandoButtonsOpen, this.targetExpandoButtonsOpen), ]), cond( neq(this.expandoButtonsOpen, this.targetExpandoButtonsOpen), set( this.expandoButtonsOpen, runTiming( expandoButtonClock, this.expandoButtonsOpen, this.targetExpandoButtonsOpen, true, expandoButtonsAnimationConfig, ), ), ), this.expandoButtonsOpen, ]); this.cameraRollIconStyle = { ...unboundStyles.cameraRollIcon, opacity: expandoButtonsOpen, }; this.cameraIconStyle = { ...unboundStyles.cameraIcon, opacity: expandoButtonsOpen, }; const expandoButtonsWidth = interpolateNode(expandoButtonsOpen, { inputRange: [0, 1], outputRange: [26, 66], }); this.expandoButtonsStyle = { ...unboundStyles.expandoButtons, width: expandoButtonsWidth, }; const expandOpacity = sub(1, expandoButtonsOpen); this.expandIconStyle = { ...unboundStyles.expandIcon, opacity: expandOpacity, }; } setUpSendIconAnimations() { const initialSendButtonContainerOpen = trimMessage(this.props.draft) ? 1 : 0; this.sendButtonContainerOpen = new Value(initialSendButtonContainerOpen); this.targetSendButtonContainerOpen = new Value( initialSendButtonContainerOpen, ); const prevTargetSendButtonContainerOpen = new Value( initialSendButtonContainerOpen, ); const sendButtonClock = new Clock(); const sendButtonContainerOpen = block([ cond( neq( this.targetSendButtonContainerOpen, prevTargetSendButtonContainerOpen, ), [ stopClock(sendButtonClock), set( prevTargetSendButtonContainerOpen, this.targetSendButtonContainerOpen, ), ], ), cond( neq(this.sendButtonContainerOpen, this.targetSendButtonContainerOpen), set( this.sendButtonContainerOpen, runTiming( sendButtonClock, this.sendButtonContainerOpen, this.targetSendButtonContainerOpen, true, sendButtonAnimationConfig, ), ), ), this.sendButtonContainerOpen, ]); const sendButtonContainerWidth = interpolateNode(sendButtonContainerOpen, { inputRange: [0, 1], outputRange: [4, 38], }); this.sendButtonContainerStyle = { width: sendButtonContainerWidth }; } static mediaGalleryOpen(props: Props) { const { keyboardState } = props; return !!(keyboardState && keyboardState.mediaGalleryOpen); } static systemKeyboardShowing(props: Props) { const { keyboardState } = props; return !!(keyboardState && keyboardState.systemKeyboardShowing); } get systemKeyboardShowing() { return ChatInputBar.systemKeyboardShowing(this.props); } immediatelyShowSendButton() { this.sendButtonContainerOpen.setValue(1); this.targetSendButtonContainerOpen.setValue(1); } updateSendButton(currentText: string) { if (this.shouldShowTextInput) { this.targetSendButtonContainerOpen.setValue(currentText === '' ? 0 : 1); } else { this.setUpSendIconAnimations(); } } componentDidMount() { if (this.props.isActive) { this.addReplyListener(); } } componentWillUnmount() { if (this.props.isActive) { this.removeReplyListener(); } } componentDidUpdate(prevProps: Props, prevState: State) { if ( this.state.textEdited && this.state.text && this.props.threadInfo.id !== prevProps.threadInfo.id ) { this.props.moveDraft( draftKeyFromThreadID(prevProps.threadInfo.id), draftKeyFromThreadID(this.props.threadInfo.id), ); } else if (!this.state.textEdited && this.props.draft !== prevProps.draft) { this.setState({ text: this.props.draft }); } if (this.props.isActive && !prevProps.isActive) { this.addReplyListener(); } else if (!this.props.isActive && prevProps.isActive) { this.removeReplyListener(); } const currentText = trimMessage(this.state.text); const prevText = trimMessage(prevState.text); if ( (currentText === '' && prevText !== '') || (currentText !== '' && prevText === '') ) { this.updateSendButton(currentText); } const systemKeyboardIsShowing = ChatInputBar.systemKeyboardShowing( this.props, ); const systemKeyboardWasShowing = ChatInputBar.systemKeyboardShowing( prevProps, ); if (systemKeyboardIsShowing && !systemKeyboardWasShowing) { this.hideButtons(); } else if (!systemKeyboardIsShowing && systemKeyboardWasShowing) { this.expandButtons(); } const imageGalleryIsOpen = ChatInputBar.mediaGalleryOpen(this.props); const imageGalleryWasOpen = ChatInputBar.mediaGalleryOpen(prevProps); if (!imageGalleryIsOpen && imageGalleryWasOpen) { this.hideButtons(); } else if (imageGalleryIsOpen && !imageGalleryWasOpen) { this.expandButtons(); this.setIOSKeyboardHeight(); } } addReplyListener() { invariant( this.props.inputState, 'inputState should be set in addReplyListener', ); this.props.inputState.addReplyListener(this.focusAndUpdateText); } removeReplyListener() { invariant( this.props.inputState, 'inputState should be set in removeReplyListener', ); this.props.inputState.removeReplyListener(this.focusAndUpdateText); } setIOSKeyboardHeight() { if (Platform.OS !== 'ios') { return; } const { textInput } = this; if (!textInput) { return; } const keyboardHeight = getKeyboardHeight(); if (keyboardHeight === null || keyboardHeight === undefined) { return; } TextInputKeyboardMangerIOS.setKeyboardHeight(textInput, keyboardHeight); } get shouldShowTextInput(): boolean { if (threadHasPermission(this.props.threadInfo, threadPermissions.VOICED)) { return true; } // If the thread is created by somebody else while the viewer is attempting // to create it, the threadInfo might be modified in-place // and won't list the viewer as a member, // which will end up hiding the input. // In this case, we will assume that our creation action // will get translated into a join, and as long // as members are voiced, we can show the input. if (!this.props.threadCreationInProgress) { return false; } return checkIfDefaultMembersAreVoiced(this.props.threadInfo); } render() { const isMember = viewerIsMember(this.props.threadInfo); const canJoin = threadHasPermission( this.props.threadInfo, threadPermissions.JOIN_THREAD, ); let joinButton = null; if (!isMember && canJoin && !this.props.threadCreationInProgress) { let buttonContent; if (this.props.joinThreadLoadingStatus === 'loading') { buttonContent = ( ); } else { buttonContent = ( Join Chat ); } joinButton = ( ); } let content; const defaultMembersAreVoiced = checkIfDefaultMembersAreVoiced( this.props.threadInfo, ); if (this.shouldShowTextInput) { content = this.renderInput(); } else if ( threadFrozenDueToViewerBlock( this.props.threadInfo, this.props.viewerID, this.props.userInfos, ) && threadActualMembers(this.props.threadInfo.members).length === 2 ) { content = ( You can't send messages to a user that you've blocked. ); } else if (isMember) { content = ( You don't have permission to send messages. ); } else if (defaultMembersAreVoiced && canJoin) { content = null; } else { content = ( You don't have permission to send messages. ); } const keyboardInputHost = Platform.OS === 'android' ? null : ( ); return ( {joinButton} {content} {keyboardInputHost} ); } renderInput() { const expandoButton = ( ); const threadColor = `#${this.props.threadInfo.color}`; return ( {this.state.buttonsExpanded ? expandoButton : null} {this.state.buttonsExpanded ? null : expandoButton} ); } textInputRef = (textInput: ?React.ElementRef) => { this.textInput = textInput; }; clearableTextInputRef = (clearableTextInput: ?ClearableTextInput) => { this.clearableTextInput = clearableTextInput; }; updateText = (text: string) => { this.setState({ text, textEdited: true }); this.saveDraft(text); }; saveDraft = _throttle(text => { this.props.updateDraft({ key: draftKeyFromThreadID(this.props.threadInfo.id), text, }); }, 400); focusAndUpdateText = (text: string) => { const { textInput } = this; if (!textInput) { return; } const currentText = this.state.text; if (!currentText.startsWith(text)) { const prependedText = text.concat(currentText); this.updateText(prependedText); this.immediatelyShowSendButton(); this.immediatelyHideButtons(); } textInput.focus(); }; onSend = async () => { if (!trimMessage(this.state.text)) { return; } this.updateSendButton(''); const { clearableTextInput } = this; invariant( clearableTextInput, 'clearableTextInput should be sent in onSend', ); let text = await clearableTextInput.getValueAndReset(); text = trimMessage(text); if (!text) { return; } const localID = `${localIDPrefix}${this.props.nextLocalID}`; const creatorID = this.props.viewerID; invariant(creatorID, 'should have viewer ID in order to send a message'); invariant( this.props.inputState, 'inputState should be set in ChatInputBar.onSend', ); this.props.inputState.sendTextMessage( { type: messageTypes.TEXT, localID, threadID: this.props.threadInfo.id, text, creatorID, time: Date.now(), }, this.props.threadInfo, ); }; onPressJoin = () => { this.props.dispatchActionPromise(joinThreadActionTypes, this.joinAction()); }; async joinAction() { const query = this.props.calendarQuery(); return await this.props.joinThread({ threadID: this.props.threadInfo.id, calendarQuery: { startDate: query.startDate, endDate: query.endDate, filters: [ ...query.filters, { type: 'threads', threadIDs: [this.props.threadInfo.id] }, ], }, }); } expandButtons = () => { if (this.state.buttonsExpanded) { return; } this.targetExpandoButtonsOpen.setValue(1); this.setState({ buttonsExpanded: true }); }; hideButtons() { if ( ChatInputBar.mediaGalleryOpen(this.props) || !this.systemKeyboardShowing || !this.state.buttonsExpanded ) { return; } this.targetExpandoButtonsOpen.setValue(0); this.setState({ buttonsExpanded: false }); } immediatelyHideButtons() { this.expandoButtonsOpen.setValue(0); this.targetExpandoButtonsOpen.setValue(0); this.setState({ buttonsExpanded: false }); } showMediaGallery = () => { const { keyboardState } = this.props; invariant(keyboardState, 'keyboardState should be initialized'); keyboardState.showMediaGallery(this.props.threadInfo); }; dismissKeyboard = () => { const { keyboardState } = this.props; keyboardState && keyboardState.dismissKeyboard(); }; } const unboundStyles = { cameraIcon: { paddingBottom: Platform.OS === 'android' ? 11 : 8, paddingRight: 5, }, cameraRollIcon: { paddingBottom: Platform.OS === 'android' ? 11 : 8, paddingRight: 5, }, container: { backgroundColor: 'listBackground', paddingLeft: Platform.OS === 'android' ? 10 : 5, }, expandButton: { bottom: 0, position: 'absolute', right: 0, }, expandIcon: { paddingBottom: Platform.OS === 'android' ? 13 : 11, paddingRight: 2, }, expandoButtons: { alignSelf: 'flex-end', }, explanation: { color: 'listBackgroundSecondaryLabel', paddingBottom: 4, paddingTop: 1, textAlign: 'center', }, innerExpandoButtons: { alignItems: 'flex-end', alignSelf: 'flex-end', flexDirection: 'row', }, inputContainer: { flexDirection: 'row', }, joinButton: { borderRadius: 8, flex: 1, justifyContent: 'center', marginHorizontal: 12, marginVertical: 3, }, joinButtonContainer: { flexDirection: 'row', height: 48, marginBottom: 8, }, joinButtonContent: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, joinButtonText: { color: 'listForegroundLabel', fontSize: 20, marginHorizontal: 4, }, joinThreadLoadingIndicator: { paddingVertical: 2, }, sendButton: { position: 'absolute', bottom: 4, left: 0, }, sendIcon: { paddingLeft: 9, paddingRight: 8, paddingVertical: 6, }, textInput: { backgroundColor: 'listInputBackground', borderRadius: 12, color: 'listForegroundLabel', fontSize: 16, marginLeft: 4, marginRight: 4, marginTop: 6, marginBottom: 8, maxHeight: 250, paddingHorizontal: 10, paddingVertical: 5, }, }; const joinThreadLoadingStatusSelector = createLoadingStatusSelector( joinThreadActionTypes, ); const createThreadLoadingStatusSelector = createLoadingStatusSelector( newThreadActionTypes, ); type ConnectedChatInputBarBaseProps = { ...BaseProps, +onInputBarLayout?: (event: LayoutEvent) => mixed, +openCamera: () => mixed, }; function ConnectedChatInputBarBase(props: ConnectedChatInputBarBaseProps) { const navContext = React.useContext(NavContext); const keyboardState = React.useContext(KeyboardContext); const inputState = React.useContext(InputStateContext); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); const { draft, updateDraft, moveDraft } = useDrafts(props.threadInfo.id); const joinThreadLoadingStatus = useSelector(joinThreadLoadingStatusSelector); const createThreadLoadingStatus = useSelector( createThreadLoadingStatusSelector, ); const threadCreationInProgress = createThreadLoadingStatus === 'loading'; const calendarQuery = useSelector(state => nonThreadCalendarQuery({ redux: state, navContext, }), ); const nextLocalID = useSelector(state => state.nextLocalID); const userInfos = useSelector(state => state.userStore.userInfos); const styles = useStyles(unboundStyles); const colors = useColors(); const isActive = React.useMemo( () => props.threadInfo.id === activeThreadSelector(navContext), [props.threadInfo.id, navContext], ); const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); const callJoinThread = useServerCall(joinThread); return ( ); } type DummyChatInputBarProps = { ...BaseProps, +onHeightMeasured: (height: number) => mixed, }; const noop = () => {}; function DummyChatInputBar(props: DummyChatInputBarProps): React.Node { const { onHeightMeasured, ...restProps } = props; const onInputBarLayout = React.useCallback( (event: LayoutEvent) => { const { height } = event.nativeEvent.layout; onHeightMeasured(height); }, [onHeightMeasured], ); return ( ); } type ChatInputBarProps = { ...BaseProps, +navigation: ChatNavigationProp<'MessageList'>, +route: NavigationRoute<'MessageList'>, }; const ConnectedChatInputBar: React.ComponentType = React.memo( function ConnectedChatInputBar(props: ChatInputBarProps) { const { navigation, route, ...restProps } = props; const keyboardState = React.useContext(KeyboardContext); const { threadInfo } = props; const imagePastedCallback = React.useCallback( imagePastedEvent => { if (threadInfo.id !== imagePastedEvent.threadID) { return; } const pastedImage: PhotoPaste = { step: 'photo_paste', dimensions: { height: imagePastedEvent.height, width: imagePastedEvent.width, }, filename: imagePastedEvent.fileName, uri: 'file://' + imagePastedEvent.filePath, selectTime: 0, sendTime: 0, retries: 0, }; - navigation.navigate({ + navigation.navigate<'ImagePasteModal'>({ name: ImagePasteModalRouteName, params: { imagePasteStagingInfo: pastedImage, thread: threadInfo, }, }); }, [navigation, threadInfo], ); React.useEffect(() => { const imagePasteListener = NativeAppEventEmitter.addListener( 'imagePasted', imagePastedCallback, ); return () => imagePasteListener.remove(); }, [imagePastedCallback]); const chatContext = React.useContext(ChatContext); invariant(chatContext, 'should be set'); const { setChatInputBarHeight, deleteChatInputBarHeight } = chatContext; const onInputBarLayout = React.useCallback( (event: LayoutEvent) => { const { height } = event.nativeEvent.layout; setChatInputBarHeight(threadInfo.id, height); }, [threadInfo.id, setChatInputBarHeight], ); React.useEffect(() => { return () => { deleteChatInputBarHeight(threadInfo.id); }; }, [deleteChatInputBarHeight, threadInfo.id]); const openCamera = React.useCallback(() => { keyboardState?.dismissKeyboard(); - navigation.navigate({ + navigation.navigate<'CameraModal'>({ name: CameraModalRouteName, params: { presentedFrom: route.key, thread: threadInfo, }, }); }, [keyboardState, navigation, route.key, threadInfo]); return ( ); }, ); export { ConnectedChatInputBar as ChatInputBar, DummyChatInputBar }; diff --git a/native/chat/chat-thread-list.react.js b/native/chat/chat-thread-list.react.js index 3ec0916a7..04027552f 100644 --- a/native/chat/chat-thread-list.react.js +++ b/native/chat/chat-thread-list.react.js @@ -1,647 +1,647 @@ // @flow import invariant from 'invariant'; import _sum from 'lodash/fp/sum'; import * as React from 'react'; import { View, FlatList, Platform, TextInput, TouchableWithoutFeedback, BackHandler, } from 'react-native'; import { FloatingAction } from 'react-native-floating-action'; import Animated from 'react-native-reanimated'; import IonIcon from 'react-native-vector-icons/Ionicons'; import { createSelector } from 'reselect'; import { searchUsers } from 'lib/actions/user-actions'; import { type ChatThreadItem, useFlattenedChatListData, } from 'lib/selectors/chat-selectors'; import { threadSearchIndex as threadSearchIndexSelector } from 'lib/selectors/nav-selectors'; import { usersWithPersonalThreadSelector } from 'lib/selectors/user-selectors'; import SearchIndex from 'lib/shared/search-index'; import { createPendingThread, getThreadListSearchResults, } from 'lib/shared/thread-utils'; import type { UserSearchResult } from 'lib/types/search-types'; import type { ThreadInfo } from 'lib/types/thread-types'; import { threadTypes } from 'lib/types/thread-types'; import type { GlobalAccountUserInfo, UserInfo } from 'lib/types/user-types'; import { useServerCall } from 'lib/utils/action-utils'; import Button from '../components/button.react'; import Search from '../components/search.react'; import type { TabNavigationProp } from '../navigation/app-navigator.react'; import { SidebarListModalRouteName, HomeChatThreadListRouteName, BackgroundChatThreadListRouteName, type NavigationRoute, } from '../navigation/route-names'; import { useSelector } from '../redux/redux-utils'; import { type IndicatorStyle, indicatorStyleSelector, useStyles, } from '../themes/colors'; import type { ScrollEvent } from '../types/react-native'; import { AnimatedView, type AnimatedStyleObj } from '../types/styles'; import { animateTowards } from '../utils/animation-utils'; import { ChatThreadListItem, chatThreadListItemHeight, spacerHeight, } from './chat-thread-list-item.react'; import type { ChatTopTabsNavigationProp, ChatNavigationProp, } from './chat.react'; import { type MessageListParams, useNavigateToThread, } from './message-list-types'; import { sidebarHeight } from './sidebar-item.react'; const floatingActions = [ { text: 'Compose', icon: , name: 'compose', position: 1, }, ]; /* eslint-disable import/no-named-as-default-member */ const { Value, Node, interpolateNode } = Animated; /* eslint-enable import/no-named-as-default-member */ type Item = | ChatThreadItem | { +type: 'search', +searchText: string } | { +type: 'empty', +emptyItem: React.ComponentType<{}> }; type BaseProps = { +navigation: | ChatTopTabsNavigationProp<'HomeChatThreadList'> | ChatTopTabsNavigationProp<'BackgroundChatThreadList'>, +route: | NavigationRoute<'HomeChatThreadList'> | NavigationRoute<'BackgroundChatThreadList'>, +filterThreads: (threadItem: ThreadInfo) => boolean, +emptyItem?: React.ComponentType<{}>, }; type Props = { ...BaseProps, // Redux state +chatListData: $ReadOnlyArray, +viewerID: ?string, +threadSearchIndex: SearchIndex, +styles: typeof unboundStyles, +indicatorStyle: IndicatorStyle, +usersWithPersonalThread: $ReadOnlySet, +navigateToThread: (params: MessageListParams) => void, // async functions that hit server APIs +searchUsers: (usernamePrefix: string) => Promise, }; type SearchStatus = 'inactive' | 'activating' | 'active'; type State = { +searchStatus: SearchStatus, +searchText: string, +threadsSearchResults: Set, +usersSearchResults: $ReadOnlyArray, +openedSwipeableId: string, +numItemsToDisplay: number, }; type PropsAndState = { ...Props, ...State }; class ChatThreadList extends React.PureComponent { state: State = { searchStatus: 'inactive', searchText: '', threadsSearchResults: new Set(), usersSearchResults: [], openedSwipeableId: '', numItemsToDisplay: 25, }; searchInput: ?React.ElementRef; flatList: ?FlatList; scrollPos = 0; clearNavigationBlurListener: ?() => mixed; searchCancelButtonOpen: Value = new Value(0); searchCancelButtonProgress: Node; searchCancelButtonOffset: Node; constructor(props: Props) { super(props); this.searchCancelButtonProgress = animateTowards( this.searchCancelButtonOpen, 100, ); this.searchCancelButtonOffset = interpolateNode( this.searchCancelButtonProgress, { inputRange: [0, 1], outputRange: [0, 56] }, ); } componentDidMount() { this.clearNavigationBlurListener = this.props.navigation.addListener( 'blur', () => { this.setState({ numItemsToDisplay: 25 }); }, ); const chatNavigation: ?ChatNavigationProp< 'ChatThreadList', > = this.props.navigation.dangerouslyGetParent(); invariant(chatNavigation, 'ChatNavigator should be within TabNavigator'); const tabNavigation: ?TabNavigationProp< 'Chat', > = chatNavigation.dangerouslyGetParent(); invariant(tabNavigation, 'ChatNavigator should be within TabNavigator'); tabNavigation.addListener('tabPress', this.onTabPress); BackHandler.addEventListener('hardwareBackPress', this.hardwareBack); } componentWillUnmount() { this.clearNavigationBlurListener && this.clearNavigationBlurListener(); const chatNavigation: ?ChatNavigationProp< 'ChatThreadList', > = this.props.navigation.dangerouslyGetParent(); invariant(chatNavigation, 'ChatNavigator should be within TabNavigator'); const tabNavigation: ?TabNavigationProp< 'Chat', > = chatNavigation.dangerouslyGetParent(); invariant(tabNavigation, 'ChatNavigator should be within TabNavigator'); tabNavigation.removeListener('tabPress', this.onTabPress); BackHandler.removeEventListener('hardwareBackPress', this.hardwareBack); } hardwareBack = () => { if (!this.props.navigation.isFocused()) { return false; } const { searchStatus } = this.state; const isActiveOrActivating = searchStatus === 'active' || searchStatus === 'activating'; if (!isActiveOrActivating) { return false; } this.onSearchCancel(); return true; }; componentDidUpdate(prevProps: Props, prevState: State) { const { searchStatus } = this.state; const prevSearchStatus = prevState.searchStatus; const isActiveOrActivating = searchStatus === 'active' || searchStatus === 'activating'; const wasActiveOrActivating = prevSearchStatus === 'active' || prevSearchStatus === 'activating'; if (isActiveOrActivating && !wasActiveOrActivating) { this.searchCancelButtonOpen.setValue(1); } else if (!isActiveOrActivating && wasActiveOrActivating) { this.searchCancelButtonOpen.setValue(0); } const { flatList } = this; if (!flatList) { return; } if (this.state.searchText !== prevState.searchText) { flatList.scrollToOffset({ offset: 0, animated: false }); return; } if (searchStatus === 'activating' && prevSearchStatus === 'inactive') { flatList.scrollToOffset({ offset: 0, animated: true }); } } onTabPress = () => { if (!this.props.navigation.isFocused()) { return; } if (this.scrollPos > 0 && this.flatList) { this.flatList.scrollToOffset({ offset: 0, animated: true }); } else if (this.props.route.name === BackgroundChatThreadListRouteName) { this.props.navigation.navigate({ name: HomeChatThreadListRouteName }); } }; onSearchFocus = () => { if (this.state.searchStatus !== 'inactive') { return; } if (this.scrollPos === 0) { this.setState({ searchStatus: 'active' }); } else { this.setState({ searchStatus: 'activating' }); } }; clearSearch() { const { flatList } = this; flatList && flatList.scrollToOffset({ offset: 0, animated: false }); this.setState({ searchStatus: 'inactive' }); } onSearchBlur = () => { if (this.state.searchStatus !== 'active') { return; } this.clearSearch(); }; onSearchCancel = () => { this.onChangeSearchText(''); this.clearSearch(); }; renderSearch(additionalProps?: $Shape>) { const animatedSearchBoxStyle: AnimatedStyleObj = { marginRight: this.searchCancelButtonOffset, }; const searchBoxStyle = [ this.props.styles.searchBox, animatedSearchBoxStyle, ]; const buttonStyle = [ this.props.styles.cancelSearchButtonText, { opacity: this.searchCancelButtonProgress }, ]; return ( ); } searchInputRef = (searchInput: ?React.ElementRef) => { this.searchInput = searchInput; }; renderItem = (row: { item: Item, ... }) => { const item = row.item; if (item.type === 'search') { return ( {this.renderSearch({ active: false })} ); } if (item.type === 'empty') { const EmptyItem = item.emptyItem; return ; } return ( ); }; static keyExtractor = (item: Item) => { if (item.type === 'chatThreadItem') { return item.threadInfo.id; } else if (item.type === 'empty') { return 'empty'; } else { return 'search'; } }; static getItemLayout = (data: ?$ReadOnlyArray, index: number) => { if (!data) { return { length: 0, offset: 0, index }; } const offset = ChatThreadList.heightOfItems( data.filter((_, i) => i < index), ); const item = data[index]; const length = item ? ChatThreadList.itemHeight(item) : 0; return { length, offset, index }; }; static itemHeight = (item: Item) => { if (item.type === 'search') { return Platform.OS === 'ios' ? 54.5 : 55; } // itemHeight for emptyItem might be wrong because of line wrapping // but we don't care because we'll only ever be rendering this item // by itself and it should always be on-screen if (item.type === 'empty') { return 123; } let height = chatThreadListItemHeight; height += item.sidebars.length * sidebarHeight; if (item.sidebars.length > 0) { height += spacerHeight; } return height; }; static heightOfItems(data: $ReadOnlyArray): number { return _sum(data.map(ChatThreadList.itemHeight)); } listDataSelector = createSelector( (propsAndState: PropsAndState) => propsAndState.chatListData, (propsAndState: PropsAndState) => propsAndState.searchStatus, (propsAndState: PropsAndState) => propsAndState.searchText, (propsAndState: PropsAndState) => propsAndState.threadsSearchResults, (propsAndState: PropsAndState) => propsAndState.emptyItem, (propsAndState: PropsAndState) => propsAndState.usersSearchResults, (propsAndState: PropsAndState) => propsAndState.filterThreads, (propsAndState: PropsAndState) => propsAndState.viewerID, ( reduxChatListData: $ReadOnlyArray, searchStatus: SearchStatus, searchText: string, threadsSearchResults: Set, emptyItem?: React.ComponentType<{}>, usersSearchResults: $ReadOnlyArray, filterThreads: ThreadInfo => boolean, viewerID: ?string, ): $ReadOnlyArray => { const chatThreadItems = getThreadListSearchResults( reduxChatListData, searchText, filterThreads, threadsSearchResults, usersSearchResults, viewerID, ); const chatItems: Item[] = [...chatThreadItems]; if (emptyItem && chatItems.length === 0) { chatItems.push({ type: 'empty', emptyItem }); } if (searchStatus === 'inactive' || searchStatus === 'activating') { chatItems.unshift({ type: 'search', searchText }); } return chatItems; }, ); partialListDataSelector = createSelector( this.listDataSelector, (propsAndState: PropsAndState) => propsAndState.numItemsToDisplay, (items: $ReadOnlyArray, numItemsToDisplay: number) => items.slice(0, numItemsToDisplay), ); get fullListData() { return this.listDataSelector({ ...this.props, ...this.state }); } get listData() { return this.partialListDataSelector({ ...this.props, ...this.state }); } onEndReached = () => { if (this.listData.length === this.fullListData.length) { return; } this.setState(prevState => ({ numItemsToDisplay: prevState.numItemsToDisplay + 25, })); }; render() { let floatingAction; if (Platform.OS === 'android') { floatingAction = ( ); } let fixedSearch; const { searchStatus } = this.state; if (searchStatus === 'active') { fixedSearch = this.renderSearch({ autoFocus: true }); } const scrollEnabled = searchStatus === 'inactive' || searchStatus === 'active'; // this.props.viewerID is in extraData since it's used by MessagePreview // within ChatThreadListItem return ( {fixedSearch} {floatingAction} ); } flatListRef = (flatList: ?FlatList) => { this.flatList = flatList; }; onScroll = (event: ScrollEvent) => { const oldScrollPos = this.scrollPos; this.scrollPos = event.nativeEvent.contentOffset.y; if (this.scrollPos !== 0 || oldScrollPos === 0) { return; } if (this.state.searchStatus === 'activating') { this.setState({ searchStatus: 'active' }); } }; async searchUsers(usernamePrefix: string) { if (usernamePrefix.length === 0) { return []; } const { userInfos } = await this.props.searchUsers(usernamePrefix); return userInfos.filter( info => !this.props.usersWithPersonalThread.has(info.id) && info.id !== this.props.viewerID, ); } onChangeSearchText = async (searchText: string) => { const results = this.props.threadSearchIndex.getSearchResults(searchText); this.setState({ searchText, threadsSearchResults: new Set(results), numItemsToDisplay: 25, }); const usersSearchResults = await this.searchUsers(searchText); this.setState({ usersSearchResults }); }; onPressItem = ( threadInfo: ThreadInfo, pendingPersonalThreadUserInfo?: UserInfo, ) => { this.onChangeSearchText(''); if (this.searchInput) { this.searchInput.blur(); } this.props.navigateToThread({ threadInfo, pendingPersonalThreadUserInfo }); }; onPressSeeMoreSidebars = (threadInfo: ThreadInfo) => { this.onChangeSearchText(''); if (this.searchInput) { this.searchInput.blur(); } - this.props.navigation.navigate({ + this.props.navigation.navigate<'SidebarListModal'>({ name: SidebarListModalRouteName, params: { threadInfo }, }); }; onSwipeableWillOpen = (threadInfo: ThreadInfo) => { this.setState(state => ({ ...state, openedSwipeableId: threadInfo.id })); }; composeThread = () => { if (!this.props.viewerID) { return; } const threadInfo = createPendingThread({ viewerID: this.props.viewerID, threadType: threadTypes.PRIVATE, }); this.props.navigateToThread({ threadInfo, searching: true }); }; } const unboundStyles = { icon: { fontSize: 28, }, container: { flex: 1, }, searchContainer: { backgroundColor: 'listBackground', display: 'flex', justifyContent: 'center', flexDirection: 'row', }, searchBox: { flex: 1, }, search: { marginBottom: 8, marginHorizontal: 18, marginTop: 16, }, cancelSearchButton: { position: 'absolute', right: 0, top: 0, bottom: 0, display: 'flex', justifyContent: 'center', }, cancelSearchButtonText: { color: 'link', fontSize: 16, paddingHorizontal: 16, paddingTop: 8, }, flatList: { flex: 1, backgroundColor: 'listBackground', }, }; const ConnectedChatThreadList: React.ComponentType = React.memo( function ConnectedChatThreadList(props: BaseProps) { const boundChatListData = useFlattenedChatListData(); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); const threadSearchIndex = useSelector(threadSearchIndexSelector); const styles = useStyles(unboundStyles); const indicatorStyle = useSelector(indicatorStyleSelector); const callSearchUsers = useServerCall(searchUsers); const usersWithPersonalThread = useSelector( usersWithPersonalThreadSelector, ); const navigateToThread = useNavigateToThread(); return ( ); }, ); export default ConnectedChatThreadList; diff --git a/native/chat/compose-thread-button.react.js b/native/chat/compose-thread-button.react.js index 703ffd637..bf4197696 100644 --- a/native/chat/compose-thread-button.react.js +++ b/native/chat/compose-thread-button.react.js @@ -1,74 +1,74 @@ // @flow import * as React from 'react'; import { StyleSheet } from 'react-native'; import { createPendingThread } from 'lib/shared/thread-utils'; import { threadTypes } from 'lib/types/thread-types'; import Button from '../components/button.react'; import SWMansionIcon from '../components/swmansion-icon.react'; import { MessageListRouteName } from '../navigation/route-names'; import { useSelector } from '../redux/redux-utils'; import { type Colors, useColors } from '../themes/colors'; import type { ChatNavigationProp } from './chat.react'; type BaseProps = { +navigate: $PropertyType, 'navigate'>, }; type Props = { ...BaseProps, +colors: Colors, +viewerID: ?string, }; class ComposeThreadButton extends React.PureComponent { render() { const { listForegroundSecondaryLabel } = this.props.colors; return ( ); } onPress = () => { if (this.props.viewerID) { - this.props.navigate({ + this.props.navigate<'MessageList'>({ name: MessageListRouteName, params: { threadInfo: createPendingThread({ viewerID: this.props.viewerID, threadType: threadTypes.PRIVATE, }), searching: true, }, }); } }; } const styles = StyleSheet.create({ composeButton: { marginRight: 16, }, }); const ConnectedComposeThreadButton: React.ComponentType = React.memo( function ConnectedComposeThreadButton(props) { const colors = useColors(); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); return ( ); }, ); export default ConnectedComposeThreadButton; diff --git a/native/chat/message-list-header-title.react.js b/native/chat/message-list-header-title.react.js index 978cc39ab..ed65d12e4 100644 --- a/native/chat/message-list-header-title.react.js +++ b/native/chat/message-list-header-title.react.js @@ -1,110 +1,110 @@ // @flow import { HeaderTitle } from '@react-navigation/stack'; import * as React from 'react'; import { View, Platform } from 'react-native'; import Icon from 'react-native-vector-icons/Ionicons'; import type { ThreadInfo } from 'lib/types/thread-types'; import { firstLine } from 'lib/utils/string-utils'; import Button from '../components/button.react'; import { ThreadSettingsRouteName } from '../navigation/route-names'; import { useStyles } from '../themes/colors'; import type { ChatNavigationProp } from './chat.react'; type BaseProps = { +threadInfo: ThreadInfo, +navigate: $PropertyType, 'navigate'>, +isSearchEmpty: boolean, +areSettingsEnabled: boolean, }; type Props = { ...BaseProps, +styles: typeof unboundStyles, }; class MessageListHeaderTitle extends React.PureComponent { render() { let icon, fakeIcon; if (Platform.OS === 'ios' && this.props.areSettingsEnabled) { icon = ( ); fakeIcon = ( ); } const title = this.props.isSearchEmpty ? 'New Message' : this.props.threadInfo.uiName; return ( ); } onPress = () => { const threadInfo = this.props.threadInfo; - this.props.navigate({ + this.props.navigate<'ThreadSettings'>({ name: ThreadSettingsRouteName, params: { threadInfo }, key: `${ThreadSettingsRouteName}${threadInfo.id}`, }); }; } const unboundStyles = { button: { flex: 1, }, container: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: Platform.OS === 'android' ? 'flex-start' : 'center', }, fakeIcon: { paddingRight: 7, paddingTop: 3, flex: 1, minWidth: 25, opacity: 0, }, forwardIcon: { paddingLeft: 7, paddingTop: 3, color: 'headerChevron', flex: 1, minWidth: 25, }, }; const ConnectedMessageListHeaderTitle: React.ComponentType = React.memo( function ConnectedMessageListHeaderTitle(props: BaseProps) { const styles = useStyles(unboundStyles); return ; }, ); export default ConnectedMessageListHeaderTitle; diff --git a/native/chat/message-list-types.js b/native/chat/message-list-types.js index 9311507d9..9bcf45bcc 100644 --- a/native/chat/message-list-types.js +++ b/native/chat/message-list-types.js @@ -1,78 +1,78 @@ // @flow import { useNavigation } from '@react-navigation/native'; import * as React from 'react'; import type { ThreadInfo } from 'lib/types/thread-types'; import { type UserInfo } from 'lib/types/user-types'; import type { MarkdownRules } from '../markdown/rules.react'; import { useTextMessageRulesFunc } from '../markdown/rules.react'; import { MessageListRouteName } from '../navigation/route-names'; export type MessageListParams = { +threadInfo: ThreadInfo, +pendingPersonalThreadUserInfo?: UserInfo, +searching?: boolean, }; export type MessageListContextType = { +getTextMessageMarkdownRules: (useDarkStyle: boolean) => MarkdownRules, }; const MessageListContext: React.Context = React.createContext(); function useMessageListContext(threadID: ?string) { const getTextMessageMarkdownRules = useTextMessageRulesFunc(threadID); return React.useMemo( () => ({ getTextMessageMarkdownRules, }), [getTextMessageMarkdownRules], ); } type Props = { +children: React.Node, +threadID: ?string, }; function MessageListContextProvider(props: Props): React.Node { const context = useMessageListContext(props.threadID); return ( {props.children} ); } type NavigateToThreadAction = { +name: typeof MessageListRouteName, +params: MessageListParams, +key: string, }; function createNavigateToThreadAction( params: MessageListParams, ): NavigateToThreadAction { return { name: MessageListRouteName, params, key: `${MessageListRouteName}${params.threadInfo.id}`, }; } function useNavigateToThread(): (params: MessageListParams) => void { const { navigate } = useNavigation(); return React.useCallback( (params: MessageListParams) => { - navigate(createNavigateToThreadAction(params)); + navigate<'MessageList'>(createNavigateToThreadAction(params)); }, [navigate], ); } export { MessageListContext, MessageListContextProvider, createNavigateToThreadAction, useNavigateToThread, }; diff --git a/native/chat/multimedia-message.react.js b/native/chat/multimedia-message.react.js index 9e45d4742..bde88a680 100644 --- a/native/chat/multimedia-message.react.js +++ b/native/chat/multimedia-message.react.js @@ -1,240 +1,240 @@ // @flow import type { LeafRoute, NavigationProp, ParamListBase, } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native'; import * as React from 'react'; import { StyleSheet, View } from 'react-native'; import { messageKey } from 'lib/shared/message-utils'; import { useCanCreateSidebarFromMessage } from 'lib/shared/thread-utils'; import type { MediaInfo } from 'lib/types/media-types'; import { OverlayContext } from '../navigation/overlay-context'; import type { OverlayContextType } from '../navigation/overlay-context'; import { ImageModalRouteName, MultimediaMessageTooltipModalRouteName, VideoPlaybackModalRouteName, } from '../navigation/route-names'; import type { ChatMultimediaMessageInfoItem } from '../types/chat-types'; import { type VerticalBounds } from '../types/layout-types'; import type { LayoutCoordinates } from '../types/layout-types'; import ComposedMessage from './composed-message.react'; import { InnerMultimediaMessage } from './inner-multimedia-message.react'; import { multimediaMessageTooltipHeight } from './multimedia-message-tooltip-modal.react'; import { getMediaKey, multimediaMessageSendFailed, } from './multimedia-message-utils'; import { getMessageTooltipKey } from './utils'; type BaseProps = { ...React.ElementConfig, +item: ChatMultimediaMessageInfoItem, +focused: boolean, +toggleFocus: (messageKey: string) => void, +verticalBounds: ?VerticalBounds, }; type Props = { ...BaseProps, +navigation: NavigationProp, +route: LeafRoute<>, +overlayContext: ?OverlayContextType, +canCreateSidebarFromMessage: boolean, }; type State = { +clickable: boolean, }; class MultimediaMessage extends React.PureComponent { state: State = { clickable: true, }; view: ?React.ElementRef; setClickable = (clickable: boolean) => { this.setState({ clickable }); }; onPressMultimedia = ( mediaInfo: MediaInfo, initialCoordinates: LayoutCoordinates, ) => { const { navigation, item, route, verticalBounds } = this.props; - navigation.navigate({ + navigation.navigate<'VideoPlaybackModal' | 'ImageModal'>({ name: mediaInfo.type === 'video' ? VideoPlaybackModalRouteName : ImageModalRouteName, key: getMediaKey(item, mediaInfo), params: { presentedFrom: route.key, mediaInfo, item, initialCoordinates, verticalBounds, }, }); }; visibleEntryIDs() { const result = []; if (this.props.item.threadCreatedFromMessage) { result.push('open_sidebar'); } else if (this.props.canCreateSidebarFromMessage) { result.push('create_sidebar'); } if (!this.props.item.messageInfo.creator.isViewer) { result.push('report'); } return result; } onLayout = () => {}; viewRef = (view: ?React.ElementRef) => { this.view = view; }; onLongPress = () => { const visibleEntryIDs = this.visibleEntryIDs(); if (visibleEntryIDs.length === 0) { return; } const { view, props: { verticalBounds }, } = this; if (!view || !verticalBounds) { return; } if (!this.state.clickable) { return; } this.setClickable(false); const { item } = this.props; if (!this.props.focused) { this.props.toggleFocus(messageKey(item.messageInfo)); } this.props.overlayContext?.setScrollBlockingModalStatus('open'); view.measure((x, y, width, height, pageX, pageY) => { const coordinates = { x: pageX, y: pageY, width, height }; const multimediaTop = pageY; const multimediaBottom = pageY + height; const boundsTop = verticalBounds.y; const boundsBottom = verticalBounds.y + verticalBounds.height; const belowMargin = 20; const belowSpace = multimediaMessageTooltipHeight + belowMargin; const { isViewer } = item.messageInfo.creator; const aboveMargin = isViewer ? 30 : 50; const aboveSpace = multimediaMessageTooltipHeight + aboveMargin; let location = 'below', margin = belowMargin; if ( multimediaBottom + belowSpace > boundsBottom && multimediaTop - aboveSpace > boundsTop ) { location = 'above'; margin = aboveMargin; } - this.props.navigation.navigate({ + this.props.navigation.navigate<'MultimediaMessageTooltipModal'>({ name: MultimediaMessageTooltipModalRouteName, params: { presentedFrom: this.props.route.key, item, initialCoordinates: coordinates, verticalBounds, location, margin, visibleEntryIDs, }, key: getMessageTooltipKey(item), }); }); }; canNavigateToSidebar() { return ( this.props.item.threadCreatedFromMessage || this.props.canCreateSidebarFromMessage ); } render() { const { item, focused, toggleFocus, verticalBounds, navigation, route, overlayContext, canCreateSidebarFromMessage, ...viewProps } = this.props; return ( ); } } const styles = StyleSheet.create({ expand: { flex: 1, }, }); const ConnectedMultimediaMessage: React.ComponentType = React.memo( function ConnectedMultimediaMessage(props: BaseProps) { const navigation = useNavigation(); const route = useRoute(); const overlayContext = React.useContext(OverlayContext); const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage( props.item.threadInfo, props.item.messageInfo, ); return ( ); }, ); export default ConnectedMultimediaMessage; diff --git a/native/chat/robotext-message.react.js b/native/chat/robotext-message.react.js index 033cd981c..47f450ad3 100644 --- a/native/chat/robotext-message.react.js +++ b/native/chat/robotext-message.react.js @@ -1,198 +1,198 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { View } from 'react-native'; import { messageKey } from 'lib/shared/message-utils'; import { useCanCreateSidebarFromMessage } from 'lib/shared/thread-utils'; import { KeyboardContext } from '../keyboard/keyboard-state'; import { OverlayContext } from '../navigation/overlay-context'; import { RobotextMessageTooltipModalRouteName } from '../navigation/route-names'; import type { NavigationRoute } from '../navigation/route-names'; import { useStyles } from '../themes/colors'; import type { ChatRobotextMessageInfoItemWithHeight } from '../types/chat-types'; import type { VerticalBounds } from '../types/layout-types'; import { AnimatedView } from '../types/styles'; import { inlineSidebarCenterStyle } from './chat-constants'; import type { ChatNavigationProp } from './chat.react'; import { InlineSidebar } from './inline-sidebar.react'; import { InnerRobotextMessage } from './inner-robotext-message.react'; import { robotextMessageTooltipHeight } from './robotext-message-tooltip-modal.react'; import { Timestamp } from './timestamp.react'; import { getMessageTooltipKey, useContentAndHeaderOpacity } from './utils'; type Props = { ...React.ElementConfig, +item: ChatRobotextMessageInfoItemWithHeight, +navigation: ChatNavigationProp<'MessageList'>, +route: NavigationRoute<'MessageList'>, +focused: boolean, +toggleFocus: (messageKey: string) => void, +verticalBounds: ?VerticalBounds, }; function RobotextMessage(props: Props): React.Node { const { item, navigation, route, focused, toggleFocus, verticalBounds, ...viewProps } = props; let timestamp = null; if (focused || item.startsConversation) { timestamp = ( ); } const styles = useStyles(unboundStyles); let inlineSidebar = null; if (item.threadCreatedFromMessage) { inlineSidebar = ( ); } const keyboardState = React.useContext(KeyboardContext); const key = messageKey(item.messageInfo); const onPress = React.useCallback(() => { const didDismiss = keyboardState && keyboardState.dismissKeyboardIfShowing(); if (!didDismiss) { toggleFocus(key); } }, [keyboardState, toggleFocus, key]); const overlayContext = React.useContext(OverlayContext); const viewRef = React.useRef>(); const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage( item.threadInfo, item.messageInfo, ); const visibleEntryIDs = React.useMemo(() => { if (item.threadCreatedFromMessage) { return ['open_sidebar']; } else if (canCreateSidebarFromMessage) { return ['create_sidebar']; } return []; }, [item.threadCreatedFromMessage, canCreateSidebarFromMessage]); const openRobotextTooltipModal = React.useCallback( (x, y, width, height, pageX, pageY) => { invariant( verticalBounds, 'verticalBounds should be present in openRobotextTooltipModal', ); const coordinates = { x: pageX, y: pageY, width, height }; const messageTop = pageY; const messageBottom = pageY + height; const boundsTop = verticalBounds.y; const boundsBottom = verticalBounds.y + verticalBounds.height; const belowMargin = 20; const belowSpace = robotextMessageTooltipHeight + belowMargin; const { isViewer } = item.messageInfo.creator; const aboveMargin = isViewer ? 30 : 50; const aboveSpace = robotextMessageTooltipHeight + aboveMargin; let location = 'below', margin = 0; if ( messageBottom + belowSpace > boundsBottom && messageTop - aboveSpace > boundsTop ) { location = 'above'; margin = aboveMargin; } - props.navigation.navigate({ + props.navigation.navigate<'RobotextMessageTooltipModal'>({ name: RobotextMessageTooltipModalRouteName, params: { presentedFrom: props.route.key, initialCoordinates: coordinates, verticalBounds, visibleEntryIDs, location, margin, item, }, key: getMessageTooltipKey(item), }); }, [item, props.navigation, props.route.key, verticalBounds, visibleEntryIDs], ); const onLongPress = React.useCallback(() => { if (keyboardState && keyboardState.dismissKeyboardIfShowing()) { return; } if (visibleEntryIDs.length === 0) { return; } if (!viewRef.current || !verticalBounds) { return; } if (!focused) { toggleFocus(messageKey(item.messageInfo)); } invariant(overlayContext, 'RobotextMessage should have OverlayContext'); overlayContext.setScrollBlockingModalStatus('open'); viewRef.current?.measure(openRobotextTooltipModal); }, [ focused, item, keyboardState, overlayContext, toggleFocus, verticalBounds, viewRef, visibleEntryIDs, openRobotextTooltipModal, ]); const onLayout = React.useCallback(() => {}, []); const contentAndHeaderOpacity = useContentAndHeaderOpacity(item); return ( {timestamp} {inlineSidebar} ); } const unboundStyles = { sidebar: { marginTop: inlineSidebarCenterStyle.topOffset, marginBottom: -inlineSidebarCenterStyle.topOffset, alignSelf: 'center', }, }; export { RobotextMessage }; diff --git a/native/chat/settings/compose-subchannel-modal.react.js b/native/chat/settings/compose-subchannel-modal.react.js index 16132bb74..4ff1c75ae 100644 --- a/native/chat/settings/compose-subchannel-modal.react.js +++ b/native/chat/settings/compose-subchannel-modal.react.js @@ -1,150 +1,150 @@ // @flow import * as React from 'react'; import { Text } from 'react-native'; import IonIcon from 'react-native-vector-icons/Ionicons'; import { threadTypeDescriptions } from 'lib/shared/thread-utils'; import { type ThreadInfo, threadTypes } from 'lib/types/thread-types'; import Button from '../../components/button.react'; import Modal from '../../components/modal.react'; import SWMansionIcon from '../../components/swmansion-icon.react'; import type { RootNavigationProp } from '../../navigation/root-navigator.react'; import type { NavigationRoute } from '../../navigation/route-names'; import { ComposeSubchannelRouteName } from '../../navigation/route-names'; import { type Colors, useStyles, useColors } from '../../themes/colors'; export type ComposeSubchannelModalParams = { presentedFrom: string, threadInfo: ThreadInfo, }; type BaseProps = { +navigation: RootNavigationProp<'ComposeSubchannelModal'>, +route: NavigationRoute<'ComposeSubchannelModal'>, }; type Props = { ...BaseProps, +colors: Colors, +styles: typeof unboundStyles, }; class ComposeSubchannelModal extends React.PureComponent { render() { return ( Chat type ); } onPressOpen = () => { const threadInfo = this.props.route.params.threadInfo; - this.props.navigation.navigate({ + this.props.navigation.navigate<'ComposeSubchannel'>({ name: ComposeSubchannelRouteName, params: { threadType: threadTypes.COMMUNITY_OPEN_SUBTHREAD, parentThreadInfo: threadInfo, }, key: `${ComposeSubchannelRouteName}|` + `${threadInfo.id}|${threadTypes.COMMUNITY_OPEN_SUBTHREAD}`, }); }; onPressSecret = () => { const threadInfo = this.props.route.params.threadInfo; - this.props.navigation.navigate({ + this.props.navigation.navigate<'ComposeSubchannel'>({ name: ComposeSubchannelRouteName, params: { threadType: threadTypes.COMMUNITY_SECRET_SUBTHREAD, parentThreadInfo: threadInfo, }, key: `${ComposeSubchannelRouteName}|` + `${threadInfo.id}|${threadTypes.COMMUNITY_SECRET_SUBTHREAD}`, }); }; } const unboundStyles = { forwardIcon: { color: 'modalForegroundSecondaryLabel', paddingLeft: 10, }, modal: { flex: 0, }, option: { alignItems: 'center', flexDirection: 'row', paddingHorizontal: 10, paddingVertical: 20, }, optionExplanation: { color: 'modalBackgroundLabel', flex: 1, fontSize: 14, paddingLeft: 20, textAlign: 'center', }, optionText: { color: 'modalBackgroundLabel', fontSize: 20, paddingLeft: 5, }, visibility: { color: 'modalBackgroundLabel', fontSize: 24, textAlign: 'center', }, visibilityIcon: { color: 'modalBackgroundLabel', paddingRight: 3, }, }; const ConnectedComposeSubchannelModal: React.ComponentType = React.memo( function ConnectedComposeSubchannelModal(props: BaseProps) { const styles = useStyles(unboundStyles); const colors = useColors(); return ( ); }, ); export default ConnectedComposeSubchannelModal; diff --git a/native/chat/settings/thread-settings-color.react.js b/native/chat/settings/thread-settings-color.react.js index cc2d38f00..ac65ce9f1 100644 --- a/native/chat/settings/thread-settings-color.react.js +++ b/native/chat/settings/thread-settings-color.react.js @@ -1,123 +1,123 @@ // @flow import * as React from 'react'; import { Text, ActivityIndicator, View, Platform } from 'react-native'; import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import type { LoadingStatus } from 'lib/types/loading-types'; import { type ThreadInfo } from 'lib/types/thread-types'; import ColorSplotch from '../../components/color-splotch.react'; import EditSettingButton from '../../components/edit-setting-button.react'; import { ColorSelectorModalRouteName } from '../../navigation/route-names'; import { useSelector } from '../../redux/redux-utils'; import { type Colors, useColors, useStyles } from '../../themes/colors'; import type { ThreadSettingsNavigate } from './thread-settings.react'; type BaseProps = { +threadInfo: ThreadInfo, +colorEditValue: string, +setColorEditValue: (color: string) => void, +canChangeSettings: boolean, +navigate: ThreadSettingsNavigate, +threadSettingsRouteKey: string, }; type Props = { ...BaseProps, // Redux state +loadingStatus: LoadingStatus, +colors: Colors, +styles: typeof unboundStyles, }; class ThreadSettingsColor extends React.PureComponent { render() { let colorButton; if (this.props.loadingStatus !== 'loading') { colorButton = ( ); } else { colorButton = ( ); } return ( Color {colorButton} ); } onPressEditColor = () => { - this.props.navigate({ + this.props.navigate<'ColorSelectorModal'>({ name: ColorSelectorModalRouteName, params: { presentedFrom: this.props.threadSettingsRouteKey, color: this.props.colorEditValue, threadInfo: this.props.threadInfo, setColor: this.props.setColorEditValue, }, }); }; } const unboundStyles = { colorLine: { lineHeight: Platform.select({ android: 22, default: 25 }), }, colorRow: { backgroundColor: 'panelForeground', flexDirection: 'row', paddingBottom: 8, paddingHorizontal: 24, paddingTop: 4, }, currentValue: { flex: 1, paddingLeft: 4, }, label: { color: 'panelForegroundTertiaryLabel', fontSize: 16, width: 96, }, }; const loadingStatusSelector = createLoadingStatusSelector( changeThreadSettingsActionTypes, `${changeThreadSettingsActionTypes.started}:color`, ); const ConnectedThreadSettingsColor: React.ComponentType = React.memo( function ConnectedThreadSettingsColor(props: BaseProps) { const loadingStatus = useSelector(loadingStatusSelector); const colors = useColors(); const styles = useStyles(unboundStyles); return ( ); }, ); export default ConnectedThreadSettingsColor; diff --git a/native/chat/settings/thread-settings-delete-thread.react.js b/native/chat/settings/thread-settings-delete-thread.react.js index 6926776e0..d49b8d2b5 100644 --- a/native/chat/settings/thread-settings-delete-thread.react.js +++ b/native/chat/settings/thread-settings-delete-thread.react.js @@ -1,64 +1,64 @@ // @flow import * as React from 'react'; import { Text, View } from 'react-native'; import type { ThreadInfo } from 'lib/types/thread-types'; import Button from '../../components/button.react'; import { DeleteThreadRouteName } from '../../navigation/route-names'; import { useColors, useStyles } from '../../themes/colors'; import type { ViewStyle } from '../../types/styles'; import type { ThreadSettingsNavigate } from './thread-settings.react'; type Props = { +threadInfo: ThreadInfo, +navigate: ThreadSettingsNavigate, +buttonStyle: ViewStyle, }; function ThreadSettingsDeleteThread(props: Props): React.Node { const { navigate, threadInfo } = props; const onPress = React.useCallback(() => { - navigate({ + navigate<'DeleteThread'>({ name: DeleteThreadRouteName, params: { threadInfo }, key: `${DeleteThreadRouteName}${threadInfo.id}`, }); }, [navigate, threadInfo]); const colors = useColors(); const { panelIosHighlightUnderlay } = colors; const styles = useStyles(unboundStyles); return ( ); } const unboundStyles = { button: { flexDirection: 'row', paddingHorizontal: 12, paddingVertical: 10, }, container: { backgroundColor: 'panelForeground', paddingHorizontal: 12, }, text: { color: 'redText', flex: 1, fontSize: 16, }, }; export default ThreadSettingsDeleteThread; diff --git a/native/chat/settings/thread-settings-member.react.js b/native/chat/settings/thread-settings-member.react.js index 2354dfdd6..372947050 100644 --- a/native/chat/settings/thread-settings-member.react.js +++ b/native/chat/settings/thread-settings-member.react.js @@ -1,285 +1,285 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { View, Text, Platform, ActivityIndicator, TouchableOpacity, } from 'react-native'; import { removeUsersFromThreadActionTypes, changeThreadMemberRolesActionTypes, } from 'lib/actions/thread-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { memberIsAdmin, memberHasAdminPowers, getAvailableThreadMemberActions, } from 'lib/shared/thread-utils'; import { stringForUser } from 'lib/shared/user-utils'; import type { LoadingStatus } from 'lib/types/loading-types'; import { type ThreadInfo, type RelativeMemberInfo, } from 'lib/types/thread-types'; import PencilIcon from '../../components/pencil-icon.react'; import { SingleLine } from '../../components/single-line.react'; import { type KeyboardState, KeyboardContext, } from '../../keyboard/keyboard-state'; import { OverlayContext, type OverlayContextType, } from '../../navigation/overlay-context'; import { ThreadSettingsMemberTooltipModalRouteName } from '../../navigation/route-names'; import { useSelector } from '../../redux/redux-utils'; import { type Colors, useColors, useStyles } from '../../themes/colors'; import type { VerticalBounds } from '../../types/layout-types'; import type { ThreadSettingsNavigate } from './thread-settings.react'; type BaseProps = { +memberInfo: RelativeMemberInfo, +threadInfo: ThreadInfo, +canEdit: boolean, +navigate: ThreadSettingsNavigate, +firstListItem: boolean, +lastListItem: boolean, +verticalBounds: ?VerticalBounds, +threadSettingsRouteKey: string, }; type Props = { ...BaseProps, // Redux state +removeUserLoadingStatus: LoadingStatus, +changeRoleLoadingStatus: LoadingStatus, +colors: Colors, +styles: typeof unboundStyles, // withKeyboardState +keyboardState: ?KeyboardState, // withOverlayContext +overlayContext: ?OverlayContextType, }; class ThreadSettingsMember extends React.PureComponent { editButton: ?React.ElementRef; render() { const userText = stringForUser(this.props.memberInfo); let userInfo = null; if (this.props.memberInfo.username) { userInfo = ( {userText} ); } else { userInfo = ( {userText} ); } let editButton = null; if ( this.props.removeUserLoadingStatus === 'loading' || this.props.changeRoleLoadingStatus === 'loading' ) { editButton = ( ); } else if ( getAvailableThreadMemberActions( this.props.memberInfo, this.props.threadInfo, this.props.canEdit, ).length !== 0 ) { editButton = ( ); } let roleInfo = null; if (memberIsAdmin(this.props.memberInfo, this.props.threadInfo)) { roleInfo = ( admin ); } else if (memberHasAdminPowers(this.props.memberInfo)) { roleInfo = ( parent admin ); } const firstItem = this.props.firstListItem ? null : this.props.styles.topBorder; const lastItem = this.props.lastListItem ? this.props.styles.lastInnerContainer : null; return ( {userInfo} {editButton} {roleInfo} ); } editButtonRef = (editButton: ?React.ElementRef) => { this.editButton = editButton; }; onEditButtonLayout = () => {}; onPressEdit = () => { if (this.dismissKeyboardIfShowing()) { return; } const { editButton, props: { verticalBounds }, } = this; if (!editButton || !verticalBounds) { return; } const { overlayContext } = this.props; invariant( overlayContext, 'ThreadSettingsMember should have OverlayContext', ); overlayContext.setScrollBlockingModalStatus('open'); editButton.measure((x, y, width, height, pageX, pageY) => { const coordinates = { x: pageX, y: pageY, width, height }; - this.props.navigate({ + this.props.navigate<'ThreadSettingsMemberTooltipModal'>({ name: ThreadSettingsMemberTooltipModalRouteName, params: { presentedFrom: this.props.threadSettingsRouteKey, initialCoordinates: coordinates, verticalBounds, visibleEntryIDs: getAvailableThreadMemberActions( this.props.memberInfo, this.props.threadInfo, this.props.canEdit, ), memberInfo: this.props.memberInfo, threadInfo: this.props.threadInfo, }, }); }); }; dismissKeyboardIfShowing = () => { const { keyboardState } = this.props; return !!(keyboardState && keyboardState.dismissKeyboardIfShowing()); }; } const unboundStyles = { anonymous: { color: 'panelForegroundTertiaryLabel', fontStyle: 'italic', }, container: { backgroundColor: 'panelForeground', flex: 1, paddingHorizontal: 12, }, editButton: { paddingLeft: 10, }, topBorder: { borderColor: 'panelForegroundBorder', borderTopWidth: 1, }, innerContainer: { flex: 1, paddingHorizontal: 12, paddingVertical: 8, }, lastInnerContainer: { paddingBottom: Platform.OS === 'ios' ? 12 : 10, }, role: { color: 'panelForegroundTertiaryLabel', flex: 1, fontSize: 14, paddingTop: 4, }, row: { flex: 1, flexDirection: 'row', }, username: { color: 'panelForegroundSecondaryLabel', flex: 1, fontSize: 16, lineHeight: 20, }, }; const ConnectedThreadSettingsMember: React.ComponentType = React.memo( function ConnectedThreadSettingsMember(props: BaseProps) { const memberID = props.memberInfo.id; const removeUserLoadingStatus = useSelector(state => createLoadingStatusSelector( removeUsersFromThreadActionTypes, `${removeUsersFromThreadActionTypes.started}:${memberID}`, )(state), ); const changeRoleLoadingStatus = useSelector(state => createLoadingStatusSelector( changeThreadMemberRolesActionTypes, `${changeThreadMemberRolesActionTypes.started}:${memberID}`, )(state), ); const colors = useColors(); const styles = useStyles(unboundStyles); const keyboardState = React.useContext(KeyboardContext); const overlayContext = React.useContext(OverlayContext); return ( ); }, ); export default ConnectedThreadSettingsMember; diff --git a/native/chat/sidebar-navigation.js b/native/chat/sidebar-navigation.js index 555d773c3..2dc8a714e 100644 --- a/native/chat/sidebar-navigation.js +++ b/native/chat/sidebar-navigation.js @@ -1,79 +1,81 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { createPendingSidebar } from 'lib/shared/thread-utils'; import type { ThreadInfo } from 'lib/types/thread-types'; import type { DispatchFunctions, BindServerCall } from 'lib/utils/action-utils'; import type { InputState } from '../input/input-state'; import { getDefaultTextMessageRules } from '../markdown/rules.react'; import type { AppNavigationProp } from '../navigation/app-navigator.react'; import type { MessageTooltipRouteNames } from '../navigation/route-names'; import type { TooltipRoute } from '../navigation/tooltip.react'; import { useSelector } from '../redux/redux-utils'; import type { ChatMessageInfoItemWithHeight } from '../types/chat-types'; import type { ChatContextType } from './chat-context'; import { createNavigateToThreadAction, useNavigateToThread, } from './message-list-types'; function getSidebarThreadInfo( sourceMessage: ChatMessageInfoItemWithHeight, viewerID?: ?string, ): ?ThreadInfo { const threadCreatedFromMessage = sourceMessage.threadCreatedFromMessage; if (threadCreatedFromMessage) { return threadCreatedFromMessage; } if (!viewerID) { return null; } const { messageInfo, threadInfo } = sourceMessage; return createPendingSidebar( messageInfo, threadInfo, viewerID, getDefaultTextMessageRules().simpleMarkdownRules, ); } function navigateToSidebar( route: TooltipRoute, dispatchFunctions: DispatchFunctions, bindServerCall: BindServerCall, inputState: ?InputState, navigation: AppNavigationProp, viewerID: ?string, chatContext: ?ChatContextType, ) { invariant(viewerID, 'viewerID should be set'); const threadInfo = getSidebarThreadInfo(route.params.item, viewerID); invariant(threadInfo, 'threadInfo should be set'); chatContext?.setCurrentTransitionSidebarSourceID( route.params.item.messageInfo.id, ); - navigation.navigate(createNavigateToThreadAction({ threadInfo })); + navigation.navigate<'MessageList'>( + createNavigateToThreadAction({ threadInfo }), + ); } function useNavigateToSidebar(item: ChatMessageInfoItemWithHeight): () => void { const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); const threadInfo = React.useMemo(() => getSidebarThreadInfo(item, viewerID), [ item, viewerID, ]); const navigateToThread = useNavigateToThread(); return React.useCallback(() => { invariant(threadInfo, 'threadInfo should be set'); navigateToThread({ threadInfo }); }, [navigateToThread, threadInfo]); } export { navigateToSidebar, getSidebarThreadInfo, useNavigateToSidebar }; diff --git a/native/chat/text-message.react.js b/native/chat/text-message.react.js index 6ded8d428..e247e8e12 100644 --- a/native/chat/text-message.react.js +++ b/native/chat/text-message.react.js @@ -1,232 +1,232 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { View } from 'react-native'; import { messageKey } from 'lib/shared/message-utils'; import { threadHasPermission, useCanCreateSidebarFromMessage, } from 'lib/shared/thread-utils'; import { threadPermissions } from 'lib/types/thread-types'; import { MarkdownLinkContext } from '../markdown/markdown-link-context'; import { OverlayContext, type OverlayContextType, } from '../navigation/overlay-context'; import type { NavigationRoute } from '../navigation/route-names'; import { TextMessageTooltipModalRouteName } from '../navigation/route-names'; import type { ChatTextMessageInfoItemWithHeight } from '../types/chat-types'; import type { VerticalBounds } from '../types/layout-types'; import type { ChatNavigationProp } from './chat.react'; import ComposedMessage from './composed-message.react'; import { InnerTextMessage } from './inner-text-message.react'; import textMessageSendFailed from './text-message-send-failed'; import { textMessageTooltipHeight } from './text-message-tooltip-modal.react'; import { getMessageTooltipKey } from './utils'; type BaseProps = { ...React.ElementConfig, +item: ChatTextMessageInfoItemWithHeight, +navigation: ChatNavigationProp<'MessageList'>, +route: NavigationRoute<'MessageList'>, +focused: boolean, +toggleFocus: (messageKey: string) => void, +verticalBounds: ?VerticalBounds, }; type Props = { ...BaseProps, // Redux state +canCreateSidebarFromMessage: boolean, // withOverlayContext +overlayContext: ?OverlayContextType, // MarkdownLinkContext +linkModalActive: boolean, +linkIsBlockingPresses: boolean, }; class TextMessage extends React.PureComponent { message: ?React.ElementRef; render() { const { item, navigation, route, focused, toggleFocus, verticalBounds, overlayContext, linkModalActive, linkIsBlockingPresses, canCreateSidebarFromMessage, ...viewProps } = this.props; let swipeOptions = 'none'; const canReply = this.canReply(); const canNavigateToSidebar = this.canNavigateToSidebar(); if (linkModalActive) { swipeOptions = 'none'; } else if (canReply && canNavigateToSidebar) { swipeOptions = 'both'; } else if (canReply) { swipeOptions = 'reply'; } else if (canNavigateToSidebar) { swipeOptions = 'sidebar'; } return ( ); } messageRef = (message: ?React.ElementRef) => { this.message = message; }; canReply() { return threadHasPermission( this.props.item.threadInfo, threadPermissions.VOICED, ); } canNavigateToSidebar() { return ( this.props.item.threadCreatedFromMessage || this.props.canCreateSidebarFromMessage ); } visibleEntryIDs() { const result = ['copy']; if (this.canReply()) { result.push('reply'); } if (this.props.item.threadCreatedFromMessage) { result.push('open_sidebar'); } else if (this.props.canCreateSidebarFromMessage) { result.push('create_sidebar'); } if (!this.props.item.messageInfo.creator.isViewer) { result.push('report'); } return result; } onPress = () => { const visibleEntryIDs = this.visibleEntryIDs(); if (visibleEntryIDs.length === 0) { return; } const { message, props: { verticalBounds, linkIsBlockingPresses }, } = this; if (!message || !verticalBounds || linkIsBlockingPresses) { return; } const { focused, toggleFocus, item } = this.props; if (!focused) { toggleFocus(messageKey(item.messageInfo)); } const { overlayContext } = this.props; invariant(overlayContext, 'TextMessage should have OverlayContext'); overlayContext.setScrollBlockingModalStatus('open'); message.measure((x, y, width, height, pageX, pageY) => { const coordinates = { x: pageX, y: pageY, width, height }; const messageTop = pageY; const messageBottom = pageY + height; const boundsTop = verticalBounds.y; const boundsBottom = verticalBounds.y + verticalBounds.height; const belowMargin = 20; const belowSpace = textMessageTooltipHeight + belowMargin; const { isViewer } = item.messageInfo.creator; const aboveMargin = isViewer ? 30 : 50; const aboveSpace = textMessageTooltipHeight + aboveMargin; let location = 'below', margin = belowMargin; if ( messageBottom + belowSpace > boundsBottom && messageTop - aboveSpace > boundsTop ) { location = 'above'; margin = aboveMargin; } - this.props.navigation.navigate({ + this.props.navigation.navigate<'TextMessageTooltipModal'>({ name: TextMessageTooltipModalRouteName, params: { presentedFrom: this.props.route.key, initialCoordinates: coordinates, verticalBounds, visibleEntryIDs, location, margin, item, }, key: getMessageTooltipKey(item), }); }); }; } const ConnectedTextMessage: React.ComponentType = React.memo( function ConnectedTextMessage(props: BaseProps) { const overlayContext = React.useContext(OverlayContext); const [linkModalActive, setLinkModalActive] = React.useState(false); const [linkPressActive, setLinkPressActive] = React.useState(false); const markdownLinkContext = React.useMemo( () => ({ setLinkModalActive, setLinkPressActive, }), [setLinkModalActive, setLinkPressActive], ); const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage( props.item.threadInfo, props.item.messageInfo, ); const linkIsBlockingPresses = linkModalActive || linkPressActive; return ( ); }, ); export { ConnectedTextMessage as TextMessage }; diff --git a/native/chat/thread-settings-button.react.js b/native/chat/thread-settings-button.react.js index 88f60a1de..8380093af 100644 --- a/native/chat/thread-settings-button.react.js +++ b/native/chat/thread-settings-button.react.js @@ -1,56 +1,56 @@ // @flow import * as React from 'react'; import Icon from 'react-native-vector-icons/Ionicons'; import { type ThreadInfo } from 'lib/types/thread-types'; import Button from '../components/button.react'; import { ThreadSettingsRouteName } from '../navigation/route-names'; import { useStyles } from '../themes/colors'; import type { ChatNavigationProp } from './chat.react'; type BaseProps = { +threadInfo: ThreadInfo, +navigate: $PropertyType, 'navigate'>, }; type Props = { ...BaseProps, +styles: typeof unboundStyles, }; class ThreadSettingsButton extends React.PureComponent { render() { return ( ); } onPress = () => { const threadInfo = this.props.threadInfo; - this.props.navigate({ + this.props.navigate<'ThreadSettings'>({ name: ThreadSettingsRouteName, params: { threadInfo }, key: `${ThreadSettingsRouteName}${threadInfo.id}`, }); }; } const unboundStyles = { button: { color: 'link', paddingHorizontal: 10, }, }; const ConnectedThreadSettingsButton: React.ComponentType = React.memo( function ConnectedThreadSettingsButton(props: BaseProps) { const styles = useStyles(unboundStyles); return ; }, ); export default ConnectedThreadSettingsButton; diff --git a/native/flow-typed/npm/@react-navigation/bottom-tabs_v5.x.x.js b/native/flow-typed/npm/@react-navigation/bottom-tabs_v5.x.x.js index 30c91c83b..d09a0aea5 100644 --- a/native/flow-typed/npm/@react-navigation/bottom-tabs_v5.x.x.js +++ b/native/flow-typed/npm/@react-navigation/bottom-tabs_v5.x.x.js @@ -1,2103 +1,2132 @@ // flow-typed signature: 6070a4afddfa183e7c7bda53e69c0044 // flow-typed version: dc2d6a22c7/@react-navigation/bottom-tabs_v5.x.x/flow_>=v0.104.x declare module '@react-navigation/bottom-tabs' { //--------------------------------------------------------------------------- // SECTION 1: IDENTICAL TYPE DEFINITIONS // This section is identical across all React Navigation libdefs and contains // shared definitions. We wish we could make it DRY and import from a shared // definition, but that isn't yet possible. //--------------------------------------------------------------------------- /** * We start with some definitions that we have copy-pasted from React Native * source files. */ // This is a bastardization of the true StyleObj type located in // react-native/Libraries/StyleSheet/StyleSheetTypes. We unfortunately can't // import that here, and it's too lengthy (and consequently too brittle) to // copy-paste here either. declare type StyleObj = | null | void | number | false | '' | $ReadOnlyArray | { [name: string]: any, ... }; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; declare type AnimatedTextStyleProp = StyleObj; // Vaguely copied from // react-native/Libraries/Animated/src/animations/Animation.js declare type EndResult = { finished: boolean, ... }; declare type EndCallback = (result: EndResult) => void; declare interface Animation { start( fromValue: number, onUpdate: (value: number) => void, onEnd: ?EndCallback, previousAnimation: ?Animation, animatedValue: AnimatedValue, ): void; stop(): void; } declare type AnimationConfig = { isInteraction?: boolean, useNativeDriver: boolean, onComplete?: ?EndCallback, iterations?: number, ... }; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedTracking.js declare interface AnimatedTracking { constructor( value: AnimatedValue, parent: any, animationClass: any, animationConfig: Object, callback?: ?EndCallback, ): void; update(): void; } // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedValue.js declare type ValueListenerCallback = (state: { value: number, ... }) => void; declare interface AnimatedValue { constructor(value: number): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; extractOffset(): void; addListener(callback: ValueListenerCallback): string; removeListener(id: string): void; removeAllListeners(): void; stopAnimation(callback?: ?(value: number) => void): void; resetAnimation(callback?: ?(value: number) => void): void; interpolate(config: InterpolationConfigType): AnimatedInterpolation; animate(animation: Animation, callback: ?EndCallback): void; stopTracking(): void; track(tracking: AnimatedTracking): void; } // Copied from // react-native/Libraries/Animated/src/animations/TimingAnimation.js declare type TimingAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, easing?: (value: number) => number, duration?: number, delay?: number, ... }; // Copied from // react-native/Libraries/Animated/src/animations/SpringAnimation.js declare type SpringAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, overshootClamping?: boolean, restDisplacementThreshold?: number, restSpeedThreshold?: number, velocity?: number, bounciness?: number, speed?: number, tension?: number, friction?: number, stiffness?: number, damping?: number, mass?: number, delay?: number, ... }; // Copied from react-native/Libraries/Types/CoreEventTypes.js declare type SyntheticEvent = $ReadOnly<{| bubbles: ?boolean, cancelable: ?boolean, currentTarget: number, defaultPrevented: ?boolean, dispatchConfig: $ReadOnly<{| registrationName: string, |}>, eventPhase: ?number, preventDefault: () => void, isDefaultPrevented: () => boolean, stopPropagation: () => void, isPropagationStopped: () => boolean, isTrusted: ?boolean, nativeEvent: T, persist: () => void, target: ?number, timeStamp: number, type: ?string, |}>; declare type Layout = $ReadOnly<{| x: number, y: number, width: number, height: number, |}>; declare type LayoutEvent = SyntheticEvent< $ReadOnly<{| layout: Layout, |}>, >; declare type BlurEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type FocusEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type ResponderSyntheticEvent = $ReadOnly<{| ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray< $ReadOnly<{| touchActive: boolean, startPageX: number, startPageY: number, startTimeStamp: number, currentPageX: number, currentPageY: number, currentTimeStamp: number, previousPageX: number, previousPageY: number, previousTimeStamp: number, |}>, >, |}>, |}>; declare type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, identifier: number, locationX: number, locationY: number, pageX: number, pageY: number, target: ?number, timestamp: number, touches: $ReadOnlyArray<$PropertyType>, |}>, >; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js declare type ExtrapolateType = 'extend' | 'identity' | 'clamp'; declare type InterpolationConfigType = { inputRange: Array, outputRange: Array | Array, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, ... }; declare interface AnimatedInterpolation { interpolate(config: InterpolationConfigType): AnimatedInterpolation; } // Copied from react-native/Libraries/Components/View/ViewAccessibility.js declare type AccessibilityRole = | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'imagebutton' | 'header' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menu' | 'menubar' | 'menuitem' | 'progressbar' | 'radio' | 'radiogroup' | 'scrollbar' | 'spinbutton' | 'switch' | 'tab' | 'tablist' | 'timer' | 'toolbar'; declare type AccessibilityActionInfo = $ReadOnly<{ name: string, label?: string, ... }>; declare type AccessibilityActionEvent = SyntheticEvent< $ReadOnly<{actionName: string, ...}>, >; declare type AccessibilityState = { disabled?: boolean, selected?: boolean, checked?: ?boolean | 'mixed', busy?: boolean, expanded?: boolean, ... }; declare type AccessibilityValue = $ReadOnly<{| min?: number, max?: number, now?: number, text?: string, |}>; // Copied from // react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js declare type Stringish = string; declare type EdgeInsetsProp = $ReadOnly<$Partial>; declare type TouchableWithoutFeedbackProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, accessibilityElementsHidden?: ?boolean, accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityLabel?: ?Stringish, accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, children?: ?React$Node, delayLongPress?: ?number, delayPressIn?: ?number, delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, hitSlop?: ?EdgeInsetsProp, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(event: BlurEvent) => mixed, onFocus?: ?(event: FocusEvent) => mixed, onLayout?: ?(event: LayoutEvent) => mixed, onLongPress?: ?(event: PressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, pressRetentionOffset?: ?EdgeInsetsProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, |}>; // Copied from react-native/Libraries/Image/ImageSource.js declare type ImageURISource = $ReadOnly<{ uri?: ?string, bundle?: ?string, method?: ?string, headers?: ?Object, body?: ?string, cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), width?: ?number, height?: ?number, scale?: ?number, ... }>; /** * The following is copied from react-native-gesture-handler's libdef */ declare type StateUndetermined = 0; declare type StateFailed = 1; declare type StateBegan = 2; declare type StateCancelled = 3; declare type StateActive = 4; declare type StateEnd = 5; declare type GestureHandlerState = | StateUndetermined | StateFailed | StateBegan | StateCancelled | StateActive | StateEnd; declare type $SyntheticEvent = { +nativeEvent: $ReadOnly<$Exact>, ... }; declare type $Event = $SyntheticEvent<{ handlerTag: number, numberOfPointers: number, state: GestureHandlerState, oldState: GestureHandlerState, ...$Exact, ... }>; declare type $EventHandlers = {| onGestureEvent?: ($Event) => mixed, onHandlerStateChange?: ($Event) => mixed, onBegan?: ($Event) => mixed, onFailed?: ($Event) => mixed, onCancelled?: ($Event) => mixed, onActivated?: ($Event) => mixed, onEnded?: ($Event) => mixed, |}; declare type HitSlop = | number | {| left?: number, top?: number, right?: number, bottom?: number, vertical?: number, horizontal?: number, width?: number, height?: number, |} | {| width: number, left: number, |} | {| width: number, right: number, |} | {| height: number, top: number, |} | {| height: number, bottom: number, |}; declare type $GestureHandlerProps< AdditionalProps: {...}, ExtraEventsProps: {...} > = $ReadOnly<{| ...$Exact, ...$EventHandlers, id?: string, enabled?: boolean, waitFor?: React$Ref | Array>, simultaneousHandlers?: React$Ref | Array>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, children?: React$Node, |}>; declare type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], activeOffsetX?: number | [number, number], failOffsetY?: number | [number, number], failOffsetX?: number | [number, number], minDist?: number, minVelocity?: number, minVelocityX?: number, minVelocityY?: number, minPointers?: number, maxPointers?: number, avgTouches?: boolean, ... }, { x: number, y: number, absoluteX: number, absoluteY: number, translationX: number, translationY: number, velocityX: number, velocityY: number, ... } >; /** * MAGIC */ declare type $If = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), Test, Then, Else, >; declare type $IsA = $Call< (Y => true) & (mixed => false), X, >; declare type $IsUndefined = $IsA; declare type $Partial = $ReadOnly<$Rest>; + // If { ...T, ... } counts as a T, then we're inexact + declare type $IsExact = $Call< + (T => false) & (mixed => true), + { ...T, ... }, + >; + /** * Actions, state, etc. */ declare export type ScreenParams = { +[key: string]: mixed, ... }; declare export type BackAction = {| +type: 'GO_BACK', +source?: string, +target?: string, |}; declare export type NavigateAction = {| +type: 'NAVIGATE', +payload: | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type ResetAction = {| +type: 'RESET', +payload: StaleNavigationState, +source?: string, +target?: string, |}; declare export type SetParamsAction = {| +type: 'SET_PARAMS', +payload: {| +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type CommonAction = | BackAction | NavigateAction | ResetAction | SetParamsAction; declare type NavigateActionCreator = {| (routeName: string, params?: ScreenParams): NavigateAction, ( | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, ): NavigateAction, |}; declare export type CommonActionsType = {| +navigate: NavigateActionCreator, +goBack: () => BackAction, +reset: (state: PossiblyStaleNavigationState) => ResetAction, +setParams: (params: ScreenParams) => SetParamsAction, |}; declare export type GenericNavigationAction = {| +type: string, +payload?: { +[key: string]: mixed, ... }, +source?: string, +target?: string, |}; declare export type LeafRoute = {| +key: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StateRoute = {| ...LeafRoute, +state: NavigationState | StaleNavigationState, |}; declare export type Route = | LeafRoute | StateRoute; declare export type NavigationState = {| +key: string, +index: number, +routeNames: $ReadOnlyArray, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type: string, +stale: false, |}; declare export type StaleLeafRoute = {| +key?: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StaleStateRoute = {| ...StaleLeafRoute, +state: StaleNavigationState, |}; declare export type StaleRoute = | StaleLeafRoute | StaleStateRoute; declare export type StaleNavigationState = {| // It's possible to pass React Nav a StaleNavigationState with an undefined // index, but React Nav will always return one with the index set. This is // the same as for the type property below, but in the case of index we tend // to rely on it being set more... +index: number, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type?: string, +stale?: true, |}; declare export type PossiblyStaleNavigationState = | NavigationState | StaleNavigationState; declare export type PossiblyStaleRoute = | Route | StaleRoute; /** * Routers */ declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, > = { +[key: string]: (...args: any) => (Action | State => Action), ... }; declare export type DefaultRouterOptions = { +initialRouteName?: string, ... }; declare export type RouterFactory< State: NavigationState, Action: GenericNavigationAction, RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, +routeParamList: ParamListBase, |}; declare export type Router< State: NavigationState, Action: GenericNavigationAction, > = {| +type: $PropertyType, +getInitialState: (options: RouterConfigOptions) => State, +getRehydratedState: ( partialState: PossiblyStaleNavigationState, options: RouterConfigOptions, ) => State, +getStateForRouteNamesChange: ( state: State, options: RouterConfigOptions, ) => State, +getStateForRouteFocus: (state: State, key: string) => State, +getStateForAction: ( state: State, action: Action, options: RouterConfigOptions, ) => ?PossiblyStaleNavigationState; +shouldActionChangeFocus: (action: GenericNavigationAction) => boolean, +actionCreators?: ActionCreators, |}; /** * Stack actions and router */ declare export type StackNavigationState = {| ...NavigationState, +type: 'stack', |}; declare export type ReplaceAction = {| +type: 'REPLACE', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PushAction = {| +type: 'PUSH', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PopAction = {| +type: 'POP', +payload: {| +count: number |}, +source?: string, +target?: string, |}; declare export type PopToTopAction = {| +type: 'POP_TO_TOP', +source?: string, +target?: string, |}; declare export type StackAction = | CommonAction | ReplaceAction | PushAction | PopAction | PopToTopAction; declare export type StackActionsType = {| +replace: (routeName: string, params?: ScreenParams) => ReplaceAction, +push: (routeName: string, params?: ScreenParams) => PushAction, +pop: (count?: number) => PopAction, +popToTop: () => PopToTopAction, |}; declare export type StackRouterOptions = $Exact; /** * Tab actions and router */ declare export type TabNavigationState = {| ...NavigationState, +type: 'tab', +history: $ReadOnlyArray<{| type: 'route', key: string |}>, |}; declare export type JumpToAction = {| +type: 'JUMP_TO', +payload: {| +name: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type TabAction = | CommonAction | JumpToAction; declare export type TabActionsType = {| +jumpTo: string => JumpToAction, |}; declare export type TabRouterOptions = {| ...$Exact, +backBehavior?: 'initialRoute' | 'order' | 'history' | 'none', |}; /** * Drawer actions and router */ declare type DrawerHistoryEntry = | {| +type: 'route', +key: string |} | {| +type: 'drawer' |}; declare export type DrawerNavigationState = {| ...NavigationState, +type: 'drawer', +history: $ReadOnlyArray, |}; declare export type OpenDrawerAction = {| +type: 'OPEN_DRAWER', +source?: string, +target?: string, |}; declare export type CloseDrawerAction = {| +type: 'CLOSE_DRAWER', +source?: string, +target?: string, |}; declare export type ToggleDrawerAction = {| +type: 'TOGGLE_DRAWER', +source?: string, +target?: string, |}; declare export type DrawerAction = | TabAction | OpenDrawerAction | CloseDrawerAction | ToggleDrawerAction; declare export type DrawerActionsType = {| ...TabActionsType, +openDrawer: () => OpenDrawerAction, +closeDrawer: () => CloseDrawerAction, +toggleDrawer: () => ToggleDrawerAction, |}; declare export type DrawerRouterOptions = {| ...TabRouterOptions, +openByDefault?: boolean, |}; /** * Events */ declare export type EventMapBase = { +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, ... }; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, {| |}, >; declare type EventDataProperties = $If< $IsUndefined, {| |}, {| +data: Data |}, >; declare type EventArg< EventName: string, CanPreventDefault: ?boolean = false, Data = void, > = {| ...EventPreventDefaultProperties, ...EventDataProperties, +type: EventName, +target?: string, |}; declare type GlobalEventMap = {| +state: {| +data: {| +state: State |}, +canPreventDefault: false |}, |}; declare type EventMapCore = {| ...GlobalEventMap, +focus: {| +data: void, +canPreventDefault: false |}, +blur: {| +data: void, +canPreventDefault: false |}, +beforeRemove: {| +data: {| +action: GenericNavigationAction |}, +canPreventDefault: true, |}, |}; declare type EventListenerCallback< EventName: string, State: PossiblyStaleNavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = (e: EventArg< EventName, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'canPreventDefault', >, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'data', >, >) => mixed; /** * Navigation prop */ + declare type PartialWithMergeProperty = $If< + $IsExact, + { ...$Partial, +merge: true }, + { ...$Partial, +merge: true, ... }, + >; + + declare type EitherExactOrPartialWithMergeProperty = + | ParamsType + | PartialWithMergeProperty; + declare export type SimpleNavigate = >( routeName: DestinationRouteName, - params: $ElementType, + params: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, ) => void; declare export type Navigate = & SimpleNavigate & >( - route: + route: $If< + $IsUndefined<$ElementType>, + | {| +key: string |} | + {| +name: DestinationRouteName, +key?: string |}, | {| +key: string, - +params?: $ElementType, - |} - | {| + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, + |} | + {| +name: DestinationRouteName, +key?: string, - +params?: $ElementType, + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, |}, + >, ) => void; declare type NavigationHelpers< ParamList: ParamListBase, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, EventMap: EventMapBase = EventMapCore, > = { +navigate: Navigate, +dispatch: ( action: | GenericNavigationAction | (State => GenericNavigationAction), ) => void, +reset: PossiblyStaleNavigationState => void, +goBack: () => void, +isFocused: () => boolean, +canGoBack: () => boolean, +dangerouslyGetParent: >() => ?Parent, +dangerouslyGetState: () => NavigationState, +addListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => () => void, +removeListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => void, ... }; + declare type SetParamsInput< + ParamList: ParamListBase, + RouteName: $Keys = $Keys, + > = $If< + $IsUndefined<$ElementType>, + empty, + $Partial<$NonMaybeType<$ElementType>>, + >; + declare export type NavigationProp< ParamList: ParamListBase, RouteName: $Keys = $Keys, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = { ...$Exact>, +setOptions: (options: $Partial) => void, - +setParams: ( - params: $If< - $IsUndefined<$ElementType>, - empty, - $Partial<$NonMaybeType<$ElementType>>, - >, - ) => void, + +setParams: (params: SetParamsInput) => void, ... }; /** * CreateNavigator */ declare export type RouteProp< ParamList: ParamListBase, RouteName: $Keys, > = {| ...LeafRoute, +params: $ElementType, |}; declare export type ScreenListeners< State: NavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = $ObjMapi< {| [name: $Keys]: empty |}, >(K, empty) => EventListenerCallback, >; declare type BaseScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = {| +name: RouteName, +options?: | ScreenOptions | ({| route: RouteProp, navigation: NavProp, |}) => ScreenOptions, +listeners?: | ScreenListeners | ({| route: RouteProp, navigation: NavProp, |}) => ScreenListeners, +initialParams?: $Partial<$ElementType>, |}; declare export type ScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +component: React$ComponentType<{| route: RouteProp, navigation: NavProp, |}>, |} | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +children: ({| route: RouteProp, navigation: NavProp, |}) => React$Node, |}; declare export type ScreenComponent< GlobalParamList: ParamListBase, ParamList: ParamListBase, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = < RouteName: $Keys, NavProp: NavigationProp< GlobalParamList, RouteName, State, ScreenOptions, EventMap, >, >(props: ScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >) => React$Node; declare type ScreenOptionsProp = {| +screenOptions?: | ScreenOptions | ({| route: LeafRoute<>, navigation: NavProp |}) => ScreenOptions, |}; declare export type ExtraNavigatorPropsBase = { ...$Exact, +children?: React$Node, ... }; declare export type NavigatorPropsBase = { ...$Exact, ...ScreenOptionsProp, ... }; declare export type CreateNavigator< State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, ExtraNavigatorProps: ExtraNavigatorPropsBase, > = < GlobalParamList: ParamListBase, ParamList: ParamListBase, NavProp: NavigationHelpers< GlobalParamList, State, EventMap, >, >() => {| +Screen: ScreenComponent< GlobalParamList, ParamList, State, ScreenOptions, EventMap, >, +Navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, |}; declare export type CreateNavigatorFactory = < State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, NavProp: NavigationHelpers< ParamListBase, State, EventMap, >, ExtraNavigatorProps: ExtraNavigatorPropsBase, >( navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, ) => CreateNavigator; /** * useNavigationBuilder */ declare export type Descriptor< NavProp, ScreenOptions: {...} = {...}, > = {| +render: () => React$Node, +options: $ReadOnly, +navigation: NavProp, |}; declare export type UseNavigationBuilder = < State: NavigationState, Action: GenericNavigationAction, ScreenOptions: {...}, RouterOptions: DefaultRouterOptions, NavProp, >( routerFactory: RouterFactory, options: {| ...$Exact, ...ScreenOptionsProp, +children?: React$Node, |}, ) => {| +state: State, +descriptors: {| +[key: string]: Descriptor |}, +navigation: NavProp, |}; /** * EdgeInsets */ declare type EdgeInsets = {| +top: number, +right: number, +bottom: number, +left: number, |}; /** * TransitionPreset */ declare export type TransitionSpec = | {| animation: 'spring', config: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |} | {| animation: 'timing', config: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |}; declare export type StackCardInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +index: number, +closing: AnimatedInterpolation, +swiping: AnimatedInterpolation, +inverted: AnimatedInterpolation, +layouts: {| +screen: {| +width: number, +height: number |}, |}, +insets: EdgeInsets, |}; declare export type StackCardInterpolatedStyle = {| containerStyle?: AnimatedViewStyleProp, cardStyle?: AnimatedViewStyleProp, overlayStyle?: AnimatedViewStyleProp, shadowStyle?: AnimatedViewStyleProp, |}; declare export type StackCardStyleInterpolator = ( props: StackCardInterpolationProps, ) => StackCardInterpolatedStyle; declare export type StackHeaderInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +layouts: {| +header: {| +width: number, +height: number |}, +screen: {| +width: number, +height: number |}, +title?: {| +width: number, +height: number |}, +leftLabel?: {| +width: number, +height: number |}, |}, |}; declare export type StackHeaderInterpolatedStyle = {| leftLabelStyle?: AnimatedViewStyleProp, leftButtonStyle?: AnimatedViewStyleProp, rightButtonStyle?: AnimatedViewStyleProp, titleStyle?: AnimatedViewStyleProp, backgroundStyle?: AnimatedViewStyleProp, |}; declare export type StackHeaderStyleInterpolator = ( props: StackHeaderInterpolationProps, ) => StackHeaderInterpolatedStyle; declare type GestureDirection = | 'horizontal' | 'horizontal-inverted' | 'vertical' | 'vertical-inverted'; declare export type TransitionPreset = {| +gestureDirection: GestureDirection, +transitionSpec: {| +open: TransitionSpec, +close: TransitionSpec, |}, +cardStyleInterpolator: StackCardStyleInterpolator, +headerStyleInterpolator: StackHeaderStyleInterpolator, |}; /** * Stack options */ declare export type StackDescriptor = Descriptor< StackNavigationProp<>, StackOptions, >; declare type Scene = {| +route: T, +descriptor: StackDescriptor, +progress: {| +current: AnimatedInterpolation, +next?: AnimatedInterpolation, +previous?: AnimatedInterpolation, |}, |}; declare export type StackHeaderProps = {| +mode: 'float' | 'screen', +layout: {| +width: number, +height: number |}, +insets: EdgeInsets, +scene: Scene>, +previous?: Scene>, +navigation: StackNavigationProp, +styleInterpolator: StackHeaderStyleInterpolator, |}; declare export type StackHeaderLeftButtonProps = $Partial<{| +onPress: (() => void), +pressColorAndroid: string; +backImage: (props: {| tintColor: string |}) => React$Node, +tintColor: string, +label: string, +truncatedLabel: string, +labelVisible: boolean, +labelStyle: AnimatedTextStyleProp, +allowFontScaling: boolean, +onLabelLayout: LayoutEvent => void, +screenLayout: {| +width: number, +height: number |}, +titleLayout: {| +width: number, +height: number |}, +canGoBack: boolean, |}>; declare type StackHeaderTitleInputBase = { +onLayout: LayoutEvent => void, +children: string, +allowFontScaling: ?boolean, +tintColor: ?string, +style: ?AnimatedTextStyleProp, ... }; declare export type StackHeaderTitleInputProps = $Exact; declare export type StackOptions = $Partial<{| +title: string, +header: StackHeaderProps => React$Node, +headerShown: boolean, +cardShadowEnabled: boolean, +cardOverlayEnabled: boolean, +cardOverlay: {| style: ViewStyleProp |} => React$Node, +cardStyle: ViewStyleProp, +animationEnabled: boolean, +animationTypeForReplace: 'push' | 'pop', +gestureEnabled: boolean, +gestureResponseDistance: {| vertical?: number, horizontal?: number |}, +gestureVelocityImpact: number, +safeAreaInsets: $Partial, // Transition ...TransitionPreset, // Header +headerTitle: string | (StackHeaderTitleInputProps => React$Node), +headerTitleAlign: 'left' | 'center', +headerTitleStyle: AnimatedTextStyleProp, +headerTitleContainerStyle: ViewStyleProp, +headerTintColor: string, +headerTitleAllowFontScaling: boolean, +headerBackAllowFontScaling: boolean, +headerBackTitle: string | null, +headerBackTitleStyle: TextStyleProp, +headerBackTitleVisible: boolean, +headerTruncatedBackTitle: string, +headerLeft: StackHeaderLeftButtonProps => React$Node, +headerLeftContainerStyle: ViewStyleProp, +headerRight: {| tintColor?: string |} => React$Node, +headerRightContainerStyle: ViewStyleProp, +headerBackImage: $PropertyType, +headerPressColorAndroid: string, +headerBackground: ({| style: ViewStyleProp |}) => React$Node, +headerStyle: ViewStyleProp, +headerTransparent: boolean, +headerStatusBarHeight: number, |}>; /** * Stack navigation prop */ declare export type StackNavigationEventMap = {| ...EventMapCore, +transitionStart: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +transitionEnd: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +gestureStart: {| +data: void, +canPreventDefault: false |}, +gestureEnd: {| +data: void, +canPreventDefault: false |}, +gestureCancel: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactStackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = { ...$Exact>, +replace: SimpleNavigate, +push: SimpleNavigate, +pop: (count?: number) => void, +popToTop: () => void, ... }; declare export type StackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = $Exact>; /** * Miscellaneous stack exports */ declare type StackNavigationConfig = {| +mode?: 'card' | 'modal', +headerMode?: 'float' | 'screen' | 'none', +keyboardHandlingEnabled?: boolean, +detachInactiveScreens?: boolean, |}; declare export type ExtraStackNavigatorProps = {| ...$Exact, ...StackRouterOptions, ...StackNavigationConfig, |}; declare export type StackNavigatorProps< NavProp: InexactStackNavigationProp<> = StackNavigationProp<>, > = {| ...ExtraStackNavigatorProps, ...ScreenOptionsProp, |}; /** * Bottom tab options */ declare export type BottomTabBarButtonProps = {| ...$Diff< TouchableWithoutFeedbackProps, {| onPress?: ?(event: PressEvent) => mixed |}, >, +to?: string, +children: React$Node, +onPress?: (MouseEvent | PressEvent) => void, |}; declare export type TabBarVisibilityAnimationConfig = | {| +animation: 'spring', +config?: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |} | {| +animation: 'timing', +config?: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |}; declare export type BottomTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| focused: boolean, color: string |}) => React$Node, +tabBarIcon: ({| focused: boolean, color: string, size: number, |}) => React$Node, +tabBarBadge: number | string, +tabBarBadgeStyle: TextStyleProp, +tabBarAccessibilityLabel: string, +tabBarTestID: string, +tabBarVisible: boolean, +tabBarVisibilityAnimationConfig: $Partial<{| +show: TabBarVisibilityAnimationConfig, +hide: TabBarVisibilityAnimationConfig, |}>, +tabBarButton: BottomTabBarButtonProps => React$Node, +unmountOnBlur: boolean, |}>; /** * Bottom tab navigation prop */ declare export type BottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactTabNavigationProp< ParamList: ParamListBase, RouteName: $Keys, Options: {...}, EventMap: EventMapBase, > = { ...$Exact>, +jumpTo: SimpleNavigate, ... }; declare export type InexactBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type BottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous bottom tab exports */ declare export type BottomTabDescriptor = Descriptor< BottomTabNavigationProp<>, BottomTabOptions, >; declare export type BottomTabBarOptions = $Partial<{| +keyboardHidesTabBar: boolean, +activeTintColor: string, +inactiveTintColor: string, +activeBackgroundColor: string, +inactiveBackgroundColor: string, +allowFontScaling: boolean, +showLabel: boolean, +showIcon: boolean, +labelStyle: TextStyleProp, +iconStyle: TextStyleProp, +tabStyle: ViewStyleProp, +labelPosition: 'beside-icon' | 'below-icon', +adaptive: boolean, +safeAreaInsets: $Partial, +style: ViewStyleProp, |}>; declare type BottomTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: BottomTabNavigationProp<>, +descriptors: {| +[key: string]: BottomTabDescriptor |}, |}; declare export type BottomTabBarProps = {| ...BottomTabBarOptions, ...BottomTabNavigationBuilderResult, |} declare type BottomTabNavigationConfig = {| +lazy?: boolean, +tabBar?: BottomTabBarProps => React$Node, +tabBarOptions?: BottomTabBarOptions, +detachInactiveScreens?: boolean, |}; declare export type ExtraBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...BottomTabNavigationConfig, |}; declare export type BottomTabNavigatorProps< NavProp: InexactBottomTabNavigationProp<> = BottomTabNavigationProp<>, > = {| ...ExtraBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material bottom tab options */ declare export type MaterialBottomTabOptions = $Partial<{| +title: string, +tabBarColor: string, +tabBarLabel: string, +tabBarIcon: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarBadge: boolean | number | string, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material bottom tab navigation prop */ declare export type MaterialBottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, |}; declare export type InexactMaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material bottom tab exports */ declare export type PaperFont = {| +fontFamily: string, +fontWeight?: | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', |}; declare export type PaperFonts = {| +regular: PaperFont, +medium: PaperFont, +light: PaperFont, +thin: PaperFont, |}; declare export type PaperTheme = {| +dark: boolean, +mode?: 'adaptive' | 'exact', +roundness: number, +colors: {| +primary: string, +background: string, +surface: string, +accent: string, +error: string, +text: string, +onSurface: string, +onBackground: string, +disabled: string, +placeholder: string, +backdrop: string, +notification: string, |}, +fonts: PaperFonts, +animation: {| +scale: number, |}, |}; declare export type PaperRoute = {| +key: string, +title?: string, +icon?: any, +badge?: string | number | boolean, +color?: string, +accessibilityLabel?: string, +testID?: string, |}; declare export type PaperTouchableProps = {| ...TouchableWithoutFeedbackProps, +key: string, +route: PaperRoute, +children: React$Node, +borderless?: boolean, +centered?: boolean, +rippleColor?: string, |}; declare export type MaterialBottomTabNavigationConfig = {| +shifting?: boolean, +labeled?: boolean, +renderTouchable?: PaperTouchableProps => React$Node, +activeColor?: string, +inactiveColor?: string, +sceneAnimationEnabled?: boolean, +keyboardHidesNavigationBar?: boolean, +barStyle?: ViewStyleProp, +style?: ViewStyleProp, +theme?: PaperTheme, |}; declare export type ExtraMaterialBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialBottomTabNavigationConfig, |}; declare export type MaterialBottomTabNavigatorProps< NavProp: InexactMaterialBottomTabNavigationProp<> = MaterialBottomTabNavigationProp<>, > = {| ...ExtraMaterialBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material top tab options */ declare export type MaterialTopTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarIcon: ({| +focused: boolean, +color: string |}) => React$Node, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material top tab navigation prop */ declare export type MaterialTopTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, +swipeStart: {| +data: void, +canPreventDefault: false |}, +swipeEnd: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactMaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material top tab exports */ declare type MaterialTopTabPagerCommonProps = {| +keyboardDismissMode: 'none' | 'on-drag' | 'auto', +swipeEnabled: boolean, +swipeVelocityImpact?: number, +springVelocityScale?: number, +springConfig: $Partial<{| +damping: number, +mass: number, +stiffness: number, +restSpeedThreshold: number, +restDisplacementThreshold: number, |}>, +timingConfig: $Partial<{| +duration: number, |}>, |}; declare export type MaterialTopTabPagerProps = {| ...MaterialTopTabPagerCommonProps, +onSwipeStart?: () => void, +onSwipeEnd?: () => void, +onIndexChange: (index: number) => void, +navigationState: TabNavigationState, +layout: {| +width: number, +height: number |}, +removeClippedSubviews: boolean, +children: ({| +addListener: (type: 'enter', listener: number => void) => void, +removeListener: (type: 'enter', listener: number => void) => void, +position: any, // Reanimated.Node +render: React$Node => React$Node, +jumpTo: string => void, |}) => React$Node, +gestureHandlerProps: PanGestureHandlerProps, |}; declare export type MaterialTopTabBarIndicatorProps = {| +navigationState: TabNavigationState, +width: string, +style?: ViewStyleProp, +getTabWidth: number => number, |}; declare export type MaterialTopTabBarOptions = $Partial<{| +scrollEnabled: boolean, +bounces: boolean, +pressColor: string, +pressOpacity: number, +getAccessible: ({| +route: Route<> |}) => boolean, +renderBadge: ({| +route: Route<> |}) => React$Node, +renderIndicator: MaterialTopTabBarIndicatorProps => React$Node, +tabStyle: ViewStyleProp, +indicatorStyle: ViewStyleProp, +indicatorContainerStyle: ViewStyleProp, +labelStyle: TextStyleProp, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, +activeTintColor: string, +inactiveTintColor: string, +iconStyle: ViewStyleProp, +labelStyle: TextStyleProp, +showLabel: boolean, +showIcon: boolean, +allowFontScaling: boolean, |}>; declare export type MaterialTopTabDescriptor = Descriptor< MaterialBottomTabNavigationProp<>, MaterialBottomTabOptions, >; declare type MaterialTopTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: MaterialTopTabNavigationProp<>, +descriptors: {| +[key: string]: MaterialTopTabDescriptor |}, |}; declare export type MaterialTopTabBarProps = {| ...MaterialTopTabBarOptions, ...MaterialTopTabNavigationBuilderResult, +layout: {| +width: number, +height: number |}, +position: any, // Reanimated.Node +jumpTo: string => void, |}; declare export type MaterialTopTabNavigationConfig = {| ...$Partial, +position?: any, // Reanimated.Value +tabBarPosition?: 'top' | 'bottom', +initialLayout?: $Partial<{| +width: number, +height: number |}>, +lazy?: boolean, +lazyPreloadDistance?: number, +removeClippedSubviews?: boolean, +sceneContainerStyle?: ViewStyleProp, +style?: ViewStyleProp, +gestureHandlerProps?: PanGestureHandlerProps, +pager?: MaterialTopTabPagerProps => React$Node, +lazyPlaceholder?: ({| +route: Route<> |}) => React$Node, +tabBar?: MaterialTopTabBarProps => React$Node, +tabBarOptions?: MaterialTopTabBarOptions, |}; declare export type ExtraMaterialTopTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialTopTabNavigationConfig, |}; declare export type MaterialTopTabNavigatorProps< NavProp: InexactMaterialTopTabNavigationProp<> = MaterialTopTabNavigationProp<>, > = {| ...ExtraMaterialTopTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Drawer options */ declare export type DrawerOptions = $Partial<{| title: string, drawerLabel: | string | ({| +color: string, +focused: boolean |}) => React$Node, drawerIcon: ({| +color: string, +size: number, +focused: boolean, |}) => React$Node, gestureEnabled: boolean, swipeEnabled: boolean, unmountOnBlur: boolean, |}>; /** * Drawer navigation prop */ declare export type DrawerNavigationEventMap = {| ...EventMapCore, +drawerOpen: {| +data: void, +canPreventDefault: false |}, +drawerClose: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactDrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = { ...$Exact>, +jumpTo: SimpleNavigate, +openDrawer: () => void, +closeDrawer: () => void, +toggleDrawer: () => void, ... }; declare export type DrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = $Exact>; /** * Miscellaneous drawer exports */ declare export type DrawerDescriptor = Descriptor< DrawerNavigationProp<>, DrawerOptions, >; declare export type DrawerItemListBaseOptions = $Partial<{| +activeTintColor: string, +activeBackgroundColor: string, +inactiveTintColor: string, +inactiveBackgroundColor: string, +itemStyle: ViewStyleProp, +labelStyle: TextStyleProp, |}>; declare export type DrawerContentOptions = $Partial<{| ...DrawerItemListBaseOptions, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, |}>; declare type DrawerNavigationBuilderResult = {| +state: DrawerNavigationState, +navigation: DrawerNavigationProp<>, +descriptors: {| +[key: string]: DrawerDescriptor |}, |}; declare export type DrawerContentProps = {| ...DrawerContentOptions, ...DrawerNavigationBuilderResult, +progress: any, // Reanimated.Node |}; declare export type DrawerNavigationConfig = {| +drawerPosition?: 'left' | 'right', +drawerType?: 'front' | 'back' | 'slide' | 'permanent', +edgeWidth?: number, +hideStatusBar?: boolean, +keyboardDismissMode?: 'on-drag' | 'none', +minSwipeDistance?: number, +overlayColor?: string, +statusBarAnimation?: 'slide' | 'none' | 'fade', +gestureHandlerProps?: PanGestureHandlerProps, +lazy?: boolean, +drawerContent?: DrawerContentProps => React$Node, +drawerContentOptions?: DrawerContentOptions, +sceneContainerStyle?: ViewStyleProp, +drawerStyle?: ViewStyleProp, +detachInactiveScreens?: boolean, |}; declare export type ExtraDrawerNavigatorProps = {| ...$Exact, ...DrawerRouterOptions, ...DrawerNavigationConfig, |}; declare export type DrawerNavigatorProps< NavProp: InexactDrawerNavigationProp<> = DrawerNavigationProp<>, > = {| ...ExtraDrawerNavigatorProps, ...ScreenOptionsProp, |}; /** * BaseNavigationContainer */ declare export type BaseNavigationContainerProps = {| +children: React$Node, +initialState?: PossiblyStaleNavigationState, +onStateChange?: (state: ?PossiblyStaleNavigationState) => void, +independent?: boolean, |}; declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| +data: {| +options: { +[key: string]: mixed, ... } |}, +canPreventDefault: false, |}, +__unsafe_action__: {| +data: {| +action: GenericNavigationAction, +noop: boolean, |}, +canPreventDefault: false, |}, |}; declare export type BaseNavigationContainerInterface = {| ...$Exact>, +setParams: (params: ScreenParams) => void, +resetRoot: (state?: ?PossiblyStaleNavigationState) => void, +getRootState: () => PossiblyStaleNavigationState, |}; /** * State utils */ declare export type GetStateFromPath = ( path: string, options?: LinkingConfig, ) => PossiblyStaleNavigationState; declare export type GetPathFromState = ( state?: ?PossiblyStaleNavigationState, options?: LinkingConfig, ) => string; declare export type GetFocusedRouteNameFromRoute = PossiblyStaleRoute => ?string; /** * Linking */ declare export type ScreenLinkingConfig = {| +path?: string, +exact?: boolean, +parse?: {| +[param: string]: string => mixed |}, +stringify?: {| +[param: string]: mixed => string |}, +screens?: ScreenLinkingConfigMap, +initialRouteName?: string, |}; declare export type ScreenLinkingConfigMap = {| +[routeName: string]: string | ScreenLinkingConfig, |}; declare export type LinkingConfig = {| +initialRouteName?: string, +screens: ScreenLinkingConfigMap, |}; declare export type LinkingOptions = {| +enabled?: boolean, +prefixes: $ReadOnlyArray, +config?: LinkingConfig, +getStateFromPath?: GetStateFromPath, +getPathFromState?: GetPathFromState, |}; /** * NavigationContainer */ declare export type Theme = {| +dark: boolean, +colors: {| +primary: string, +background: string, +card: string, +text: string, +border: string, |}, |}; declare export type NavigationContainerType = React$AbstractComponent< {| ...BaseNavigationContainerProps, +theme?: Theme, +linking?: LinkingOptions, +fallback?: React$Node, +onReady?: () => mixed, |}, BaseNavigationContainerInterface, >; //--------------------------------------------------------------------------- // SECTION 2: EXPORTED MODULE // This section defines the module exports and contains exported types that // are not present in any other React Navigation libdef. //--------------------------------------------------------------------------- /** * createBottomTabNavigator */ declare export var createBottomTabNavigator: CreateNavigator< TabNavigationState, BottomTabOptions, BottomTabNavigationEventMap, ExtraBottomTabNavigatorProps, >; /** * BottomTabBar */ declare export var BottomTabBar: React$ComponentType; /** * BottomTabView */ declare export type BottomTabViewProps = {| ...BottomTabNavigationConfig, ...BottomTabNavigationBuilderResult, |}; declare export var BottomTabView: React$ComponentType; } diff --git a/native/flow-typed/npm/@react-navigation/devtools_v5.x.x.js b/native/flow-typed/npm/@react-navigation/devtools_v5.x.x.js index 60915affd..265ebe99f 100644 --- a/native/flow-typed/npm/@react-navigation/devtools_v5.x.x.js +++ b/native/flow-typed/npm/@react-navigation/devtools_v5.x.x.js @@ -1,2080 +1,2109 @@ // flow-typed signature: c98b7550ee0851a8d0707331178800d8 // flow-typed version: dc2d6a22c7/@react-navigation/devtools_v5.x.x/flow_>=v0.104.x declare module '@react-navigation/devtools' { //--------------------------------------------------------------------------- // SECTION 1: IDENTICAL TYPE DEFINITIONS // This section is identical across all React Navigation libdefs and contains // shared definitions. We wish we could make it DRY and import from a shared // definition, but that isn't yet possible. //--------------------------------------------------------------------------- /** * We start with some definitions that we have copy-pasted from React Native * source files. */ // This is a bastardization of the true StyleObj type located in // react-native/Libraries/StyleSheet/StyleSheetTypes. We unfortunately can't // import that here, and it's too lengthy (and consequently too brittle) to // copy-paste here either. declare type StyleObj = | null | void | number | false | '' | $ReadOnlyArray | { [name: string]: any, ... }; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; declare type AnimatedTextStyleProp = StyleObj; // Vaguely copied from // react-native/Libraries/Animated/src/animations/Animation.js declare type EndResult = { finished: boolean, ... }; declare type EndCallback = (result: EndResult) => void; declare interface Animation { start( fromValue: number, onUpdate: (value: number) => void, onEnd: ?EndCallback, previousAnimation: ?Animation, animatedValue: AnimatedValue, ): void; stop(): void; } declare type AnimationConfig = { isInteraction?: boolean, useNativeDriver: boolean, onComplete?: ?EndCallback, iterations?: number, ... }; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedTracking.js declare interface AnimatedTracking { constructor( value: AnimatedValue, parent: any, animationClass: any, animationConfig: Object, callback?: ?EndCallback, ): void; update(): void; } // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedValue.js declare type ValueListenerCallback = (state: { value: number, ... }) => void; declare interface AnimatedValue { constructor(value: number): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; extractOffset(): void; addListener(callback: ValueListenerCallback): string; removeListener(id: string): void; removeAllListeners(): void; stopAnimation(callback?: ?(value: number) => void): void; resetAnimation(callback?: ?(value: number) => void): void; interpolate(config: InterpolationConfigType): AnimatedInterpolation; animate(animation: Animation, callback: ?EndCallback): void; stopTracking(): void; track(tracking: AnimatedTracking): void; } // Copied from // react-native/Libraries/Animated/src/animations/TimingAnimation.js declare type TimingAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, easing?: (value: number) => number, duration?: number, delay?: number, ... }; // Copied from // react-native/Libraries/Animated/src/animations/SpringAnimation.js declare type SpringAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, overshootClamping?: boolean, restDisplacementThreshold?: number, restSpeedThreshold?: number, velocity?: number, bounciness?: number, speed?: number, tension?: number, friction?: number, stiffness?: number, damping?: number, mass?: number, delay?: number, ... }; // Copied from react-native/Libraries/Types/CoreEventTypes.js declare type SyntheticEvent = $ReadOnly<{| bubbles: ?boolean, cancelable: ?boolean, currentTarget: number, defaultPrevented: ?boolean, dispatchConfig: $ReadOnly<{| registrationName: string, |}>, eventPhase: ?number, preventDefault: () => void, isDefaultPrevented: () => boolean, stopPropagation: () => void, isPropagationStopped: () => boolean, isTrusted: ?boolean, nativeEvent: T, persist: () => void, target: ?number, timeStamp: number, type: ?string, |}>; declare type Layout = $ReadOnly<{| x: number, y: number, width: number, height: number, |}>; declare type LayoutEvent = SyntheticEvent< $ReadOnly<{| layout: Layout, |}>, >; declare type BlurEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type FocusEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type ResponderSyntheticEvent = $ReadOnly<{| ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray< $ReadOnly<{| touchActive: boolean, startPageX: number, startPageY: number, startTimeStamp: number, currentPageX: number, currentPageY: number, currentTimeStamp: number, previousPageX: number, previousPageY: number, previousTimeStamp: number, |}>, >, |}>, |}>; declare type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, identifier: number, locationX: number, locationY: number, pageX: number, pageY: number, target: ?number, timestamp: number, touches: $ReadOnlyArray<$PropertyType>, |}>, >; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js declare type ExtrapolateType = 'extend' | 'identity' | 'clamp'; declare type InterpolationConfigType = { inputRange: Array, outputRange: Array | Array, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, ... }; declare interface AnimatedInterpolation { interpolate(config: InterpolationConfigType): AnimatedInterpolation; } // Copied from react-native/Libraries/Components/View/ViewAccessibility.js declare type AccessibilityRole = | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'imagebutton' | 'header' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menu' | 'menubar' | 'menuitem' | 'progressbar' | 'radio' | 'radiogroup' | 'scrollbar' | 'spinbutton' | 'switch' | 'tab' | 'tablist' | 'timer' | 'toolbar'; declare type AccessibilityActionInfo = $ReadOnly<{ name: string, label?: string, ... }>; declare type AccessibilityActionEvent = SyntheticEvent< $ReadOnly<{actionName: string, ...}>, >; declare type AccessibilityState = { disabled?: boolean, selected?: boolean, checked?: ?boolean | 'mixed', busy?: boolean, expanded?: boolean, ... }; declare type AccessibilityValue = $ReadOnly<{| min?: number, max?: number, now?: number, text?: string, |}>; // Copied from // react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js declare type Stringish = string; declare type EdgeInsetsProp = $ReadOnly<$Partial>; declare type TouchableWithoutFeedbackProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, accessibilityElementsHidden?: ?boolean, accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityLabel?: ?Stringish, accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, children?: ?React$Node, delayLongPress?: ?number, delayPressIn?: ?number, delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, hitSlop?: ?EdgeInsetsProp, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(event: BlurEvent) => mixed, onFocus?: ?(event: FocusEvent) => mixed, onLayout?: ?(event: LayoutEvent) => mixed, onLongPress?: ?(event: PressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, pressRetentionOffset?: ?EdgeInsetsProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, |}>; // Copied from react-native/Libraries/Image/ImageSource.js declare type ImageURISource = $ReadOnly<{ uri?: ?string, bundle?: ?string, method?: ?string, headers?: ?Object, body?: ?string, cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), width?: ?number, height?: ?number, scale?: ?number, ... }>; /** * The following is copied from react-native-gesture-handler's libdef */ declare type StateUndetermined = 0; declare type StateFailed = 1; declare type StateBegan = 2; declare type StateCancelled = 3; declare type StateActive = 4; declare type StateEnd = 5; declare type GestureHandlerState = | StateUndetermined | StateFailed | StateBegan | StateCancelled | StateActive | StateEnd; declare type $SyntheticEvent = { +nativeEvent: $ReadOnly<$Exact>, ... }; declare type $Event = $SyntheticEvent<{ handlerTag: number, numberOfPointers: number, state: GestureHandlerState, oldState: GestureHandlerState, ...$Exact, ... }>; declare type $EventHandlers = {| onGestureEvent?: ($Event) => mixed, onHandlerStateChange?: ($Event) => mixed, onBegan?: ($Event) => mixed, onFailed?: ($Event) => mixed, onCancelled?: ($Event) => mixed, onActivated?: ($Event) => mixed, onEnded?: ($Event) => mixed, |}; declare type HitSlop = | number | {| left?: number, top?: number, right?: number, bottom?: number, vertical?: number, horizontal?: number, width?: number, height?: number, |} | {| width: number, left: number, |} | {| width: number, right: number, |} | {| height: number, top: number, |} | {| height: number, bottom: number, |}; declare type $GestureHandlerProps< AdditionalProps: {...}, ExtraEventsProps: {...} > = $ReadOnly<{| ...$Exact, ...$EventHandlers, id?: string, enabled?: boolean, waitFor?: React$Ref | Array>, simultaneousHandlers?: React$Ref | Array>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, children?: React$Node, |}>; declare type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], activeOffsetX?: number | [number, number], failOffsetY?: number | [number, number], failOffsetX?: number | [number, number], minDist?: number, minVelocity?: number, minVelocityX?: number, minVelocityY?: number, minPointers?: number, maxPointers?: number, avgTouches?: boolean, ... }, { x: number, y: number, absoluteX: number, absoluteY: number, translationX: number, translationY: number, velocityX: number, velocityY: number, ... } >; /** * MAGIC */ declare type $If = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), Test, Then, Else, >; declare type $IsA = $Call< (Y => true) & (mixed => false), X, >; declare type $IsUndefined = $IsA; declare type $Partial = $ReadOnly<$Rest>; + // If { ...T, ... } counts as a T, then we're inexact + declare type $IsExact = $Call< + (T => false) & (mixed => true), + { ...T, ... }, + >; + /** * Actions, state, etc. */ declare export type ScreenParams = { +[key: string]: mixed, ... }; declare export type BackAction = {| +type: 'GO_BACK', +source?: string, +target?: string, |}; declare export type NavigateAction = {| +type: 'NAVIGATE', +payload: | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type ResetAction = {| +type: 'RESET', +payload: StaleNavigationState, +source?: string, +target?: string, |}; declare export type SetParamsAction = {| +type: 'SET_PARAMS', +payload: {| +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type CommonAction = | BackAction | NavigateAction | ResetAction | SetParamsAction; declare type NavigateActionCreator = {| (routeName: string, params?: ScreenParams): NavigateAction, ( | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, ): NavigateAction, |}; declare export type CommonActionsType = {| +navigate: NavigateActionCreator, +goBack: () => BackAction, +reset: (state: PossiblyStaleNavigationState) => ResetAction, +setParams: (params: ScreenParams) => SetParamsAction, |}; declare export type GenericNavigationAction = {| +type: string, +payload?: { +[key: string]: mixed, ... }, +source?: string, +target?: string, |}; declare export type LeafRoute = {| +key: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StateRoute = {| ...LeafRoute, +state: NavigationState | StaleNavigationState, |}; declare export type Route = | LeafRoute | StateRoute; declare export type NavigationState = {| +key: string, +index: number, +routeNames: $ReadOnlyArray, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type: string, +stale: false, |}; declare export type StaleLeafRoute = {| +key?: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StaleStateRoute = {| ...StaleLeafRoute, +state: StaleNavigationState, |}; declare export type StaleRoute = | StaleLeafRoute | StaleStateRoute; declare export type StaleNavigationState = {| // It's possible to pass React Nav a StaleNavigationState with an undefined // index, but React Nav will always return one with the index set. This is // the same as for the type property below, but in the case of index we tend // to rely on it being set more... +index: number, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type?: string, +stale?: true, |}; declare export type PossiblyStaleNavigationState = | NavigationState | StaleNavigationState; declare export type PossiblyStaleRoute = | Route | StaleRoute; /** * Routers */ declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, > = { +[key: string]: (...args: any) => (Action | State => Action), ... }; declare export type DefaultRouterOptions = { +initialRouteName?: string, ... }; declare export type RouterFactory< State: NavigationState, Action: GenericNavigationAction, RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, +routeParamList: ParamListBase, |}; declare export type Router< State: NavigationState, Action: GenericNavigationAction, > = {| +type: $PropertyType, +getInitialState: (options: RouterConfigOptions) => State, +getRehydratedState: ( partialState: PossiblyStaleNavigationState, options: RouterConfigOptions, ) => State, +getStateForRouteNamesChange: ( state: State, options: RouterConfigOptions, ) => State, +getStateForRouteFocus: (state: State, key: string) => State, +getStateForAction: ( state: State, action: Action, options: RouterConfigOptions, ) => ?PossiblyStaleNavigationState; +shouldActionChangeFocus: (action: GenericNavigationAction) => boolean, +actionCreators?: ActionCreators, |}; /** * Stack actions and router */ declare export type StackNavigationState = {| ...NavigationState, +type: 'stack', |}; declare export type ReplaceAction = {| +type: 'REPLACE', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PushAction = {| +type: 'PUSH', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PopAction = {| +type: 'POP', +payload: {| +count: number |}, +source?: string, +target?: string, |}; declare export type PopToTopAction = {| +type: 'POP_TO_TOP', +source?: string, +target?: string, |}; declare export type StackAction = | CommonAction | ReplaceAction | PushAction | PopAction | PopToTopAction; declare export type StackActionsType = {| +replace: (routeName: string, params?: ScreenParams) => ReplaceAction, +push: (routeName: string, params?: ScreenParams) => PushAction, +pop: (count?: number) => PopAction, +popToTop: () => PopToTopAction, |}; declare export type StackRouterOptions = $Exact; /** * Tab actions and router */ declare export type TabNavigationState = {| ...NavigationState, +type: 'tab', +history: $ReadOnlyArray<{| type: 'route', key: string |}>, |}; declare export type JumpToAction = {| +type: 'JUMP_TO', +payload: {| +name: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type TabAction = | CommonAction | JumpToAction; declare export type TabActionsType = {| +jumpTo: string => JumpToAction, |}; declare export type TabRouterOptions = {| ...$Exact, +backBehavior?: 'initialRoute' | 'order' | 'history' | 'none', |}; /** * Drawer actions and router */ declare type DrawerHistoryEntry = | {| +type: 'route', +key: string |} | {| +type: 'drawer' |}; declare export type DrawerNavigationState = {| ...NavigationState, +type: 'drawer', +history: $ReadOnlyArray, |}; declare export type OpenDrawerAction = {| +type: 'OPEN_DRAWER', +source?: string, +target?: string, |}; declare export type CloseDrawerAction = {| +type: 'CLOSE_DRAWER', +source?: string, +target?: string, |}; declare export type ToggleDrawerAction = {| +type: 'TOGGLE_DRAWER', +source?: string, +target?: string, |}; declare export type DrawerAction = | TabAction | OpenDrawerAction | CloseDrawerAction | ToggleDrawerAction; declare export type DrawerActionsType = {| ...TabActionsType, +openDrawer: () => OpenDrawerAction, +closeDrawer: () => CloseDrawerAction, +toggleDrawer: () => ToggleDrawerAction, |}; declare export type DrawerRouterOptions = {| ...TabRouterOptions, +openByDefault?: boolean, |}; /** * Events */ declare export type EventMapBase = { +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, ... }; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, {| |}, >; declare type EventDataProperties = $If< $IsUndefined, {| |}, {| +data: Data |}, >; declare type EventArg< EventName: string, CanPreventDefault: ?boolean = false, Data = void, > = {| ...EventPreventDefaultProperties, ...EventDataProperties, +type: EventName, +target?: string, |}; declare type GlobalEventMap = {| +state: {| +data: {| +state: State |}, +canPreventDefault: false |}, |}; declare type EventMapCore = {| ...GlobalEventMap, +focus: {| +data: void, +canPreventDefault: false |}, +blur: {| +data: void, +canPreventDefault: false |}, +beforeRemove: {| +data: {| +action: GenericNavigationAction |}, +canPreventDefault: true, |}, |}; declare type EventListenerCallback< EventName: string, State: PossiblyStaleNavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = (e: EventArg< EventName, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'canPreventDefault', >, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'data', >, >) => mixed; /** * Navigation prop */ + declare type PartialWithMergeProperty = $If< + $IsExact, + { ...$Partial, +merge: true }, + { ...$Partial, +merge: true, ... }, + >; + + declare type EitherExactOrPartialWithMergeProperty = + | ParamsType + | PartialWithMergeProperty; + declare export type SimpleNavigate = >( routeName: DestinationRouteName, - params: $ElementType, + params: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, ) => void; declare export type Navigate = & SimpleNavigate & >( - route: + route: $If< + $IsUndefined<$ElementType>, + | {| +key: string |} | + {| +name: DestinationRouteName, +key?: string |}, | {| +key: string, - +params?: $ElementType, - |} - | {| + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, + |} | + {| +name: DestinationRouteName, +key?: string, - +params?: $ElementType, + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, |}, + >, ) => void; declare type NavigationHelpers< ParamList: ParamListBase, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, EventMap: EventMapBase = EventMapCore, > = { +navigate: Navigate, +dispatch: ( action: | GenericNavigationAction | (State => GenericNavigationAction), ) => void, +reset: PossiblyStaleNavigationState => void, +goBack: () => void, +isFocused: () => boolean, +canGoBack: () => boolean, +dangerouslyGetParent: >() => ?Parent, +dangerouslyGetState: () => NavigationState, +addListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => () => void, +removeListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => void, ... }; + declare type SetParamsInput< + ParamList: ParamListBase, + RouteName: $Keys = $Keys, + > = $If< + $IsUndefined<$ElementType>, + empty, + $Partial<$NonMaybeType<$ElementType>>, + >; + declare export type NavigationProp< ParamList: ParamListBase, RouteName: $Keys = $Keys, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = { ...$Exact>, +setOptions: (options: $Partial) => void, - +setParams: ( - params: $If< - $IsUndefined<$ElementType>, - empty, - $Partial<$NonMaybeType<$ElementType>>, - >, - ) => void, + +setParams: (params: SetParamsInput) => void, ... }; /** * CreateNavigator */ declare export type RouteProp< ParamList: ParamListBase, RouteName: $Keys, > = {| ...LeafRoute, +params: $ElementType, |}; declare export type ScreenListeners< State: NavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = $ObjMapi< {| [name: $Keys]: empty |}, >(K, empty) => EventListenerCallback, >; declare type BaseScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = {| +name: RouteName, +options?: | ScreenOptions | ({| route: RouteProp, navigation: NavProp, |}) => ScreenOptions, +listeners?: | ScreenListeners | ({| route: RouteProp, navigation: NavProp, |}) => ScreenListeners, +initialParams?: $Partial<$ElementType>, |}; declare export type ScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +component: React$ComponentType<{| route: RouteProp, navigation: NavProp, |}>, |} | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +children: ({| route: RouteProp, navigation: NavProp, |}) => React$Node, |}; declare export type ScreenComponent< GlobalParamList: ParamListBase, ParamList: ParamListBase, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = < RouteName: $Keys, NavProp: NavigationProp< GlobalParamList, RouteName, State, ScreenOptions, EventMap, >, >(props: ScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >) => React$Node; declare type ScreenOptionsProp = {| +screenOptions?: | ScreenOptions | ({| route: LeafRoute<>, navigation: NavProp |}) => ScreenOptions, |}; declare export type ExtraNavigatorPropsBase = { ...$Exact, +children?: React$Node, ... }; declare export type NavigatorPropsBase = { ...$Exact, ...ScreenOptionsProp, ... }; declare export type CreateNavigator< State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, ExtraNavigatorProps: ExtraNavigatorPropsBase, > = < GlobalParamList: ParamListBase, ParamList: ParamListBase, NavProp: NavigationHelpers< GlobalParamList, State, EventMap, >, >() => {| +Screen: ScreenComponent< GlobalParamList, ParamList, State, ScreenOptions, EventMap, >, +Navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, |}; declare export type CreateNavigatorFactory = < State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, NavProp: NavigationHelpers< ParamListBase, State, EventMap, >, ExtraNavigatorProps: ExtraNavigatorPropsBase, >( navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, ) => CreateNavigator; /** * useNavigationBuilder */ declare export type Descriptor< NavProp, ScreenOptions: {...} = {...}, > = {| +render: () => React$Node, +options: $ReadOnly, +navigation: NavProp, |}; declare export type UseNavigationBuilder = < State: NavigationState, Action: GenericNavigationAction, ScreenOptions: {...}, RouterOptions: DefaultRouterOptions, NavProp, >( routerFactory: RouterFactory, options: {| ...$Exact, ...ScreenOptionsProp, +children?: React$Node, |}, ) => {| +state: State, +descriptors: {| +[key: string]: Descriptor |}, +navigation: NavProp, |}; /** * EdgeInsets */ declare type EdgeInsets = {| +top: number, +right: number, +bottom: number, +left: number, |}; /** * TransitionPreset */ declare export type TransitionSpec = | {| animation: 'spring', config: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |} | {| animation: 'timing', config: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |}; declare export type StackCardInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +index: number, +closing: AnimatedInterpolation, +swiping: AnimatedInterpolation, +inverted: AnimatedInterpolation, +layouts: {| +screen: {| +width: number, +height: number |}, |}, +insets: EdgeInsets, |}; declare export type StackCardInterpolatedStyle = {| containerStyle?: AnimatedViewStyleProp, cardStyle?: AnimatedViewStyleProp, overlayStyle?: AnimatedViewStyleProp, shadowStyle?: AnimatedViewStyleProp, |}; declare export type StackCardStyleInterpolator = ( props: StackCardInterpolationProps, ) => StackCardInterpolatedStyle; declare export type StackHeaderInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +layouts: {| +header: {| +width: number, +height: number |}, +screen: {| +width: number, +height: number |}, +title?: {| +width: number, +height: number |}, +leftLabel?: {| +width: number, +height: number |}, |}, |}; declare export type StackHeaderInterpolatedStyle = {| leftLabelStyle?: AnimatedViewStyleProp, leftButtonStyle?: AnimatedViewStyleProp, rightButtonStyle?: AnimatedViewStyleProp, titleStyle?: AnimatedViewStyleProp, backgroundStyle?: AnimatedViewStyleProp, |}; declare export type StackHeaderStyleInterpolator = ( props: StackHeaderInterpolationProps, ) => StackHeaderInterpolatedStyle; declare type GestureDirection = | 'horizontal' | 'horizontal-inverted' | 'vertical' | 'vertical-inverted'; declare export type TransitionPreset = {| +gestureDirection: GestureDirection, +transitionSpec: {| +open: TransitionSpec, +close: TransitionSpec, |}, +cardStyleInterpolator: StackCardStyleInterpolator, +headerStyleInterpolator: StackHeaderStyleInterpolator, |}; /** * Stack options */ declare export type StackDescriptor = Descriptor< StackNavigationProp<>, StackOptions, >; declare type Scene = {| +route: T, +descriptor: StackDescriptor, +progress: {| +current: AnimatedInterpolation, +next?: AnimatedInterpolation, +previous?: AnimatedInterpolation, |}, |}; declare export type StackHeaderProps = {| +mode: 'float' | 'screen', +layout: {| +width: number, +height: number |}, +insets: EdgeInsets, +scene: Scene>, +previous?: Scene>, +navigation: StackNavigationProp, +styleInterpolator: StackHeaderStyleInterpolator, |}; declare export type StackHeaderLeftButtonProps = $Partial<{| +onPress: (() => void), +pressColorAndroid: string; +backImage: (props: {| tintColor: string |}) => React$Node, +tintColor: string, +label: string, +truncatedLabel: string, +labelVisible: boolean, +labelStyle: AnimatedTextStyleProp, +allowFontScaling: boolean, +onLabelLayout: LayoutEvent => void, +screenLayout: {| +width: number, +height: number |}, +titleLayout: {| +width: number, +height: number |}, +canGoBack: boolean, |}>; declare type StackHeaderTitleInputBase = { +onLayout: LayoutEvent => void, +children: string, +allowFontScaling: ?boolean, +tintColor: ?string, +style: ?AnimatedTextStyleProp, ... }; declare export type StackHeaderTitleInputProps = $Exact; declare export type StackOptions = $Partial<{| +title: string, +header: StackHeaderProps => React$Node, +headerShown: boolean, +cardShadowEnabled: boolean, +cardOverlayEnabled: boolean, +cardOverlay: {| style: ViewStyleProp |} => React$Node, +cardStyle: ViewStyleProp, +animationEnabled: boolean, +animationTypeForReplace: 'push' | 'pop', +gestureEnabled: boolean, +gestureResponseDistance: {| vertical?: number, horizontal?: number |}, +gestureVelocityImpact: number, +safeAreaInsets: $Partial, // Transition ...TransitionPreset, // Header +headerTitle: string | (StackHeaderTitleInputProps => React$Node), +headerTitleAlign: 'left' | 'center', +headerTitleStyle: AnimatedTextStyleProp, +headerTitleContainerStyle: ViewStyleProp, +headerTintColor: string, +headerTitleAllowFontScaling: boolean, +headerBackAllowFontScaling: boolean, +headerBackTitle: string | null, +headerBackTitleStyle: TextStyleProp, +headerBackTitleVisible: boolean, +headerTruncatedBackTitle: string, +headerLeft: StackHeaderLeftButtonProps => React$Node, +headerLeftContainerStyle: ViewStyleProp, +headerRight: {| tintColor?: string |} => React$Node, +headerRightContainerStyle: ViewStyleProp, +headerBackImage: $PropertyType, +headerPressColorAndroid: string, +headerBackground: ({| style: ViewStyleProp |}) => React$Node, +headerStyle: ViewStyleProp, +headerTransparent: boolean, +headerStatusBarHeight: number, |}>; /** * Stack navigation prop */ declare export type StackNavigationEventMap = {| ...EventMapCore, +transitionStart: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +transitionEnd: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +gestureStart: {| +data: void, +canPreventDefault: false |}, +gestureEnd: {| +data: void, +canPreventDefault: false |}, +gestureCancel: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactStackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = { ...$Exact>, +replace: SimpleNavigate, +push: SimpleNavigate, +pop: (count?: number) => void, +popToTop: () => void, ... }; declare export type StackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = $Exact>; /** * Miscellaneous stack exports */ declare type StackNavigationConfig = {| +mode?: 'card' | 'modal', +headerMode?: 'float' | 'screen' | 'none', +keyboardHandlingEnabled?: boolean, +detachInactiveScreens?: boolean, |}; declare export type ExtraStackNavigatorProps = {| ...$Exact, ...StackRouterOptions, ...StackNavigationConfig, |}; declare export type StackNavigatorProps< NavProp: InexactStackNavigationProp<> = StackNavigationProp<>, > = {| ...ExtraStackNavigatorProps, ...ScreenOptionsProp, |}; /** * Bottom tab options */ declare export type BottomTabBarButtonProps = {| ...$Diff< TouchableWithoutFeedbackProps, {| onPress?: ?(event: PressEvent) => mixed |}, >, +to?: string, +children: React$Node, +onPress?: (MouseEvent | PressEvent) => void, |}; declare export type TabBarVisibilityAnimationConfig = | {| +animation: 'spring', +config?: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |} | {| +animation: 'timing', +config?: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |}; declare export type BottomTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| focused: boolean, color: string |}) => React$Node, +tabBarIcon: ({| focused: boolean, color: string, size: number, |}) => React$Node, +tabBarBadge: number | string, +tabBarBadgeStyle: TextStyleProp, +tabBarAccessibilityLabel: string, +tabBarTestID: string, +tabBarVisible: boolean, +tabBarVisibilityAnimationConfig: $Partial<{| +show: TabBarVisibilityAnimationConfig, +hide: TabBarVisibilityAnimationConfig, |}>, +tabBarButton: BottomTabBarButtonProps => React$Node, +unmountOnBlur: boolean, |}>; /** * Bottom tab navigation prop */ declare export type BottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactTabNavigationProp< ParamList: ParamListBase, RouteName: $Keys, Options: {...}, EventMap: EventMapBase, > = { ...$Exact>, +jumpTo: SimpleNavigate, ... }; declare export type InexactBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type BottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous bottom tab exports */ declare export type BottomTabDescriptor = Descriptor< BottomTabNavigationProp<>, BottomTabOptions, >; declare export type BottomTabBarOptions = $Partial<{| +keyboardHidesTabBar: boolean, +activeTintColor: string, +inactiveTintColor: string, +activeBackgroundColor: string, +inactiveBackgroundColor: string, +allowFontScaling: boolean, +showLabel: boolean, +showIcon: boolean, +labelStyle: TextStyleProp, +iconStyle: TextStyleProp, +tabStyle: ViewStyleProp, +labelPosition: 'beside-icon' | 'below-icon', +adaptive: boolean, +safeAreaInsets: $Partial, +style: ViewStyleProp, |}>; declare type BottomTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: BottomTabNavigationProp<>, +descriptors: {| +[key: string]: BottomTabDescriptor |}, |}; declare export type BottomTabBarProps = {| ...BottomTabBarOptions, ...BottomTabNavigationBuilderResult, |} declare type BottomTabNavigationConfig = {| +lazy?: boolean, +tabBar?: BottomTabBarProps => React$Node, +tabBarOptions?: BottomTabBarOptions, +detachInactiveScreens?: boolean, |}; declare export type ExtraBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...BottomTabNavigationConfig, |}; declare export type BottomTabNavigatorProps< NavProp: InexactBottomTabNavigationProp<> = BottomTabNavigationProp<>, > = {| ...ExtraBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material bottom tab options */ declare export type MaterialBottomTabOptions = $Partial<{| +title: string, +tabBarColor: string, +tabBarLabel: string, +tabBarIcon: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarBadge: boolean | number | string, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material bottom tab navigation prop */ declare export type MaterialBottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, |}; declare export type InexactMaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material bottom tab exports */ declare export type PaperFont = {| +fontFamily: string, +fontWeight?: | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', |}; declare export type PaperFonts = {| +regular: PaperFont, +medium: PaperFont, +light: PaperFont, +thin: PaperFont, |}; declare export type PaperTheme = {| +dark: boolean, +mode?: 'adaptive' | 'exact', +roundness: number, +colors: {| +primary: string, +background: string, +surface: string, +accent: string, +error: string, +text: string, +onSurface: string, +onBackground: string, +disabled: string, +placeholder: string, +backdrop: string, +notification: string, |}, +fonts: PaperFonts, +animation: {| +scale: number, |}, |}; declare export type PaperRoute = {| +key: string, +title?: string, +icon?: any, +badge?: string | number | boolean, +color?: string, +accessibilityLabel?: string, +testID?: string, |}; declare export type PaperTouchableProps = {| ...TouchableWithoutFeedbackProps, +key: string, +route: PaperRoute, +children: React$Node, +borderless?: boolean, +centered?: boolean, +rippleColor?: string, |}; declare export type MaterialBottomTabNavigationConfig = {| +shifting?: boolean, +labeled?: boolean, +renderTouchable?: PaperTouchableProps => React$Node, +activeColor?: string, +inactiveColor?: string, +sceneAnimationEnabled?: boolean, +keyboardHidesNavigationBar?: boolean, +barStyle?: ViewStyleProp, +style?: ViewStyleProp, +theme?: PaperTheme, |}; declare export type ExtraMaterialBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialBottomTabNavigationConfig, |}; declare export type MaterialBottomTabNavigatorProps< NavProp: InexactMaterialBottomTabNavigationProp<> = MaterialBottomTabNavigationProp<>, > = {| ...ExtraMaterialBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material top tab options */ declare export type MaterialTopTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarIcon: ({| +focused: boolean, +color: string |}) => React$Node, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material top tab navigation prop */ declare export type MaterialTopTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, +swipeStart: {| +data: void, +canPreventDefault: false |}, +swipeEnd: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactMaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material top tab exports */ declare type MaterialTopTabPagerCommonProps = {| +keyboardDismissMode: 'none' | 'on-drag' | 'auto', +swipeEnabled: boolean, +swipeVelocityImpact?: number, +springVelocityScale?: number, +springConfig: $Partial<{| +damping: number, +mass: number, +stiffness: number, +restSpeedThreshold: number, +restDisplacementThreshold: number, |}>, +timingConfig: $Partial<{| +duration: number, |}>, |}; declare export type MaterialTopTabPagerProps = {| ...MaterialTopTabPagerCommonProps, +onSwipeStart?: () => void, +onSwipeEnd?: () => void, +onIndexChange: (index: number) => void, +navigationState: TabNavigationState, +layout: {| +width: number, +height: number |}, +removeClippedSubviews: boolean, +children: ({| +addListener: (type: 'enter', listener: number => void) => void, +removeListener: (type: 'enter', listener: number => void) => void, +position: any, // Reanimated.Node +render: React$Node => React$Node, +jumpTo: string => void, |}) => React$Node, +gestureHandlerProps: PanGestureHandlerProps, |}; declare export type MaterialTopTabBarIndicatorProps = {| +navigationState: TabNavigationState, +width: string, +style?: ViewStyleProp, +getTabWidth: number => number, |}; declare export type MaterialTopTabBarOptions = $Partial<{| +scrollEnabled: boolean, +bounces: boolean, +pressColor: string, +pressOpacity: number, +getAccessible: ({| +route: Route<> |}) => boolean, +renderBadge: ({| +route: Route<> |}) => React$Node, +renderIndicator: MaterialTopTabBarIndicatorProps => React$Node, +tabStyle: ViewStyleProp, +indicatorStyle: ViewStyleProp, +indicatorContainerStyle: ViewStyleProp, +labelStyle: TextStyleProp, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, +activeTintColor: string, +inactiveTintColor: string, +iconStyle: ViewStyleProp, +labelStyle: TextStyleProp, +showLabel: boolean, +showIcon: boolean, +allowFontScaling: boolean, |}>; declare export type MaterialTopTabDescriptor = Descriptor< MaterialBottomTabNavigationProp<>, MaterialBottomTabOptions, >; declare type MaterialTopTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: MaterialTopTabNavigationProp<>, +descriptors: {| +[key: string]: MaterialTopTabDescriptor |}, |}; declare export type MaterialTopTabBarProps = {| ...MaterialTopTabBarOptions, ...MaterialTopTabNavigationBuilderResult, +layout: {| +width: number, +height: number |}, +position: any, // Reanimated.Node +jumpTo: string => void, |}; declare export type MaterialTopTabNavigationConfig = {| ...$Partial, +position?: any, // Reanimated.Value +tabBarPosition?: 'top' | 'bottom', +initialLayout?: $Partial<{| +width: number, +height: number |}>, +lazy?: boolean, +lazyPreloadDistance?: number, +removeClippedSubviews?: boolean, +sceneContainerStyle?: ViewStyleProp, +style?: ViewStyleProp, +gestureHandlerProps?: PanGestureHandlerProps, +pager?: MaterialTopTabPagerProps => React$Node, +lazyPlaceholder?: ({| +route: Route<> |}) => React$Node, +tabBar?: MaterialTopTabBarProps => React$Node, +tabBarOptions?: MaterialTopTabBarOptions, |}; declare export type ExtraMaterialTopTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialTopTabNavigationConfig, |}; declare export type MaterialTopTabNavigatorProps< NavProp: InexactMaterialTopTabNavigationProp<> = MaterialTopTabNavigationProp<>, > = {| ...ExtraMaterialTopTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Drawer options */ declare export type DrawerOptions = $Partial<{| title: string, drawerLabel: | string | ({| +color: string, +focused: boolean |}) => React$Node, drawerIcon: ({| +color: string, +size: number, +focused: boolean, |}) => React$Node, gestureEnabled: boolean, swipeEnabled: boolean, unmountOnBlur: boolean, |}>; /** * Drawer navigation prop */ declare export type DrawerNavigationEventMap = {| ...EventMapCore, +drawerOpen: {| +data: void, +canPreventDefault: false |}, +drawerClose: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactDrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = { ...$Exact>, +jumpTo: SimpleNavigate, +openDrawer: () => void, +closeDrawer: () => void, +toggleDrawer: () => void, ... }; declare export type DrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = $Exact>; /** * Miscellaneous drawer exports */ declare export type DrawerDescriptor = Descriptor< DrawerNavigationProp<>, DrawerOptions, >; declare export type DrawerItemListBaseOptions = $Partial<{| +activeTintColor: string, +activeBackgroundColor: string, +inactiveTintColor: string, +inactiveBackgroundColor: string, +itemStyle: ViewStyleProp, +labelStyle: TextStyleProp, |}>; declare export type DrawerContentOptions = $Partial<{| ...DrawerItemListBaseOptions, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, |}>; declare type DrawerNavigationBuilderResult = {| +state: DrawerNavigationState, +navigation: DrawerNavigationProp<>, +descriptors: {| +[key: string]: DrawerDescriptor |}, |}; declare export type DrawerContentProps = {| ...DrawerContentOptions, ...DrawerNavigationBuilderResult, +progress: any, // Reanimated.Node |}; declare export type DrawerNavigationConfig = {| +drawerPosition?: 'left' | 'right', +drawerType?: 'front' | 'back' | 'slide' | 'permanent', +edgeWidth?: number, +hideStatusBar?: boolean, +keyboardDismissMode?: 'on-drag' | 'none', +minSwipeDistance?: number, +overlayColor?: string, +statusBarAnimation?: 'slide' | 'none' | 'fade', +gestureHandlerProps?: PanGestureHandlerProps, +lazy?: boolean, +drawerContent?: DrawerContentProps => React$Node, +drawerContentOptions?: DrawerContentOptions, +sceneContainerStyle?: ViewStyleProp, +drawerStyle?: ViewStyleProp, +detachInactiveScreens?: boolean, |}; declare export type ExtraDrawerNavigatorProps = {| ...$Exact, ...DrawerRouterOptions, ...DrawerNavigationConfig, |}; declare export type DrawerNavigatorProps< NavProp: InexactDrawerNavigationProp<> = DrawerNavigationProp<>, > = {| ...ExtraDrawerNavigatorProps, ...ScreenOptionsProp, |}; /** * BaseNavigationContainer */ declare export type BaseNavigationContainerProps = {| +children: React$Node, +initialState?: PossiblyStaleNavigationState, +onStateChange?: (state: ?PossiblyStaleNavigationState) => void, +independent?: boolean, |}; declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| +data: {| +options: { +[key: string]: mixed, ... } |}, +canPreventDefault: false, |}, +__unsafe_action__: {| +data: {| +action: GenericNavigationAction, +noop: boolean, |}, +canPreventDefault: false, |}, |}; declare export type BaseNavigationContainerInterface = {| ...$Exact>, +setParams: (params: ScreenParams) => void, +resetRoot: (state?: ?PossiblyStaleNavigationState) => void, +getRootState: () => PossiblyStaleNavigationState, |}; /** * State utils */ declare export type GetStateFromPath = ( path: string, options?: LinkingConfig, ) => PossiblyStaleNavigationState; declare export type GetPathFromState = ( state?: ?PossiblyStaleNavigationState, options?: LinkingConfig, ) => string; declare export type GetFocusedRouteNameFromRoute = PossiblyStaleRoute => ?string; /** * Linking */ declare export type ScreenLinkingConfig = {| +path?: string, +exact?: boolean, +parse?: {| +[param: string]: string => mixed |}, +stringify?: {| +[param: string]: mixed => string |}, +screens?: ScreenLinkingConfigMap, +initialRouteName?: string, |}; declare export type ScreenLinkingConfigMap = {| +[routeName: string]: string | ScreenLinkingConfig, |}; declare export type LinkingConfig = {| +initialRouteName?: string, +screens: ScreenLinkingConfigMap, |}; declare export type LinkingOptions = {| +enabled?: boolean, +prefixes: $ReadOnlyArray, +config?: LinkingConfig, +getStateFromPath?: GetStateFromPath, +getPathFromState?: GetPathFromState, |}; /** * NavigationContainer */ declare export type Theme = {| +dark: boolean, +colors: {| +primary: string, +background: string, +card: string, +text: string, +border: string, |}, |}; declare export type NavigationContainerType = React$AbstractComponent< {| ...BaseNavigationContainerProps, +theme?: Theme, +linking?: LinkingOptions, +fallback?: React$Node, +onReady?: () => mixed, |}, BaseNavigationContainerInterface, >; //--------------------------------------------------------------------------- // SECTION 2: EXPORTED MODULE // This section defines the module exports and contains exported types that // are not present in any other React Navigation libdef. //--------------------------------------------------------------------------- declare export function useReduxDevToolsExtension( container: { +current: ?React$ElementRef, ... }, ): void; } diff --git a/native/flow-typed/npm/@react-navigation/material-top-tabs_v5.x.x.js b/native/flow-typed/npm/@react-navigation/material-top-tabs_v5.x.x.js index df91da4b8..f38dd1cbc 100644 --- a/native/flow-typed/npm/@react-navigation/material-top-tabs_v5.x.x.js +++ b/native/flow-typed/npm/@react-navigation/material-top-tabs_v5.x.x.js @@ -1,2107 +1,2136 @@ // flow-typed signature: 2ccdb5706282eb16a225b90e11079dc1 // flow-typed version: dc2d6a22c7/@react-navigation/material-top-tabs_v5.x.x/flow_>=v0.104.x declare module '@react-navigation/material-top-tabs' { //--------------------------------------------------------------------------- // SECTION 1: IDENTICAL TYPE DEFINITIONS // This section is identical across all React Navigation libdefs and contains // shared definitions. We wish we could make it DRY and import from a shared // definition, but that isn't yet possible. //--------------------------------------------------------------------------- /** * We start with some definitions that we have copy-pasted from React Native * source files. */ // This is a bastardization of the true StyleObj type located in // react-native/Libraries/StyleSheet/StyleSheetTypes. We unfortunately can't // import that here, and it's too lengthy (and consequently too brittle) to // copy-paste here either. declare type StyleObj = | null | void | number | false | '' | $ReadOnlyArray | { [name: string]: any, ... }; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; declare type AnimatedTextStyleProp = StyleObj; // Vaguely copied from // react-native/Libraries/Animated/src/animations/Animation.js declare type EndResult = { finished: boolean, ... }; declare type EndCallback = (result: EndResult) => void; declare interface Animation { start( fromValue: number, onUpdate: (value: number) => void, onEnd: ?EndCallback, previousAnimation: ?Animation, animatedValue: AnimatedValue, ): void; stop(): void; } declare type AnimationConfig = { isInteraction?: boolean, useNativeDriver: boolean, onComplete?: ?EndCallback, iterations?: number, ... }; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedTracking.js declare interface AnimatedTracking { constructor( value: AnimatedValue, parent: any, animationClass: any, animationConfig: Object, callback?: ?EndCallback, ): void; update(): void; } // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedValue.js declare type ValueListenerCallback = (state: { value: number, ... }) => void; declare interface AnimatedValue { constructor(value: number): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; extractOffset(): void; addListener(callback: ValueListenerCallback): string; removeListener(id: string): void; removeAllListeners(): void; stopAnimation(callback?: ?(value: number) => void): void; resetAnimation(callback?: ?(value: number) => void): void; interpolate(config: InterpolationConfigType): AnimatedInterpolation; animate(animation: Animation, callback: ?EndCallback): void; stopTracking(): void; track(tracking: AnimatedTracking): void; } // Copied from // react-native/Libraries/Animated/src/animations/TimingAnimation.js declare type TimingAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, easing?: (value: number) => number, duration?: number, delay?: number, ... }; // Copied from // react-native/Libraries/Animated/src/animations/SpringAnimation.js declare type SpringAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, overshootClamping?: boolean, restDisplacementThreshold?: number, restSpeedThreshold?: number, velocity?: number, bounciness?: number, speed?: number, tension?: number, friction?: number, stiffness?: number, damping?: number, mass?: number, delay?: number, ... }; // Copied from react-native/Libraries/Types/CoreEventTypes.js declare type SyntheticEvent = $ReadOnly<{| bubbles: ?boolean, cancelable: ?boolean, currentTarget: number, defaultPrevented: ?boolean, dispatchConfig: $ReadOnly<{| registrationName: string, |}>, eventPhase: ?number, preventDefault: () => void, isDefaultPrevented: () => boolean, stopPropagation: () => void, isPropagationStopped: () => boolean, isTrusted: ?boolean, nativeEvent: T, persist: () => void, target: ?number, timeStamp: number, type: ?string, |}>; declare type Layout = $ReadOnly<{| x: number, y: number, width: number, height: number, |}>; declare type LayoutEvent = SyntheticEvent< $ReadOnly<{| layout: Layout, |}>, >; declare type BlurEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type FocusEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type ResponderSyntheticEvent = $ReadOnly<{| ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray< $ReadOnly<{| touchActive: boolean, startPageX: number, startPageY: number, startTimeStamp: number, currentPageX: number, currentPageY: number, currentTimeStamp: number, previousPageX: number, previousPageY: number, previousTimeStamp: number, |}>, >, |}>, |}>; declare type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, identifier: number, locationX: number, locationY: number, pageX: number, pageY: number, target: ?number, timestamp: number, touches: $ReadOnlyArray<$PropertyType>, |}>, >; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js declare type ExtrapolateType = 'extend' | 'identity' | 'clamp'; declare type InterpolationConfigType = { inputRange: Array, outputRange: Array | Array, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, ... }; declare interface AnimatedInterpolation { interpolate(config: InterpolationConfigType): AnimatedInterpolation; } // Copied from react-native/Libraries/Components/View/ViewAccessibility.js declare type AccessibilityRole = | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'imagebutton' | 'header' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menu' | 'menubar' | 'menuitem' | 'progressbar' | 'radio' | 'radiogroup' | 'scrollbar' | 'spinbutton' | 'switch' | 'tab' | 'tablist' | 'timer' | 'toolbar'; declare type AccessibilityActionInfo = $ReadOnly<{ name: string, label?: string, ... }>; declare type AccessibilityActionEvent = SyntheticEvent< $ReadOnly<{actionName: string, ...}>, >; declare type AccessibilityState = { disabled?: boolean, selected?: boolean, checked?: ?boolean | 'mixed', busy?: boolean, expanded?: boolean, ... }; declare type AccessibilityValue = $ReadOnly<{| min?: number, max?: number, now?: number, text?: string, |}>; // Copied from // react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js declare type Stringish = string; declare type EdgeInsetsProp = $ReadOnly<$Partial>; declare type TouchableWithoutFeedbackProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, accessibilityElementsHidden?: ?boolean, accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityLabel?: ?Stringish, accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, children?: ?React$Node, delayLongPress?: ?number, delayPressIn?: ?number, delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, hitSlop?: ?EdgeInsetsProp, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(event: BlurEvent) => mixed, onFocus?: ?(event: FocusEvent) => mixed, onLayout?: ?(event: LayoutEvent) => mixed, onLongPress?: ?(event: PressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, pressRetentionOffset?: ?EdgeInsetsProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, |}>; // Copied from react-native/Libraries/Image/ImageSource.js declare type ImageURISource = $ReadOnly<{ uri?: ?string, bundle?: ?string, method?: ?string, headers?: ?Object, body?: ?string, cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), width?: ?number, height?: ?number, scale?: ?number, ... }>; /** * The following is copied from react-native-gesture-handler's libdef */ declare type StateUndetermined = 0; declare type StateFailed = 1; declare type StateBegan = 2; declare type StateCancelled = 3; declare type StateActive = 4; declare type StateEnd = 5; declare type GestureHandlerState = | StateUndetermined | StateFailed | StateBegan | StateCancelled | StateActive | StateEnd; declare type $SyntheticEvent = { +nativeEvent: $ReadOnly<$Exact>, ... }; declare type $Event = $SyntheticEvent<{ handlerTag: number, numberOfPointers: number, state: GestureHandlerState, oldState: GestureHandlerState, ...$Exact, ... }>; declare type $EventHandlers = {| onGestureEvent?: ($Event) => mixed, onHandlerStateChange?: ($Event) => mixed, onBegan?: ($Event) => mixed, onFailed?: ($Event) => mixed, onCancelled?: ($Event) => mixed, onActivated?: ($Event) => mixed, onEnded?: ($Event) => mixed, |}; declare type HitSlop = | number | {| left?: number, top?: number, right?: number, bottom?: number, vertical?: number, horizontal?: number, width?: number, height?: number, |} | {| width: number, left: number, |} | {| width: number, right: number, |} | {| height: number, top: number, |} | {| height: number, bottom: number, |}; declare type $GestureHandlerProps< AdditionalProps: {...}, ExtraEventsProps: {...} > = $ReadOnly<{| ...$Exact, ...$EventHandlers, id?: string, enabled?: boolean, waitFor?: React$Ref | Array>, simultaneousHandlers?: React$Ref | Array>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, children?: React$Node, |}>; declare type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], activeOffsetX?: number | [number, number], failOffsetY?: number | [number, number], failOffsetX?: number | [number, number], minDist?: number, minVelocity?: number, minVelocityX?: number, minVelocityY?: number, minPointers?: number, maxPointers?: number, avgTouches?: boolean, ... }, { x: number, y: number, absoluteX: number, absoluteY: number, translationX: number, translationY: number, velocityX: number, velocityY: number, ... } >; /** * MAGIC */ declare type $If = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), Test, Then, Else, >; declare type $IsA = $Call< (Y => true) & (mixed => false), X, >; declare type $IsUndefined = $IsA; declare type $Partial = $ReadOnly<$Rest>; + // If { ...T, ... } counts as a T, then we're inexact + declare type $IsExact = $Call< + (T => false) & (mixed => true), + { ...T, ... }, + >; + /** * Actions, state, etc. */ declare export type ScreenParams = { +[key: string]: mixed, ... }; declare export type BackAction = {| +type: 'GO_BACK', +source?: string, +target?: string, |}; declare export type NavigateAction = {| +type: 'NAVIGATE', +payload: | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type ResetAction = {| +type: 'RESET', +payload: StaleNavigationState, +source?: string, +target?: string, |}; declare export type SetParamsAction = {| +type: 'SET_PARAMS', +payload: {| +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type CommonAction = | BackAction | NavigateAction | ResetAction | SetParamsAction; declare type NavigateActionCreator = {| (routeName: string, params?: ScreenParams): NavigateAction, ( | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, ): NavigateAction, |}; declare export type CommonActionsType = {| +navigate: NavigateActionCreator, +goBack: () => BackAction, +reset: (state: PossiblyStaleNavigationState) => ResetAction, +setParams: (params: ScreenParams) => SetParamsAction, |}; declare export type GenericNavigationAction = {| +type: string, +payload?: { +[key: string]: mixed, ... }, +source?: string, +target?: string, |}; declare export type LeafRoute = {| +key: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StateRoute = {| ...LeafRoute, +state: NavigationState | StaleNavigationState, |}; declare export type Route = | LeafRoute | StateRoute; declare export type NavigationState = {| +key: string, +index: number, +routeNames: $ReadOnlyArray, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type: string, +stale: false, |}; declare export type StaleLeafRoute = {| +key?: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StaleStateRoute = {| ...StaleLeafRoute, +state: StaleNavigationState, |}; declare export type StaleRoute = | StaleLeafRoute | StaleStateRoute; declare export type StaleNavigationState = {| // It's possible to pass React Nav a StaleNavigationState with an undefined // index, but React Nav will always return one with the index set. This is // the same as for the type property below, but in the case of index we tend // to rely on it being set more... +index: number, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type?: string, +stale?: true, |}; declare export type PossiblyStaleNavigationState = | NavigationState | StaleNavigationState; declare export type PossiblyStaleRoute = | Route | StaleRoute; /** * Routers */ declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, > = { +[key: string]: (...args: any) => (Action | State => Action), ... }; declare export type DefaultRouterOptions = { +initialRouteName?: string, ... }; declare export type RouterFactory< State: NavigationState, Action: GenericNavigationAction, RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, +routeParamList: ParamListBase, |}; declare export type Router< State: NavigationState, Action: GenericNavigationAction, > = {| +type: $PropertyType, +getInitialState: (options: RouterConfigOptions) => State, +getRehydratedState: ( partialState: PossiblyStaleNavigationState, options: RouterConfigOptions, ) => State, +getStateForRouteNamesChange: ( state: State, options: RouterConfigOptions, ) => State, +getStateForRouteFocus: (state: State, key: string) => State, +getStateForAction: ( state: State, action: Action, options: RouterConfigOptions, ) => ?PossiblyStaleNavigationState; +shouldActionChangeFocus: (action: GenericNavigationAction) => boolean, +actionCreators?: ActionCreators, |}; /** * Stack actions and router */ declare export type StackNavigationState = {| ...NavigationState, +type: 'stack', |}; declare export type ReplaceAction = {| +type: 'REPLACE', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PushAction = {| +type: 'PUSH', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PopAction = {| +type: 'POP', +payload: {| +count: number |}, +source?: string, +target?: string, |}; declare export type PopToTopAction = {| +type: 'POP_TO_TOP', +source?: string, +target?: string, |}; declare export type StackAction = | CommonAction | ReplaceAction | PushAction | PopAction | PopToTopAction; declare export type StackActionsType = {| +replace: (routeName: string, params?: ScreenParams) => ReplaceAction, +push: (routeName: string, params?: ScreenParams) => PushAction, +pop: (count?: number) => PopAction, +popToTop: () => PopToTopAction, |}; declare export type StackRouterOptions = $Exact; /** * Tab actions and router */ declare export type TabNavigationState = {| ...NavigationState, +type: 'tab', +history: $ReadOnlyArray<{| type: 'route', key: string |}>, |}; declare export type JumpToAction = {| +type: 'JUMP_TO', +payload: {| +name: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type TabAction = | CommonAction | JumpToAction; declare export type TabActionsType = {| +jumpTo: string => JumpToAction, |}; declare export type TabRouterOptions = {| ...$Exact, +backBehavior?: 'initialRoute' | 'order' | 'history' | 'none', |}; /** * Drawer actions and router */ declare type DrawerHistoryEntry = | {| +type: 'route', +key: string |} | {| +type: 'drawer' |}; declare export type DrawerNavigationState = {| ...NavigationState, +type: 'drawer', +history: $ReadOnlyArray, |}; declare export type OpenDrawerAction = {| +type: 'OPEN_DRAWER', +source?: string, +target?: string, |}; declare export type CloseDrawerAction = {| +type: 'CLOSE_DRAWER', +source?: string, +target?: string, |}; declare export type ToggleDrawerAction = {| +type: 'TOGGLE_DRAWER', +source?: string, +target?: string, |}; declare export type DrawerAction = | TabAction | OpenDrawerAction | CloseDrawerAction | ToggleDrawerAction; declare export type DrawerActionsType = {| ...TabActionsType, +openDrawer: () => OpenDrawerAction, +closeDrawer: () => CloseDrawerAction, +toggleDrawer: () => ToggleDrawerAction, |}; declare export type DrawerRouterOptions = {| ...TabRouterOptions, +openByDefault?: boolean, |}; /** * Events */ declare export type EventMapBase = { +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, ... }; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, {| |}, >; declare type EventDataProperties = $If< $IsUndefined, {| |}, {| +data: Data |}, >; declare type EventArg< EventName: string, CanPreventDefault: ?boolean = false, Data = void, > = {| ...EventPreventDefaultProperties, ...EventDataProperties, +type: EventName, +target?: string, |}; declare type GlobalEventMap = {| +state: {| +data: {| +state: State |}, +canPreventDefault: false |}, |}; declare type EventMapCore = {| ...GlobalEventMap, +focus: {| +data: void, +canPreventDefault: false |}, +blur: {| +data: void, +canPreventDefault: false |}, +beforeRemove: {| +data: {| +action: GenericNavigationAction |}, +canPreventDefault: true, |}, |}; declare type EventListenerCallback< EventName: string, State: PossiblyStaleNavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = (e: EventArg< EventName, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'canPreventDefault', >, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'data', >, >) => mixed; /** * Navigation prop */ + declare type PartialWithMergeProperty = $If< + $IsExact, + { ...$Partial, +merge: true }, + { ...$Partial, +merge: true, ... }, + >; + + declare type EitherExactOrPartialWithMergeProperty = + | ParamsType + | PartialWithMergeProperty; + declare export type SimpleNavigate = >( routeName: DestinationRouteName, - params: $ElementType, + params: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, ) => void; declare export type Navigate = & SimpleNavigate & >( - route: + route: $If< + $IsUndefined<$ElementType>, + | {| +key: string |} | + {| +name: DestinationRouteName, +key?: string |}, | {| +key: string, - +params?: $ElementType, - |} - | {| + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, + |} | + {| +name: DestinationRouteName, +key?: string, - +params?: $ElementType, + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, |}, + >, ) => void; declare type NavigationHelpers< ParamList: ParamListBase, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, EventMap: EventMapBase = EventMapCore, > = { +navigate: Navigate, +dispatch: ( action: | GenericNavigationAction | (State => GenericNavigationAction), ) => void, +reset: PossiblyStaleNavigationState => void, +goBack: () => void, +isFocused: () => boolean, +canGoBack: () => boolean, +dangerouslyGetParent: >() => ?Parent, +dangerouslyGetState: () => NavigationState, +addListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => () => void, +removeListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => void, ... }; + declare type SetParamsInput< + ParamList: ParamListBase, + RouteName: $Keys = $Keys, + > = $If< + $IsUndefined<$ElementType>, + empty, + $Partial<$NonMaybeType<$ElementType>>, + >; + declare export type NavigationProp< ParamList: ParamListBase, RouteName: $Keys = $Keys, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = { ...$Exact>, +setOptions: (options: $Partial) => void, - +setParams: ( - params: $If< - $IsUndefined<$ElementType>, - empty, - $Partial<$NonMaybeType<$ElementType>>, - >, - ) => void, + +setParams: (params: SetParamsInput) => void, ... }; /** * CreateNavigator */ declare export type RouteProp< ParamList: ParamListBase, RouteName: $Keys, > = {| ...LeafRoute, +params: $ElementType, |}; declare export type ScreenListeners< State: NavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = $ObjMapi< {| [name: $Keys]: empty |}, >(K, empty) => EventListenerCallback, >; declare type BaseScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = {| +name: RouteName, +options?: | ScreenOptions | ({| route: RouteProp, navigation: NavProp, |}) => ScreenOptions, +listeners?: | ScreenListeners | ({| route: RouteProp, navigation: NavProp, |}) => ScreenListeners, +initialParams?: $Partial<$ElementType>, |}; declare export type ScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +component: React$ComponentType<{| route: RouteProp, navigation: NavProp, |}>, |} | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +children: ({| route: RouteProp, navigation: NavProp, |}) => React$Node, |}; declare export type ScreenComponent< GlobalParamList: ParamListBase, ParamList: ParamListBase, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = < RouteName: $Keys, NavProp: NavigationProp< GlobalParamList, RouteName, State, ScreenOptions, EventMap, >, >(props: ScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >) => React$Node; declare type ScreenOptionsProp = {| +screenOptions?: | ScreenOptions | ({| route: LeafRoute<>, navigation: NavProp |}) => ScreenOptions, |}; declare export type ExtraNavigatorPropsBase = { ...$Exact, +children?: React$Node, ... }; declare export type NavigatorPropsBase = { ...$Exact, ...ScreenOptionsProp, ... }; declare export type CreateNavigator< State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, ExtraNavigatorProps: ExtraNavigatorPropsBase, > = < GlobalParamList: ParamListBase, ParamList: ParamListBase, NavProp: NavigationHelpers< GlobalParamList, State, EventMap, >, >() => {| +Screen: ScreenComponent< GlobalParamList, ParamList, State, ScreenOptions, EventMap, >, +Navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, |}; declare export type CreateNavigatorFactory = < State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, NavProp: NavigationHelpers< ParamListBase, State, EventMap, >, ExtraNavigatorProps: ExtraNavigatorPropsBase, >( navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, ) => CreateNavigator; /** * useNavigationBuilder */ declare export type Descriptor< NavProp, ScreenOptions: {...} = {...}, > = {| +render: () => React$Node, +options: $ReadOnly, +navigation: NavProp, |}; declare export type UseNavigationBuilder = < State: NavigationState, Action: GenericNavigationAction, ScreenOptions: {...}, RouterOptions: DefaultRouterOptions, NavProp, >( routerFactory: RouterFactory, options: {| ...$Exact, ...ScreenOptionsProp, +children?: React$Node, |}, ) => {| +state: State, +descriptors: {| +[key: string]: Descriptor |}, +navigation: NavProp, |}; /** * EdgeInsets */ declare type EdgeInsets = {| +top: number, +right: number, +bottom: number, +left: number, |}; /** * TransitionPreset */ declare export type TransitionSpec = | {| animation: 'spring', config: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |} | {| animation: 'timing', config: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |}; declare export type StackCardInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +index: number, +closing: AnimatedInterpolation, +swiping: AnimatedInterpolation, +inverted: AnimatedInterpolation, +layouts: {| +screen: {| +width: number, +height: number |}, |}, +insets: EdgeInsets, |}; declare export type StackCardInterpolatedStyle = {| containerStyle?: AnimatedViewStyleProp, cardStyle?: AnimatedViewStyleProp, overlayStyle?: AnimatedViewStyleProp, shadowStyle?: AnimatedViewStyleProp, |}; declare export type StackCardStyleInterpolator = ( props: StackCardInterpolationProps, ) => StackCardInterpolatedStyle; declare export type StackHeaderInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +layouts: {| +header: {| +width: number, +height: number |}, +screen: {| +width: number, +height: number |}, +title?: {| +width: number, +height: number |}, +leftLabel?: {| +width: number, +height: number |}, |}, |}; declare export type StackHeaderInterpolatedStyle = {| leftLabelStyle?: AnimatedViewStyleProp, leftButtonStyle?: AnimatedViewStyleProp, rightButtonStyle?: AnimatedViewStyleProp, titleStyle?: AnimatedViewStyleProp, backgroundStyle?: AnimatedViewStyleProp, |}; declare export type StackHeaderStyleInterpolator = ( props: StackHeaderInterpolationProps, ) => StackHeaderInterpolatedStyle; declare type GestureDirection = | 'horizontal' | 'horizontal-inverted' | 'vertical' | 'vertical-inverted'; declare export type TransitionPreset = {| +gestureDirection: GestureDirection, +transitionSpec: {| +open: TransitionSpec, +close: TransitionSpec, |}, +cardStyleInterpolator: StackCardStyleInterpolator, +headerStyleInterpolator: StackHeaderStyleInterpolator, |}; /** * Stack options */ declare export type StackDescriptor = Descriptor< StackNavigationProp<>, StackOptions, >; declare type Scene = {| +route: T, +descriptor: StackDescriptor, +progress: {| +current: AnimatedInterpolation, +next?: AnimatedInterpolation, +previous?: AnimatedInterpolation, |}, |}; declare export type StackHeaderProps = {| +mode: 'float' | 'screen', +layout: {| +width: number, +height: number |}, +insets: EdgeInsets, +scene: Scene>, +previous?: Scene>, +navigation: StackNavigationProp, +styleInterpolator: StackHeaderStyleInterpolator, |}; declare export type StackHeaderLeftButtonProps = $Partial<{| +onPress: (() => void), +pressColorAndroid: string; +backImage: (props: {| tintColor: string |}) => React$Node, +tintColor: string, +label: string, +truncatedLabel: string, +labelVisible: boolean, +labelStyle: AnimatedTextStyleProp, +allowFontScaling: boolean, +onLabelLayout: LayoutEvent => void, +screenLayout: {| +width: number, +height: number |}, +titleLayout: {| +width: number, +height: number |}, +canGoBack: boolean, |}>; declare type StackHeaderTitleInputBase = { +onLayout: LayoutEvent => void, +children: string, +allowFontScaling: ?boolean, +tintColor: ?string, +style: ?AnimatedTextStyleProp, ... }; declare export type StackHeaderTitleInputProps = $Exact; declare export type StackOptions = $Partial<{| +title: string, +header: StackHeaderProps => React$Node, +headerShown: boolean, +cardShadowEnabled: boolean, +cardOverlayEnabled: boolean, +cardOverlay: {| style: ViewStyleProp |} => React$Node, +cardStyle: ViewStyleProp, +animationEnabled: boolean, +animationTypeForReplace: 'push' | 'pop', +gestureEnabled: boolean, +gestureResponseDistance: {| vertical?: number, horizontal?: number |}, +gestureVelocityImpact: number, +safeAreaInsets: $Partial, // Transition ...TransitionPreset, // Header +headerTitle: string | (StackHeaderTitleInputProps => React$Node), +headerTitleAlign: 'left' | 'center', +headerTitleStyle: AnimatedTextStyleProp, +headerTitleContainerStyle: ViewStyleProp, +headerTintColor: string, +headerTitleAllowFontScaling: boolean, +headerBackAllowFontScaling: boolean, +headerBackTitle: string | null, +headerBackTitleStyle: TextStyleProp, +headerBackTitleVisible: boolean, +headerTruncatedBackTitle: string, +headerLeft: StackHeaderLeftButtonProps => React$Node, +headerLeftContainerStyle: ViewStyleProp, +headerRight: {| tintColor?: string |} => React$Node, +headerRightContainerStyle: ViewStyleProp, +headerBackImage: $PropertyType, +headerPressColorAndroid: string, +headerBackground: ({| style: ViewStyleProp |}) => React$Node, +headerStyle: ViewStyleProp, +headerTransparent: boolean, +headerStatusBarHeight: number, |}>; /** * Stack navigation prop */ declare export type StackNavigationEventMap = {| ...EventMapCore, +transitionStart: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +transitionEnd: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +gestureStart: {| +data: void, +canPreventDefault: false |}, +gestureEnd: {| +data: void, +canPreventDefault: false |}, +gestureCancel: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactStackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = { ...$Exact>, +replace: SimpleNavigate, +push: SimpleNavigate, +pop: (count?: number) => void, +popToTop: () => void, ... }; declare export type StackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = $Exact>; /** * Miscellaneous stack exports */ declare type StackNavigationConfig = {| +mode?: 'card' | 'modal', +headerMode?: 'float' | 'screen' | 'none', +keyboardHandlingEnabled?: boolean, +detachInactiveScreens?: boolean, |}; declare export type ExtraStackNavigatorProps = {| ...$Exact, ...StackRouterOptions, ...StackNavigationConfig, |}; declare export type StackNavigatorProps< NavProp: InexactStackNavigationProp<> = StackNavigationProp<>, > = {| ...ExtraStackNavigatorProps, ...ScreenOptionsProp, |}; /** * Bottom tab options */ declare export type BottomTabBarButtonProps = {| ...$Diff< TouchableWithoutFeedbackProps, {| onPress?: ?(event: PressEvent) => mixed |}, >, +to?: string, +children: React$Node, +onPress?: (MouseEvent | PressEvent) => void, |}; declare export type TabBarVisibilityAnimationConfig = | {| +animation: 'spring', +config?: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |} | {| +animation: 'timing', +config?: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |}; declare export type BottomTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| focused: boolean, color: string |}) => React$Node, +tabBarIcon: ({| focused: boolean, color: string, size: number, |}) => React$Node, +tabBarBadge: number | string, +tabBarBadgeStyle: TextStyleProp, +tabBarAccessibilityLabel: string, +tabBarTestID: string, +tabBarVisible: boolean, +tabBarVisibilityAnimationConfig: $Partial<{| +show: TabBarVisibilityAnimationConfig, +hide: TabBarVisibilityAnimationConfig, |}>, +tabBarButton: BottomTabBarButtonProps => React$Node, +unmountOnBlur: boolean, |}>; /** * Bottom tab navigation prop */ declare export type BottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactTabNavigationProp< ParamList: ParamListBase, RouteName: $Keys, Options: {...}, EventMap: EventMapBase, > = { ...$Exact>, +jumpTo: SimpleNavigate, ... }; declare export type InexactBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type BottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous bottom tab exports */ declare export type BottomTabDescriptor = Descriptor< BottomTabNavigationProp<>, BottomTabOptions, >; declare export type BottomTabBarOptions = $Partial<{| +keyboardHidesTabBar: boolean, +activeTintColor: string, +inactiveTintColor: string, +activeBackgroundColor: string, +inactiveBackgroundColor: string, +allowFontScaling: boolean, +showLabel: boolean, +showIcon: boolean, +labelStyle: TextStyleProp, +iconStyle: TextStyleProp, +tabStyle: ViewStyleProp, +labelPosition: 'beside-icon' | 'below-icon', +adaptive: boolean, +safeAreaInsets: $Partial, +style: ViewStyleProp, |}>; declare type BottomTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: BottomTabNavigationProp<>, +descriptors: {| +[key: string]: BottomTabDescriptor |}, |}; declare export type BottomTabBarProps = {| ...BottomTabBarOptions, ...BottomTabNavigationBuilderResult, |} declare type BottomTabNavigationConfig = {| +lazy?: boolean, +tabBar?: BottomTabBarProps => React$Node, +tabBarOptions?: BottomTabBarOptions, +detachInactiveScreens?: boolean, |}; declare export type ExtraBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...BottomTabNavigationConfig, |}; declare export type BottomTabNavigatorProps< NavProp: InexactBottomTabNavigationProp<> = BottomTabNavigationProp<>, > = {| ...ExtraBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material bottom tab options */ declare export type MaterialBottomTabOptions = $Partial<{| +title: string, +tabBarColor: string, +tabBarLabel: string, +tabBarIcon: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarBadge: boolean | number | string, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material bottom tab navigation prop */ declare export type MaterialBottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, |}; declare export type InexactMaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material bottom tab exports */ declare export type PaperFont = {| +fontFamily: string, +fontWeight?: | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', |}; declare export type PaperFonts = {| +regular: PaperFont, +medium: PaperFont, +light: PaperFont, +thin: PaperFont, |}; declare export type PaperTheme = {| +dark: boolean, +mode?: 'adaptive' | 'exact', +roundness: number, +colors: {| +primary: string, +background: string, +surface: string, +accent: string, +error: string, +text: string, +onSurface: string, +onBackground: string, +disabled: string, +placeholder: string, +backdrop: string, +notification: string, |}, +fonts: PaperFonts, +animation: {| +scale: number, |}, |}; declare export type PaperRoute = {| +key: string, +title?: string, +icon?: any, +badge?: string | number | boolean, +color?: string, +accessibilityLabel?: string, +testID?: string, |}; declare export type PaperTouchableProps = {| ...TouchableWithoutFeedbackProps, +key: string, +route: PaperRoute, +children: React$Node, +borderless?: boolean, +centered?: boolean, +rippleColor?: string, |}; declare export type MaterialBottomTabNavigationConfig = {| +shifting?: boolean, +labeled?: boolean, +renderTouchable?: PaperTouchableProps => React$Node, +activeColor?: string, +inactiveColor?: string, +sceneAnimationEnabled?: boolean, +keyboardHidesNavigationBar?: boolean, +barStyle?: ViewStyleProp, +style?: ViewStyleProp, +theme?: PaperTheme, |}; declare export type ExtraMaterialBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialBottomTabNavigationConfig, |}; declare export type MaterialBottomTabNavigatorProps< NavProp: InexactMaterialBottomTabNavigationProp<> = MaterialBottomTabNavigationProp<>, > = {| ...ExtraMaterialBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material top tab options */ declare export type MaterialTopTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarIcon: ({| +focused: boolean, +color: string |}) => React$Node, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material top tab navigation prop */ declare export type MaterialTopTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, +swipeStart: {| +data: void, +canPreventDefault: false |}, +swipeEnd: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactMaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material top tab exports */ declare type MaterialTopTabPagerCommonProps = {| +keyboardDismissMode: 'none' | 'on-drag' | 'auto', +swipeEnabled: boolean, +swipeVelocityImpact?: number, +springVelocityScale?: number, +springConfig: $Partial<{| +damping: number, +mass: number, +stiffness: number, +restSpeedThreshold: number, +restDisplacementThreshold: number, |}>, +timingConfig: $Partial<{| +duration: number, |}>, |}; declare export type MaterialTopTabPagerProps = {| ...MaterialTopTabPagerCommonProps, +onSwipeStart?: () => void, +onSwipeEnd?: () => void, +onIndexChange: (index: number) => void, +navigationState: TabNavigationState, +layout: {| +width: number, +height: number |}, +removeClippedSubviews: boolean, +children: ({| +addListener: (type: 'enter', listener: number => void) => void, +removeListener: (type: 'enter', listener: number => void) => void, +position: any, // Reanimated.Node +render: React$Node => React$Node, +jumpTo: string => void, |}) => React$Node, +gestureHandlerProps: PanGestureHandlerProps, |}; declare export type MaterialTopTabBarIndicatorProps = {| +navigationState: TabNavigationState, +width: string, +style?: ViewStyleProp, +getTabWidth: number => number, |}; declare export type MaterialTopTabBarOptions = $Partial<{| +scrollEnabled: boolean, +bounces: boolean, +pressColor: string, +pressOpacity: number, +getAccessible: ({| +route: Route<> |}) => boolean, +renderBadge: ({| +route: Route<> |}) => React$Node, +renderIndicator: MaterialTopTabBarIndicatorProps => React$Node, +tabStyle: ViewStyleProp, +indicatorStyle: ViewStyleProp, +indicatorContainerStyle: ViewStyleProp, +labelStyle: TextStyleProp, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, +activeTintColor: string, +inactiveTintColor: string, +iconStyle: ViewStyleProp, +labelStyle: TextStyleProp, +showLabel: boolean, +showIcon: boolean, +allowFontScaling: boolean, |}>; declare export type MaterialTopTabDescriptor = Descriptor< MaterialBottomTabNavigationProp<>, MaterialBottomTabOptions, >; declare type MaterialTopTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: MaterialTopTabNavigationProp<>, +descriptors: {| +[key: string]: MaterialTopTabDescriptor |}, |}; declare export type MaterialTopTabBarProps = {| ...MaterialTopTabBarOptions, ...MaterialTopTabNavigationBuilderResult, +layout: {| +width: number, +height: number |}, +position: any, // Reanimated.Node +jumpTo: string => void, |}; declare export type MaterialTopTabNavigationConfig = {| ...$Partial, +position?: any, // Reanimated.Value +tabBarPosition?: 'top' | 'bottom', +initialLayout?: $Partial<{| +width: number, +height: number |}>, +lazy?: boolean, +lazyPreloadDistance?: number, +removeClippedSubviews?: boolean, +sceneContainerStyle?: ViewStyleProp, +style?: ViewStyleProp, +gestureHandlerProps?: PanGestureHandlerProps, +pager?: MaterialTopTabPagerProps => React$Node, +lazyPlaceholder?: ({| +route: Route<> |}) => React$Node, +tabBar?: MaterialTopTabBarProps => React$Node, +tabBarOptions?: MaterialTopTabBarOptions, |}; declare export type ExtraMaterialTopTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialTopTabNavigationConfig, |}; declare export type MaterialTopTabNavigatorProps< NavProp: InexactMaterialTopTabNavigationProp<> = MaterialTopTabNavigationProp<>, > = {| ...ExtraMaterialTopTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Drawer options */ declare export type DrawerOptions = $Partial<{| title: string, drawerLabel: | string | ({| +color: string, +focused: boolean |}) => React$Node, drawerIcon: ({| +color: string, +size: number, +focused: boolean, |}) => React$Node, gestureEnabled: boolean, swipeEnabled: boolean, unmountOnBlur: boolean, |}>; /** * Drawer navigation prop */ declare export type DrawerNavigationEventMap = {| ...EventMapCore, +drawerOpen: {| +data: void, +canPreventDefault: false |}, +drawerClose: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactDrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = { ...$Exact>, +jumpTo: SimpleNavigate, +openDrawer: () => void, +closeDrawer: () => void, +toggleDrawer: () => void, ... }; declare export type DrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = $Exact>; /** * Miscellaneous drawer exports */ declare export type DrawerDescriptor = Descriptor< DrawerNavigationProp<>, DrawerOptions, >; declare export type DrawerItemListBaseOptions = $Partial<{| +activeTintColor: string, +activeBackgroundColor: string, +inactiveTintColor: string, +inactiveBackgroundColor: string, +itemStyle: ViewStyleProp, +labelStyle: TextStyleProp, |}>; declare export type DrawerContentOptions = $Partial<{| ...DrawerItemListBaseOptions, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, |}>; declare type DrawerNavigationBuilderResult = {| +state: DrawerNavigationState, +navigation: DrawerNavigationProp<>, +descriptors: {| +[key: string]: DrawerDescriptor |}, |}; declare export type DrawerContentProps = {| ...DrawerContentOptions, ...DrawerNavigationBuilderResult, +progress: any, // Reanimated.Node |}; declare export type DrawerNavigationConfig = {| +drawerPosition?: 'left' | 'right', +drawerType?: 'front' | 'back' | 'slide' | 'permanent', +edgeWidth?: number, +hideStatusBar?: boolean, +keyboardDismissMode?: 'on-drag' | 'none', +minSwipeDistance?: number, +overlayColor?: string, +statusBarAnimation?: 'slide' | 'none' | 'fade', +gestureHandlerProps?: PanGestureHandlerProps, +lazy?: boolean, +drawerContent?: DrawerContentProps => React$Node, +drawerContentOptions?: DrawerContentOptions, +sceneContainerStyle?: ViewStyleProp, +drawerStyle?: ViewStyleProp, +detachInactiveScreens?: boolean, |}; declare export type ExtraDrawerNavigatorProps = {| ...$Exact, ...DrawerRouterOptions, ...DrawerNavigationConfig, |}; declare export type DrawerNavigatorProps< NavProp: InexactDrawerNavigationProp<> = DrawerNavigationProp<>, > = {| ...ExtraDrawerNavigatorProps, ...ScreenOptionsProp, |}; /** * BaseNavigationContainer */ declare export type BaseNavigationContainerProps = {| +children: React$Node, +initialState?: PossiblyStaleNavigationState, +onStateChange?: (state: ?PossiblyStaleNavigationState) => void, +independent?: boolean, |}; declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| +data: {| +options: { +[key: string]: mixed, ... } |}, +canPreventDefault: false, |}, +__unsafe_action__: {| +data: {| +action: GenericNavigationAction, +noop: boolean, |}, +canPreventDefault: false, |}, |}; declare export type BaseNavigationContainerInterface = {| ...$Exact>, +setParams: (params: ScreenParams) => void, +resetRoot: (state?: ?PossiblyStaleNavigationState) => void, +getRootState: () => PossiblyStaleNavigationState, |}; /** * State utils */ declare export type GetStateFromPath = ( path: string, options?: LinkingConfig, ) => PossiblyStaleNavigationState; declare export type GetPathFromState = ( state?: ?PossiblyStaleNavigationState, options?: LinkingConfig, ) => string; declare export type GetFocusedRouteNameFromRoute = PossiblyStaleRoute => ?string; /** * Linking */ declare export type ScreenLinkingConfig = {| +path?: string, +exact?: boolean, +parse?: {| +[param: string]: string => mixed |}, +stringify?: {| +[param: string]: mixed => string |}, +screens?: ScreenLinkingConfigMap, +initialRouteName?: string, |}; declare export type ScreenLinkingConfigMap = {| +[routeName: string]: string | ScreenLinkingConfig, |}; declare export type LinkingConfig = {| +initialRouteName?: string, +screens: ScreenLinkingConfigMap, |}; declare export type LinkingOptions = {| +enabled?: boolean, +prefixes: $ReadOnlyArray, +config?: LinkingConfig, +getStateFromPath?: GetStateFromPath, +getPathFromState?: GetPathFromState, |}; /** * NavigationContainer */ declare export type Theme = {| +dark: boolean, +colors: {| +primary: string, +background: string, +card: string, +text: string, +border: string, |}, |}; declare export type NavigationContainerType = React$AbstractComponent< {| ...BaseNavigationContainerProps, +theme?: Theme, +linking?: LinkingOptions, +fallback?: React$Node, +onReady?: () => mixed, |}, BaseNavigationContainerInterface, >; //--------------------------------------------------------------------------- // SECTION 2: EXPORTED MODULE // This section defines the module exports and contains exported types that // are not present in any other React Navigation libdef. //--------------------------------------------------------------------------- /** * createMaterialTopTabNavigator */ declare export var createMaterialTopTabNavigator: CreateNavigator< TabNavigationState, MaterialTopTabOptions, MaterialTopTabNavigationEventMap, ExtraMaterialTopTabNavigatorProps, >; /** * MaterialTopTabView */ declare export type MaterialTopTabViewProps = {| ...MaterialTopTabNavigationConfig, ...MaterialTopTabNavigationBuilderResult, |}; declare export var MaterialTopTabView: React$ComponentType< MaterialTopTabViewProps, >; /** * MaterialTopTabBar */ declare export var MaterialTopTabBar: React$ComponentType< MaterialTopTabBarProps, >; } diff --git a/native/flow-typed/npm/@react-navigation/native_v5.x.x.js b/native/flow-typed/npm/@react-navigation/native_v5.x.x.js index 885408c26..e4848cb31 100644 --- a/native/flow-typed/npm/@react-navigation/native_v5.x.x.js +++ b/native/flow-typed/npm/@react-navigation/native_v5.x.x.js @@ -1,2244 +1,2273 @@ // flow-typed signature: 219fd8b2f5868928e02073db11adb8a5 // flow-typed version: dc2d6a22c7/@react-navigation/native_v5.x.x/flow_>=v0.104.x declare module '@react-navigation/native' { //--------------------------------------------------------------------------- // SECTION 1: IDENTICAL TYPE DEFINITIONS // This section is identical across all React Navigation libdefs and contains // shared definitions. We wish we could make it DRY and import from a shared // definition, but that isn't yet possible. //--------------------------------------------------------------------------- /** * We start with some definitions that we have copy-pasted from React Native * source files. */ // This is a bastardization of the true StyleObj type located in // react-native/Libraries/StyleSheet/StyleSheetTypes. We unfortunately can't // import that here, and it's too lengthy (and consequently too brittle) to // copy-paste here either. declare type StyleObj = | null | void | number | false | '' | $ReadOnlyArray | { [name: string]: any, ... }; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; declare type AnimatedTextStyleProp = StyleObj; // Vaguely copied from // react-native/Libraries/Animated/src/animations/Animation.js declare type EndResult = { finished: boolean, ... }; declare type EndCallback = (result: EndResult) => void; declare interface Animation { start( fromValue: number, onUpdate: (value: number) => void, onEnd: ?EndCallback, previousAnimation: ?Animation, animatedValue: AnimatedValue, ): void; stop(): void; } declare type AnimationConfig = { isInteraction?: boolean, useNativeDriver: boolean, onComplete?: ?EndCallback, iterations?: number, ... }; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedTracking.js declare interface AnimatedTracking { constructor( value: AnimatedValue, parent: any, animationClass: any, animationConfig: Object, callback?: ?EndCallback, ): void; update(): void; } // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedValue.js declare type ValueListenerCallback = (state: { value: number, ... }) => void; declare interface AnimatedValue { constructor(value: number): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; extractOffset(): void; addListener(callback: ValueListenerCallback): string; removeListener(id: string): void; removeAllListeners(): void; stopAnimation(callback?: ?(value: number) => void): void; resetAnimation(callback?: ?(value: number) => void): void; interpolate(config: InterpolationConfigType): AnimatedInterpolation; animate(animation: Animation, callback: ?EndCallback): void; stopTracking(): void; track(tracking: AnimatedTracking): void; } // Copied from // react-native/Libraries/Animated/src/animations/TimingAnimation.js declare type TimingAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, easing?: (value: number) => number, duration?: number, delay?: number, ... }; // Copied from // react-native/Libraries/Animated/src/animations/SpringAnimation.js declare type SpringAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, overshootClamping?: boolean, restDisplacementThreshold?: number, restSpeedThreshold?: number, velocity?: number, bounciness?: number, speed?: number, tension?: number, friction?: number, stiffness?: number, damping?: number, mass?: number, delay?: number, ... }; // Copied from react-native/Libraries/Types/CoreEventTypes.js declare type SyntheticEvent = $ReadOnly<{| bubbles: ?boolean, cancelable: ?boolean, currentTarget: number, defaultPrevented: ?boolean, dispatchConfig: $ReadOnly<{| registrationName: string, |}>, eventPhase: ?number, preventDefault: () => void, isDefaultPrevented: () => boolean, stopPropagation: () => void, isPropagationStopped: () => boolean, isTrusted: ?boolean, nativeEvent: T, persist: () => void, target: ?number, timeStamp: number, type: ?string, |}>; declare type Layout = $ReadOnly<{| x: number, y: number, width: number, height: number, |}>; declare type LayoutEvent = SyntheticEvent< $ReadOnly<{| layout: Layout, |}>, >; declare type BlurEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type FocusEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type ResponderSyntheticEvent = $ReadOnly<{| ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray< $ReadOnly<{| touchActive: boolean, startPageX: number, startPageY: number, startTimeStamp: number, currentPageX: number, currentPageY: number, currentTimeStamp: number, previousPageX: number, previousPageY: number, previousTimeStamp: number, |}>, >, |}>, |}>; declare type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, identifier: number, locationX: number, locationY: number, pageX: number, pageY: number, target: ?number, timestamp: number, touches: $ReadOnlyArray<$PropertyType>, |}>, >; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js declare type ExtrapolateType = 'extend' | 'identity' | 'clamp'; declare type InterpolationConfigType = { inputRange: Array, outputRange: Array | Array, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, ... }; declare interface AnimatedInterpolation { interpolate(config: InterpolationConfigType): AnimatedInterpolation; } // Copied from react-native/Libraries/Components/View/ViewAccessibility.js declare type AccessibilityRole = | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'imagebutton' | 'header' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menu' | 'menubar' | 'menuitem' | 'progressbar' | 'radio' | 'radiogroup' | 'scrollbar' | 'spinbutton' | 'switch' | 'tab' | 'tablist' | 'timer' | 'toolbar'; declare type AccessibilityActionInfo = $ReadOnly<{ name: string, label?: string, ... }>; declare type AccessibilityActionEvent = SyntheticEvent< $ReadOnly<{actionName: string, ...}>, >; declare type AccessibilityState = { disabled?: boolean, selected?: boolean, checked?: ?boolean | 'mixed', busy?: boolean, expanded?: boolean, ... }; declare type AccessibilityValue = $ReadOnly<{| min?: number, max?: number, now?: number, text?: string, |}>; // Copied from // react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js declare type Stringish = string; declare type EdgeInsetsProp = $ReadOnly<$Partial>; declare type TouchableWithoutFeedbackProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, accessibilityElementsHidden?: ?boolean, accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityLabel?: ?Stringish, accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, children?: ?React$Node, delayLongPress?: ?number, delayPressIn?: ?number, delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, hitSlop?: ?EdgeInsetsProp, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(event: BlurEvent) => mixed, onFocus?: ?(event: FocusEvent) => mixed, onLayout?: ?(event: LayoutEvent) => mixed, onLongPress?: ?(event: PressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, pressRetentionOffset?: ?EdgeInsetsProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, |}>; // Copied from react-native/Libraries/Image/ImageSource.js declare type ImageURISource = $ReadOnly<{ uri?: ?string, bundle?: ?string, method?: ?string, headers?: ?Object, body?: ?string, cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), width?: ?number, height?: ?number, scale?: ?number, ... }>; /** * The following is copied from react-native-gesture-handler's libdef */ declare type StateUndetermined = 0; declare type StateFailed = 1; declare type StateBegan = 2; declare type StateCancelled = 3; declare type StateActive = 4; declare type StateEnd = 5; declare type GestureHandlerState = | StateUndetermined | StateFailed | StateBegan | StateCancelled | StateActive | StateEnd; declare type $SyntheticEvent = { +nativeEvent: $ReadOnly<$Exact>, ... }; declare type $Event = $SyntheticEvent<{ handlerTag: number, numberOfPointers: number, state: GestureHandlerState, oldState: GestureHandlerState, ...$Exact, ... }>; declare type $EventHandlers = {| onGestureEvent?: ($Event) => mixed, onHandlerStateChange?: ($Event) => mixed, onBegan?: ($Event) => mixed, onFailed?: ($Event) => mixed, onCancelled?: ($Event) => mixed, onActivated?: ($Event) => mixed, onEnded?: ($Event) => mixed, |}; declare type HitSlop = | number | {| left?: number, top?: number, right?: number, bottom?: number, vertical?: number, horizontal?: number, width?: number, height?: number, |} | {| width: number, left: number, |} | {| width: number, right: number, |} | {| height: number, top: number, |} | {| height: number, bottom: number, |}; declare type $GestureHandlerProps< AdditionalProps: {...}, ExtraEventsProps: {...} > = $ReadOnly<{| ...$Exact, ...$EventHandlers, id?: string, enabled?: boolean, waitFor?: React$Ref | Array>, simultaneousHandlers?: React$Ref | Array>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, children?: React$Node, |}>; declare type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], activeOffsetX?: number | [number, number], failOffsetY?: number | [number, number], failOffsetX?: number | [number, number], minDist?: number, minVelocity?: number, minVelocityX?: number, minVelocityY?: number, minPointers?: number, maxPointers?: number, avgTouches?: boolean, ... }, { x: number, y: number, absoluteX: number, absoluteY: number, translationX: number, translationY: number, velocityX: number, velocityY: number, ... } >; /** * MAGIC */ declare type $If = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), Test, Then, Else, >; declare type $IsA = $Call< (Y => true) & (mixed => false), X, >; declare type $IsUndefined = $IsA; declare type $Partial = $ReadOnly<$Rest>; + // If { ...T, ... } counts as a T, then we're inexact + declare type $IsExact = $Call< + (T => false) & (mixed => true), + { ...T, ... }, + >; + /** * Actions, state, etc. */ declare export type ScreenParams = { +[key: string]: mixed, ... }; declare export type BackAction = {| +type: 'GO_BACK', +source?: string, +target?: string, |}; declare export type NavigateAction = {| +type: 'NAVIGATE', +payload: | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type ResetAction = {| +type: 'RESET', +payload: StaleNavigationState, +source?: string, +target?: string, |}; declare export type SetParamsAction = {| +type: 'SET_PARAMS', +payload: {| +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type CommonAction = | BackAction | NavigateAction | ResetAction | SetParamsAction; declare type NavigateActionCreator = {| (routeName: string, params?: ScreenParams): NavigateAction, ( | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, ): NavigateAction, |}; declare export type CommonActionsType = {| +navigate: NavigateActionCreator, +goBack: () => BackAction, +reset: (state: PossiblyStaleNavigationState) => ResetAction, +setParams: (params: ScreenParams) => SetParamsAction, |}; declare export type GenericNavigationAction = {| +type: string, +payload?: { +[key: string]: mixed, ... }, +source?: string, +target?: string, |}; declare export type LeafRoute = {| +key: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StateRoute = {| ...LeafRoute, +state: NavigationState | StaleNavigationState, |}; declare export type Route = | LeafRoute | StateRoute; declare export type NavigationState = {| +key: string, +index: number, +routeNames: $ReadOnlyArray, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type: string, +stale: false, |}; declare export type StaleLeafRoute = {| +key?: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StaleStateRoute = {| ...StaleLeafRoute, +state: StaleNavigationState, |}; declare export type StaleRoute = | StaleLeafRoute | StaleStateRoute; declare export type StaleNavigationState = {| // It's possible to pass React Nav a StaleNavigationState with an undefined // index, but React Nav will always return one with the index set. This is // the same as for the type property below, but in the case of index we tend // to rely on it being set more... +index: number, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type?: string, +stale?: true, |}; declare export type PossiblyStaleNavigationState = | NavigationState | StaleNavigationState; declare export type PossiblyStaleRoute = | Route | StaleRoute; /** * Routers */ declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, > = { +[key: string]: (...args: any) => (Action | State => Action), ... }; declare export type DefaultRouterOptions = { +initialRouteName?: string, ... }; declare export type RouterFactory< State: NavigationState, Action: GenericNavigationAction, RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, +routeParamList: ParamListBase, |}; declare export type Router< State: NavigationState, Action: GenericNavigationAction, > = {| +type: $PropertyType, +getInitialState: (options: RouterConfigOptions) => State, +getRehydratedState: ( partialState: PossiblyStaleNavigationState, options: RouterConfigOptions, ) => State, +getStateForRouteNamesChange: ( state: State, options: RouterConfigOptions, ) => State, +getStateForRouteFocus: (state: State, key: string) => State, +getStateForAction: ( state: State, action: Action, options: RouterConfigOptions, ) => ?PossiblyStaleNavigationState; +shouldActionChangeFocus: (action: GenericNavigationAction) => boolean, +actionCreators?: ActionCreators, |}; /** * Stack actions and router */ declare export type StackNavigationState = {| ...NavigationState, +type: 'stack', |}; declare export type ReplaceAction = {| +type: 'REPLACE', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PushAction = {| +type: 'PUSH', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PopAction = {| +type: 'POP', +payload: {| +count: number |}, +source?: string, +target?: string, |}; declare export type PopToTopAction = {| +type: 'POP_TO_TOP', +source?: string, +target?: string, |}; declare export type StackAction = | CommonAction | ReplaceAction | PushAction | PopAction | PopToTopAction; declare export type StackActionsType = {| +replace: (routeName: string, params?: ScreenParams) => ReplaceAction, +push: (routeName: string, params?: ScreenParams) => PushAction, +pop: (count?: number) => PopAction, +popToTop: () => PopToTopAction, |}; declare export type StackRouterOptions = $Exact; /** * Tab actions and router */ declare export type TabNavigationState = {| ...NavigationState, +type: 'tab', +history: $ReadOnlyArray<{| type: 'route', key: string |}>, |}; declare export type JumpToAction = {| +type: 'JUMP_TO', +payload: {| +name: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type TabAction = | CommonAction | JumpToAction; declare export type TabActionsType = {| +jumpTo: string => JumpToAction, |}; declare export type TabRouterOptions = {| ...$Exact, +backBehavior?: 'initialRoute' | 'order' | 'history' | 'none', |}; /** * Drawer actions and router */ declare type DrawerHistoryEntry = | {| +type: 'route', +key: string |} | {| +type: 'drawer' |}; declare export type DrawerNavigationState = {| ...NavigationState, +type: 'drawer', +history: $ReadOnlyArray, |}; declare export type OpenDrawerAction = {| +type: 'OPEN_DRAWER', +source?: string, +target?: string, |}; declare export type CloseDrawerAction = {| +type: 'CLOSE_DRAWER', +source?: string, +target?: string, |}; declare export type ToggleDrawerAction = {| +type: 'TOGGLE_DRAWER', +source?: string, +target?: string, |}; declare export type DrawerAction = | TabAction | OpenDrawerAction | CloseDrawerAction | ToggleDrawerAction; declare export type DrawerActionsType = {| ...TabActionsType, +openDrawer: () => OpenDrawerAction, +closeDrawer: () => CloseDrawerAction, +toggleDrawer: () => ToggleDrawerAction, |}; declare export type DrawerRouterOptions = {| ...TabRouterOptions, +openByDefault?: boolean, |}; /** * Events */ declare export type EventMapBase = { +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, ... }; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, {| |}, >; declare type EventDataProperties = $If< $IsUndefined, {| |}, {| +data: Data |}, >; declare type EventArg< EventName: string, CanPreventDefault: ?boolean = false, Data = void, > = {| ...EventPreventDefaultProperties, ...EventDataProperties, +type: EventName, +target?: string, |}; declare type GlobalEventMap = {| +state: {| +data: {| +state: State |}, +canPreventDefault: false |}, |}; declare type EventMapCore = {| ...GlobalEventMap, +focus: {| +data: void, +canPreventDefault: false |}, +blur: {| +data: void, +canPreventDefault: false |}, +beforeRemove: {| +data: {| +action: GenericNavigationAction |}, +canPreventDefault: true, |}, |}; declare type EventListenerCallback< EventName: string, State: PossiblyStaleNavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = (e: EventArg< EventName, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'canPreventDefault', >, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'data', >, >) => mixed; /** * Navigation prop */ + declare type PartialWithMergeProperty = $If< + $IsExact, + { ...$Partial, +merge: true }, + { ...$Partial, +merge: true, ... }, + >; + + declare type EitherExactOrPartialWithMergeProperty = + | ParamsType + | PartialWithMergeProperty; + declare export type SimpleNavigate = >( routeName: DestinationRouteName, - params: $ElementType, + params: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, ) => void; declare export type Navigate = & SimpleNavigate & >( - route: + route: $If< + $IsUndefined<$ElementType>, + | {| +key: string |} | + {| +name: DestinationRouteName, +key?: string |}, | {| +key: string, - +params?: $ElementType, - |} - | {| + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, + |} | + {| +name: DestinationRouteName, +key?: string, - +params?: $ElementType, + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, |}, + >, ) => void; declare type NavigationHelpers< ParamList: ParamListBase, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, EventMap: EventMapBase = EventMapCore, > = { +navigate: Navigate, +dispatch: ( action: | GenericNavigationAction | (State => GenericNavigationAction), ) => void, +reset: PossiblyStaleNavigationState => void, +goBack: () => void, +isFocused: () => boolean, +canGoBack: () => boolean, +dangerouslyGetParent: >() => ?Parent, +dangerouslyGetState: () => NavigationState, +addListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => () => void, +removeListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => void, ... }; + declare type SetParamsInput< + ParamList: ParamListBase, + RouteName: $Keys = $Keys, + > = $If< + $IsUndefined<$ElementType>, + empty, + $Partial<$NonMaybeType<$ElementType>>, + >; + declare export type NavigationProp< ParamList: ParamListBase, RouteName: $Keys = $Keys, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = { ...$Exact>, +setOptions: (options: $Partial) => void, - +setParams: ( - params: $If< - $IsUndefined<$ElementType>, - empty, - $Partial<$NonMaybeType<$ElementType>>, - >, - ) => void, + +setParams: (params: SetParamsInput) => void, ... }; /** * CreateNavigator */ declare export type RouteProp< ParamList: ParamListBase, RouteName: $Keys, > = {| ...LeafRoute, +params: $ElementType, |}; declare export type ScreenListeners< State: NavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = $ObjMapi< {| [name: $Keys]: empty |}, >(K, empty) => EventListenerCallback, >; declare type BaseScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = {| +name: RouteName, +options?: | ScreenOptions | ({| route: RouteProp, navigation: NavProp, |}) => ScreenOptions, +listeners?: | ScreenListeners | ({| route: RouteProp, navigation: NavProp, |}) => ScreenListeners, +initialParams?: $Partial<$ElementType>, |}; declare export type ScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +component: React$ComponentType<{| route: RouteProp, navigation: NavProp, |}>, |} | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +children: ({| route: RouteProp, navigation: NavProp, |}) => React$Node, |}; declare export type ScreenComponent< GlobalParamList: ParamListBase, ParamList: ParamListBase, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = < RouteName: $Keys, NavProp: NavigationProp< GlobalParamList, RouteName, State, ScreenOptions, EventMap, >, >(props: ScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >) => React$Node; declare type ScreenOptionsProp = {| +screenOptions?: | ScreenOptions | ({| route: LeafRoute<>, navigation: NavProp |}) => ScreenOptions, |}; declare export type ExtraNavigatorPropsBase = { ...$Exact, +children?: React$Node, ... }; declare export type NavigatorPropsBase = { ...$Exact, ...ScreenOptionsProp, ... }; declare export type CreateNavigator< State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, ExtraNavigatorProps: ExtraNavigatorPropsBase, > = < GlobalParamList: ParamListBase, ParamList: ParamListBase, NavProp: NavigationHelpers< GlobalParamList, State, EventMap, >, >() => {| +Screen: ScreenComponent< GlobalParamList, ParamList, State, ScreenOptions, EventMap, >, +Navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, |}; declare export type CreateNavigatorFactory = < State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, NavProp: NavigationHelpers< ParamListBase, State, EventMap, >, ExtraNavigatorProps: ExtraNavigatorPropsBase, >( navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, ) => CreateNavigator; /** * useNavigationBuilder */ declare export type Descriptor< NavProp, ScreenOptions: {...} = {...}, > = {| +render: () => React$Node, +options: $ReadOnly, +navigation: NavProp, |}; declare export type UseNavigationBuilder = < State: NavigationState, Action: GenericNavigationAction, ScreenOptions: {...}, RouterOptions: DefaultRouterOptions, NavProp, >( routerFactory: RouterFactory, options: {| ...$Exact, ...ScreenOptionsProp, +children?: React$Node, |}, ) => {| +state: State, +descriptors: {| +[key: string]: Descriptor |}, +navigation: NavProp, |}; /** * EdgeInsets */ declare type EdgeInsets = {| +top: number, +right: number, +bottom: number, +left: number, |}; /** * TransitionPreset */ declare export type TransitionSpec = | {| animation: 'spring', config: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |} | {| animation: 'timing', config: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |}; declare export type StackCardInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +index: number, +closing: AnimatedInterpolation, +swiping: AnimatedInterpolation, +inverted: AnimatedInterpolation, +layouts: {| +screen: {| +width: number, +height: number |}, |}, +insets: EdgeInsets, |}; declare export type StackCardInterpolatedStyle = {| containerStyle?: AnimatedViewStyleProp, cardStyle?: AnimatedViewStyleProp, overlayStyle?: AnimatedViewStyleProp, shadowStyle?: AnimatedViewStyleProp, |}; declare export type StackCardStyleInterpolator = ( props: StackCardInterpolationProps, ) => StackCardInterpolatedStyle; declare export type StackHeaderInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +layouts: {| +header: {| +width: number, +height: number |}, +screen: {| +width: number, +height: number |}, +title?: {| +width: number, +height: number |}, +leftLabel?: {| +width: number, +height: number |}, |}, |}; declare export type StackHeaderInterpolatedStyle = {| leftLabelStyle?: AnimatedViewStyleProp, leftButtonStyle?: AnimatedViewStyleProp, rightButtonStyle?: AnimatedViewStyleProp, titleStyle?: AnimatedViewStyleProp, backgroundStyle?: AnimatedViewStyleProp, |}; declare export type StackHeaderStyleInterpolator = ( props: StackHeaderInterpolationProps, ) => StackHeaderInterpolatedStyle; declare type GestureDirection = | 'horizontal' | 'horizontal-inverted' | 'vertical' | 'vertical-inverted'; declare export type TransitionPreset = {| +gestureDirection: GestureDirection, +transitionSpec: {| +open: TransitionSpec, +close: TransitionSpec, |}, +cardStyleInterpolator: StackCardStyleInterpolator, +headerStyleInterpolator: StackHeaderStyleInterpolator, |}; /** * Stack options */ declare export type StackDescriptor = Descriptor< StackNavigationProp<>, StackOptions, >; declare type Scene = {| +route: T, +descriptor: StackDescriptor, +progress: {| +current: AnimatedInterpolation, +next?: AnimatedInterpolation, +previous?: AnimatedInterpolation, |}, |}; declare export type StackHeaderProps = {| +mode: 'float' | 'screen', +layout: {| +width: number, +height: number |}, +insets: EdgeInsets, +scene: Scene>, +previous?: Scene>, +navigation: StackNavigationProp, +styleInterpolator: StackHeaderStyleInterpolator, |}; declare export type StackHeaderLeftButtonProps = $Partial<{| +onPress: (() => void), +pressColorAndroid: string; +backImage: (props: {| tintColor: string |}) => React$Node, +tintColor: string, +label: string, +truncatedLabel: string, +labelVisible: boolean, +labelStyle: AnimatedTextStyleProp, +allowFontScaling: boolean, +onLabelLayout: LayoutEvent => void, +screenLayout: {| +width: number, +height: number |}, +titleLayout: {| +width: number, +height: number |}, +canGoBack: boolean, |}>; declare type StackHeaderTitleInputBase = { +onLayout: LayoutEvent => void, +children: string, +allowFontScaling: ?boolean, +tintColor: ?string, +style: ?AnimatedTextStyleProp, ... }; declare export type StackHeaderTitleInputProps = $Exact; declare export type StackOptions = $Partial<{| +title: string, +header: StackHeaderProps => React$Node, +headerShown: boolean, +cardShadowEnabled: boolean, +cardOverlayEnabled: boolean, +cardOverlay: {| style: ViewStyleProp |} => React$Node, +cardStyle: ViewStyleProp, +animationEnabled: boolean, +animationTypeForReplace: 'push' | 'pop', +gestureEnabled: boolean, +gestureResponseDistance: {| vertical?: number, horizontal?: number |}, +gestureVelocityImpact: number, +safeAreaInsets: $Partial, // Transition ...TransitionPreset, // Header +headerTitle: string | (StackHeaderTitleInputProps => React$Node), +headerTitleAlign: 'left' | 'center', +headerTitleStyle: AnimatedTextStyleProp, +headerTitleContainerStyle: ViewStyleProp, +headerTintColor: string, +headerTitleAllowFontScaling: boolean, +headerBackAllowFontScaling: boolean, +headerBackTitle: string | null, +headerBackTitleStyle: TextStyleProp, +headerBackTitleVisible: boolean, +headerTruncatedBackTitle: string, +headerLeft: StackHeaderLeftButtonProps => React$Node, +headerLeftContainerStyle: ViewStyleProp, +headerRight: {| tintColor?: string |} => React$Node, +headerRightContainerStyle: ViewStyleProp, +headerBackImage: $PropertyType, +headerPressColorAndroid: string, +headerBackground: ({| style: ViewStyleProp |}) => React$Node, +headerStyle: ViewStyleProp, +headerTransparent: boolean, +headerStatusBarHeight: number, |}>; /** * Stack navigation prop */ declare export type StackNavigationEventMap = {| ...EventMapCore, +transitionStart: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +transitionEnd: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +gestureStart: {| +data: void, +canPreventDefault: false |}, +gestureEnd: {| +data: void, +canPreventDefault: false |}, +gestureCancel: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactStackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = { ...$Exact>, +replace: SimpleNavigate, +push: SimpleNavigate, +pop: (count?: number) => void, +popToTop: () => void, ... }; declare export type StackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = $Exact>; /** * Miscellaneous stack exports */ declare type StackNavigationConfig = {| +mode?: 'card' | 'modal', +headerMode?: 'float' | 'screen' | 'none', +keyboardHandlingEnabled?: boolean, +detachInactiveScreens?: boolean, |}; declare export type ExtraStackNavigatorProps = {| ...$Exact, ...StackRouterOptions, ...StackNavigationConfig, |}; declare export type StackNavigatorProps< NavProp: InexactStackNavigationProp<> = StackNavigationProp<>, > = {| ...ExtraStackNavigatorProps, ...ScreenOptionsProp, |}; /** * Bottom tab options */ declare export type BottomTabBarButtonProps = {| ...$Diff< TouchableWithoutFeedbackProps, {| onPress?: ?(event: PressEvent) => mixed |}, >, +to?: string, +children: React$Node, +onPress?: (MouseEvent | PressEvent) => void, |}; declare export type TabBarVisibilityAnimationConfig = | {| +animation: 'spring', +config?: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |} | {| +animation: 'timing', +config?: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |}; declare export type BottomTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| focused: boolean, color: string |}) => React$Node, +tabBarIcon: ({| focused: boolean, color: string, size: number, |}) => React$Node, +tabBarBadge: number | string, +tabBarBadgeStyle: TextStyleProp, +tabBarAccessibilityLabel: string, +tabBarTestID: string, +tabBarVisible: boolean, +tabBarVisibilityAnimationConfig: $Partial<{| +show: TabBarVisibilityAnimationConfig, +hide: TabBarVisibilityAnimationConfig, |}>, +tabBarButton: BottomTabBarButtonProps => React$Node, +unmountOnBlur: boolean, |}>; /** * Bottom tab navigation prop */ declare export type BottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactTabNavigationProp< ParamList: ParamListBase, RouteName: $Keys, Options: {...}, EventMap: EventMapBase, > = { ...$Exact>, +jumpTo: SimpleNavigate, ... }; declare export type InexactBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type BottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous bottom tab exports */ declare export type BottomTabDescriptor = Descriptor< BottomTabNavigationProp<>, BottomTabOptions, >; declare export type BottomTabBarOptions = $Partial<{| +keyboardHidesTabBar: boolean, +activeTintColor: string, +inactiveTintColor: string, +activeBackgroundColor: string, +inactiveBackgroundColor: string, +allowFontScaling: boolean, +showLabel: boolean, +showIcon: boolean, +labelStyle: TextStyleProp, +iconStyle: TextStyleProp, +tabStyle: ViewStyleProp, +labelPosition: 'beside-icon' | 'below-icon', +adaptive: boolean, +safeAreaInsets: $Partial, +style: ViewStyleProp, |}>; declare type BottomTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: BottomTabNavigationProp<>, +descriptors: {| +[key: string]: BottomTabDescriptor |}, |}; declare export type BottomTabBarProps = {| ...BottomTabBarOptions, ...BottomTabNavigationBuilderResult, |} declare type BottomTabNavigationConfig = {| +lazy?: boolean, +tabBar?: BottomTabBarProps => React$Node, +tabBarOptions?: BottomTabBarOptions, +detachInactiveScreens?: boolean, |}; declare export type ExtraBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...BottomTabNavigationConfig, |}; declare export type BottomTabNavigatorProps< NavProp: InexactBottomTabNavigationProp<> = BottomTabNavigationProp<>, > = {| ...ExtraBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material bottom tab options */ declare export type MaterialBottomTabOptions = $Partial<{| +title: string, +tabBarColor: string, +tabBarLabel: string, +tabBarIcon: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarBadge: boolean | number | string, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material bottom tab navigation prop */ declare export type MaterialBottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, |}; declare export type InexactMaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material bottom tab exports */ declare export type PaperFont = {| +fontFamily: string, +fontWeight?: | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', |}; declare export type PaperFonts = {| +regular: PaperFont, +medium: PaperFont, +light: PaperFont, +thin: PaperFont, |}; declare export type PaperTheme = {| +dark: boolean, +mode?: 'adaptive' | 'exact', +roundness: number, +colors: {| +primary: string, +background: string, +surface: string, +accent: string, +error: string, +text: string, +onSurface: string, +onBackground: string, +disabled: string, +placeholder: string, +backdrop: string, +notification: string, |}, +fonts: PaperFonts, +animation: {| +scale: number, |}, |}; declare export type PaperRoute = {| +key: string, +title?: string, +icon?: any, +badge?: string | number | boolean, +color?: string, +accessibilityLabel?: string, +testID?: string, |}; declare export type PaperTouchableProps = {| ...TouchableWithoutFeedbackProps, +key: string, +route: PaperRoute, +children: React$Node, +borderless?: boolean, +centered?: boolean, +rippleColor?: string, |}; declare export type MaterialBottomTabNavigationConfig = {| +shifting?: boolean, +labeled?: boolean, +renderTouchable?: PaperTouchableProps => React$Node, +activeColor?: string, +inactiveColor?: string, +sceneAnimationEnabled?: boolean, +keyboardHidesNavigationBar?: boolean, +barStyle?: ViewStyleProp, +style?: ViewStyleProp, +theme?: PaperTheme, |}; declare export type ExtraMaterialBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialBottomTabNavigationConfig, |}; declare export type MaterialBottomTabNavigatorProps< NavProp: InexactMaterialBottomTabNavigationProp<> = MaterialBottomTabNavigationProp<>, > = {| ...ExtraMaterialBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material top tab options */ declare export type MaterialTopTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarIcon: ({| +focused: boolean, +color: string |}) => React$Node, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material top tab navigation prop */ declare export type MaterialTopTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, +swipeStart: {| +data: void, +canPreventDefault: false |}, +swipeEnd: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactMaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material top tab exports */ declare type MaterialTopTabPagerCommonProps = {| +keyboardDismissMode: 'none' | 'on-drag' | 'auto', +swipeEnabled: boolean, +swipeVelocityImpact?: number, +springVelocityScale?: number, +springConfig: $Partial<{| +damping: number, +mass: number, +stiffness: number, +restSpeedThreshold: number, +restDisplacementThreshold: number, |}>, +timingConfig: $Partial<{| +duration: number, |}>, |}; declare export type MaterialTopTabPagerProps = {| ...MaterialTopTabPagerCommonProps, +onSwipeStart?: () => void, +onSwipeEnd?: () => void, +onIndexChange: (index: number) => void, +navigationState: TabNavigationState, +layout: {| +width: number, +height: number |}, +removeClippedSubviews: boolean, +children: ({| +addListener: (type: 'enter', listener: number => void) => void, +removeListener: (type: 'enter', listener: number => void) => void, +position: any, // Reanimated.Node +render: React$Node => React$Node, +jumpTo: string => void, |}) => React$Node, +gestureHandlerProps: PanGestureHandlerProps, |}; declare export type MaterialTopTabBarIndicatorProps = {| +navigationState: TabNavigationState, +width: string, +style?: ViewStyleProp, +getTabWidth: number => number, |}; declare export type MaterialTopTabBarOptions = $Partial<{| +scrollEnabled: boolean, +bounces: boolean, +pressColor: string, +pressOpacity: number, +getAccessible: ({| +route: Route<> |}) => boolean, +renderBadge: ({| +route: Route<> |}) => React$Node, +renderIndicator: MaterialTopTabBarIndicatorProps => React$Node, +tabStyle: ViewStyleProp, +indicatorStyle: ViewStyleProp, +indicatorContainerStyle: ViewStyleProp, +labelStyle: TextStyleProp, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, +activeTintColor: string, +inactiveTintColor: string, +iconStyle: ViewStyleProp, +labelStyle: TextStyleProp, +showLabel: boolean, +showIcon: boolean, +allowFontScaling: boolean, |}>; declare export type MaterialTopTabDescriptor = Descriptor< MaterialBottomTabNavigationProp<>, MaterialBottomTabOptions, >; declare type MaterialTopTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: MaterialTopTabNavigationProp<>, +descriptors: {| +[key: string]: MaterialTopTabDescriptor |}, |}; declare export type MaterialTopTabBarProps = {| ...MaterialTopTabBarOptions, ...MaterialTopTabNavigationBuilderResult, +layout: {| +width: number, +height: number |}, +position: any, // Reanimated.Node +jumpTo: string => void, |}; declare export type MaterialTopTabNavigationConfig = {| ...$Partial, +position?: any, // Reanimated.Value +tabBarPosition?: 'top' | 'bottom', +initialLayout?: $Partial<{| +width: number, +height: number |}>, +lazy?: boolean, +lazyPreloadDistance?: number, +removeClippedSubviews?: boolean, +sceneContainerStyle?: ViewStyleProp, +style?: ViewStyleProp, +gestureHandlerProps?: PanGestureHandlerProps, +pager?: MaterialTopTabPagerProps => React$Node, +lazyPlaceholder?: ({| +route: Route<> |}) => React$Node, +tabBar?: MaterialTopTabBarProps => React$Node, +tabBarOptions?: MaterialTopTabBarOptions, |}; declare export type ExtraMaterialTopTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialTopTabNavigationConfig, |}; declare export type MaterialTopTabNavigatorProps< NavProp: InexactMaterialTopTabNavigationProp<> = MaterialTopTabNavigationProp<>, > = {| ...ExtraMaterialTopTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Drawer options */ declare export type DrawerOptions = $Partial<{| title: string, drawerLabel: | string | ({| +color: string, +focused: boolean |}) => React$Node, drawerIcon: ({| +color: string, +size: number, +focused: boolean, |}) => React$Node, gestureEnabled: boolean, swipeEnabled: boolean, unmountOnBlur: boolean, |}>; /** * Drawer navigation prop */ declare export type DrawerNavigationEventMap = {| ...EventMapCore, +drawerOpen: {| +data: void, +canPreventDefault: false |}, +drawerClose: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactDrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = { ...$Exact>, +jumpTo: SimpleNavigate, +openDrawer: () => void, +closeDrawer: () => void, +toggleDrawer: () => void, ... }; declare export type DrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = $Exact>; /** * Miscellaneous drawer exports */ declare export type DrawerDescriptor = Descriptor< DrawerNavigationProp<>, DrawerOptions, >; declare export type DrawerItemListBaseOptions = $Partial<{| +activeTintColor: string, +activeBackgroundColor: string, +inactiveTintColor: string, +inactiveBackgroundColor: string, +itemStyle: ViewStyleProp, +labelStyle: TextStyleProp, |}>; declare export type DrawerContentOptions = $Partial<{| ...DrawerItemListBaseOptions, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, |}>; declare type DrawerNavigationBuilderResult = {| +state: DrawerNavigationState, +navigation: DrawerNavigationProp<>, +descriptors: {| +[key: string]: DrawerDescriptor |}, |}; declare export type DrawerContentProps = {| ...DrawerContentOptions, ...DrawerNavigationBuilderResult, +progress: any, // Reanimated.Node |}; declare export type DrawerNavigationConfig = {| +drawerPosition?: 'left' | 'right', +drawerType?: 'front' | 'back' | 'slide' | 'permanent', +edgeWidth?: number, +hideStatusBar?: boolean, +keyboardDismissMode?: 'on-drag' | 'none', +minSwipeDistance?: number, +overlayColor?: string, +statusBarAnimation?: 'slide' | 'none' | 'fade', +gestureHandlerProps?: PanGestureHandlerProps, +lazy?: boolean, +drawerContent?: DrawerContentProps => React$Node, +drawerContentOptions?: DrawerContentOptions, +sceneContainerStyle?: ViewStyleProp, +drawerStyle?: ViewStyleProp, +detachInactiveScreens?: boolean, |}; declare export type ExtraDrawerNavigatorProps = {| ...$Exact, ...DrawerRouterOptions, ...DrawerNavigationConfig, |}; declare export type DrawerNavigatorProps< NavProp: InexactDrawerNavigationProp<> = DrawerNavigationProp<>, > = {| ...ExtraDrawerNavigatorProps, ...ScreenOptionsProp, |}; /** * BaseNavigationContainer */ declare export type BaseNavigationContainerProps = {| +children: React$Node, +initialState?: PossiblyStaleNavigationState, +onStateChange?: (state: ?PossiblyStaleNavigationState) => void, +independent?: boolean, |}; declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| +data: {| +options: { +[key: string]: mixed, ... } |}, +canPreventDefault: false, |}, +__unsafe_action__: {| +data: {| +action: GenericNavigationAction, +noop: boolean, |}, +canPreventDefault: false, |}, |}; declare export type BaseNavigationContainerInterface = {| ...$Exact>, +setParams: (params: ScreenParams) => void, +resetRoot: (state?: ?PossiblyStaleNavigationState) => void, +getRootState: () => PossiblyStaleNavigationState, |}; /** * State utils */ declare export type GetStateFromPath = ( path: string, options?: LinkingConfig, ) => PossiblyStaleNavigationState; declare export type GetPathFromState = ( state?: ?PossiblyStaleNavigationState, options?: LinkingConfig, ) => string; declare export type GetFocusedRouteNameFromRoute = PossiblyStaleRoute => ?string; /** * Linking */ declare export type ScreenLinkingConfig = {| +path?: string, +exact?: boolean, +parse?: {| +[param: string]: string => mixed |}, +stringify?: {| +[param: string]: mixed => string |}, +screens?: ScreenLinkingConfigMap, +initialRouteName?: string, |}; declare export type ScreenLinkingConfigMap = {| +[routeName: string]: string | ScreenLinkingConfig, |}; declare export type LinkingConfig = {| +initialRouteName?: string, +screens: ScreenLinkingConfigMap, |}; declare export type LinkingOptions = {| +enabled?: boolean, +prefixes: $ReadOnlyArray, +config?: LinkingConfig, +getStateFromPath?: GetStateFromPath, +getPathFromState?: GetPathFromState, |}; /** * NavigationContainer */ declare export type Theme = {| +dark: boolean, +colors: {| +primary: string, +background: string, +card: string, +text: string, +border: string, |}, |}; declare export type NavigationContainerType = React$AbstractComponent< {| ...BaseNavigationContainerProps, +theme?: Theme, +linking?: LinkingOptions, +fallback?: React$Node, +onReady?: () => mixed, |}, BaseNavigationContainerInterface, >; //--------------------------------------------------------------------------- // SECTION 2: EXPORTED MODULE // This section defines the module exports and contains exported types that // are not present in any other React Navigation libdef. //--------------------------------------------------------------------------- /** * Actions and routers */ declare export var CommonActions: CommonActionsType; declare export var StackActions: StackActionsType; declare export var TabActions: TabActionsType; declare export var DrawerActions: DrawerActionsType; declare export var BaseRouter: RouterFactory< NavigationState, CommonAction, DefaultRouterOptions, >; declare export var StackRouter: RouterFactory< StackNavigationState, StackAction, StackRouterOptions, >; declare export var TabRouter: RouterFactory< TabNavigationState, TabAction, TabRouterOptions, >; declare export var DrawerRouter: RouterFactory< DrawerNavigationState, DrawerAction, DrawerRouterOptions, >; /** * Navigator utils */ declare export var BaseNavigationContainer: React$AbstractComponent< BaseNavigationContainerProps, BaseNavigationContainerInterface, >; declare export var createNavigatorFactory: CreateNavigatorFactory; declare export var useNavigationBuilder: UseNavigationBuilder; declare export var NavigationHelpersContext: React$Context< ?NavigationHelpers, >; /** * Navigation prop / route accessors */ declare export var NavigationContext: React$Context< ?NavigationProp, >; declare export function useNavigation(): NavigationProp; declare export var NavigationRouteContext: React$Context>; declare export function useRoute(): LeafRoute<>; declare export function useNavigationState( selector: NavigationState => T, ): T; /** * Focus utils */ declare export function useFocusEffect( effect: () => ?(() => mixed), ): void; declare export function useIsFocused(): boolean; /** * State utils */ declare export var getStateFromPath: GetStateFromPath; declare export var getPathFromState: GetPathFromState; declare export function getActionFromState( state: PossiblyStaleNavigationState, ): ?NavigateAction; declare export var getFocusedRouteNameFromRoute: GetFocusedRouteNameFromRoute; /** * useScrollToTop */ declare type ScrollToOptions = { y?: number, animated?: boolean, ... }; declare type ScrollToOffsetOptions = { offset: number, animated?: boolean, ... }; declare type ScrollableView = | { scrollToTop(): void, ... } | { scrollTo(options: ScrollToOptions): void, ... } | { scrollToOffset(options: ScrollToOffsetOptions): void, ... } | { scrollResponderScrollTo(options: ScrollToOptions): void, ... }; declare type ScrollableWrapper = | { getScrollResponder(): React$Node, ... } | { getNode(): ScrollableView, ... } | ScrollableView; declare export function useScrollToTop( ref: { +current: ?ScrollableWrapper, ... }, ): void; /** * Themes */ declare export var DefaultTheme: Theme & { +dark: false, ... }; declare export var DarkTheme: Theme & { +dark: true, ... }; declare export function useTheme(): Theme; declare export var ThemeProvider: React$ComponentType<{| +value: Theme, +children: React$Node, |}>; /** * Linking */ declare export var Link: React$ComponentType<{ +to: string, +action?: GenericNavigationAction, +target?: string, +children: React$Node, ... }>; declare export function useLinking( container: { +current: ?React$ElementRef, ... }, options: LinkingOptions, ): {| +getInitialState: () => Promise |}; declare export function useLinkTo(): (path: string) => void; declare export function useLinkProps(props: {| +to: To, +action?: GenericNavigationAction, |}): {| +href: To, +accessibilityRole: 'link', +onPress: (MouseEvent | PressEvent) => void, |}; declare export function useLinkBuilder(): ( name: string, params?: ScreenParams, ) => ?string; /** * NavigationContainer */ declare export var NavigationContainer: NavigationContainerType; /** * useBackButton */ declare export function useBackButton( container: { +current: ?React$ElementRef, ... }, ): void; } diff --git a/native/flow-typed/npm/@react-navigation/stack_v5.x.x.js b/native/flow-typed/npm/@react-navigation/stack_v5.x.x.js index dbefb2902..0f44088cf 100644 --- a/native/flow-typed/npm/@react-navigation/stack_v5.x.x.js +++ b/native/flow-typed/npm/@react-navigation/stack_v5.x.x.js @@ -1,2198 +1,2227 @@ // flow-typed signature: 5b28e0fdf284df0de63f1b8f132e6f5c // flow-typed version: dc2d6a22c7/@react-navigation/stack_v5.x.x/flow_>=v0.104.x declare module '@react-navigation/stack' { //--------------------------------------------------------------------------- // SECTION 1: IDENTICAL TYPE DEFINITIONS // This section is identical across all React Navigation libdefs and contains // shared definitions. We wish we could make it DRY and import from a shared // definition, but that isn't yet possible. //--------------------------------------------------------------------------- /** * We start with some definitions that we have copy-pasted from React Native * source files. */ // This is a bastardization of the true StyleObj type located in // react-native/Libraries/StyleSheet/StyleSheetTypes. We unfortunately can't // import that here, and it's too lengthy (and consequently too brittle) to // copy-paste here either. declare type StyleObj = | null | void | number | false | '' | $ReadOnlyArray | { [name: string]: any, ... }; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; declare type AnimatedTextStyleProp = StyleObj; // Vaguely copied from // react-native/Libraries/Animated/src/animations/Animation.js declare type EndResult = { finished: boolean, ... }; declare type EndCallback = (result: EndResult) => void; declare interface Animation { start( fromValue: number, onUpdate: (value: number) => void, onEnd: ?EndCallback, previousAnimation: ?Animation, animatedValue: AnimatedValue, ): void; stop(): void; } declare type AnimationConfig = { isInteraction?: boolean, useNativeDriver: boolean, onComplete?: ?EndCallback, iterations?: number, ... }; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedTracking.js declare interface AnimatedTracking { constructor( value: AnimatedValue, parent: any, animationClass: any, animationConfig: Object, callback?: ?EndCallback, ): void; update(): void; } // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedValue.js declare type ValueListenerCallback = (state: { value: number, ... }) => void; declare interface AnimatedValue { constructor(value: number): void; setValue(value: number): void; setOffset(offset: number): void; flattenOffset(): void; extractOffset(): void; addListener(callback: ValueListenerCallback): string; removeListener(id: string): void; removeAllListeners(): void; stopAnimation(callback?: ?(value: number) => void): void; resetAnimation(callback?: ?(value: number) => void): void; interpolate(config: InterpolationConfigType): AnimatedInterpolation; animate(animation: Animation, callback: ?EndCallback): void; stopTracking(): void; track(tracking: AnimatedTracking): void; } // Copied from // react-native/Libraries/Animated/src/animations/TimingAnimation.js declare type TimingAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, easing?: (value: number) => number, duration?: number, delay?: number, ... }; // Copied from // react-native/Libraries/Animated/src/animations/SpringAnimation.js declare type SpringAnimationConfigSingle = AnimationConfig & { toValue: number | AnimatedValue, overshootClamping?: boolean, restDisplacementThreshold?: number, restSpeedThreshold?: number, velocity?: number, bounciness?: number, speed?: number, tension?: number, friction?: number, stiffness?: number, damping?: number, mass?: number, delay?: number, ... }; // Copied from react-native/Libraries/Types/CoreEventTypes.js declare type SyntheticEvent = $ReadOnly<{| bubbles: ?boolean, cancelable: ?boolean, currentTarget: number, defaultPrevented: ?boolean, dispatchConfig: $ReadOnly<{| registrationName: string, |}>, eventPhase: ?number, preventDefault: () => void, isDefaultPrevented: () => boolean, stopPropagation: () => void, isPropagationStopped: () => boolean, isTrusted: ?boolean, nativeEvent: T, persist: () => void, target: ?number, timeStamp: number, type: ?string, |}>; declare type Layout = $ReadOnly<{| x: number, y: number, width: number, height: number, |}>; declare type LayoutEvent = SyntheticEvent< $ReadOnly<{| layout: Layout, |}>, >; declare type BlurEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type FocusEvent = SyntheticEvent< $ReadOnly<{| target: number, |}>, >; declare type ResponderSyntheticEvent = $ReadOnly<{| ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray< $ReadOnly<{| touchActive: boolean, startPageX: number, startPageY: number, startTimeStamp: number, currentPageX: number, currentPageY: number, currentTimeStamp: number, previousPageX: number, previousPageY: number, previousTimeStamp: number, |}>, >, |}>, |}>; declare type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, identifier: number, locationX: number, locationY: number, pageX: number, pageY: number, target: ?number, timestamp: number, touches: $ReadOnlyArray<$PropertyType>, |}>, >; // Vaguely copied from // react-native/Libraries/Animated/src/nodes/AnimatedInterpolation.js declare type ExtrapolateType = 'extend' | 'identity' | 'clamp'; declare type InterpolationConfigType = { inputRange: Array, outputRange: Array | Array, easing?: (input: number) => number, extrapolate?: ExtrapolateType, extrapolateLeft?: ExtrapolateType, extrapolateRight?: ExtrapolateType, ... }; declare interface AnimatedInterpolation { interpolate(config: InterpolationConfigType): AnimatedInterpolation; } // Copied from react-native/Libraries/Components/View/ViewAccessibility.js declare type AccessibilityRole = | 'none' | 'button' | 'link' | 'search' | 'image' | 'keyboardkey' | 'text' | 'adjustable' | 'imagebutton' | 'header' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menu' | 'menubar' | 'menuitem' | 'progressbar' | 'radio' | 'radiogroup' | 'scrollbar' | 'spinbutton' | 'switch' | 'tab' | 'tablist' | 'timer' | 'toolbar'; declare type AccessibilityActionInfo = $ReadOnly<{ name: string, label?: string, ... }>; declare type AccessibilityActionEvent = SyntheticEvent< $ReadOnly<{actionName: string, ...}>, >; declare type AccessibilityState = { disabled?: boolean, selected?: boolean, checked?: ?boolean | 'mixed', busy?: boolean, expanded?: boolean, ... }; declare type AccessibilityValue = $ReadOnly<{| min?: number, max?: number, now?: number, text?: string, |}>; // Copied from // react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js declare type Stringish = string; declare type EdgeInsetsProp = $ReadOnly<$Partial>; declare type TouchableWithoutFeedbackProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, accessibilityElementsHidden?: ?boolean, accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityLabel?: ?Stringish, accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, children?: ?React$Node, delayLongPress?: ?number, delayPressIn?: ?number, delayPressOut?: ?number, disabled?: ?boolean, focusable?: ?boolean, hitSlop?: ?EdgeInsetsProp, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), nativeID?: ?string, onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, onBlur?: ?(event: BlurEvent) => mixed, onFocus?: ?(event: FocusEvent) => mixed, onLayout?: ?(event: LayoutEvent) => mixed, onLongPress?: ?(event: PressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, pressRetentionOffset?: ?EdgeInsetsProp, rejectResponderTermination?: ?boolean, testID?: ?string, touchSoundDisabled?: ?boolean, |}>; // Copied from react-native/Libraries/Image/ImageSource.js declare type ImageURISource = $ReadOnly<{ uri?: ?string, bundle?: ?string, method?: ?string, headers?: ?Object, body?: ?string, cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), width?: ?number, height?: ?number, scale?: ?number, ... }>; /** * The following is copied from react-native-gesture-handler's libdef */ declare type StateUndetermined = 0; declare type StateFailed = 1; declare type StateBegan = 2; declare type StateCancelled = 3; declare type StateActive = 4; declare type StateEnd = 5; declare type GestureHandlerState = | StateUndetermined | StateFailed | StateBegan | StateCancelled | StateActive | StateEnd; declare type $SyntheticEvent = { +nativeEvent: $ReadOnly<$Exact>, ... }; declare type $Event = $SyntheticEvent<{ handlerTag: number, numberOfPointers: number, state: GestureHandlerState, oldState: GestureHandlerState, ...$Exact, ... }>; declare type $EventHandlers = {| onGestureEvent?: ($Event) => mixed, onHandlerStateChange?: ($Event) => mixed, onBegan?: ($Event) => mixed, onFailed?: ($Event) => mixed, onCancelled?: ($Event) => mixed, onActivated?: ($Event) => mixed, onEnded?: ($Event) => mixed, |}; declare type HitSlop = | number | {| left?: number, top?: number, right?: number, bottom?: number, vertical?: number, horizontal?: number, width?: number, height?: number, |} | {| width: number, left: number, |} | {| width: number, right: number, |} | {| height: number, top: number, |} | {| height: number, bottom: number, |}; declare type $GestureHandlerProps< AdditionalProps: {...}, ExtraEventsProps: {...} > = $ReadOnly<{| ...$Exact, ...$EventHandlers, id?: string, enabled?: boolean, waitFor?: React$Ref | Array>, simultaneousHandlers?: React$Ref | Array>, shouldCancelWhenOutside?: boolean, minPointers?: number, hitSlop?: HitSlop, children?: React$Node, |}>; declare type PanGestureHandlerProps = $GestureHandlerProps< { activeOffsetY?: number | [number, number], activeOffsetX?: number | [number, number], failOffsetY?: number | [number, number], failOffsetX?: number | [number, number], minDist?: number, minVelocity?: number, minVelocityX?: number, minVelocityY?: number, minPointers?: number, maxPointers?: number, avgTouches?: boolean, ... }, { x: number, y: number, absoluteX: number, absoluteY: number, translationX: number, translationY: number, velocityX: number, velocityY: number, ... } >; /** * MAGIC */ declare type $If = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), Test, Then, Else, >; declare type $IsA = $Call< (Y => true) & (mixed => false), X, >; declare type $IsUndefined = $IsA; declare type $Partial = $ReadOnly<$Rest>; + // If { ...T, ... } counts as a T, then we're inexact + declare type $IsExact = $Call< + (T => false) & (mixed => true), + { ...T, ... }, + >; + /** * Actions, state, etc. */ declare export type ScreenParams = { +[key: string]: mixed, ... }; declare export type BackAction = {| +type: 'GO_BACK', +source?: string, +target?: string, |}; declare export type NavigateAction = {| +type: 'NAVIGATE', +payload: | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type ResetAction = {| +type: 'RESET', +payload: StaleNavigationState, +source?: string, +target?: string, |}; declare export type SetParamsAction = {| +type: 'SET_PARAMS', +payload: {| +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type CommonAction = | BackAction | NavigateAction | ResetAction | SetParamsAction; declare type NavigateActionCreator = {| (routeName: string, params?: ScreenParams): NavigateAction, ( | {| +key: string, +params?: ScreenParams |} | {| +name: string, +key?: string, +params?: ScreenParams |}, ): NavigateAction, |}; declare export type CommonActionsType = {| +navigate: NavigateActionCreator, +goBack: () => BackAction, +reset: (state: PossiblyStaleNavigationState) => ResetAction, +setParams: (params: ScreenParams) => SetParamsAction, |}; declare export type GenericNavigationAction = {| +type: string, +payload?: { +[key: string]: mixed, ... }, +source?: string, +target?: string, |}; declare export type LeafRoute = {| +key: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StateRoute = {| ...LeafRoute, +state: NavigationState | StaleNavigationState, |}; declare export type Route = | LeafRoute | StateRoute; declare export type NavigationState = {| +key: string, +index: number, +routeNames: $ReadOnlyArray, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type: string, +stale: false, |}; declare export type StaleLeafRoute = {| +key?: string, +name: RouteName, +params?: ScreenParams, |}; declare export type StaleStateRoute = {| ...StaleLeafRoute, +state: StaleNavigationState, |}; declare export type StaleRoute = | StaleLeafRoute | StaleStateRoute; declare export type StaleNavigationState = {| // It's possible to pass React Nav a StaleNavigationState with an undefined // index, but React Nav will always return one with the index set. This is // the same as for the type property below, but in the case of index we tend // to rely on it being set more... +index: number, +history?: $ReadOnlyArray, +routes: $ReadOnlyArray>, +type?: string, +stale?: true, |}; declare export type PossiblyStaleNavigationState = | NavigationState | StaleNavigationState; declare export type PossiblyStaleRoute = | Route | StaleRoute; /** * Routers */ declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, > = { +[key: string]: (...args: any) => (Action | State => Action), ... }; declare export type DefaultRouterOptions = { +initialRouteName?: string, ... }; declare export type RouterFactory< State: NavigationState, Action: GenericNavigationAction, RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, +routeParamList: ParamListBase, |}; declare export type Router< State: NavigationState, Action: GenericNavigationAction, > = {| +type: $PropertyType, +getInitialState: (options: RouterConfigOptions) => State, +getRehydratedState: ( partialState: PossiblyStaleNavigationState, options: RouterConfigOptions, ) => State, +getStateForRouteNamesChange: ( state: State, options: RouterConfigOptions, ) => State, +getStateForRouteFocus: (state: State, key: string) => State, +getStateForAction: ( state: State, action: Action, options: RouterConfigOptions, ) => ?PossiblyStaleNavigationState; +shouldActionChangeFocus: (action: GenericNavigationAction) => boolean, +actionCreators?: ActionCreators, |}; /** * Stack actions and router */ declare export type StackNavigationState = {| ...NavigationState, +type: 'stack', |}; declare export type ReplaceAction = {| +type: 'REPLACE', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PushAction = {| +type: 'PUSH', +payload: {| +name: string, +key?: ?string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type PopAction = {| +type: 'POP', +payload: {| +count: number |}, +source?: string, +target?: string, |}; declare export type PopToTopAction = {| +type: 'POP_TO_TOP', +source?: string, +target?: string, |}; declare export type StackAction = | CommonAction | ReplaceAction | PushAction | PopAction | PopToTopAction; declare export type StackActionsType = {| +replace: (routeName: string, params?: ScreenParams) => ReplaceAction, +push: (routeName: string, params?: ScreenParams) => PushAction, +pop: (count?: number) => PopAction, +popToTop: () => PopToTopAction, |}; declare export type StackRouterOptions = $Exact; /** * Tab actions and router */ declare export type TabNavigationState = {| ...NavigationState, +type: 'tab', +history: $ReadOnlyArray<{| type: 'route', key: string |}>, |}; declare export type JumpToAction = {| +type: 'JUMP_TO', +payload: {| +name: string, +params?: ScreenParams |}, +source?: string, +target?: string, |}; declare export type TabAction = | CommonAction | JumpToAction; declare export type TabActionsType = {| +jumpTo: string => JumpToAction, |}; declare export type TabRouterOptions = {| ...$Exact, +backBehavior?: 'initialRoute' | 'order' | 'history' | 'none', |}; /** * Drawer actions and router */ declare type DrawerHistoryEntry = | {| +type: 'route', +key: string |} | {| +type: 'drawer' |}; declare export type DrawerNavigationState = {| ...NavigationState, +type: 'drawer', +history: $ReadOnlyArray, |}; declare export type OpenDrawerAction = {| +type: 'OPEN_DRAWER', +source?: string, +target?: string, |}; declare export type CloseDrawerAction = {| +type: 'CLOSE_DRAWER', +source?: string, +target?: string, |}; declare export type ToggleDrawerAction = {| +type: 'TOGGLE_DRAWER', +source?: string, +target?: string, |}; declare export type DrawerAction = | TabAction | OpenDrawerAction | CloseDrawerAction | ToggleDrawerAction; declare export type DrawerActionsType = {| ...TabActionsType, +openDrawer: () => OpenDrawerAction, +closeDrawer: () => CloseDrawerAction, +toggleDrawer: () => ToggleDrawerAction, |}; declare export type DrawerRouterOptions = {| ...TabRouterOptions, +openByDefault?: boolean, |}; /** * Events */ declare export type EventMapBase = { +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, ... }; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, {| |}, >; declare type EventDataProperties = $If< $IsUndefined, {| |}, {| +data: Data |}, >; declare type EventArg< EventName: string, CanPreventDefault: ?boolean = false, Data = void, > = {| ...EventPreventDefaultProperties, ...EventDataProperties, +type: EventName, +target?: string, |}; declare type GlobalEventMap = {| +state: {| +data: {| +state: State |}, +canPreventDefault: false |}, |}; declare type EventMapCore = {| ...GlobalEventMap, +focus: {| +data: void, +canPreventDefault: false |}, +blur: {| +data: void, +canPreventDefault: false |}, +beforeRemove: {| +data: {| +action: GenericNavigationAction |}, +canPreventDefault: true, |}, |}; declare type EventListenerCallback< EventName: string, State: PossiblyStaleNavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = (e: EventArg< EventName, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'canPreventDefault', >, $PropertyType< $ElementType< {| ...EventMap, ...EventMapCore |}, EventName, >, 'data', >, >) => mixed; /** * Navigation prop */ + declare type PartialWithMergeProperty = $If< + $IsExact, + { ...$Partial, +merge: true }, + { ...$Partial, +merge: true, ... }, + >; + + declare type EitherExactOrPartialWithMergeProperty = + | ParamsType + | PartialWithMergeProperty; + declare export type SimpleNavigate = >( routeName: DestinationRouteName, - params: $ElementType, + params: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, ) => void; declare export type Navigate = & SimpleNavigate & >( - route: + route: $If< + $IsUndefined<$ElementType>, + | {| +key: string |} | + {| +name: DestinationRouteName, +key?: string |}, | {| +key: string, - +params?: $ElementType, - |} - | {| + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, + |} | + {| +name: DestinationRouteName, +key?: string, - +params?: $ElementType, + +params?: EitherExactOrPartialWithMergeProperty< + $ElementType, + >, |}, + >, ) => void; declare type NavigationHelpers< ParamList: ParamListBase, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, EventMap: EventMapBase = EventMapCore, > = { +navigate: Navigate, +dispatch: ( action: | GenericNavigationAction | (State => GenericNavigationAction), ) => void, +reset: PossiblyStaleNavigationState => void, +goBack: () => void, +isFocused: () => boolean, +canGoBack: () => boolean, +dangerouslyGetParent: >() => ?Parent, +dangerouslyGetState: () => NavigationState, +addListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => () => void, +removeListener: |}, >>( name: EventName, callback: EventListenerCallback, ) => void, ... }; + declare type SetParamsInput< + ParamList: ParamListBase, + RouteName: $Keys = $Keys, + > = $If< + $IsUndefined<$ElementType>, + empty, + $Partial<$NonMaybeType<$ElementType>>, + >; + declare export type NavigationProp< ParamList: ParamListBase, RouteName: $Keys = $Keys, State: PossiblyStaleNavigationState = PossiblyStaleNavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = { ...$Exact>, +setOptions: (options: $Partial) => void, - +setParams: ( - params: $If< - $IsUndefined<$ElementType>, - empty, - $Partial<$NonMaybeType<$ElementType>>, - >, - ) => void, + +setParams: (params: SetParamsInput) => void, ... }; /** * CreateNavigator */ declare export type RouteProp< ParamList: ParamListBase, RouteName: $Keys, > = {| ...LeafRoute, +params: $ElementType, |}; declare export type ScreenListeners< State: NavigationState = NavigationState, EventMap: EventMapBase = EventMapCore, > = $ObjMapi< {| [name: $Keys]: empty |}, >(K, empty) => EventListenerCallback, >; declare type BaseScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = {| +name: RouteName, +options?: | ScreenOptions | ({| route: RouteProp, navigation: NavProp, |}) => ScreenOptions, +listeners?: | ScreenListeners | ({| route: RouteProp, navigation: NavProp, |}) => ScreenListeners, +initialParams?: $Partial<$ElementType>, |}; declare export type ScreenProps< ParamList: ParamListBase, NavProp, RouteName: $Keys = $Keys, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +component: React$ComponentType<{| route: RouteProp, navigation: NavProp, |}>, |} | {| ...BaseScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >, +children: ({| route: RouteProp, navigation: NavProp, |}) => React$Node, |}; declare export type ScreenComponent< GlobalParamList: ParamListBase, ParamList: ParamListBase, State: NavigationState = NavigationState, ScreenOptions: {...} = {...}, EventMap: EventMapBase = EventMapCore, > = < RouteName: $Keys, NavProp: NavigationProp< GlobalParamList, RouteName, State, ScreenOptions, EventMap, >, >(props: ScreenProps< ParamList, NavProp, RouteName, State, ScreenOptions, EventMap, >) => React$Node; declare type ScreenOptionsProp = {| +screenOptions?: | ScreenOptions | ({| route: LeafRoute<>, navigation: NavProp |}) => ScreenOptions, |}; declare export type ExtraNavigatorPropsBase = { ...$Exact, +children?: React$Node, ... }; declare export type NavigatorPropsBase = { ...$Exact, ...ScreenOptionsProp, ... }; declare export type CreateNavigator< State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, ExtraNavigatorProps: ExtraNavigatorPropsBase, > = < GlobalParamList: ParamListBase, ParamList: ParamListBase, NavProp: NavigationHelpers< GlobalParamList, State, EventMap, >, >() => {| +Screen: ScreenComponent< GlobalParamList, ParamList, State, ScreenOptions, EventMap, >, +Navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, |}; declare export type CreateNavigatorFactory = < State: NavigationState, ScreenOptions: {...}, EventMap: EventMapBase, NavProp: NavigationHelpers< ParamListBase, State, EventMap, >, ExtraNavigatorProps: ExtraNavigatorPropsBase, >( navigator: React$ComponentType<{| ...$Exact, ...ScreenOptionsProp, |}>, ) => CreateNavigator; /** * useNavigationBuilder */ declare export type Descriptor< NavProp, ScreenOptions: {...} = {...}, > = {| +render: () => React$Node, +options: $ReadOnly, +navigation: NavProp, |}; declare export type UseNavigationBuilder = < State: NavigationState, Action: GenericNavigationAction, ScreenOptions: {...}, RouterOptions: DefaultRouterOptions, NavProp, >( routerFactory: RouterFactory, options: {| ...$Exact, ...ScreenOptionsProp, +children?: React$Node, |}, ) => {| +state: State, +descriptors: {| +[key: string]: Descriptor |}, +navigation: NavProp, |}; /** * EdgeInsets */ declare type EdgeInsets = {| +top: number, +right: number, +bottom: number, +left: number, |}; /** * TransitionPreset */ declare export type TransitionSpec = | {| animation: 'spring', config: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |} | {| animation: 'timing', config: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, ... }, >, |}; declare export type StackCardInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +index: number, +closing: AnimatedInterpolation, +swiping: AnimatedInterpolation, +inverted: AnimatedInterpolation, +layouts: {| +screen: {| +width: number, +height: number |}, |}, +insets: EdgeInsets, |}; declare export type StackCardInterpolatedStyle = {| containerStyle?: AnimatedViewStyleProp, cardStyle?: AnimatedViewStyleProp, overlayStyle?: AnimatedViewStyleProp, shadowStyle?: AnimatedViewStyleProp, |}; declare export type StackCardStyleInterpolator = ( props: StackCardInterpolationProps, ) => StackCardInterpolatedStyle; declare export type StackHeaderInterpolationProps = {| +current: {| +progress: AnimatedInterpolation, |}, +next?: {| +progress: AnimatedInterpolation, |}, +layouts: {| +header: {| +width: number, +height: number |}, +screen: {| +width: number, +height: number |}, +title?: {| +width: number, +height: number |}, +leftLabel?: {| +width: number, +height: number |}, |}, |}; declare export type StackHeaderInterpolatedStyle = {| leftLabelStyle?: AnimatedViewStyleProp, leftButtonStyle?: AnimatedViewStyleProp, rightButtonStyle?: AnimatedViewStyleProp, titleStyle?: AnimatedViewStyleProp, backgroundStyle?: AnimatedViewStyleProp, |}; declare export type StackHeaderStyleInterpolator = ( props: StackHeaderInterpolationProps, ) => StackHeaderInterpolatedStyle; declare type GestureDirection = | 'horizontal' | 'horizontal-inverted' | 'vertical' | 'vertical-inverted'; declare export type TransitionPreset = {| +gestureDirection: GestureDirection, +transitionSpec: {| +open: TransitionSpec, +close: TransitionSpec, |}, +cardStyleInterpolator: StackCardStyleInterpolator, +headerStyleInterpolator: StackHeaderStyleInterpolator, |}; /** * Stack options */ declare export type StackDescriptor = Descriptor< StackNavigationProp<>, StackOptions, >; declare type Scene = {| +route: T, +descriptor: StackDescriptor, +progress: {| +current: AnimatedInterpolation, +next?: AnimatedInterpolation, +previous?: AnimatedInterpolation, |}, |}; declare export type StackHeaderProps = {| +mode: 'float' | 'screen', +layout: {| +width: number, +height: number |}, +insets: EdgeInsets, +scene: Scene>, +previous?: Scene>, +navigation: StackNavigationProp, +styleInterpolator: StackHeaderStyleInterpolator, |}; declare export type StackHeaderLeftButtonProps = $Partial<{| +onPress: (() => void), +pressColorAndroid: string; +backImage: (props: {| tintColor: string |}) => React$Node, +tintColor: string, +label: string, +truncatedLabel: string, +labelVisible: boolean, +labelStyle: AnimatedTextStyleProp, +allowFontScaling: boolean, +onLabelLayout: LayoutEvent => void, +screenLayout: {| +width: number, +height: number |}, +titleLayout: {| +width: number, +height: number |}, +canGoBack: boolean, |}>; declare type StackHeaderTitleInputBase = { +onLayout: LayoutEvent => void, +children: string, +allowFontScaling: ?boolean, +tintColor: ?string, +style: ?AnimatedTextStyleProp, ... }; declare export type StackHeaderTitleInputProps = $Exact; declare export type StackOptions = $Partial<{| +title: string, +header: StackHeaderProps => React$Node, +headerShown: boolean, +cardShadowEnabled: boolean, +cardOverlayEnabled: boolean, +cardOverlay: {| style: ViewStyleProp |} => React$Node, +cardStyle: ViewStyleProp, +animationEnabled: boolean, +animationTypeForReplace: 'push' | 'pop', +gestureEnabled: boolean, +gestureResponseDistance: {| vertical?: number, horizontal?: number |}, +gestureVelocityImpact: number, +safeAreaInsets: $Partial, // Transition ...TransitionPreset, // Header +headerTitle: string | (StackHeaderTitleInputProps => React$Node), +headerTitleAlign: 'left' | 'center', +headerTitleStyle: AnimatedTextStyleProp, +headerTitleContainerStyle: ViewStyleProp, +headerTintColor: string, +headerTitleAllowFontScaling: boolean, +headerBackAllowFontScaling: boolean, +headerBackTitle: string | null, +headerBackTitleStyle: TextStyleProp, +headerBackTitleVisible: boolean, +headerTruncatedBackTitle: string, +headerLeft: StackHeaderLeftButtonProps => React$Node, +headerLeftContainerStyle: ViewStyleProp, +headerRight: {| tintColor?: string |} => React$Node, +headerRightContainerStyle: ViewStyleProp, +headerBackImage: $PropertyType, +headerPressColorAndroid: string, +headerBackground: ({| style: ViewStyleProp |}) => React$Node, +headerStyle: ViewStyleProp, +headerTransparent: boolean, +headerStatusBarHeight: number, |}>; /** * Stack navigation prop */ declare export type StackNavigationEventMap = {| ...EventMapCore, +transitionStart: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +transitionEnd: {| +data: {| +closing: boolean |}, +canPreventDefault: false, |}, +gestureStart: {| +data: void, +canPreventDefault: false |}, +gestureEnd: {| +data: void, +canPreventDefault: false |}, +gestureCancel: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactStackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = { ...$Exact>, +replace: SimpleNavigate, +push: SimpleNavigate, +pop: (count?: number) => void, +popToTop: () => void, ... }; declare export type StackNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = StackOptions, EventMap: EventMapBase = StackNavigationEventMap, > = $Exact>; /** * Miscellaneous stack exports */ declare type StackNavigationConfig = {| +mode?: 'card' | 'modal', +headerMode?: 'float' | 'screen' | 'none', +keyboardHandlingEnabled?: boolean, +detachInactiveScreens?: boolean, |}; declare export type ExtraStackNavigatorProps = {| ...$Exact, ...StackRouterOptions, ...StackNavigationConfig, |}; declare export type StackNavigatorProps< NavProp: InexactStackNavigationProp<> = StackNavigationProp<>, > = {| ...ExtraStackNavigatorProps, ...ScreenOptionsProp, |}; /** * Bottom tab options */ declare export type BottomTabBarButtonProps = {| ...$Diff< TouchableWithoutFeedbackProps, {| onPress?: ?(event: PressEvent) => mixed |}, >, +to?: string, +children: React$Node, +onPress?: (MouseEvent | PressEvent) => void, |}; declare export type TabBarVisibilityAnimationConfig = | {| +animation: 'spring', +config?: $Diff< SpringAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |} | {| +animation: 'timing', +config?: $Diff< TimingAnimationConfigSingle, { toValue: number | AnimatedValue, useNativeDriver: boolean, ... }, >, |}; declare export type BottomTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| focused: boolean, color: string |}) => React$Node, +tabBarIcon: ({| focused: boolean, color: string, size: number, |}) => React$Node, +tabBarBadge: number | string, +tabBarBadgeStyle: TextStyleProp, +tabBarAccessibilityLabel: string, +tabBarTestID: string, +tabBarVisible: boolean, +tabBarVisibilityAnimationConfig: $Partial<{| +show: TabBarVisibilityAnimationConfig, +hide: TabBarVisibilityAnimationConfig, |}>, +tabBarButton: BottomTabBarButtonProps => React$Node, +unmountOnBlur: boolean, |}>; /** * Bottom tab navigation prop */ declare export type BottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, |}; declare type InexactTabNavigationProp< ParamList: ParamListBase, RouteName: $Keys, Options: {...}, EventMap: EventMapBase, > = { ...$Exact>, +jumpTo: SimpleNavigate, ... }; declare export type InexactBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type BottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = BottomTabOptions, EventMap: EventMapBase = BottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous bottom tab exports */ declare export type BottomTabDescriptor = Descriptor< BottomTabNavigationProp<>, BottomTabOptions, >; declare export type BottomTabBarOptions = $Partial<{| +keyboardHidesTabBar: boolean, +activeTintColor: string, +inactiveTintColor: string, +activeBackgroundColor: string, +inactiveBackgroundColor: string, +allowFontScaling: boolean, +showLabel: boolean, +showIcon: boolean, +labelStyle: TextStyleProp, +iconStyle: TextStyleProp, +tabStyle: ViewStyleProp, +labelPosition: 'beside-icon' | 'below-icon', +adaptive: boolean, +safeAreaInsets: $Partial, +style: ViewStyleProp, |}>; declare type BottomTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: BottomTabNavigationProp<>, +descriptors: {| +[key: string]: BottomTabDescriptor |}, |}; declare export type BottomTabBarProps = {| ...BottomTabBarOptions, ...BottomTabNavigationBuilderResult, |} declare type BottomTabNavigationConfig = {| +lazy?: boolean, +tabBar?: BottomTabBarProps => React$Node, +tabBarOptions?: BottomTabBarOptions, +detachInactiveScreens?: boolean, |}; declare export type ExtraBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...BottomTabNavigationConfig, |}; declare export type BottomTabNavigatorProps< NavProp: InexactBottomTabNavigationProp<> = BottomTabNavigationProp<>, > = {| ...ExtraBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material bottom tab options */ declare export type MaterialBottomTabOptions = $Partial<{| +title: string, +tabBarColor: string, +tabBarLabel: string, +tabBarIcon: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarBadge: boolean | number | string, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material bottom tab navigation prop */ declare export type MaterialBottomTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, |}; declare export type InexactMaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialBottomTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialBottomTabOptions, EventMap: EventMapBase = MaterialBottomTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material bottom tab exports */ declare export type PaperFont = {| +fontFamily: string, +fontWeight?: | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', |}; declare export type PaperFonts = {| +regular: PaperFont, +medium: PaperFont, +light: PaperFont, +thin: PaperFont, |}; declare export type PaperTheme = {| +dark: boolean, +mode?: 'adaptive' | 'exact', +roundness: number, +colors: {| +primary: string, +background: string, +surface: string, +accent: string, +error: string, +text: string, +onSurface: string, +onBackground: string, +disabled: string, +placeholder: string, +backdrop: string, +notification: string, |}, +fonts: PaperFonts, +animation: {| +scale: number, |}, |}; declare export type PaperRoute = {| +key: string, +title?: string, +icon?: any, +badge?: string | number | boolean, +color?: string, +accessibilityLabel?: string, +testID?: string, |}; declare export type PaperTouchableProps = {| ...TouchableWithoutFeedbackProps, +key: string, +route: PaperRoute, +children: React$Node, +borderless?: boolean, +centered?: boolean, +rippleColor?: string, |}; declare export type MaterialBottomTabNavigationConfig = {| +shifting?: boolean, +labeled?: boolean, +renderTouchable?: PaperTouchableProps => React$Node, +activeColor?: string, +inactiveColor?: string, +sceneAnimationEnabled?: boolean, +keyboardHidesNavigationBar?: boolean, +barStyle?: ViewStyleProp, +style?: ViewStyleProp, +theme?: PaperTheme, |}; declare export type ExtraMaterialBottomTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialBottomTabNavigationConfig, |}; declare export type MaterialBottomTabNavigatorProps< NavProp: InexactMaterialBottomTabNavigationProp<> = MaterialBottomTabNavigationProp<>, > = {| ...ExtraMaterialBottomTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Material top tab options */ declare export type MaterialTopTabOptions = $Partial<{| +title: string, +tabBarLabel: | string | ({| +focused: boolean, +color: string |}) => React$Node, +tabBarIcon: ({| +focused: boolean, +color: string |}) => React$Node, +tabBarAccessibilityLabel: string, +tabBarTestID: string, |}>; /** * Material top tab navigation prop */ declare export type MaterialTopTabNavigationEventMap = {| ...EventMapCore, +tabPress: {| +data: void, +canPreventDefault: true |}, +tabLongPress: {| +data: void, +canPreventDefault: false |}, +swipeStart: {| +data: void, +canPreventDefault: false |}, +swipeEnd: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactMaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = InexactTabNavigationProp< ParamList, RouteName, Options, EventMap, >; declare export type MaterialTopTabNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = MaterialTopTabOptions, EventMap: EventMapBase = MaterialTopTabNavigationEventMap, > = $Exact>; /** * Miscellaneous material top tab exports */ declare type MaterialTopTabPagerCommonProps = {| +keyboardDismissMode: 'none' | 'on-drag' | 'auto', +swipeEnabled: boolean, +swipeVelocityImpact?: number, +springVelocityScale?: number, +springConfig: $Partial<{| +damping: number, +mass: number, +stiffness: number, +restSpeedThreshold: number, +restDisplacementThreshold: number, |}>, +timingConfig: $Partial<{| +duration: number, |}>, |}; declare export type MaterialTopTabPagerProps = {| ...MaterialTopTabPagerCommonProps, +onSwipeStart?: () => void, +onSwipeEnd?: () => void, +onIndexChange: (index: number) => void, +navigationState: TabNavigationState, +layout: {| +width: number, +height: number |}, +removeClippedSubviews: boolean, +children: ({| +addListener: (type: 'enter', listener: number => void) => void, +removeListener: (type: 'enter', listener: number => void) => void, +position: any, // Reanimated.Node +render: React$Node => React$Node, +jumpTo: string => void, |}) => React$Node, +gestureHandlerProps: PanGestureHandlerProps, |}; declare export type MaterialTopTabBarIndicatorProps = {| +navigationState: TabNavigationState, +width: string, +style?: ViewStyleProp, +getTabWidth: number => number, |}; declare export type MaterialTopTabBarOptions = $Partial<{| +scrollEnabled: boolean, +bounces: boolean, +pressColor: string, +pressOpacity: number, +getAccessible: ({| +route: Route<> |}) => boolean, +renderBadge: ({| +route: Route<> |}) => React$Node, +renderIndicator: MaterialTopTabBarIndicatorProps => React$Node, +tabStyle: ViewStyleProp, +indicatorStyle: ViewStyleProp, +indicatorContainerStyle: ViewStyleProp, +labelStyle: TextStyleProp, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, +activeTintColor: string, +inactiveTintColor: string, +iconStyle: ViewStyleProp, +labelStyle: TextStyleProp, +showLabel: boolean, +showIcon: boolean, +allowFontScaling: boolean, |}>; declare export type MaterialTopTabDescriptor = Descriptor< MaterialBottomTabNavigationProp<>, MaterialBottomTabOptions, >; declare type MaterialTopTabNavigationBuilderResult = {| +state: TabNavigationState, +navigation: MaterialTopTabNavigationProp<>, +descriptors: {| +[key: string]: MaterialTopTabDescriptor |}, |}; declare export type MaterialTopTabBarProps = {| ...MaterialTopTabBarOptions, ...MaterialTopTabNavigationBuilderResult, +layout: {| +width: number, +height: number |}, +position: any, // Reanimated.Node +jumpTo: string => void, |}; declare export type MaterialTopTabNavigationConfig = {| ...$Partial, +position?: any, // Reanimated.Value +tabBarPosition?: 'top' | 'bottom', +initialLayout?: $Partial<{| +width: number, +height: number |}>, +lazy?: boolean, +lazyPreloadDistance?: number, +removeClippedSubviews?: boolean, +sceneContainerStyle?: ViewStyleProp, +style?: ViewStyleProp, +gestureHandlerProps?: PanGestureHandlerProps, +pager?: MaterialTopTabPagerProps => React$Node, +lazyPlaceholder?: ({| +route: Route<> |}) => React$Node, +tabBar?: MaterialTopTabBarProps => React$Node, +tabBarOptions?: MaterialTopTabBarOptions, |}; declare export type ExtraMaterialTopTabNavigatorProps = {| ...$Exact, ...TabRouterOptions, ...MaterialTopTabNavigationConfig, |}; declare export type MaterialTopTabNavigatorProps< NavProp: InexactMaterialTopTabNavigationProp<> = MaterialTopTabNavigationProp<>, > = {| ...ExtraMaterialTopTabNavigatorProps, ...ScreenOptionsProp, |}; /** * Drawer options */ declare export type DrawerOptions = $Partial<{| title: string, drawerLabel: | string | ({| +color: string, +focused: boolean |}) => React$Node, drawerIcon: ({| +color: string, +size: number, +focused: boolean, |}) => React$Node, gestureEnabled: boolean, swipeEnabled: boolean, unmountOnBlur: boolean, |}>; /** * Drawer navigation prop */ declare export type DrawerNavigationEventMap = {| ...EventMapCore, +drawerOpen: {| +data: void, +canPreventDefault: false |}, +drawerClose: {| +data: void, +canPreventDefault: false |}, |}; declare export type InexactDrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = { ...$Exact>, +jumpTo: SimpleNavigate, +openDrawer: () => void, +closeDrawer: () => void, +toggleDrawer: () => void, ... }; declare export type DrawerNavigationProp< ParamList: ParamListBase = ParamListBase, RouteName: $Keys = $Keys, Options: {...} = DrawerOptions, EventMap: EventMapBase = DrawerNavigationEventMap, > = $Exact>; /** * Miscellaneous drawer exports */ declare export type DrawerDescriptor = Descriptor< DrawerNavigationProp<>, DrawerOptions, >; declare export type DrawerItemListBaseOptions = $Partial<{| +activeTintColor: string, +activeBackgroundColor: string, +inactiveTintColor: string, +inactiveBackgroundColor: string, +itemStyle: ViewStyleProp, +labelStyle: TextStyleProp, |}>; declare export type DrawerContentOptions = $Partial<{| ...DrawerItemListBaseOptions, +contentContainerStyle: ViewStyleProp, +style: ViewStyleProp, |}>; declare type DrawerNavigationBuilderResult = {| +state: DrawerNavigationState, +navigation: DrawerNavigationProp<>, +descriptors: {| +[key: string]: DrawerDescriptor |}, |}; declare export type DrawerContentProps = {| ...DrawerContentOptions, ...DrawerNavigationBuilderResult, +progress: any, // Reanimated.Node |}; declare export type DrawerNavigationConfig = {| +drawerPosition?: 'left' | 'right', +drawerType?: 'front' | 'back' | 'slide' | 'permanent', +edgeWidth?: number, +hideStatusBar?: boolean, +keyboardDismissMode?: 'on-drag' | 'none', +minSwipeDistance?: number, +overlayColor?: string, +statusBarAnimation?: 'slide' | 'none' | 'fade', +gestureHandlerProps?: PanGestureHandlerProps, +lazy?: boolean, +drawerContent?: DrawerContentProps => React$Node, +drawerContentOptions?: DrawerContentOptions, +sceneContainerStyle?: ViewStyleProp, +drawerStyle?: ViewStyleProp, +detachInactiveScreens?: boolean, |}; declare export type ExtraDrawerNavigatorProps = {| ...$Exact, ...DrawerRouterOptions, ...DrawerNavigationConfig, |}; declare export type DrawerNavigatorProps< NavProp: InexactDrawerNavigationProp<> = DrawerNavigationProp<>, > = {| ...ExtraDrawerNavigatorProps, ...ScreenOptionsProp, |}; /** * BaseNavigationContainer */ declare export type BaseNavigationContainerProps = {| +children: React$Node, +initialState?: PossiblyStaleNavigationState, +onStateChange?: (state: ?PossiblyStaleNavigationState) => void, +independent?: boolean, |}; declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| +data: {| +options: { +[key: string]: mixed, ... } |}, +canPreventDefault: false, |}, +__unsafe_action__: {| +data: {| +action: GenericNavigationAction, +noop: boolean, |}, +canPreventDefault: false, |}, |}; declare export type BaseNavigationContainerInterface = {| ...$Exact>, +setParams: (params: ScreenParams) => void, +resetRoot: (state?: ?PossiblyStaleNavigationState) => void, +getRootState: () => PossiblyStaleNavigationState, |}; /** * State utils */ declare export type GetStateFromPath = ( path: string, options?: LinkingConfig, ) => PossiblyStaleNavigationState; declare export type GetPathFromState = ( state?: ?PossiblyStaleNavigationState, options?: LinkingConfig, ) => string; declare export type GetFocusedRouteNameFromRoute = PossiblyStaleRoute => ?string; /** * Linking */ declare export type ScreenLinkingConfig = {| +path?: string, +exact?: boolean, +parse?: {| +[param: string]: string => mixed |}, +stringify?: {| +[param: string]: mixed => string |}, +screens?: ScreenLinkingConfigMap, +initialRouteName?: string, |}; declare export type ScreenLinkingConfigMap = {| +[routeName: string]: string | ScreenLinkingConfig, |}; declare export type LinkingConfig = {| +initialRouteName?: string, +screens: ScreenLinkingConfigMap, |}; declare export type LinkingOptions = {| +enabled?: boolean, +prefixes: $ReadOnlyArray, +config?: LinkingConfig, +getStateFromPath?: GetStateFromPath, +getPathFromState?: GetPathFromState, |}; /** * NavigationContainer */ declare export type Theme = {| +dark: boolean, +colors: {| +primary: string, +background: string, +card: string, +text: string, +border: string, |}, |}; declare export type NavigationContainerType = React$AbstractComponent< {| ...BaseNavigationContainerProps, +theme?: Theme, +linking?: LinkingOptions, +fallback?: React$Node, +onReady?: () => mixed, |}, BaseNavigationContainerInterface, >; //--------------------------------------------------------------------------- // SECTION 2: EXPORTED MODULE // This section defines the module exports and contains exported types that // are not present in any other React Navigation libdef. //--------------------------------------------------------------------------- /** * StackView */ declare export var StackView: React$ComponentType<{| ...StackNavigationConfig, +state: StackNavigationState, +navigation: StackNavigationProp<>, +descriptors: {| +[key: string]: StackDescriptor |}, |}>; /** * createStackNavigator */ declare export var createStackNavigator: CreateNavigator< StackNavigationState, StackOptions, StackNavigationEventMap, ExtraStackNavigatorProps, >; /** * Header components */ declare export var Header: React$ComponentType; declare export type StackHeaderTitleProps = $Partial; declare export var HeaderTitle: React$ComponentType; declare export type HeaderBackButtonProps = $Partial<{| ...StackHeaderLeftButtonProps, +disabled: boolean, +accessibilityLabel: string, |}>; declare export var HeaderBackButton: React$ComponentType< HeaderBackButtonProps, >; declare export type HeaderBackgroundProps = $Partial<{ +children: React$Node, +style: AnimatedViewStyleProp, ... }>; declare export var HeaderBackground: React$ComponentType< HeaderBackgroundProps, >; /** * Style/animation options */ declare export var CardStyleInterpolators: {| +forHorizontalIOS: StackCardStyleInterpolator, +forVerticalIOS: StackCardStyleInterpolator, +forModalPresentationIOS: StackCardStyleInterpolator, +forFadeFromBottomAndroid: StackCardStyleInterpolator, +forRevealFromBottomAndroid: StackCardStyleInterpolator, +forScaleFromCenterAndroid: StackCardStyleInterpolator, +forNoAnimation: StackCardStyleInterpolator, |}; declare export var HeaderStyleInterpolators: {| +forUIKit: StackHeaderStyleInterpolator, +forFade: StackHeaderStyleInterpolator, +forSlideLeft: StackHeaderStyleInterpolator, +forSlideRight: StackHeaderStyleInterpolator, +forSlideUp: StackHeaderStyleInterpolator, +forNoAnimation: StackHeaderStyleInterpolator, |}; declare export var TransitionSpecs: {| +TransitionIOSSpec: TransitionSpec, +FadeInFromBottomAndroidSpec: TransitionSpec, +FadeOutToBottomAndroidSpec: TransitionSpec, +RevealFromBottomAndroidSpec: TransitionSpec, +ScaleFromCenterAndroidSpec: TransitionSpec, |}; declare export var TransitionPresets: {| +SlideFromRightIOS: TransitionPreset, +ModalSlideFromBottomIOS: TransitionPreset, +ModalPresentationIOS: TransitionPreset, +FadeFromBottomAndroid: TransitionPreset, +RevealFromBottomAndroid: TransitionPreset, +ScaleFromCenterAndroid: TransitionPreset, +DefaultTransition: TransitionPreset, +ModalTransition: TransitionPreset, |}; /** * Image assets */ declare export var Assets: $ReadOnlyArray; /** * CardAnimation accessors */ declare export var CardAnimationContext: React$Context< ?StackCardInterpolationProps, >; declare export function useCardAnimation(): StackCardInterpolationProps /** * HeaderHeight accessors */ declare export var HeaderHeightContext: React$Context; declare export function useHeaderHeight(): number; /** * GestureHandler accessors */ declare type GestureHandlerRef = React$Ref< React$ComponentType, >; declare export var GestureHandlerRefContext: React$Context< ?GestureHandlerRef, >; declare export function useGestureHandlerRef(): GestureHandlerRef; } diff --git a/native/profile/relationship-list-item.react.js b/native/profile/relationship-list-item.react.js index 2fe9da291..a226c6e68 100644 --- a/native/profile/relationship-list-item.react.js +++ b/native/profile/relationship-list-item.react.js @@ -1,344 +1,344 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { Alert, View, Text, TouchableOpacity, ActivityIndicator, } from 'react-native'; import { updateRelationshipsActionTypes, updateRelationships, } from 'lib/actions/relationship-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import type { LoadingStatus } from 'lib/types/loading-types'; import { type RelationshipRequest, type RelationshipAction, type RelationshipErrors, userRelationshipStatus, relationshipActions, } from 'lib/types/relationship-types'; import type { AccountUserInfo, GlobalAccountUserInfo, } from 'lib/types/user-types'; import { type DispatchActionPromise, useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils'; import PencilIcon from '../components/pencil-icon.react'; import { SingleLine } from '../components/single-line.react'; import { type KeyboardState, KeyboardContext, } from '../keyboard/keyboard-state'; import { OverlayContext, type OverlayContextType, } from '../navigation/overlay-context'; import type { NavigationRoute } from '../navigation/route-names'; import { RelationshipListItemTooltipModalRouteName, FriendListRouteName, BlockListRouteName, } from '../navigation/route-names'; import { useSelector } from '../redux/redux-utils'; import { type Colors, useColors, useStyles } from '../themes/colors'; import type { VerticalBounds } from '../types/layout-types'; import type { RelationshipListNavigate } from './relationship-list.react'; type BaseProps = { +userInfo: AccountUserInfo, +lastListItem: boolean, +verticalBounds: ?VerticalBounds, +relationshipListRoute: NavigationRoute<'FriendList' | 'BlockList'>, +navigate: RelationshipListNavigate, +onSelect: (selectedUser: GlobalAccountUserInfo) => void, }; type Props = { ...BaseProps, // Redux state +removeUserLoadingStatus: LoadingStatus, +colors: Colors, +styles: typeof unboundStyles, // Redux dispatch functions +dispatchActionPromise: DispatchActionPromise, // async functions that hit server APIs +updateRelationships: ( request: RelationshipRequest, ) => Promise, // withOverlayContext +overlayContext: ?OverlayContextType, // withKeyboardState +keyboardState: ?KeyboardState, }; class RelationshipListItem extends React.PureComponent { editButton = React.createRef>(); render() { const { lastListItem, removeUserLoadingStatus, userInfo, relationshipListRoute, } = this.props; const relationshipsToEdit = { [FriendListRouteName]: [userRelationshipStatus.FRIEND], [BlockListRouteName]: [ userRelationshipStatus.BOTH_BLOCKED, userRelationshipStatus.BLOCKED_BY_VIEWER, ], }[relationshipListRoute.name]; const canEditFriendRequest = { [FriendListRouteName]: true, [BlockListRouteName]: false, }[relationshipListRoute.name]; const borderBottom = lastListItem ? null : this.props.styles.borderBottom; let editButton = null; if (removeUserLoadingStatus === 'loading') { editButton = ( ); } else if (relationshipsToEdit.includes(userInfo.relationshipStatus)) { editButton = ( ); } else if ( userInfo.relationshipStatus === userRelationshipStatus.REQUEST_RECEIVED && canEditFriendRequest ) { editButton = ( Accept Reject ); } else if ( userInfo.relationshipStatus === userRelationshipStatus.REQUEST_SENT && canEditFriendRequest ) { editButton = ( Cancel request ); } else { editButton = ( Add ); } return ( {this.props.userInfo.username} {editButton} ); } onSelect = () => { const { id, username } = this.props.userInfo; this.props.onSelect({ id, username }); }; visibleEntryIDs() { const { relationshipListRoute } = this.props; const id = { [FriendListRouteName]: 'unfriend', [BlockListRouteName]: 'unblock', }[relationshipListRoute.name]; return [id]; } onPressEdit = () => { if (this.props.keyboardState?.dismissKeyboardIfShowing()) { return; } const { editButton, props: { verticalBounds }, } = this; const { overlayContext, userInfo } = this.props; invariant( overlayContext, 'RelationshipListItem should have OverlayContext', ); overlayContext.setScrollBlockingModalStatus('open'); if (!editButton.current || !verticalBounds) { return; } const { relationshipStatus, ...restUserInfo } = userInfo; const relativeUserInfo = { ...restUserInfo, isViewer: false, }; editButton.current.measure((x, y, width, height, pageX, pageY) => { const coordinates = { x: pageX, y: pageY, width, height }; - this.props.navigate({ + this.props.navigate<'RelationshipListItemTooltipModal'>({ name: RelationshipListItemTooltipModalRouteName, params: { presentedFrom: this.props.relationshipListRoute.key, initialCoordinates: coordinates, verticalBounds, visibleEntryIDs: this.visibleEntryIDs(), relativeUserInfo, }, }); }); }; // We need to set onLayout in order to allow .measure() to be on the ref onLayout = () => {}; onPressFriendUser = () => { this.onPressUpdateFriendship(relationshipActions.FRIEND); }; onPressUnfriendUser = () => { this.onPressUpdateFriendship(relationshipActions.UNFRIEND); }; onPressUpdateFriendship(action: RelationshipAction) { const { id } = this.props.userInfo; const customKeyName = `${updateRelationshipsActionTypes.started}:${id}`; this.props.dispatchActionPromise( updateRelationshipsActionTypes, this.updateFriendship(action), { customKeyName }, ); } async updateFriendship(action: RelationshipAction) { try { return await this.props.updateRelationships({ action, userIDs: [this.props.userInfo.id], }); } catch (e) { Alert.alert('Unknown error', 'Uhh... try again?', [{ text: 'OK' }], { cancelable: true, }); throw e; } } } const unboundStyles = { editButton: { paddingLeft: 10, }, container: { flex: 1, paddingHorizontal: 12, backgroundColor: 'panelForeground', }, innerContainer: { paddingVertical: 10, paddingHorizontal: 12, borderColor: 'panelForegroundBorder', flexDirection: 'row', }, borderBottom: { borderBottomWidth: 1, }, buttonContainer: { flexDirection: 'row', }, editButtonWithMargin: { marginLeft: 15, }, username: { color: 'panelForegroundSecondaryLabel', flex: 1, fontSize: 16, lineHeight: 20, }, blueAction: { color: 'link', fontSize: 16, paddingLeft: 6, }, redAction: { color: 'redText', fontSize: 16, paddingLeft: 6, }, }; const ConnectedRelationshipListItem: React.ComponentType = React.memo( function ConnectedRelationshipListItem(props: BaseProps) { const removeUserLoadingStatus = useSelector(state => createLoadingStatusSelector( updateRelationshipsActionTypes, `${updateRelationshipsActionTypes.started}:${props.userInfo.id}`, )(state), ); const colors = useColors(); const styles = useStyles(unboundStyles); const dispatchActionPromise = useDispatchActionPromise(); const boundUpdateRelationships = useServerCall(updateRelationships); const overlayContext = React.useContext(OverlayContext); const keyboardState = React.useContext(KeyboardContext); return ( ); }, ); export default ConnectedRelationshipListItem;