Skip to content

Commit

Permalink
[RNMobile] Add radial gradient infrastructure (#22493)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewalczak authored Jun 17, 2020
1 parent 7531814 commit ca98385
Show file tree
Hide file tree
Showing 22 changed files with 491 additions and 98 deletions.
2 changes: 1 addition & 1 deletion packages/base-styles/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ $spinner-size: 18px;
$mobile-header-toolbar-height: 44px;
$mobile-floating-toolbar-height: 44px;
$mobile-floating-toolbar-margin: 8px;

$mobile-color-swatch: 48px;

/**
* Shadows.
Expand Down
27 changes: 13 additions & 14 deletions packages/block-library/src/cover/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ const Cover = ( {
const onSelectMedia = ( media ) => {
setDidUploadFail( false );
const onSelect = attributesFromMedia( setAttributes );
// Remove gradient attribute
setAttributes( { gradient: undefined, customGradient: undefined } );
onSelect( media );
};

Expand Down Expand Up @@ -204,28 +202,29 @@ const Cover = ( {
attributes={ attributes }
setAttributes={ setAttributes }
/>
<PanelBody title={ __( 'Dimensions' ) }>
<RangeControl
label={ __( 'Minimum height in pixels' ) }
minimumValue={ COVER_MIN_HEIGHT }
maximumValue={ COVER_MAX_HEIGHT }
value={ CONTAINER_HEIGHT }
onChange={ onHeightChange }
style={ styles.rangeCellContainer }
/>
</PanelBody>
{ url ? (
<PanelBody title={ __( 'Overlay' ) }>
<PanelBody>
<RangeControl
label={ __( 'Background Opacity' ) }
label={ __( 'Opacity' ) }
minimumValue={ 0 }
maximumValue={ 100 }
value={ dimRatio }
onChange={ onOpactiyChange }
style={ styles.rangeCellContainer }
separatorType={ 'topFullWidth' }
/>
</PanelBody>
) : null }
<PanelBody title={ __( 'Dimensions' ) }>
<RangeControl
label={ __( 'Minimum height in pixels' ) }
minimumValue={ COVER_MIN_HEIGHT }
maximumValue={ COVER_MAX_HEIGHT }
value={ CONTAINER_HEIGHT }
onChange={ onHeightChange }
style={ styles.rangeCellContainer }
/>
</PanelBody>
</InspectorControls>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ function OverlayColorSettings( { attributes, setAttributes } ) {

return (
<PanelColorGradientSettings
title={ __( 'Color Settings' ) }
title={ __( 'Overlay' ) }
initialOpen={ false }
settings={ [
{
label: __( 'Overlay Color' ),
label: __( 'Color' ),
onColorChange,
colorValue,
gradientValue,
Expand Down
11 changes: 2 additions & 9 deletions packages/components/src/color-control/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,17 @@ import ColorCell from '../mobile/bottom-sheet/color-cell';

function ColorControl( {
label,
help,
instanceId,
className,
onPress,
color,
withColorIndicator,
...props
} ) {
const id = `inspector-color-control-${ instanceId }`;

return (
<ColorCell
label={ label }
id={ id }
help={ help }
className={ className }
aria-describedby={ !! help ? id + '__help' : undefined }
onPress={ onPress }
color={ color }
withColorIndicator={ withColorIndicator }
{ ...props }
/>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/color-indicator/style.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
}

.circleOption {
height: 48px;
width: 48px;
height: $mobile-color-swatch;
width: $mobile-color-swatch;
border-radius: 24px;
margin-right: 8px;
justify-content: center;
Expand Down
124 changes: 112 additions & 12 deletions packages/components/src/color-palette/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,31 @@ import {
View,
Animated,
Easing,
Dimensions,
Platform,
Text,
} from 'react-native';
import { map, uniq } from 'lodash';
/**
* WordPress dependencies
*/
import { useRef, useEffect, createRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useRef, useEffect } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './style.scss';
import ColorIndicator from '../color-indicator';
import { colorsUtils } from '../mobile/color-settings/utils';
import { performLayoutAnimation } from '../mobile/layout-animation';

const ANIMATION_DURATION = 200;

let contentWidth = 0;
let scrollPosition = 0;
let customIndicatorWidth = 0;

function ColorPalette( {
setColor,
activeColor,
Expand All @@ -38,7 +47,8 @@ function ColorPalette( {
'linear-gradient(360deg, rgba(0,0,255,.8), 0%, rgba(0,0,255,0) 70.71%)',
];

const scrollViewRef = createRef();
const scrollViewRef = useRef();
const isIOS = Platform.OS === 'ios';

const isGradientSegment = currentSegment === colorsUtils.segments[ 1 ];

Expand All @@ -51,14 +61,37 @@ function ColorPalette( {
);
const colors = isGradientSegment ? defaultGradientColors : defaultColors;

const customIndicatorColor = isGradientSegment
? activeColor
: customSwatchGradients;
const isCustomGradientColor = isGradientColor && isSelectedCustom();
const shouldShowCustomIndicator =
! isGradientSegment || isCustomGradientColor;

const accessibilityHint = isGradientSegment
? __( 'Navigates to customize the gradient' )
: __( 'Navigates to custom color picker' );
const customText = __( 'Custom' );

useEffect( () => {
scrollViewRef.current.scrollTo( { x: 0, y: 0 } );
if ( scrollViewRef.current ) {
if ( isSelectedCustom() ) {
scrollViewRef.current.scrollToEnd();
} else {
scrollViewRef.current.scrollTo( { x: 0, y: 0 } );
}
}
}, [ currentSegment ] );

function isSelectedCustom() {
return (
! isGradientColor && activeColor && ! colors.includes( activeColor )
);
const isWithinColors = activeColor && colors.includes( activeColor );
if ( activeColor ) {
if ( isGradientSegment ) {
return isGradientColor && ! isWithinColors;
}
return ! isGradientColor && ! isWithinColors;
}
return false;
}

function isSelected( color ) {
Expand Down Expand Up @@ -93,16 +126,64 @@ function ColorPalette( {
outputRange: [ 1, 0.7, 1 ],
} );

function deselectCustomGradient() {
const { width } = Dimensions.get( 'window' );
const isVisible =
contentWidth - scrollPosition - customIndicatorWidth < width;

if ( isCustomGradientColor ) {
performLayoutAnimation();
if ( ! isIOS ) {
// Scroll position on Android doesn't adjust automatically when removing the last item from the horizontal list.
// https://github.com/facebook/react-native/issues/27504
// Workaround: Force the scroll when deselecting custom gradient color and when custom indicator is visible on layout.
if (
isCustomGradientColor &&
isVisible &&
scrollViewRef.current
) {
scrollViewRef.current.scrollTo( {
x: scrollPosition - customIndicatorWidth,
} );
}
}
}
}

function onColorPress( color ) {
deselectCustomGradient();
performAnimation( color );
setColor( color );
}

function onContentSizeChange( width ) {
contentWidth = width;
if ( isSelectedCustom() && scrollViewRef.current ) {
scrollViewRef.current.scrollToEnd( { animated: ! isIOS } );
}
}

function onCustomIndicatorLayout( { nativeEvent } ) {
const { width } = nativeEvent.layout;
if ( width !== customIndicatorWidth ) {
customIndicatorWidth = width;
}
}

function onScroll( { nativeEvent } ) {
scrollPosition = nativeEvent.contentOffset.x;
}

const verticalSeparatorStyle = usePreferredColorSchemeStyle(
styles.verticalSeparator,
styles.verticalSeparatorDark
);

const customTextStyle = usePreferredColorSchemeStyle(
[ styles.customText, ! isIOS && styles.customTextAndroid ],
styles.customTextDark
);

return (
<ScrollView
contentContainerStyle={ styles.contentContainer }
Expand All @@ -111,6 +192,9 @@ function ColorPalette( {
showsHorizontalScrollIndicator={ false }
keyboardShouldPersistTaps="always"
disableScrollViewPanResponder
scrollEventThrottle={ 16 }
onScroll={ onScroll }
onContentSizeChange={ onContentSizeChange }
onScrollBeginDrag={ () => shouldEnableBottomSheetScroll( false ) }
onScrollEndDrag={ () => shouldEnableBottomSheetScroll( true ) }
ref={ scrollViewRef }
Expand All @@ -121,6 +205,9 @@ function ColorPalette( {
<TouchableWithoutFeedback
onPress={ () => onColorPress( color ) }
key={ `${ color }-${ isSelected( color ) }` }
accessibilityRole={ 'button' }
accessibilityState={ { selected: isSelected( color ) } }
accessibilityHint={ color }
>
<Animated.View
style={ {
Expand All @@ -141,20 +228,33 @@ function ColorPalette( {
</TouchableWithoutFeedback>
);
} ) }
{ ! isGradientSegment && (
<>
{ shouldShowCustomIndicator && (
<View
style={ styles.customIndicatorWrapper }
onLayout={ onCustomIndicatorLayout }
>
<View style={ verticalSeparatorStyle } />
<TouchableWithoutFeedback onPress={ onCustomPress }>
<View>
<TouchableWithoutFeedback
onPress={ onCustomPress }
accessibilityRole={ 'button' }
accessibilityState={ { selected: isSelectedCustom() } }
accessibilityHint={ accessibilityHint }
>
<View style={ styles.customIndicatorWrapper }>
<ColorIndicator
withCustomPicker={ ! isGradientSegment }
color={ customSwatchGradients }
color={ customIndicatorColor }
isSelected={ isSelectedCustom() }
style={ styles.colorIndicator }
/>
<Text style={ customTextStyle }>
{ isIOS
? customText
: customText.toUpperCase() }
</Text>
</View>
</TouchableWithoutFeedback>
</>
</View>
) }
</ScrollView>
);
Expand Down
19 changes: 19 additions & 0 deletions packages/components/src/color-palette/style.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,22 @@
margin-top: 12px;
margin-bottom: 12px;
}

.customIndicatorWrapper {
flex-direction: row;
align-items: center;
}

.customText {
font-size: 16px;
color: $gray-dark;
}

.customTextDark {
color: $white;
}

.customTextAndroid {
letter-spacing: 1.25;
font-weight: medium;
}
Loading

0 comments on commit ca98385

Please sign in to comment.