Skip to content

ColorPicker now support backgroundColor prop #2328

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
Nov 23, 2022
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
46 changes: 30 additions & 16 deletions demo/src/screens/componentScreens/ColorPickerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import _ from 'lodash';
import React, {Component} from 'react';
import {StyleSheet, ScrollView} from 'react-native';
import {Colors, View, Text, ColorPicker, ColorPalette, ColorName} from 'react-native-ui-lib';

import {renderMultipleSegmentOptions} from '../ExampleScreenPresenter';

interface Props {}
interface State {
color: string,
textColor: string,
customColors: string[],
paletteChange: boolean
color: string;
textColor: string;
customColors: string[];
paletteChange: boolean;
backgroundColor: string;
}

const INITIAL_COLOR = Colors.$backgroundPrimaryHeavy;
Expand All @@ -24,37 +25,37 @@ const colors = [
'#8B1079', '#A0138E', '#B13DAC', '#C164BD', '#D08BCD', '#E0B1DE', '#EFD8EE', '#F7EBF7'
];


export default class ColorPickerScreen extends Component<Props, State> {
state: State = {
color: INITIAL_COLOR,
textColor: Colors.$textDefaultLight,
customColors: [],
paletteChange: false
paletteChange: false,
backgroundColor: Colors.$backgroundDefault
};

onDismiss = () => {
console.log(`screen onDismiss`);
}
};

onSubmit = (color: string, textColor: string) => {
const {customColors} = this.state;
customColors.push(color);
this.setState({color, textColor, customColors: _.clone(customColors), paletteChange: false});
}
};

onValueChange = (value: string, options: object) => {
this.setState({color: value, textColor: options ? _.get(options, 'tintColor') : undefined, paletteChange: false});
}
};

onPaletteValueChange = (value: string, options: object) => {
this.setState({color: value, textColor: options ? _.get(options, 'tintColor') : undefined, paletteChange: true});
}
};

