Skip to content

Commit 9a199e3

Browse files
Inbal-Tishethanshar
authored andcommitted
Feat/ColorPicker updates (#614)
* Adding testID * Adding containerMargins prop * typo * Changing ColorSwatch style for tablets * demo for numberOfRows in tablet * fix RTL issues * adding 'dialogProps' prop * remove comment * fix merge issue * Adding ScrollBar component; using it in ColorPalette component * Adding gradientMargins prop * ScrollBar - fix for containerWidth change * ColorPalette changing containerMargins to containerWidth; Fix icon isuue
1 parent f40b900 commit 9a199e3

File tree

10 files changed

+302
-115
lines changed

10 files changed

+302
-115
lines changed

demo/src/screens/componentScreens/ColorSwatchScreen.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash';
22
import React, {Component} from 'react';
33
import {ScrollView} from 'react-native';
4-
import {Colors, View, Text, ColorSwatch, ColorPalette} from 'react-native-ui-lib'; //eslint-disable-line
4+
import {Constants, Colors, View, Text, ColorSwatch, ColorPalette} from 'react-native-ui-lib'; //eslint-disable-line
55

66

77
export default class ColorSwatchScreen extends Component {
@@ -50,14 +50,14 @@ export default class ColorSwatchScreen extends Component {
5050
</View>
5151

5252
<Text marginT-20 text60 dark10>ColorPalette</Text>
53-
<Text marginB-10 text70 style={{color}}>Slected Color: {color}</Text>
53+
<Text marginB-10 text70 style={{color}}>Selected Color: {color}</Text>
5454
<ColorPalette value={color} onValueChange={this.onValueChange} colors={this.colors}/>
5555

5656
<Text margin-10 text60 dark10>Scrollable</Text>
5757
<ColorPalette value={color1} onValueChange={this.onValueChange1} colors={this.mainColors}/>
5858

5959
<Text margin-10 text60 dark10>Pagination</Text>
60-
<ColorPalette numberOfRows={4} value={color2} onValueChange={this.onValueChange2} colors={this.allColors}/>
60+
<ColorPalette numberOfRows={!Constants.isTablet ? 4 : undefined} value={color2} onValueChange={this.onValueChange2} colors={this.allColors}/>
6161
</View>
6262
</ScrollView>
6363
);

src/assets/icons/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export const icons = {
55
get checkSmall() {
66
return require('./check-small.png');
77
},
8+
get plusSmall() {
9+
return require('./plusSmall.png');
10+
},
811
get search() {
912
return require('./search.png');
1013
},

src/components/colorPicker/ColorPalette.js

Lines changed: 53 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,27 @@ import _ from 'lodash';
22
import PropTypes from 'prop-types';
33
import memoize from 'memoize-one';
44
import React from 'react';
5-
import {StyleSheet, ScrollView, Animated, Easing, UIManager, findNodeHandle} from 'react-native';
5+
import {StyleSheet, UIManager, findNodeHandle} from 'react-native';
66
import {Constants} from '../../helpers';
77
import {Colors} from '../../style';
88
import {PureBaseComponent} from '../../commons';
99
import View from '../view';
1010
import Carousel from '../carousel';
1111
import PageControl from '../pageControl';
12-
import Image from '../image';
1312
import ColorSwatch, {SWATCH_SIZE} from './ColorSwatch';
13+
import ScrollBar from '../scrollBar';
1414

1515

1616
const VERTICAL_PADDING = 16;
1717
const HORIZONTAL_PADDING = 20;
1818
const MINIMUM_MARGIN = 16;
1919
const SCROLLABLE_HEIGHT = 92;
20-
const GRADIENT_WIDTH = 27;
2120
const DEFAULT_NUMBER_OF_ROWS = 3;
22-
const gradientImage = () => require('./assets/gradient.png');
2321

2422
/**
2523
* @description: A color palette component
2624
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/ColorPickerScreen.js
2725
* @notes: This is a screen width component
28-
* @extends: ScrollView
2926
*/
3027
export default class ColorPalette extends PureBaseComponent {
3128
static displayName = 'ColorPalette';
@@ -39,6 +36,10 @@ export default class ColorPalette extends PureBaseComponent {
3936
* Style to pass the palette container
4037
*/
4138
containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
39+
/**
40+
* The container margins
41+
*/
42+
containerWidth: PropTypes.number,
4243
/**
4344
* Whether to use pagination when number of colors exceeds the number of rows
4445
*/
@@ -80,12 +81,11 @@ export default class ColorPalette extends PureBaseComponent {
8081

8182
this.state = {
8283
currentPage: 0,
83-
scrollable: false,
84-
gradientOpacity: new Animated.Value(0)
84+
scrollable: false
8585
};
8686

8787
this.carousel = React.createRef();
88-
this.scrollView = React.createRef();
88+
this.scrollBar = React.createRef();
8989
this.initLocalVariables();
9090
}
9191

@@ -99,7 +99,7 @@ export default class ColorPalette extends PureBaseComponent {
9999

100100
onOrientationChanged = () => {
101101
this.initLocalVariables();
102-
this.setState({gradientOpacity: new Animated.Value(0)}); // only to trigger render
102+
this.setState({orientation: Constants.orientation}); // only to trigger render
103103
}
104104

105105
initLocalVariables() {
@@ -127,15 +127,21 @@ export default class ColorPalette extends PureBaseComponent {
127127
return this.getUniqueColors(this.props.colors);
128128
}
129129

130-
getUniqueColors = memoize((colors) => {
131-
const c = _.map(colors, color => {
132-
if (Colors.isTransparent(color)) {
133-
return color;
134-
}
135-
return _.toUpper(color);
136-
});
137-
return _.uniq(c);
138-
});
130+
get containerWidth() {
131+
return this.props.containerWidth || Constants.screenWidth;
132+
}
133+
134+
getUniqueColors = memoize(
135+
(colors) => {
136+
const c = _.map(colors, color => {
137+
if (Colors.isTransparent(color)) {
138+
return color;
139+
}
140+
return _.toUpper(color);
141+
});
142+
return _.uniq(c);
143+
}
144+
);
139145

140146
getNumberOfRows() {
141147
const {numberOfRows} = this.props;
@@ -154,7 +160,7 @@ export default class ColorPalette extends PureBaseComponent {
154160
// additional items have the minimum width of the margin between them and the previous item's width
155161
const additionalItemMinimumWidth = SWATCH_SIZE + MINIMUM_MARGIN;
156162
// floor(space left / size of additional items)
157-
itemsPerRow += Math.floor((Constants.screenWidth - firstItemWidth) / additionalItemMinimumWidth);
163+
itemsPerRow += Math.floor((this.containerWidth - firstItemWidth) / additionalItemMinimumWidth);
158164

159165
return itemsPerRow;
160166
}
@@ -170,26 +176,14 @@ export default class ColorPalette extends PureBaseComponent {
170176
}
171177

172178
// Now that we have the itemsPerRow set, we can calculate the actual innerMargin
173-
const remainingSpace = Constants.screenWidth - this.itemsPerRow * SWATCH_SIZE - 2 * HORIZONTAL_PADDING;
179+
const remainingSpace = this.containerWidth - this.itemsPerRow * SWATCH_SIZE - 2 * HORIZONTAL_PADDING;
174180
// With pagination - there's 1 less space than the number of items
175181
const numberOfMargins = this.itemsPerRow - 1;
176182
const margin = remainingSpace / numberOfMargins;
177183
// We have to subtract something since otherwise some Android devices will overflow into the next line
178184
return (margin - 0.001) / 2;
179185
}
180186

181-
animateGradientOpacity = (offsetX, contentWidth) => {
182-
const overflow = contentWidth - Constants.screenWidth;
183-
const newValue = offsetX > 0 && offsetX >= overflow - 1 ? 0 : 1;
184-
185-
Animated.timing(this.state.gradientOpacity, {
186-
toValue: newValue,
187-
easing: Easing.inOut(Easing.linear),
188-
duration: 300,
189-
useNativeDriver: true
190-
}).start();
191-
};
192-
193187
scrollToSelected() {
194188
const {scrollable, currentPage} = this.state;
195189

@@ -199,18 +193,19 @@ export default class ColorPalette extends PureBaseComponent {
199193
if (childRef) {
200194
const handle = findNodeHandle(childRef);
201195
if (handle) {
202-
UIManager.measureLayoutRelativeToParent(handle, e => {
203-
console.warn(e);
204-
},
205-
(x, y, w, h) => {
206-
if (x + w > Constants.screenWidth) {
207-
this.scrollView.current.scrollTo({
208-
x: x + w + HORIZONTAL_PADDING - Constants.screenWidth,
209-
y: 0,
210-
animated: false
211-
});
212-
}
213-
});
196+
UIManager.measureLayoutRelativeToParent(handle,
197+
e => {
198+
console.warn(e);
199+
},
200+
(x, y, w, h) => {
201+
if (x + w > this.containerWidth) {
202+
this.scrollBar.current.scrollTo({
203+
x: x + w + HORIZONTAL_PADDING - this.containerWidth,
204+
y: 0,
205+
animated: false
206+
});
207+
}
208+
});
214209
}
215210
}
216211
} else if (this.usePagination) {
@@ -219,16 +214,7 @@ export default class ColorPalette extends PureBaseComponent {
219214
}
220215

221216
onContentSizeChange = contentWidth => {
222-
if (contentWidth > Constants.screenWidth) {
223-
this.setState({scrollable: true, gradientOpacity: new Animated.Value(1)});
224-
}
225-
};
226-
227-
onScroll = event => {
228-
const {contentOffset, contentSize} = event.nativeEvent;
229-
const offsetX = contentOffset.x;
230-
const contentWidth = contentSize.width;
231-
this.animateGradientOpacity(offsetX, contentWidth);
217+
this.setState({scrollable: contentWidth > this.containerWidth, contentWidth});
232218
};
233219

234220
onChangePage = index => {
@@ -245,25 +231,6 @@ export default class ColorPalette extends PureBaseComponent {
245231
}, 0);
246232
};
247233

248-
renderGradient() {
249-
return (
250-
<Animated.View
251-
pointerEvents="none"
252-
style={{
253-
position: 'absolute',
254-
right: 0,
255-
opacity: this.state.gradientOpacity
256-
}}
257-
>
258-
<Image
259-
source={gradientImage()}
260-
resizeMode={'stretch'}
261-
style={{width: GRADIENT_WIDTH, height: SCROLLABLE_HEIGHT - 12, tintColor: Colors.white}}
262-
/>
263-
</Animated.View>
264-
);
265-
}
266-
267234
getHorizontalMargins = (index) => {
268235
const isFirst = index === 0;
269236
const isOnLeft = isFirst || index % this.itemsPerRow === 0;
@@ -300,7 +267,7 @@ export default class ColorPalette extends PureBaseComponent {
300267
};
301268

302269
renderColorSwatch(color, index) {
303-
const {animatedIndex} = this.props;
270+
const {animatedIndex, testID} = this.props;
304271

305272
return (
306273
<ColorSwatch
@@ -313,6 +280,7 @@ export default class ColorPalette extends PureBaseComponent {
313280
animated={index === animatedIndex}
314281
onPress={this.onValueChange}
315282
ref={r => (this.itemsRefs[index] = r)}
283+
testID={`${testID}-${color}`}
316284
/>
317285
);
318286
}
@@ -334,49 +302,35 @@ export default class ColorPalette extends PureBaseComponent {
334302
);
335303
}
336304

337-
renderScroll() {
305+
renderScrollableContent() {
338306
const {containerStyle, ...others} = this.props;
339-
const {scrollable} = this.state;
307+
const {scrollable, contentWidth} = this.state;
340308

341309
return (
342-
<ScrollView
343-
ref={this.scrollView}
344-
horizontal
345-
showsHorizontalScrollIndicator={false}
310+
<ScrollBar
311+
ref={this.scrollBar}
346312
style={[containerStyle, styles.scrollContainer]}
347313
scrollEnabled={scrollable}
348314
onContentSizeChange={this.onContentSizeChange}
349-
onScroll={this.onScroll}
315+
height={SCROLLABLE_HEIGHT}
316+
containerProps={{width: !scrollable ? contentWidth : undefined}}
317+
gradientHeight={SCROLLABLE_HEIGHT - 12}
350318
>
351319
{this.renderPalette(others, styles.scrollContent, this.colors)}
352-
</ScrollView>
320+
</ScrollBar>
353321
);
354322
}
355323

356-
renderScrollableContent() {
357-
const {scrollable} = this.state;
358-
359-
if (scrollable) {
360-
return (
361-
<View row>
362-
{this.renderScroll()}
363-
{this.renderGradient()}
364-
</View>
365-
);
366-
}
367-
return this.renderScroll();
368-
}
369-
370324
renderPaginationContent() {
371325
const {containerStyle, loop, ...others} = this.props;
372326
const {currentPage} = this.state;
373327
const colorGroups = _.chunk(this.colors, this.itemsPerPage);
374328

375329
return (
376330
<View center style={[containerStyle, styles.paginationContainer]}>
377-
<Carousel loop={loop} onChangePage={this.onChangePage} ref={this.carousel}>
331+
<Carousel migrate loop={loop} onChangePage={this.onChangePage} ref={this.carousel}>
378332
{_.map(colorGroups, (colorsPerPage, index) => {
379-
return this.renderPalette(others, {...styles.page, width: Constants.screenWidth}, colorsPerPage, index);
333+
return this.renderPalette(others, {...styles.page, width: this.containerWidth}, colorsPerPage, index);
380334
})}
381335
</Carousel>
382336
<PageControl
@@ -399,7 +353,7 @@ export default class ColorPalette extends PureBaseComponent {
399353
const styles = StyleSheet.create({
400354
paletteContainer: {
401355
flexDirection: 'row',
402-
alignItems: 'flex-start',
356+
alignItems: 'center',
403357
paddingLeft: HORIZONTAL_PADDING,
404358
paddingVertical: VERTICAL_PADDING
405359
},

src/components/colorPicker/ColorSwatch.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import TouchableOpacity from '../touchableOpacity';
88
import Image from '../image';
99
import {PureBaseComponent} from '../../commons';
1010
import {Colors} from '../../style';
11+
import {Constants} from '../../helpers';
1112

1213

1314
const transparentImage = require('./assets/transparentSwatch/TransparentSwatch.png');
14-
const DEFAULT_SIZE = 36;
15+
const DEFAULT_SIZE = Constants.isTablet ? 44 : 36;
1516
export const SWATCH_MARGIN = 12;
1617
export const SWATCH_SIZE = DEFAULT_SIZE;
1718

@@ -144,7 +145,7 @@ export default class ColorSwatch extends PureBaseComponent {
144145
onLayout={this.onLayout}
145146
>
146147
{Colors.isTransparent(color) && (
147-
<Image source={transparentImage} style={this.styles.transparentImage} resizeMode={'center'}/>
148+
<Image source={transparentImage} style={this.styles.transparentImage} resizeMode={'cover'}/>
148149
)}
149150
<Animated.Image
150151
source={Assets.icons.check}
@@ -194,7 +195,9 @@ function createStyles({color = Colors.dark30}) {
194195
borderColor: Colors.rgba(Colors.dark30, 0.2)
195196
},
196197
transparentImage: {
197-
...StyleSheet.absoluteFillObject
198+
...StyleSheet.absoluteFillObject,
199+
width: DEFAULT_SIZE,
200+
height: DEFAULT_SIZE
198201
}
199202
});
200203
}

0 commit comments

Comments
 (0)