Skip to content

Dialog - migrate to typescript (and some fixes) #930

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions generatedTypes/components/dialog/DialogDismissibleView.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import { PanningDirections } from '../panningViews/panningProvider';
interface DialogDismissibleProps {
/**
* Additional styling
*/
style?: StyleProp<ViewStyle>;
/**
* The direction of the allowed pan (default is DOWN)
* Types: UP, DOWN, LEFT and RIGHT (using PanningProvider.Directions.###)
*/
direction?: PanningDirections;
/**
* onDismiss callback
*/
onDismiss?: () => void;
/**
* The dialog`s container style
*/
containerStyle?: StyleProp<ViewStyle>;
/**
* Whether to show the dialog or not
*/
visible?: boolean;
}
declare const _default: React.ComponentClass<DialogDismissibleProps, any>;
export default _default;
6 changes: 3 additions & 3 deletions generatedTypes/components/dialog/OverlayFadingBackground.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/// <reference types="react" />
interface Props {
dialogVisibility: boolean;
modalVisibility: boolean;
overlayBackgroundColor: string;
dialogVisibility?: boolean;
modalVisibility?: boolean;
overlayBackgroundColor?: string;
}
declare const OverlayFadingBackground: {
({ dialogVisibility, modalVisibility, overlayBackgroundColor }: Props): JSX.Element;
Expand Down
68 changes: 68 additions & 0 deletions generatedTypes/components/dialog/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import { StyleProp, ViewStyle, ModalPropsIOS, AccessibilityProps } from 'react-native';
import { AlignmentModifiers } from '../../commons/modifiers';
import { PanningDirections } from '../panningViews/panningProvider';
interface RNPartialProps extends Pick<ModalPropsIOS, 'supportedOrientations'>, Pick<AccessibilityProps, 'accessibilityLabel'> {
}
export interface DialogProps extends AlignmentModifiers, RNPartialProps {
/**
* Control visibility of the dialog
*/
visible?: boolean;
/**
* Dismiss callback for when clicking on the background
*/
onDismiss?: (props: any) => void;
/**
* The color of the overlay background
*/
overlayBackgroundColor?: string;
/**
* The dialog width (default: 90%)
*/
width?: string | number;
/**
* The dialog height (default: undefined)
*/
height?: string | number;
/**
* The direction of the allowed pan (default is DOWN).
* Types: UP, DOWN, LEFT and RIGHT (using PanningProvider.Directions.###).
* Pass null to remove pan.
*/
panDirection?: PanningDirections;
/**
* Whether or not to handle SafeArea
*/
useSafeArea?: boolean;
/**
* Called once the modal has been dismissed (iOS only) - Deprecated, use onDialogDismissed instead
*/
onModalDismissed?: (props: any) => void;
/**
* Called once the dialog has been dismissed completely
*/
onDialogDismissed?: (props: any) => void;
/**
* If this is added only the header will be pannable;
* this allows for scrollable content (the children of the dialog)
* props are transferred to the renderPannableHeader
*/
renderPannableHeader?: (props: any) => JSX.Element;
/**
* The props that will be passed to the pannable header
*/
pannableHeaderProps?: any;
/**
* The Dialog`s container style
*/
containerStyle?: StyleProp<ViewStyle>;
/**
* Used as a testing identifier
*/
testID?: string;
}
declare const _default: React.ComponentClass<DialogProps & {
useCustomTheme?: boolean | undefined;
}, any>;
export default _default;
2 changes: 1 addition & 1 deletion generatedTypes/components/view/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export interface ViewPropTypes extends Omit<ViewProps, 'style'>, ContainerModifi
* Set background color
*/
backgroundColor?: string;
style?: StyleProp<ViewStyle> | Animated.AnimatedProps<StyleProp<ViewStyle>>;
style?: StyleProp<ViewStyle | Animated.AnimatedProps<ViewStyle>>;
}
declare const _default: React.ComponentClass<ViewPropTypes & {
useCustomTheme?: boolean | undefined;
Expand Down
11 changes: 6 additions & 5 deletions generatedTypes/helpers/Constants.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
export declare enum orientations {
PORTRAIT = "portrait",
LANDSCAPE = "landscape"
}
export declare function updateConstants(dimensions: any): void;
declare const constants: {
orientations: {
PORTRAIT: string;
LANDSCAPE: string;
};
orientations: typeof orientations;
isAndroid: boolean;
isIOS: boolean;
getAndroidVersion: () => number | undefined;
readonly statusBarHeight: number;
isRTL: boolean;
readonly orientation: string;
readonly orientation: orientations;
readonly isLandscape: boolean;
readonly screenWidth: number;
readonly screenHeight: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,63 +1,90 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, {PureComponent} from 'react';
import {Animated, Easing, StyleSheet} from 'react-native';
import {Animated, Easing, StyleSheet, StyleProp, ViewStyle, LayoutChangeEvent} from 'react-native';
import {Constants} from '../../helpers';
import View from '../view';
import asPanViewConsumer from '../panningViews/asPanViewConsumer';
import PanningProvider from '../panningViews/panningProvider';
import PanningProvider, {PanningDirections, PanAmountsProps, PanDirectionsProps, PanLocationProps} from '../panningViews/panningProvider';
import PanResponderView from '../panningViews/panResponderView';

const MAXIMUM_DRAGS_AFTER_SWIPE = 2;

class DialogDismissibleView extends PureComponent {
static propTypes = {
/**
* The direction of the allowed pan (default is DOWN)
* Types: UP, DOWN, LEFT and RIGHT (using PanningProvider.Directions.###)
*/
direction: PropTypes.oneOf(Object.values(PanningProvider.Directions)),
/**
* onDismiss callback
*/
onDismiss: PropTypes.func,
/**
* The dialog`s container style
*/
containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
/**
* Whether to show the dialog or not
*/
visible: PropTypes.bool
};
interface PanContextProps {
isPanning: boolean;
dragDeltas: PanAmountsProps;
swipeDirections: PanDirectionsProps;
}

interface DialogDismissibleProps {
/**
* Additional styling
*/
style?: StyleProp<ViewStyle>;
/**
* The direction of the allowed pan (default is DOWN)
* Types: UP, DOWN, LEFT and RIGHT (using PanningProvider.Directions.###)
*/
direction?: PanningDirections;
/**
* onDismiss callback
*/
onDismiss?: () => void;
/**
* The dialog`s container style
*/
containerStyle?: StyleProp<ViewStyle>;
/**
* Whether to show the dialog or not
*/
visible?: boolean;
}

interface Props extends DialogDismissibleProps {
context: PanContextProps;
}

interface State {
visible?: boolean;
hide: boolean;
}

interface LocationProps {
left: number;
top: number;
}

static defaultProps = {
direction: PanningProvider.Directions.DOWN,
onDismiss: _.noop
const DEFAULT_DIRECTION = PanningProvider.Directions.DOWN;

class DialogDismissibleView extends PureComponent<Props, State> {

public static defaultProps: Partial<Props> = {
direction: DEFAULT_DIRECTION,
onDismiss: () => {}
};

constructor(props) {
private hiddenLocation: LocationProps;
private animatedValue = new Animated.Value(0);
private width = Constants.screenWidth;
private height = Constants.screenHeight;
private counter = 0;
private swipe: PanDirectionsProps = {};
private thresholdX = 0;
private thresholdY = 0;
private ref = React.createRef<any>();

constructor(props: Props) {
super(props);

this.setInitialValues();
this.hiddenLocation = this.getHiddenLocation(0, 0);
this.state = {
visible: props.visible,
hide: false
};
}

setInitialValues() {
this.hiddenLocation = {};
this.resetSwipe();
this.animatedValue = new Animated.Value(0);
this.width = Constants.screenWidth;
this.height = Constants.screenHeight;
this.hiddenLocation = this.getHiddenLocation(0, 0);
}

componentDidUpdate(prevProps) {
const {isPanning, dragDeltas, swipeDirections} = this.props.context; // eslint-disable-line
const {dragDeltas: prevDragDeltas, swipeDirections: prevSwipeDirections} = prevProps.context; // eslint-disable-line
componentDidUpdate(prevProps: Props) {
const {isPanning, dragDeltas, swipeDirections} = this.props.context;
const {dragDeltas: prevDragDeltas, swipeDirections: prevSwipeDirections} = prevProps.context;
const {hide} = this.state;

if (
Expand All @@ -81,7 +108,7 @@ class DialogDismissibleView extends PureComponent {
}
}

static getDerivedStateFromProps(nextProps, prevState) {
static getDerivedStateFromProps(nextProps: DialogDismissibleProps, prevState: State) {
const {visible} = nextProps;
const {visible: prevVisible} = prevState;

Expand All @@ -97,8 +124,8 @@ class DialogDismissibleView extends PureComponent {
this.swipe = {};
};

isSwiping = () => {
return this.swipe.x || this.swipe.y;
isSwiping = (): boolean => {
return !_.isUndefined(this.swipe.x) || !_.isUndefined(this.swipe.y);
};

onDrag = () => {
Expand All @@ -111,11 +138,11 @@ class DialogDismissibleView extends PureComponent {
}
};

onSwipe = swipeDirections => {
onSwipe = (swipeDirections: PanDirectionsProps) => {
this.swipe = swipeDirections;
};

getHiddenLocation = (left, top) => {
getHiddenLocation = (left: number, top: number): LocationProps => {
const {direction} = this.props;
const topInset = Constants.isIphoneX ? Constants.getSafeAreaInsets().top : Constants.isIOS ? 20 : 0;
const bottomInset = Constants.isIphoneX ? Constants.getSafeAreaInsets().bottom : Constants.isIOS ? 20 : 0;
Expand All @@ -140,7 +167,7 @@ class DialogDismissibleView extends PureComponent {
return result;
};

animateTo = (toValue, animationEndCallback) => {
animateTo = (toValue: number, animationEndCallback?: Animated.EndCallback) => {
Animated.timing(this.animatedValue, {
toValue,
duration: 300,
Expand Down Expand Up @@ -168,17 +195,19 @@ class DialogDismissibleView extends PureComponent {
};
};

onLayout = event => {
onLayout = (event: LayoutChangeEvent) => {
// DO NOT move the width\height into the measureInWindow - it causes errors with orientation change
const layout = event.nativeEvent.layout;
this.width = layout.width;
this.height = layout.height;
this.thresholdX = this.width / 2;
this.thresholdY = this.height / 2;
this.ref.measureInWindow((x, y) => {
this.hiddenLocation = this.getHiddenLocation(x, y);
this.animateTo(1);
});
if (this.ref.current) {
this.ref.current.measureInWindow((x: number, y: number) => {
this.hiddenLocation = this.getHiddenLocation(x, y);
this.animateTo(1);
});
}
};

hide = () => {
Expand All @@ -187,16 +216,16 @@ class DialogDismissibleView extends PureComponent {
this.animateTo(0, () => this.setState({visible: false, hide: false}, onDismiss));
};

resetToShown = (left, top, direction) => {
resetToShown = (left: number, top: number, direction: PanningDirections) => {
const toValue = [PanningProvider.Directions.LEFT, PanningProvider.Directions.RIGHT].includes(direction)
? 1 + left / this.hiddenLocation.left
: 1 + top / this.hiddenLocation.top;

this.animateTo(toValue);
};

onPanLocationChanged = ({left, top}) => {
const {direction} = this.props;
onPanLocationChanged = ({left = 0, top = 0}: PanLocationProps) => {
const {direction = DEFAULT_DIRECTION} = this.props;
const endValue = {x: Math.round(left), y: Math.round(top)};
if (this.isSwiping()) {
this.hide();
Expand All @@ -220,7 +249,7 @@ class DialogDismissibleView extends PureComponent {
const {visible} = this.state;

return (
<View ref={r => (this.ref = r)} style={containerStyle} onLayout={this.onLayout}>
<View ref={this.ref} style={containerStyle} onLayout={this.onLayout}>
<PanResponderView
// !visible && styles.hidden is done to fix a bug is iOS
style={[style, this.getAnimationStyle(), !visible && styles.hidden]}
Expand All @@ -234,7 +263,7 @@ class DialogDismissibleView extends PureComponent {
}
}

export default asPanViewConsumer(DialogDismissibleView);
export default asPanViewConsumer<DialogDismissibleProps>(DialogDismissibleView);

const styles = StyleSheet.create({
hidden: {
Expand Down
6 changes: 3 additions & 3 deletions src/components/dialog/OverlayFadingBackground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import View from '../view';
import {Animated} from 'react-native';

interface Props {
dialogVisibility: boolean;
modalVisibility: boolean;
overlayBackgroundColor: string;
dialogVisibility?: boolean;
modalVisibility?: boolean;
overlayBackgroundColor?: string;
}

const OverlayFadingBackground = ({
Expand Down
Loading