@wordpress/components
Version:
UI components for WordPress.
233 lines (214 loc) • 6.06 kB
JavaScript
/**
* External dependencies
*/
import { View, Text, TouchableWithoutFeedback } from 'react-native';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useState, useContext } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
import { useRoute, useNavigation } from '@react-navigation/native';
/**
* Internal dependencies
*/
import ColorPalette from '../../color-palette';
import ColorIndicator from '../../color-indicator';
import NavBar from '../bottom-sheet/nav-bar';
import SegmentedControls from '../segmented-control';
import { colorsUtils } from './utils';
import PanelBody from '../../panel/body';
import { BottomSheetContext } from '../bottom-sheet/bottom-sheet-context';
import ColorControl from '../../color-control';
import styles from './style.scss';
const HIT_SLOP = { top: 8, bottom: 8, left: 8, right: 8 };
const PaletteScreen = () => {
const route = useRoute();
const navigation = useNavigation();
const { shouldEnableBottomSheetScroll } = useContext( BottomSheetContext );
const {
label,
onColorChange,
onGradientChange,
onColorCleared,
colorValue,
defaultSettings,
hideNavigation = false,
} = route.params || {};
const { segments, isGradient } = colorsUtils;
const [ currentValue, setCurrentValue ] = useState( colorValue );
const isGradientColor = isGradient( currentValue );
const selectedSegmentIndex = isGradientColor ? 1 : 0;
const [ currentSegment, setCurrentSegment ] = useState(
segments[ selectedSegmentIndex ]
);
const isGradientSegment = currentSegment === colorsUtils.segments[ 1 ];
const currentSegmentColors = ! isGradientSegment
? defaultSettings.colors
: defaultSettings.gradients;
const allAvailableColors = defaultSettings?.allAvailableColors || [];
const allAvailableGradients = currentSegmentColors
.flatMap( ( { gradients } ) => gradients )
.filter( Boolean );
const horizontalSeparatorStyle = usePreferredColorSchemeStyle(
styles.horizontalSeparator,
styles.horizontalSeparatorDark
);
const clearButtonStyle = usePreferredColorSchemeStyle(
styles.clearButton,
styles.clearButtonDark
);
const selectedColorTextStyle = usePreferredColorSchemeStyle(
styles.colorText,
styles.colorTextDark
);
const isSolidSegment = currentSegment === segments[ 0 ];
const isCustomGadientShown = ! isSolidSegment && isGradientColor;
const setColor = ( color ) => {
setCurrentValue( color );
if ( isSolidSegment && onColorChange && onGradientChange ) {
onColorChange( color );
} else if ( isSolidSegment && onColorChange ) {
onColorChange( color );
} else if ( ! isSolidSegment && onGradientChange ) {
onGradientChange( color );
}
};
function onClear() {
setCurrentValue( undefined );
if ( onColorCleared ) {
onColorCleared();
}
}
function onCustomPress() {
if ( isSolidSegment ) {
navigation.navigate( colorsUtils.screens.picker, {
currentValue,
setColor,
} );
} else {
navigation.navigate( colorsUtils.screens.gradientPicker, {
setColor,
isGradientColor,
currentValue,
} );
}
}
function getClearButton() {
return (
<TouchableWithoutFeedback
accessibilityLabel={ __( 'Clear selected color' ) }
onPress={ onClear }
hitSlop={ HIT_SLOP }
>
<View style={ styles.clearButtonContainer }>
<Text style={ clearButtonStyle }>{ __( 'Reset' ) }</Text>
</View>
</TouchableWithoutFeedback>
);
}
function getFooter() {
if ( onGradientChange ) {
return (
<SegmentedControls
segments={ segments }
segmentHandler={ setCurrentSegment }
selectedIndex={ segments.indexOf( currentSegment ) }
addonLeft={
currentValue && (
<ColorIndicator
color={ currentValue }
style={ styles.colorIndicator }
/>
)
}
addonRight={ currentValue && getClearButton() }
/>
);
}
return (
<View style={ styles.footer }>
<View style={ styles.flex }>
{ currentValue && (
<ColorIndicator
color={ currentValue }
style={ styles.colorIndicator }
/>
) }
</View>
{ currentValue ? (
<Text
style={ selectedColorTextStyle }
maxFontSizeMultiplier={ 2 }
selectable
>
{ currentValue.toUpperCase() }
</Text>
) : (
<Text
style={ styles.selectColorText }
maxFontSizeMultiplier={ 2 }
>
{ __( 'Select a color above' ) }
</Text>
) }
<View style={ styles.flex }>
{ currentValue && getClearButton() }
</View>
</View>
);
}
return (
<View>
{ ! hideNavigation && (
<NavBar>
<NavBar.BackButton onPress={ navigation.goBack } />
<NavBar.Heading>{ label } </NavBar.Heading>
</NavBar>
) }
<View style={ styles.colorPalettes }>
{ currentSegmentColors.map( ( palette, paletteKey ) => {
const paletteSettings = {
colors: palette.colors,
gradients: palette.gradients,
allColors: allAvailableColors,
allGradients: allAvailableGradients,
};
// Limit to show the custom indicator to the first available palette
const enableCustomColor = paletteKey === 0;
return (
<ColorPalette
enableCustomColor={ enableCustomColor }
label={ palette.name }
key={ paletteKey }
setColor={ setColor }
activeColor={ currentValue }
isGradientColor={ isGradientColor }
currentSegment={ currentSegment }
onCustomPress={ onCustomPress }
shouldEnableBottomSheetScroll={
shouldEnableBottomSheetScroll
}
defaultSettings={ paletteSettings }
/>
);
} ) }
</View>
{ isCustomGadientShown && (
<>
<View style={ horizontalSeparatorStyle } />
<PanelBody>
<ColorControl
label={ __( 'Customize Gradient' ) }
onPress={ onCustomPress }
withColorIndicator={ false }
/>
</PanelBody>
</>
) }
<View style={ horizontalSeparatorStyle } />
{ getFooter() }
</View>
);
};
export default PaletteScreen;