Skip to content

Commit c6e2749

Browse files
committed
Merge branch 'master' into release
2 parents ae81f0a + 3dafa66 commit c6e2749

File tree

97 files changed

+2959
-671
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2959
-671
lines changed

CONTRIBUTING.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Contributing
2+
If you got here it means you want to dedicate some of your time and help us improve this library.
3+
So first of all, thank you ❤️
4+
5+
When contributing to this repository, please first discuss the change you wish to make via [issue](https://github.com/wix/react-native-ui-lib/issues/new/choose),
6+
[Discord channel](https://discord.gg/2eW4g6Z), or any other method with the owners of this repository before making a change.
7+
8+
## Pull Request Process
9+
10+
1. First make sure the environment is working and synced with master. For installation details go [here](https://github.com/wix/react-native-ui-lib/blob/master/markdowns/getting-started/setup.md#demo-app)
11+
2. Before submitting a PR we suggest running `npm run prepush` command that verifies our lint, TS and tests were not broken.
12+
3. Please use our PR prefixes accordingly. `fix` for bugfix, `feat` for feature, `infra` for infrastructure changes and `docs` for documentation related changes (e.g `fix/ButtonStyle`, `feat/Avatar_colorProp`)
13+
4. Please don't change our PR template.
14+
- In the Description section add everything that can help the reviewer and the reviewing process, like a description of the issue and the way you decided to go about it, screenshots or gifs, etc.
15+
- The Changelog section is important. Write a message for the library users - this message will be included in our release notes.
16+
5. We try to make the PR review process as quick as possible, please be patient
17+
18+
19+
### Code Standards
20+
21+
- Readability and clean code above all - we believe a clean code is easier to maintain and refactor when needed.
22+
- Deciding on an API is not trivial but we always aim to keep it generic and intuitive - feel free to consult with us.
23+
- Our documentation is derived from our components' prop comments, make sure to add a clear description when adding new props.
24+
- When possible, consider adding tests for the new functionality you added.
25+
- Try separating logic from UI as much as possible using hooks and presenters.
26+
- Keep components small and single purposed.
27+
28+
#### Controlled vs Uncontrolled components
29+
When facing a new component's API we usually aim for making it controlled.
30+
This is in order to give the user most control over what will be rendered in the component.
31+
Having said that, keep in mind that in some cases (mostly due to performance concerns) we decide on making a component uncontrolled.
32+
33+
34+
35+
36+
## Typescript Status
37+
Currently most of our code is migrated to typescript though we still have some leftovers of javascript code and manual typings.
38+
Until we complete the migration you are required to do the following for new TS files
39+
40+
Before pushing new code make sure to run `npm run build:dev` - this check for TS errors and create appropriate declarations (`d.ts`) files under generatedTypes folder. Make sure to push these files as well!

demo/src/configurations.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Assets, Colors, Typography, Spacings, Incubator} from 'react-native-ui-lib'; // eslint-disable-line
22

33
Assets.loadAssetsGroup('icons.demo', {
4+
chevronDown: require('./assets/icons/chevronDown.png'),
45
add: require('./assets/icons/add.png'),
56
camera: require('./assets/icons/cameraSelected.png'),
67
close: require('./assets/icons/close.png'),
@@ -22,7 +23,8 @@ Typography.loadTypographies({
2223
h1: {...Typography.text40},
2324
h2: {...Typography.text50},
2425
h3: {...Typography.text60},
25-
body: Typography.text70
26+
body: Typography.text70,
27+
bodySmall: Typography.text80
2628
});
2729

2830
Spacings.loadSpacings({

demo/src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ module.exports = {
225225
get IncubatorTextFieldScreen() {
226226
return require('./screens/incubatorScreens/IncubatorTextFieldScreen').default;
227227
},
228+
get PanViewScreen() {
229+
return require('./screens/incubatorScreens/PanViewScreen').default;
230+
},
228231
// realExamples
229232
get AppleMusic() {
230233
return require('./screens/realExamples/AppleMusic').default;

demo/src/screens/ExampleScreenPresenter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export function renderColorOption(title,
107107
}
108108

109109
export function renderSliderOption(title, key, {min = 0, max = 10, step = 1, initial = 0, sliderText = ''}) {
110-
const value = this.state[key];
110+
const value = this.state[key] || initial;
111111
return (
112112
<View marginV-s2>
113113
<Text marginB-s1 text70M>
@@ -123,7 +123,7 @@ export function renderSliderOption(title, key, {min = 0, max = 10, step = 1, ini
123123
step={step}
124124
onValueChange={value => this.setState({[key]: value})}
125125
/>
126-
<Text marginL-s4 text70>
126+
<Text marginL-s4 text70 style={styles.text}>
127127
{sliderText}
128128
{value}
129129
</Text>
@@ -135,5 +135,8 @@ export function renderSliderOption(title, key, {min = 0, max = 10, step = 1, ini
135135
const styles = StyleSheet.create({
136136
rowWrap: {
137137
flexWrap: 'wrap'
138+
},
139+
text: {
140+
width: 30
138141
}
139142
});

demo/src/screens/MenuStructure.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ export const navigationData = {
156156
screens: [
157157
{title: 'Native TouchableOpacity', tags: 'touchable native', screen: 'unicorn.incubator.TouchableOpacityScreen'},
158158
{title: '(New) TextField', tags: 'text field input', screen: 'unicorn.components.IncubatorTextFieldScreen'},
159-
{title: 'WheelPicker (Incubator)', tags: 'wheel picker spinner experimental', screen: 'unicorn.incubator.WheelPickerScreen'}
159+
{title: 'WheelPicker (Incubator)', tags: 'wheel picker spinner experimental', screen: 'unicorn.incubator.WheelPickerScreen'},
160+
{title: 'Pan View', tags: 'pan swipe drag', screen: 'unicorn.incubator.PanViewScreen'}
160161
]
161162
},
162163
Inspirations: {
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import React, {Component} from 'react';
22
import {StyleSheet, ScrollView, View} from 'react-native';
3-
import {StateScreen, Constants, PageControl} from 'react-native-ui-lib';//eslint-disable-line
4-
const localImageSource = require('../../assets/images/empty-state.jpg'); // eslint-disable-line
5-
const remoteImageSource = {uri: 'https://static.pexels.com/photos/169651/pexels-photo-169651.jpeg'};
3+
import {StateScreen, Constants, PageControl} from 'react-native-ui-lib';
4+
const localImageSource = require('../../assets/images/empty-state.jpg');
5+
const remoteImageSource = {uri: 'https://cdn.pixabay.com/photo/2017/04/19/20/10/morning-2243465_1280.jpg'};
66

7-
export default class EmptyStateScreen extends Component {
8-
constructor(props) {
9-
super(props);
10-
this.state = {currentPage: 0};
11-
}
7+
type State = {
8+
currentPage: number;
9+
};
10+
11+
export default class EmptyStateScreen extends Component<{}, State> {
12+
state = {currentPage: 0};
1213

13-
setCurrentPage(offsetX) {
14+
setCurrentPage(offsetX: number) {
1415
if (offsetX >= 0) {
1516
this.setState({
16-
currentPage: Math.floor(offsetX / Constants.screenWidth),
17+
currentPage: Math.floor(offsetX / Constants.screenWidth)
1718
});
1819
}
1920
}
@@ -26,24 +27,24 @@ export default class EmptyStateScreen extends Component {
2627
horizontal
2728
showsHorizontalScrollIndicator={false}
2829
pagingEnabled
29-
onScroll={(event) => {
30+
onScroll={event => {
3031
this.setCurrentPage(event.nativeEvent.contentOffset.x);
3132
}}
3233
scrollEventThrottle={200}
3334
>
3435
<View style={styles.pageView}>
3536
<StateScreen
36-
title='Oppsie (with local image)'
37-
subtitle='Nothing to see here..'
38-
ctaLabel='OK'
37+
title={'Oppsie (with local image)'}
38+
subtitle={'Nothing to see here..'}
39+
ctaLabel={'OK'}
3940
imageSource={localImageSource}
4041
/>
4142
</View>
4243
<View style={styles.pageView}>
4344
<StateScreen
44-
title='Oppsie (with remote image)'
45-
subtitle='Nothing to see here..'
46-
ctaLabel='OK'
45+
title={'Oppsie (with remote image)'}
46+
subtitle={'Nothing to see here..'}
47+
ctaLabel={'OK'}
4748
imageSource={remoteImageSource}
4849
/>
4950
</View>
@@ -53,7 +54,7 @@ export default class EmptyStateScreen extends Component {
5354
position: 'absolute',
5455
bottom: 10,
5556
left: 0,
56-
width: Constants.screenWidth,
57+
width: Constants.screenWidth
5758
}}
5859
numOfPages={2}
5960
currentPage={this.state.currentPage}
@@ -66,10 +67,10 @@ export default class EmptyStateScreen extends Component {
6667
const styles = StyleSheet.create({
6768
container: {
6869
flex: 1,
69-
flexDirection: 'column',
70+
flexDirection: 'column'
7071
},
7172
pageView: {
7273
width: Constants.screenWidth,
73-
height: Constants.screenHeight,
74-
},
74+
height: Constants.screenHeight
75+
}
7576
});

demo/src/screens/componentScreens/SectionsWheelPickerScreen.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, {useState, useCallback} from 'react';
33
import {Alert} from 'react-native';
44
import {Text, View, SectionsWheelPicker, SegmentedControl, Button, Incubator} from 'react-native-ui-lib';
55

6+
const {WheelPicker} = Incubator;
67
const SectionsWheelPickerScreen = () => {
78
const [numOfSections, setNumOfSections] = useState(1);
89

@@ -65,21 +66,24 @@ const SectionsWheelPickerScreen = () => {
6566
onChange: onDaysChange,
6667
selectedValue: selectedDays,
6768
label: 'Days',
68-
style: numOfSections === 1 ? {flex: 1} : {flex: 1, alignItems: 'flex-end'}
69+
align: numOfSections === 1 ? WheelPicker.alignments.CENTER : WheelPicker.alignments.RIGHT,
70+
style: {flex: 1}
6971
},
7072
{
7173
items: getItems(hours),
7274
onChange: onHoursChange,
7375
selectedValue: selectedHours,
7476
label: 'Hrs',
75-
style: numOfSections === 2 ? {flex: 1, alignItems: 'flex-start'} : undefined
77+
align: numOfSections === 2 ? WheelPicker.alignments.LEFT : WheelPicker.alignments.CENTER,
78+
style: numOfSections === 2 ? {flex: 1} : undefined
7679
},
7780
{
7881
items: getItems(minutes),
7982
onChange: onMinutesChange,
8083
selectedValue: selectedMinutes,
8184
label: 'Mins',
82-
style: {flex: 1, alignItems: 'flex-start'}
85+
align: WheelPicker.alignments.LEFT,
86+
style: {flex: 1}
8387
}
8488
];
8589

demo/src/screens/componentScreens/SliderScreen.js renamed to demo/src/screens/componentScreens/SliderScreen.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,21 @@ import React, {Component} from 'react';
22
import {StyleSheet, ScrollView} from 'react-native';
33
import {Colors, View, Text, Image, Slider, GradientSlider, ColorSliderGroup} from 'react-native-ui-lib';
44

5-
65
const INITIAL_VALUE = 0;
76
const COLOR = Colors.blue30;
87

9-
export default class SliderScreen extends Component {
10-
constructor(props) {
8+
interface SliderScreenProps {
9+
componentId: string;
10+
}
11+
12+
interface SliderScreenState {
13+
alpha: number;
14+
color: string;
15+
sliderValue: number;
16+
}
17+
18+
export default class SliderScreen extends Component<SliderScreenProps, SliderScreenState> {
19+
constructor(props: SliderScreenProps) {
1120
super(props);
1221

1322
this.state = {
@@ -17,15 +26,15 @@ export default class SliderScreen extends Component {
1726
};
1827
}
1928

20-
onSliderValueChange = (value) => {
29+
onSliderValueChange = (value: number) => {
2130
this.setState({sliderValue: value});
2231
}
2332

24-
onGradientValueChange = (value, alpha) => {
33+
onGradientValueChange = (value: string, alpha: number) => {
2534
this.setState({color: value, alpha});
2635
}
2736

28-
onGroupValueChange = (value) => {
37+
onGroupValueChange = (value: string) => {
2938
console.warn('onGroupValueChange: ', value);
3039
}
3140

demo/src/screens/componentScreens/ViewScreen.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ViewScreen extends Component {
6969
<View height={2} bg-grey60 marginB-20/>
7070
{renderBooleanOption.call(this, 'Row (parent)', 'useRow')}
7171
{renderBooleanOption.call(this, 'Flex (child)', 'shouldFlex')}
72-
{renderSliderOption.call(this, 'BorderRadius(brXX)', 'borderRadius', {step: 10, min: 0, max: 60})}
72+
{renderSliderOption.call(this, 'BorderRadius(brXX)', 'borderRadius', {step: 10, min: 0, max: 60, initial: 20})}
7373
{renderSliderOption.call(this, 'Padding(padding-XX)', 'padding', {step: 4, min: 0, max: 40})}
7474
{renderSliderOption.call(this, 'Margin(margin-XX)', 'margin', {step: 4, min: 0, max: 40})}
7575
{renderRadioGroup.call(this, 'Alignment (parent)', 'alignment', ALIGNMENTS, {isRow: true})}

demo/src/screens/incubatorScreens/IncubatorTextFieldScreen.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {KeyboardAwareInsetsView} = Keyboard;
88
export default class TextFieldScreen extends Component {
99
input = React.createRef<TextInput>();
1010
input2 = React.createRef<TextInput>();
11+
inputWithValidation = React.createRef<TextInput>();
1112
state = {
1213
errorPosition: TextField.validationMessagePositions.TOP,
1314
shouldDisable: false,
@@ -121,6 +122,7 @@ export default class TextFieldScreen extends Component {
121122
<Text h3 blue50>
122123
Validation
123124
</Text>
125+
124126
<Button
125127
size={Button.sizes.xSmall}
126128
label={`Error Position: ${_.upperCase(errorPosition)}`}
@@ -150,8 +152,28 @@ export default class TextFieldScreen extends Component {
150152
// validateOnStart
151153
// validateOnBlur
152154
fieldStyle={styles.withUnderline}
155+
marginB-s4
153156
/>
154157

158+
<View row top marginT-s4>
159+
<TextField
160+
ref={this.inputWithValidation}
161+
placeholder="Enter full name"
162+
validate="required"
163+
validationMessage="This field is required"
164+
containerStyle={{flexGrow: 1}}
165+
fieldStyle={styles.withUnderline}
166+
/>
167+
<Button
168+
marginL-s5
169+
label="Validate"
170+
size={Button.sizes.xSmall}
171+
onPress={() => {
172+
this.inputWithValidation.current?.validate?.();
173+
}}
174+
/>
175+
</View>
176+
155177
<View row centerV spread>
156178
<Text h3 blue50 marginV-s4>
157179
Colors By State

0 commit comments

Comments
 (0)