render() {
const {color, textColor, customColors, paletteChange} = this.state;
const paletteValue = paletteChange ? (color || INITIAL_COLOR) : undefined;
const pickerValue = !paletteChange ? (color || INITIAL_COLOR) : undefined;
const {color, textColor, customColors, paletteChange, backgroundColor} = this.state;
const paletteValue = paletteChange ? color || INITIAL_COLOR : undefined;
const pickerValue = !paletteChange ? color || INITIAL_COLOR : undefined;

const mappedColor = ColorName.name(color);
const nearestColor = mappedColor[0];
Expand All @@ -67,18 +68,30 @@ export default class ColorPickerScreen extends Component<Props, State> {
<Text text60 margin-10 style={{color}}>
Selected Color: {color}
</Text>
<View center marginB-10 style={{height: 50, width: 200, backgroundColor: color}} >
<View center marginB-10 style={{height: 50, width: 200, backgroundColor: color}}>
<Text text60 style={{color: textColor}}>
{color}
</Text>
</View>
</View>
<View bg-$backgroundDefault>
<View marginH-20>
{renderMultipleSegmentOptions.call(this, 'backgroundColor:', 'backgroundColor', [
{label: 'Default', value: Colors.$backgroundDefault},
{label: 'Primary', value: Colors.$backgroundPrimaryHeavy},
{label: 'Success', value: Colors.$backgroundSuccessHeavy}
])}
</View>
<Text text60 marginL-20 marginB-4 marginT-24>
Theme Color
</Text>
<Text marginL-20>Choose a color for your place’s theme.</Text>
<ColorPalette value={paletteValue} onValueChange={this.onPaletteValueChange} colors={colors}/>
<ColorPalette
value={paletteValue}
onValueChange={this.onPaletteValueChange}
colors={colors}
backgroundColor={backgroundColor}
/>
<Text marginL-20 marginT-16>
Custom Colors
</Text>
Expand All @@ -90,6 +103,7 @@ export default class ColorPickerScreen extends Component<Props, State> {
onValueChange={this.onValueChange}
value={pickerValue}
// animatedIndex={0}
backgroundColor={backgroundColor}
/>
</View>

Expand Down
66 changes: 34 additions & 32 deletions src/components/colorPalette/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ interface Props {
onValueChange?: (value: string, options: object) => void;
style?: StyleProp<ViewStyle>;
testID?: string;
/**
* Give the ColorPalette a background color
*/
backgroundColor?: string;
}
export type ColorPaletteProps = Props;

Expand Down Expand Up @@ -81,7 +85,8 @@ class ColorPalette extends PureComponent<Props, State> {
static defaultProps = {
numberOfRows: DEFAULT_NUMBER_OF_ROWS,
usePagination: true,
loop: true
loop: true,
backgroundColor: Colors.$backgroundDefault
};

constructor(props: Props) {
Expand Down Expand Up @@ -219,30 +224,31 @@ class ColorPalette extends PureComponent<Props, State> {
return (margin - 0.001) / 2;
}

scrollToSelected = () => setTimeout(() => {
const {scrollable, currentPage} = this.state;

if (scrollable && this.selectedColorIndex !== undefined && this.itemsRefs.current) {
// The this.selectedColorIndex layout doesn't update on time
// so we use this.selectedColorIndex - 1 and add an offset of 1 Swatch
const childRef: any = this.itemsRefs.current[this.selectedColorIndex - 1]?.current;

if (childRef) {
const childLayout = childRef.getLayout();
const leftMargins = this.getHorizontalMargins(this.selectedColorIndex).marginLeft;
const childX = childLayout.x + childLayout.width + SWATCH_MARGIN + leftMargins + SWATCH_SIZE;
if (childX > this.containerWidth) {
this.scrollBar?.current?.scrollTo({
x: childX + HORIZONTAL_PADDING - this.containerWidth,
y: 0,
animated: false
});
scrollToSelected = () =>
setTimeout(() => {
const {scrollable, currentPage} = this.state;

if (scrollable && this.selectedColorIndex !== undefined && this.itemsRefs.current) {
// The this.selectedColorIndex layout doesn't update on time
// so we use this.selectedColorIndex - 1 and add an offset of 1 Swatch
const childRef: any = this.itemsRefs.current[this.selectedColorIndex - 1]?.current;

if (childRef) {
const childLayout = childRef.getLayout();
const leftMargins = this.getHorizontalMargins(this.selectedColorIndex).marginLeft;
const childX = childLayout.x + childLayout.width + SWATCH_MARGIN + leftMargins + SWATCH_SIZE;
if (childX > this.containerWidth) {
this.scrollBar?.current?.scrollTo({
x: childX + HORIZONTAL_PADDING - this.containerWidth,
y: 0,
animated: false
});
}
} else if (this.usePagination) {
this.carousel?.current?.goToPage(this.selectedPage || currentPage, false);
}
} else if (this.usePagination) {
this.carousel?.current?.goToPage(this.selectedPage || currentPage, false);
}
}
}, 100)
}, 100);

onContentSizeChange = (contentWidth: number) => {
this.setState({
Expand Down Expand Up @@ -331,32 +337,32 @@ class ColorPalette extends PureComponent<Props, State> {
}

renderScrollableContent() {
const {containerStyle, ...others} = this.props;
const {containerStyle, backgroundColor, ...others} = this.props;
const {scrollable, contentWidth} = this.state;

return (
<ScrollBar
ref={this.scrollBar}
style={[containerStyle, styles.scrollContainer]}
style={[containerStyle, {backgroundColor}]}
scrollEnabled={scrollable}
onContentSizeChange={this.onContentSizeChange}
height={SCROLLABLE_HEIGHT}
containerProps={{width: !scrollable ? contentWidth : undefined}}
gradientHeight={SCROLLABLE_HEIGHT - 12}
gradientColor={Colors.$backgroundDefault}
gradientColor={backgroundColor}
>
{this.renderPalette(others, styles.scrollContent, this.colors, 0)}
</ScrollBar>
);
}

renderPaginationContent() {
const {containerStyle, loop, ...others} = this.props;
const {containerStyle, loop, backgroundColor, ...others} = this.props;
const {currentPage} = this.state;
const colorGroups = _.chunk(this.colors, this.itemsPerPage);

return (
<View center style={[containerStyle, styles.paginationContainer]}>
<View center style={[containerStyle, styles.paginationContainer, {backgroundColor}]}>
<Carousel loop={loop} onChangePage={this.onChangePage} ref={this.carousel}>
{_.map(colorGroups, (colorsPerPage, index) => {
return this.renderPalette(others, {...styles.page, width: this.containerWidth}, colorsPerPage, index);
Expand Down Expand Up @@ -390,12 +396,8 @@ const styles = StyleSheet.create({
},
paginationContainer: {
flex: 1,
backgroundColor: Colors.$backgroundDefault,
paddingBottom: VERTICAL_PADDING
},
scrollContainer: {
backgroundColor: Colors.$backgroundDefault
},
page: {
flexWrap: 'wrap'
},
Expand Down
30 changes: 16 additions & 14 deletions src/components/colorPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import ColorPalette from '../colorPalette';
import {SWATCH_MARGIN, SWATCH_SIZE} from '../colorSwatch';
import ColorPickerDialog, {ColorPickerDialogProps} from './ColorPickerDialog';


interface Props extends ColorPickerDialogProps {
/**
* Array of colors for the picker's color palette (hex values)
Expand Down Expand Up @@ -36,13 +35,17 @@ interface Props extends ColorPickerDialogProps {
* }
*/
accessibilityLabels?: {
addButton?: string,
dismissButton?: string,
doneButton?: string,
input?: string
addButton?: string;
dismissButton?: string;
doneButton?: string;
input?: string;
};
style?: StyleProp<ViewStyle>;
testID?: string;
/**
* Give the ColorPicker a background color
*/
backgroundColor?: string;
}
export type ColorPickerProps = Props;

Expand All @@ -63,7 +66,8 @@ class ColorPicker extends PureComponent<Props> {
static displayName = 'ColorPicker';

static defaultProps = {
accessibilityLabels: ACCESSIBILITY_LABELS
accessibilityLabels: ACCESSIBILITY_LABELS,
backgroundColor: Colors.$backgroundDefault
};

state = {
Expand All @@ -84,14 +88,13 @@ class ColorPicker extends PureComponent<Props> {

hideDialog = () => {
this.setState({show: false});
}
};

render() {
const {initialColor, colors, value, testID, accessibilityLabels} = this.props;
const {initialColor, colors, value, testID, accessibilityLabels, backgroundColor} = this.props;
const {show} = this.state;

return (
<View row testID={testID}>
<View row testID={testID} style={{backgroundColor}}>
<ColorPalette
value={value}
colors={colors}
Expand All @@ -100,8 +103,9 @@ class ColorPicker extends PureComponent<Props> {
animatedIndex={this.animatedIndex}
onValueChange={this.onValueChange}
testID={`${testID}-palette`}
backgroundColor={backgroundColor}
/>
<View style={styles.buttonContainer}>
<View style={[styles.buttonContainer, {backgroundColor}]}>
<Button
color={Colors.$textDefault}
outlineColor={Colors.$textDefault}
Expand Down Expand Up @@ -137,7 +141,6 @@ class ColorPicker extends PureComponent<Props> {

export default ColorPicker;


const plusButtonContainerWidth = SWATCH_SIZE + 20 + 12;
const plusButtonContainerHeight = 92 - 2 * SWATCH_MARGIN;

Expand All @@ -154,8 +157,7 @@ const styles = StyleSheet.create({
marginBottom: SWATCH_MARGIN,
alignItems: 'flex-end',
justifyContent: 'center',
paddingTop: 1,
backgroundColor: Colors.$backgroundDefault
paddingTop: 1
},
button: {
width: SWATCH_SIZE,
Expand Down