Skip to content

Commit 8a93de9

Browse files
authored
Feat/incubator dialog add header (#1727)
* Add ImperativeDialog - fix bug while keeping simple * Add alignment support * Refactor (add useFadeView) and fix pointerEvents * Fix onRequestClose * Support useSafeArea * Add supportedOrientations and accessibilityLabel * Revert "Add supportedOrientations and accessibilityLabel" This reverts commit 9d8b588. * Add modalProps.supportedOrientations to the screen * Bring back containerStyle * Workaround useSafeArea performance issue * Fix types * Remove containerStyle again * Add api * IncubatorDialog - add header and default style * Improve render * Fix screen * Fix Constants import
1 parent 943cee3 commit 8a93de9

File tree

15 files changed

+316
-35
lines changed

15 files changed

+316
-35
lines changed

demo/src/screens/incubatorScreens/IncubatorDialogScreen.tsx

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {Component} from 'react';
22
import {StyleSheet, ModalProps} from 'react-native';
33
import {FlatList} from 'react-native-gesture-handler';
4-
import {View, Text, Card, Button, Incubator, Colors, BorderRadiuses, Constants} from 'react-native-ui-lib'; //eslint-disable-line
4+
import {View, Text, Card, Button, Incubator, Colors, Spacings} from 'react-native-ui-lib';
55

66
interface Item {
77
value: string;
@@ -34,10 +34,11 @@ const colors: Item[] = [
3434
export default class IncubatorDialogScreen extends Component {
3535
state = {visible: false};
3636
modalProps: ModalProps = {supportedOrientations: ['portrait', 'landscape']};
37+
headerProps: Incubator.DialogHeaderProps = {text: {title: 'Title (swipe here)'}};
3738

3839
renderVerticalItem = ({item}: {item: Item}) => {
3940
return (
40-
<Text text50 margin-20 color={item.value} onPress={this.closeDialog}>
41+
<Text text50 marginH-s5 marginV-s2 color={item.value} onPress={this.closeDialog}>
4142
{item.label}
4243
</Text>
4344
);
@@ -63,12 +64,12 @@ export default class IncubatorDialogScreen extends Component {
6364
const {visible} = this.state;
6465

6566
return (
66-
<View bg-dark80 flex padding-20>
67+
<View bg-grey80 flex padding-20>
6768
<Card height={100} center padding-20>
6869
<Text text50>IncubatorDialogScreen</Text>
6970
</Card>
7071
<View flex center>
71-
<Button marginV-20 label="Open Dialog" onPress={this.openDialog}/>
72+
<Button marginV-s5 label="Open Dialog" onPress={this.openDialog}/>
7273
</View>
7374
<Incubator.Dialog
7475
useSafeArea
@@ -77,35 +78,23 @@ export default class IncubatorDialogScreen extends Component {
7778
bottom
7879
centerH
7980
modalProps={this.modalProps}
81+
headerProps={this.headerProps}
8082
>
81-
<View style={styles.dialog}>
82-
<Text text60 margin-s2>
83-
Title (swipe here)
84-
</Text>
85-
<View height={1} bg-grey40/>
86-
<FlatList
87-
showsVerticalScrollIndicator={false}
88-
style={styles.verticalScroll}
89-
data={colors}
90-
renderItem={this.renderVerticalItem}
91-
keyExtractor={this.keyExtractor}
92-
/>
93-
</View>
83+
<FlatList
84+
showsVerticalScrollIndicator={false}
85+
contentContainerStyle={styles.verticalScroll}
86+
data={colors}
87+
renderItem={this.renderVerticalItem}
88+
keyExtractor={this.keyExtractor}
89+
/>
9490
</Incubator.Dialog>
9591
</View>
9692
);
9793
}
9894
}
9995

10096
const styles = StyleSheet.create({
101-
dialog: {
102-
marginBottom: 20,
103-
backgroundColor: Colors.white,
104-
maxHeight: Constants.screenHeight * 0.8,
105-
width: 300,
106-
borderRadius: BorderRadiuses.br20
107-
},
10897
verticalScroll: {
109-
marginTop: 20
98+
paddingVertical: Spacings.s2
11099
}
111100
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import React from 'react';
2+
import { DialogHeaderProps } from './types';
3+
declare const _default: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "showDivider">) => JSX.Element | null>;
4+
export default _default;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/// <reference types="react" />
2+
import { DialogHeaderProps } from './types';
3+
declare const DialogHeader: (props?: DialogHeaderProps) => JSX.Element | null;
4+
export default DialogHeader;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import React from 'react';
2+
import { DialogHeaderProps } from './types';
3+
declare const _default: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "showKnob">) => JSX.Element | null>;
4+
export default _default;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import React from 'react';
2+
import { DialogHeaderProps } from './types';
3+
declare const _default: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "text">) => JSX.Element | null>;
4+
export default _default;
Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1-
/// <reference types="react" />
2-
import { ImperativeDialogProps, DialogDirections, DialogDirectionsEnum } from './types';
3-
export { DialogDirections, DialogDirectionsEnum };
1+
import React from 'react';
2+
import { StyleProp, ViewStyle } from 'react-native';
3+
import { ImperativeDialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogTextProps } from './types';
4+
export { DialogDirections, DialogDirectionsEnum, DialogHeaderProps, DialogTextProps };
45
export interface DialogProps extends Omit<ImperativeDialogProps, 'initialVisibility'> {
56
/**
67
* The visibility of the dialog.
78
*/
89
visible?: boolean;
10+
/**
11+
* The Dialog's header
12+
*/
13+
headerProps?: DialogHeaderProps;
14+
/**
15+
* The Dialog`s container style (it is set to {position: 'absolute'})
16+
*/
17+
containerStyle?: StyleProp<ViewStyle>;
918
}
1019
declare const Dialog: {
1120
(props: DialogProps): JSX.Element;
1221
displayName: string;
1322
directions: typeof import("../panView").PanningDirectionsEnum;
23+
Header: (props?: DialogHeaderProps) => JSX.Element | null;
24+
Text: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "text">) => JSX.Element | null>;
25+
Knob: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "showKnob">) => JSX.Element | null>;
26+
Divider: React.MemoExoticComponent<(props: Pick<DialogHeaderProps, "showDivider">) => JSX.Element | null>;
1427
};
1528
export default Dialog;

generatedTypes/src/incubator/Dialog/types.d.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { PropsWithChildren } from 'react';
2+
import { StyleProp, TextStyle } from 'react-native';
23
import { AlignmentModifiers } from '../../commons/modifiers';
34
import { ModalProps } from '../../components/modal';
45
import { ViewProps } from '../../components/view';
6+
import { TextProps } from '../../components/text';
57
import { PanningDirections, PanningDirectionsEnum } from '../panView';
68
declare type DialogDirections = PanningDirections;
79
declare const DialogDirectionsEnum: typeof PanningDirectionsEnum;
@@ -42,3 +44,52 @@ export interface ImperativeDialogMethods {
4244
open: () => void;
4345
close: () => void;
4446
}
47+
/**
48+
* It is available as `Dialog.Text`
49+
*/
50+
export interface DialogTextProps {
51+
/**
52+
* Title
53+
*/
54+
title?: string;
55+
/**
56+
* Title text style
57+
*/
58+
titleStyle?: StyleProp<TextStyle>;
59+
/**
60+
* Title extra props
61+
*/
62+
titleProps?: TextProps;
63+
/**
64+
* Subtitle
65+
*/
66+
subtitle?: string;
67+
/**
68+
* Subtitle text style
69+
*/
70+
subtitleStyle?: StyleProp<TextStyle>;
71+
/**
72+
* Subtitle extra props
73+
*/
74+
subtitleProps?: TextProps;
75+
}
76+
export interface DialogHeaderProps extends ViewProps {
77+
/**
78+
* The dialog's default content (Dialog.Text)
79+
*/
80+
text?: DialogTextProps;
81+
/**
82+
* Replace the header's default content (Dialog.Text)
83+
*/
84+
renderContent?: (props: DialogHeaderProps) => React.ReactElement;
85+
/**
86+
* Show the header's knob (default is true)
87+
* It is available as `Dialog.Knob`
88+
*/
89+
showKnob?: boolean;
90+
/**
91+
* Show the header's divider (default is true)
92+
* It is available as `Dialog.Divider`
93+
*/
94+
showDivider?: boolean;
95+
}

generatedTypes/src/incubator/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ export { default as TouchableOpacity, TouchableOpacityProps } from './TouchableO
66
export { default as WheelPicker, WheelPickerProps, WheelPickerAlign, WheelPickerItemProps } from './WheelPicker';
77
export { default as PanView, PanViewProps, PanViewDirections, PanViewDismissThreshold } from './panView';
88
export { default as TransitionView, TransitionViewProps, TransitionViewDirection, TransitionViewDirectionEnum, TransitionViewAnimationType } from './TransitionView';
9-
export { default as Dialog, DialogProps } from './Dialog';
9+
export { default as Dialog, DialogProps, DialogHeaderProps, DialogTextProps } from './Dialog';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import {Dividers} from 'style';
3+
import View from '../../components/view';
4+
import {DialogHeaderProps} from './types';
5+
6+
const DialogDivider = (props: Pick<DialogHeaderProps, 'showDivider'>) => {
7+
const {showDivider = true} = props;
8+
9+
if (showDivider) {
10+
return <View style={Dividers.d10}/>;
11+
}
12+
13+
return null;
14+
};
15+
16+
export default React.memo(DialogDivider);

src/incubator/Dialog/DialogHeader.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {isEmpty} from 'lodash';
2+
import React, {useMemo} from 'react';
3+
import View from '../../components/view';
4+
import DialogText from './DialogText';
5+
import DialogKnob from './DialogKnob';
6+
import DialogDivider from './DialogDivider';
7+
import {DialogHeaderProps} from './types';
8+
9+
const DialogHeader = (props: DialogHeaderProps = {}) => {
10+
const {text = {}, renderContent, showKnob = true, showDivider = true, ...others} = props;
11+
12+
const _renderContent = useMemo(() => {
13+
if (renderContent) {
14+
return renderContent(props);
15+
}
16+
17+
return <DialogText text={text}/>;
18+
// eslint-disable-next-line react-hooks/exhaustive-deps
19+
}, [renderContent, text]);
20+
21+
if (!isEmpty(props)) {
22+
return (
23+
<View {...others}>
24+
<DialogKnob showKnob={showKnob}/>
25+
{_renderContent}
26+
<DialogDivider showDivider={showDivider}/>
27+
</View>
28+
);
29+
}
30+
31+
return null;
32+
};
33+
34+
export default DialogHeader;

src/incubator/Dialog/DialogKnob.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import {StyleSheet} from 'react-native';
3+
import {Spacings, Colors, BorderRadiuses} from 'style';
4+
import View from '../../components/view';
5+
import {DialogHeaderProps} from './types';
6+
7+
const DialogKnob = (props: Pick<DialogHeaderProps, 'showKnob'>) => {
8+
const {showKnob = true} = props;
9+
10+
if (showKnob) {
11+
return <View style={styles.knob}/>;
12+
}
13+
14+
return null;
15+
};
16+
17+
export default React.memo(DialogKnob);
18+
19+
const styles = StyleSheet.create({
20+
knob: {
21+
alignSelf: 'center',
22+
width: 44,
23+
height: Spacings.s1,
24+
marginTop: Spacings.s2,
25+
marginBottom: Spacings.s2,
26+
backgroundColor: Colors.grey60,
27+
borderRadius: BorderRadiuses.br10
28+
}
29+
});

src/incubator/Dialog/DialogText.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {isEmpty} from 'lodash';
2+
import React from 'react';
3+
import View from '../../components/view';
4+
import Text from '../../components/text';
5+
import {DialogHeaderProps} from './types';
6+
7+
const DialogText = (props: Pick<DialogHeaderProps, 'text'>) => {
8+
const {text = {}} = props;
9+
const {title, titleStyle, titleProps, subtitle, subtitleStyle, subtitleProps} = text;
10+
11+
if (title || subtitle) {
12+
return (
13+
<View marginH-s5 marginV-s1>
14+
{!isEmpty(title) && (
15+
<Text {...titleProps} marginB-s3 style={titleStyle}>
16+
{title}
17+
</Text>
18+
)}
19+
{!isEmpty(subtitle) && (
20+
<Text {...subtitleProps} marginB-s3 style={subtitleStyle}>
21+
{subtitle}
22+
</Text>
23+
)}
24+
</View>
25+
);
26+
}
27+
28+
return null;
29+
};
30+
31+
export default React.memo(DialogText);

0 commit comments

Comments
 (0)