diff --git a/packages/block-editor/src/components/block-styles/index.native.js b/packages/block-editor/src/components/block-styles/index.native.js
index 982274b6bd6212..858e8a2c7a5f9f 100644
--- a/packages/block-editor/src/components/block-styles/index.native.js
+++ b/packages/block-editor/src/components/block-styles/index.native.js
@@ -9,6 +9,7 @@ import { find } from 'lodash';
*/
import { store as blocksStore } from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';
+import { useMemo } from '@wordpress/element';
import { _x } from '@wordpress/i18n';
/**
@@ -33,10 +34,6 @@ function BlockStyles( { clientId, url } ) {
const { updateBlockAttributes } = useDispatch( 'core/block-editor' );
- if ( ! styles || styles.length === 0 ) {
- return null;
- }
-
const renderedStyles = find( styles, 'isDefault' )
? styles
: [
@@ -48,37 +45,46 @@ function BlockStyles( { clientId, url } ) {
...styles,
];
- const activeStyle = getActiveStyle( renderedStyles, className );
+ const mappedRenderedStyles = useMemo( () => {
+ const activeStyle = getActiveStyle( renderedStyles, className );
+
+ return renderedStyles.map( ( style ) => {
+ const styleClassName = replaceActiveStyle(
+ className,
+ activeStyle,
+ style
+ );
+ const isActive = activeStyle === style;
+
+ const onStylePress = () => {
+ updateBlockAttributes( clientId, {
+ className: styleClassName,
+ } );
+ };
+
+ return (
+
+ );
+ } );
+ }, [ renderedStyles, className, clientId ] );
+
+ if ( ! styles || styles.length === 0 ) {
+ return null;
+ }
+
return (
- { renderedStyles.map( ( style ) => {
- const styleClassName = replaceActiveStyle(
- className,
- activeStyle,
- style
- );
- const isActive = activeStyle === style;
-
- const onStylePress = () => {
- updateBlockAttributes( clientId, {
- className: styleClassName,
- } );
- };
-
- return (
-
- );
- } ) }
+ { mappedRenderedStyles }
);
}
diff --git a/packages/block-editor/src/components/block-styles/preview.native.js b/packages/block-editor/src/components/block-styles/preview.native.js
index c9f663dc7f7945..c5461bf330acb9 100644
--- a/packages/block-editor/src/components/block-styles/preview.native.js
+++ b/packages/block-editor/src/components/block-styles/preview.native.js
@@ -71,7 +71,7 @@ function StylePreview( { onPress, isActive, style, url } ) {
return (
);
} );
diff --git a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
index 126064cfd3865c..548137215fafc3 100644
--- a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
+++ b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.native.js
@@ -7,6 +7,7 @@ import { useNavigation } from '@react-navigation/native';
* WordPress dependencies
*/
import { ColorControl, PanelBody } from '@wordpress/components';
+import { useMemo } from '@wordpress/element';
/**
* Internal dependencies
@@ -16,32 +17,32 @@ import { blockSettingsScreens } from '../block-settings';
export default function PanelColorGradientSettings( { settings, title } ) {
const navigation = useNavigation();
- return (
-
- { settings.map(
- ( {
- onColorChange,
- colorValue,
- onGradientChange,
- gradientValue,
- label,
- } ) => (
- {
- navigation.navigate( blockSettingsScreens.color, {
- onColorChange,
- colorValue: gradientValue || colorValue,
- gradientValue,
- onGradientChange,
- label,
- } );
- } }
- key={ `color-setting-${ label }` }
- label={ label }
- color={ gradientValue || colorValue }
- />
- )
- ) }
-
- );
+ const mappedSettings = useMemo( () => {
+ return settings.map(
+ ( {
+ onColorChange,
+ colorValue,
+ onGradientChange,
+ gradientValue,
+ label,
+ } ) => (
+ {
+ navigation.navigate( blockSettingsScreens.color, {
+ onColorChange,
+ colorValue: gradientValue || colorValue,
+ gradientValue,
+ onGradientChange,
+ label,
+ } );
+ } }
+ key={ `color-setting-${ label }` }
+ label={ label }
+ color={ gradientValue || colorValue }
+ />
+ )
+ );
+ }, [ settings ] );
+
+ return { mappedSettings };
}
diff --git a/packages/block-library/src/button/color-edit.js b/packages/block-library/src/button/color-edit.js
index fbb1b2766ed396..e5611a97aee69d 100644
--- a/packages/block-library/src/button/color-edit.js
+++ b/packages/block-library/src/button/color-edit.js
@@ -7,7 +7,13 @@ import { pickBy, isEqual, isObject, identity, mapValues } from 'lodash';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { useState, useEffect, useRef, Platform } from '@wordpress/element';
+import {
+ useState,
+ useEffect,
+ useRef,
+ useMemo,
+ Platform,
+} from '@wordpress/element';
/**
* Internal dependencies
@@ -200,32 +206,43 @@ function ColorEdit( props ) {
};
};
+ const settings = useMemo( () => {
+ return [
+ {
+ label: __( 'Text Color' ),
+ onColorChange: onChangeColor( 'text' ),
+ colorValue: getColorObjectByAttributeValues(
+ colors,
+ textColor,
+ style?.color?.text
+ ).color,
+ },
+ {
+ label: __( 'Background Color' ),
+ onColorChange: onChangeColor( 'background' ),
+ colorValue: getColorObjectByAttributeValues(
+ colors,
+ backgroundColor,
+ style?.color?.background
+ ).color,
+ gradientValue,
+ onGradientChange: onChangeGradient,
+ },
+ ];
+ }, [
+ colors,
+ textColor,
+ backgroundColor,
+ gradientValue,
+ style?.color?.text,
+ style?.color?.background,
+ ] );
+
return (
);
}
diff --git a/packages/block-library/src/button/edit.native.js b/packages/block-library/src/button/edit.native.js
index 79e7f76363b409..b8a01e9d01174f 100644
--- a/packages/block-library/src/button/edit.native.js
+++ b/packages/block-library/src/button/edit.native.js
@@ -61,6 +61,35 @@ class ButtonEdit extends Component {
isButtonFocused: true,
placeholderTextWidth: 0,
};
+
+ this.actions = [
+ {
+ label: __( 'Remove link' ),
+ onPress: this.onClearSettings,
+ },
+ ];
+
+ this.baseOptions = {
+ url: {
+ label: __( 'Button Link URL' ),
+ placeholder: __( 'Add URL' ),
+ autoFocus: true,
+ autoFill: true,
+ },
+ openInNewTab: {
+ label: __( 'Open in new tab' ),
+ },
+ linkRel: {
+ label: __( 'Link Rel' ),
+ placeholder: __( 'None' ),
+ },
+ };
+
+ this.modOptions = {
+ ...this.baseOptions,
+ ...this.baseOptions.url,
+ autoFocus: false,
+ };
}
componentDidMount() {
@@ -218,39 +247,22 @@ class ButtonEdit extends Component {
getLinkSettings( isCompatibleWithSettings ) {
const { isLinkSheetVisible } = this.state;
const { attributes, setAttributes } = this.props;
- const actions = [
- {
- label: __( 'Remove link' ),
- onPress: this.onClearSettings,
- },
- ];
-
- const options = {
- url: {
- label: __( 'Button Link URL' ),
- placeholder: __( 'Add URL' ),
- autoFocus: ! isCompatibleWithSettings,
- autoFill: true,
- },
- openInNewTab: {
- label: __( 'Open in new tab' ),
- },
- linkRel: {
- label: __( 'Link Rel' ),
- placeholder: __( 'None' ),
- },
- };
-
return (
);
@@ -383,35 +395,35 @@ class ButtonEdit extends Component {
{ isSelected && (
-
-
-
-
-
+ <>
+
+
+
+
+
+ { this.getLinkSettings( false ) }
+
+
+
+
+
+
+ { this.getLinkSettings( true ) }
+
+
+ >
) }
-
- { this.getLinkSettings( false ) }
-
-
-
-
-
-
-
- { this.getLinkSettings( true ) }
-
-
);
}
diff --git a/packages/block-library/src/buttons/content-justification-dropdown.js b/packages/block-library/src/buttons/content-justification-dropdown.js
index 7437a8670941ec..adce63ea234e0e 100644
--- a/packages/block-library/src/buttons/content-justification-dropdown.js
+++ b/packages/block-library/src/buttons/content-justification-dropdown.js
@@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { DropdownMenu } from '@wordpress/components';
+import { useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
@@ -52,21 +53,25 @@ export default function ContentJustificationDropdown( {
toggleProps,
value,
} ) {
+ const controls = useMemo( () => {
+ return allowedValues.map( ( allowedValue ) => {
+ return {
+ ...CONTROLS[ allowedValue ],
+ isActive: value === allowedValue,
+ role: 'menuitemradio',
+ onClick: () =>
+ onChange(
+ value === allowedValue ? undefined : allowedValue
+ ),
+ };
+ } );
+ }, [ allowedValues, value ] );
+
return (
{
- return {
- ...CONTROLS[ allowedValue ],
- isActive: value === allowedValue,
- role: 'menuitemradio',
- onClick: () =>
- onChange(
- value === allowedValue ? undefined : allowedValue
- ),
- };
- } ) }
+ controls={ controls }
toggleProps={ toggleProps }
/>
);
diff --git a/packages/block-library/src/buttons/edit.native.js b/packages/block-library/src/buttons/edit.native.js
index 1cbd6804df008c..459e9d05959d17 100644
--- a/packages/block-library/src/buttons/edit.native.js
+++ b/packages/block-library/src/buttons/edit.native.js
@@ -107,19 +107,21 @@ export default function ButtonsEdit( {
return (
<>
-
-
-
- { ( toggleProps ) => (
-
- ) }
-
-
-
+ { isSelected && (
+
+
+
+ { ( toggleProps ) => (
+
+ ) }
+
+
+
+ ) }
{ resizeObserver }
-
-
-
-
-
-
+
+
+
+
+
+
+ }
+ />
+
+
+
- }
- />
-
-
-
-
-
+
+
+ >
+ ) }
{
+ const getColumnsSliders = useMemo( () => {
if ( ! editorSidebarOpened || ! isSelected ) {
return null;
}
@@ -219,39 +219,48 @@ function ColumnsEditContainer( {
/>
);
} );
- };
+ }, [ editorSidebarOpened, isSelected, innerColumns ] );
+
+ const onChangeColumnsNum = useCallback(
+ ( value ) => {
+ updateColumns( columnCount, value );
+ },
+ [ columnCount ]
+ );
return (
<>
-
-
-
- updateColumns( columnCount, value )
- }
- min={ MIN_COLUMNS_NUM }
- max={ columnCount + 1 }
- type="stepper"
- />
- { getColumnsSliders() }
-
-
-
-
-
-
-
-
+ { isSelected && (
+ <>
+
+
+
+ { getColumnsSliders }
+
+
+
+
+
+
+
+
+ >
+ ) }
{ resizeListener }
{ width && (
diff --git a/packages/block-library/src/cover/edit.native.js b/packages/block-library/src/cover/edit.native.js
index 79594d06c00bc1..bf58808ecee1da 100644
--- a/packages/block-library/src/cover/edit.native.js
+++ b/packages/block-library/src/cover/edit.native.js
@@ -22,7 +22,7 @@ import {
PanelBody,
RangeControl,
UnitControl,
- BottomSheet,
+ TextControl,
ToolbarButton,
ToolbarGroup,
Gradient,
@@ -46,7 +46,7 @@ import {
} from '@wordpress/block-editor';
import { compose, withPreferredColorScheme } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
-import { useEffect, useState, useRef } from '@wordpress/element';
+import { useEffect, useState, useRef, useCallback } from '@wordpress/element';
import { cover as icon, replace, image, warning } from '@wordpress/icons';
import { getProtocol } from '@wordpress/url';
@@ -88,6 +88,7 @@ const Cover = ( {
setAttributes,
openGeneralSidebar,
closeSettingsBottomSheet,
+ isSelected,
} ) => {
const {
backgroundType,
@@ -169,15 +170,15 @@ const Cover = ( {
onSelect( media );
};
- const onHeightChange = ( value ) => {
+ const onHeightChange = useCallback( ( value ) => {
if ( minHeight || value !== COVER_DEFAULT_HEIGHT ) {
setAttributes( { minHeight: value } );
}
- };
+ }, [] );
- const onOpacityChange = ( value ) => {
+ const onOpacityChange = useCallback( ( value ) => {
setAttributes( { dimRatio: value } );
- };
+ }, [] );
const onMediaPressed = () => {
if ( isUploadInProgress ) {
@@ -199,10 +200,10 @@ const Cover = ( {
setIsVideoLoading( false );
};
- const onClearMedia = () => {
+ const onClearMedia = useCallback( () => {
setAttributes( { id: undefined, url: undefined } );
closeSettingsBottomSheet();
- };
+ }, [] );
function setColor( color ) {
setAttributes( {
@@ -278,7 +279,7 @@ const Cover = ( {
);
- const onChangeUnit = ( nextUnit ) => {
+ const onChangeUnit = useCallback( ( nextUnit ) => {
setAttributes( {
minHeightUnit: nextUnit,
minHeight:
@@ -286,12 +287,15 @@ const Cover = ( {
? Math.max( CONTAINER_HEIGHT, COVER_MIN_HEIGHT )
: CONTAINER_HEIGHT,
} );
- };
+ }, [] );
const controls = (
{ url ? (
@@ -321,10 +325,9 @@ const Cover = ( {
key={ minHeightUnit }
/>
-
{ url ? (
-
- { controls }
+ { isSelected && controls }
{ isImage &&
url &&
diff --git a/packages/block-library/src/cover/overlay-color-settings.native.js b/packages/block-library/src/cover/overlay-color-settings.native.js
index 7ceffd1fafd636..fec53f8add57f8 100644
--- a/packages/block-library/src/cover/overlay-color-settings.native.js
+++ b/packages/block-library/src/cover/overlay-color-settings.native.js
@@ -14,19 +14,19 @@ import {
__experimentalPanelColorGradientSettings as PanelColorGradientSettings,
__experimentalUseEditorFeature as useEditorFeature,
} from '@wordpress/block-editor';
+import { useMemo } from '@wordpress/element';
-function OverlayColorSettings( { attributes, setAttributes } ) {
+function OverlayColorSettings( {
+ overlayColor,
+ customOverlayColor,
+ gradient,
+ customGradient,
+ setAttributes,
+} ) {
const EMPTY_ARRAY = [];
const colors = useEditorFeature( 'color.palette' ) || EMPTY_ARRAY;
const gradients = useEditorFeature( 'color.gradients' ) || EMPTY_ARRAY;
- const {
- overlayColor,
- customOverlayColor,
- gradient,
- customGradient,
- } = attributes;
-
const gradientValue =
customGradient || getGradientValueBySlug( gradients, gradient );
@@ -36,56 +36,60 @@ function OverlayColorSettings( { attributes, setAttributes } ) {
customOverlayColor
).color;
- const setOverlayAttribute = ( attributeName, value ) => {
- setAttributes( {
- // clear all related attributes (only one should be set)
- overlayColor: undefined,
- customOverlayColor: undefined,
- gradient: undefined,
- customGradient: undefined,
- [ attributeName ]: value,
- } );
- };
+ const settings = useMemo( () => {
+ const setOverlayAttribute = ( attributeName, value ) => {
+ setAttributes( {
+ // clear all related attributes (only one should be set)
+ overlayColor: undefined,
+ customOverlayColor: undefined,
+ gradient: undefined,
+ customGradient: undefined,
+ [ attributeName ]: value,
+ } );
+ };
+
+ const onColorChange = ( value ) => {
+ // do nothing for falsy values
+ if ( ! value ) {
+ return;
+ }
+ const colorObject = getColorObjectByColorValue( colors, value );
+ if ( colorObject?.slug ) {
+ setOverlayAttribute( 'overlayColor', colorObject.slug );
+ } else {
+ setOverlayAttribute( 'customOverlayColor', value );
+ }
+ };
- const onColorChange = ( value ) => {
- // do nothing for falsy values
- if ( ! value ) {
- return;
- }
- const colorObject = getColorObjectByColorValue( colors, value );
- if ( colorObject?.slug ) {
- setOverlayAttribute( 'overlayColor', colorObject.slug );
- } else {
- setOverlayAttribute( 'customOverlayColor', value );
- }
- };
+ const onGradientChange = ( value ) => {
+ // do nothing for falsy values
+ if ( ! value ) {
+ return;
+ }
+ const slug = getGradientSlugByValue( gradients, value );
+ if ( slug ) {
+ setOverlayAttribute( 'gradient', slug );
+ } else {
+ setOverlayAttribute( 'customGradient', value );
+ }
+ };
- const onGradientChange = ( value ) => {
- // do nothing for falsy values
- if ( ! value ) {
- return;
- }
- const slug = getGradientSlugByValue( gradients, value );
- if ( slug ) {
- setOverlayAttribute( 'gradient', slug );
- } else {
- setOverlayAttribute( 'customGradient', value );
- }
- };
+ return [
+ {
+ label: __( 'Color' ),
+ onColorChange,
+ colorValue,
+ gradientValue,
+ onGradientChange,
+ },
+ ];
+ }, [ colorValue, gradientValue, colors, gradients ] );
return (
);
}
diff --git a/packages/block-library/src/file/edit.native.js b/packages/block-library/src/file/edit.native.js
index 062270b322a58c..0a88b9c362fc23 100644
--- a/packages/block-library/src/file/edit.native.js
+++ b/packages/block-library/src/file/edit.native.js
@@ -28,7 +28,7 @@ import {
ToolbarGroup,
PanelBody,
ToggleControl,
- BottomSheet,
+ TextControl,
SelectControl,
Icon,
} from '@wordpress/components';
@@ -264,13 +264,16 @@ export class FileEdit extends Component {
);
const isCopyUrlDisabled = isUploadFailed || isUploadInProgress;
- const dimmedStyle = isCopyUrlDisabled && styles.disabledButton;
- const finalButtonStyle = Object.assign(
- {},
- actionButtonStyle,
- dimmedStyle
+
+ const dimmedActionButtonStyle = this.props.getStylesFromColorScheme(
+ styles.dimmedActionButton,
+ styles.dimmedActionButtonDark
);
+ const finalButtonStyle = isCopyUrlDisabled
+ ? dimmedActionButtonStyle
+ : actionButtonStyle;
+
return (
{ isSidebarLinkSettings || (
@@ -298,7 +301,7 @@ export class FileEdit extends Component {
onChange={ this.onChangeDownloadButtonVisibility }
/>
) }
-
-
-
- { images.length > 1 && (
-
+
+ { images.length > 1 && (
+
+ ) }
+
- ) }
-
-
- { shouldShowSizeOptions && (
- ) }
-
-
+ { shouldShowSizeOptions && (
+
+ ) }
+
+
+ ) }
{ noticeUI }
( {
+ value: slug,
+ name,
+ } ) );
}
componentDidMount() {
@@ -336,65 +359,48 @@ export class ImageEdit extends React.Component {
: width;
}
+ setMappedAttributes = ( { url: href, ...restAttributes } ) => {
+ const { setAttributes } = this.props;
+ return href === undefined
+ ? setAttributes( restAttributes )
+ : setAttributes( { ...restAttributes, href } );
+ };
+
getLinkSettings() {
const { isLinkSheetVisible } = this.state;
const {
attributes: { href: url, ...unMappedAttributes },
- setAttributes,
} = this.props;
const mappedAttributes = { ...unMappedAttributes, url };
- const setMappedAttributes = ( { url: href, ...restAttributes } ) =>
- href === undefined
- ? setAttributes( restAttributes )
- : setAttributes( { ...restAttributes, href } );
-
- const options = {
- url: {
- label: __( 'Image Link URL' ),
- placeholder: __( 'Add URL' ),
- autoFocus: false,
- autoFill: true,
- },
- openInNewTab: {
- label: __( 'Open in new tab' ),
- },
- linkRel: {
- label: __( 'Link Rel' ),
- placeholder: __( 'None' ),
- },
- };
return (
);
}
+ onSizeChangeValue( newValue ) {
+ this.onSetSizeSlug( newValue );
+ }
+
render() {
const { isCaptionSelected } = this.state;
- const {
- attributes,
- isSelected,
- image,
- imageSizes,
- clientId,
- } = this.props;
+ const { attributes, isSelected, image, clientId } = this.props;
const { align, url, alt, id, sizeSlug, className } = attributes;
- const sizeOptions = map( imageSizes, ( { name, slug } ) => ( {
- value: slug,
- name,
- } ) );
- const sizeOptionsValid = find( sizeOptions, [
+ const sizeOptionsValid = find( this.sizeOptions, [
'value',
DEFAULT_SIZE_SLUG,
] );
@@ -427,10 +433,8 @@ export class ImageEdit extends React.Component {
icon={ expand }
label={ __( 'Size' ) }
value={ sizeSlug || DEFAULT_SIZE_SLUG }
- onChangeValue={ ( newValue ) =>
- this.onSetSizeSlug( newValue )
- }
- options={ sizeOptions }
+ onChangeValue={ this.onSizeChangeValue }
+ options={ this.sizeOptions }
/>
) }
- { getInspectorControls() }
- { getMediaOptions() }
+ { isSelected && getInspectorControls() }
+ { isSelected && getMediaOptions() }
{ ! this.state.isCaptionSelected &&
getToolbarEditButton( openMediaOptions ) }
- { this.getInspectorControls() }
+ { isSelected && this.getInspectorControls() }
{ blockType.settings.title }
diff --git a/packages/block-library/src/media-text/edit.native.js b/packages/block-library/src/media-text/edit.native.js
index f6ad9cf9fdbc43..5ff58b8696be02 100644
--- a/packages/block-library/src/media-text/edit.native.js
+++ b/packages/block-library/src/media-text/edit.native.js
@@ -337,28 +337,33 @@ class MediaTextEdit extends Component {
return (
<>
- { mediaType === MEDIA_TYPE_IMAGE && this.getControls() }
-
- { ( isMediaSelected || mediaType === MEDIA_TYPE_VIDEO ) && (
-
-
-
- ) }
- { ( ! isMediaSelected ||
- mediaType === MEDIA_TYPE_VIDEO ) && (
- <>
-
-
- >
- ) }
-
+ { isSelected &&
+ mediaType === MEDIA_TYPE_IMAGE &&
+ this.getControls() }
+ { isSelected && (
+
+ { ( isMediaSelected ||
+ mediaType === MEDIA_TYPE_VIDEO ) && (
+
+
+
+ ) }
+ { ( ! isMediaSelected ||
+ mediaType === MEDIA_TYPE_VIDEO ) && (
+ <>
+
+
+ >
+ ) }
+
+ ) }
-
- setHasUrl( true ) );
}
- function onCloseSettingsSheet() {
+ const onCloseSettingsSheet = useCallback( () => {
setIsLinkSheetVisible( false );
- }
+ }, [] );
function onOpenSettingsSheet() {
setIsLinkSheetVisible( true );
}
- function onEmptyURL() {
+ const onEmptyURL = useCallback( () => {
animatedValue.setValue( 0 );
setHasUrl( false );
- }
+ }, [] );
function onIconPress() {
if ( isSelected ) {
@@ -147,30 +147,35 @@ const SocialLinkEdit = ( {
return (
{ isSelected && (
-
-
-
-
-
+ <>
+
+
+
+
+
+
+ >
) }
-
+
{
const [ isResizing, setIsResizing ] = useState( false );
const { height } = attributes;
- const updateHeight = ( value ) => {
+ const updateHeight = useCallback( ( value ) => {
setAttributes( {
height: value,
} );
- };
+ }, [] );
const handleOnResizeStart = ( ...args ) => {
onResizeStart( ...args );
@@ -82,17 +82,19 @@ const SpacerEdit = ( {
} }
/>
-
-
-
-
-
+ { isSelected && (
+
+
+
+
+
+ ) }
>
);
};
diff --git a/packages/block-library/src/video/edit-common-settings.js b/packages/block-library/src/video/edit-common-settings.js
index a180593ad055a3..3daeabf4e61be7 100644
--- a/packages/block-library/src/video/edit-common-settings.js
+++ b/packages/block-library/src/video/edit-common-settings.js
@@ -3,6 +3,13 @@
*/
import { __ } from '@wordpress/i18n';
import { ToggleControl, SelectControl } from '@wordpress/components';
+import { useMemo, useCallback } from '@wordpress/element';
+
+const options = [
+ { value: 'auto', label: __( 'Auto' ) },
+ { value: 'metadata', label: __( 'Metadata' ) },
+ { value: 'none', label: __( 'None' ) },
+];
const VideoSettings = ( { setAttributes, attributes } ) => {
const {
@@ -14,57 +21,67 @@ const VideoSettings = ( { setAttributes, attributes } ) => {
preload,
} = attributes;
- const getAutoplayHelp = ( checked ) => {
+ const getAutoplayHelp = useCallback( ( checked ) => {
return checked
? __(
'Note: Autoplaying videos may cause usability issues for some visitors.'
)
: null;
- };
+ }, [] );
+
+ const toggleFactory = useMemo( () => {
+ const toggleAttribute = ( attribute ) => {
+ return ( newValue ) => {
+ setAttributes( { [ attribute ]: newValue } );
+ };
+ };
- const toggleAttribute = ( attribute ) => {
- return ( newValue ) => {
- setAttributes( { [ attribute ]: newValue } );
+ return {
+ autoplay: toggleAttribute( 'autoplay' ),
+ loop: toggleAttribute( 'loop' ),
+ muted: toggleAttribute( 'muted' ),
+ controls: toggleAttribute( 'controls' ),
+ playsInline: toggleAttribute( 'playsInline' ),
};
- };
+ }, [] );
+
+ const onChangePreload = useCallback( ( value ) => {
+ setAttributes( { preload: value } );
+ }, [] );
return (
<>
setAttributes( { preload: value } ) }
- options={ [
- { value: 'auto', label: __( 'Auto' ) },
- { value: 'metadata', label: __( 'Metadata' ) },
- { value: 'none', label: __( 'None' ) },
- ] }
+ onChange={ onChangePreload }
+ options={ options }
/>
>
);
diff --git a/packages/block-library/src/video/edit.native.js b/packages/block-library/src/video/edit.native.js
index b1638fcdc70dea..4fac2077052b26 100644
--- a/packages/block-library/src/video/edit.native.js
+++ b/packages/block-library/src/video/edit.native.js
@@ -236,14 +236,16 @@ class VideoEdit extends React.Component {
{ ! this.state.isCaptionSelected && (
{ toolbarEditButton }
) }
-
-
-
-
-
+ { isSelected && (
+
+
+
+
+
+ ) }
{
return ;
-}
+} );
export default FooterMessageControl;
diff --git a/packages/components/src/mobile/cycle-select-control/index.native.js b/packages/components/src/mobile/cycle-select-control/index.native.js
index 4bcc6614ff0332..51da2aaf657675 100644
--- a/packages/components/src/mobile/cycle-select-control/index.native.js
+++ b/packages/components/src/mobile/cycle-select-control/index.native.js
@@ -1,35 +1,41 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
import CyclePickerCell from '../bottom-sheet/cycle-picker-cell';
-function CycleSelectControl( {
- help,
- instanceId,
- label,
- multiple = false,
- onChange,
- options = [],
- className,
- hideLabelFromVision,
- ...props
-} ) {
- const id = `inspector-select-control-${ instanceId }`;
+const CycleSelectControl = React.memo(
+ ( {
+ help,
+ instanceId,
+ label,
+ multiple = false,
+ onChange,
+ options = [],
+ className,
+ hideLabelFromVision,
+ ...props
+ } ) => {
+ const id = `inspector-select-control-${ instanceId }`;
- return (
-
- );
-}
+ return (
+
+ );
+ }
+);
export default CycleSelectControl;
diff --git a/packages/components/src/mobile/link-settings/index.native.js b/packages/components/src/mobile/link-settings/index.native.js
index 3af96a6eb7ef58..0cbd1e5395f5ee 100644
--- a/packages/components/src/mobile/link-settings/index.native.js
+++ b/packages/components/src/mobile/link-settings/index.native.js
@@ -8,7 +8,13 @@ import { Platform, Clipboard } from 'react-native';
import { compose } from '@wordpress/compose';
import { withSelect } from '@wordpress/data';
import { isURL, prependHTTP } from '@wordpress/url';
-import { useEffect, useState, useRef, useContext } from '@wordpress/element';
+import {
+ useEffect,
+ useState,
+ useRef,
+ useContext,
+ useCallback,
+} from '@wordpress/element';
import { link, external } from '@wordpress/icons';
/**
@@ -32,8 +38,6 @@ function LinkSettings( {
isVisible,
// Callback that is called on closing bottom sheet
onClose,
- // Object of attributes to be set or updated in `LinkSettings`
- attributes,
// Function called to set attributes
setAttributes,
// Callback that is called when url input field is empty
@@ -80,8 +84,12 @@ function LinkSettings( {
showIcon,
onLinkCellPressed,
urlValue,
+ // Attributes properties
+ url,
+ label,
+ linkTarget,
+ rel,
} ) {
- const { url, label, linkTarget, rel } = attributes;
const [ urlInputValue, setUrlInputValue ] = useState( '' );
const [ labelInputValue, setLabelInputValue ] = useState( '' );
const [ linkRelInputValue, setLinkRelInputValue ] = useState( '' );
@@ -131,52 +139,58 @@ function LinkSettings( {
} );
}, [ urlValue ] );
- function onChangeURL( value ) {
- if ( ! value && onEmptyURL ) {
- onEmptyURL();
- }
- setUrlInputValue( value );
- }
+ const onChangeURL = useCallback(
+ ( value ) => {
+ if ( ! value && onEmptyURL ) {
+ onEmptyURL();
+ }
+ setUrlInputValue( value );
+ },
+ [ onEmptyURL ]
+ );
- function onChangeLabel( value ) {
+ const onChangeLabel = useCallback( ( value ) => {
setLabelInputValue( value );
- }
+ }, [] );
- function onSetAttributes() {
+ const onSetAttributes = useCallback( () => {
setAttributes( {
url: prependHTTP( urlInputValue ),
label: labelInputValue,
rel: linkRelInputValue,
} );
- }
+ }, [ urlInputValue, labelInputValue, linkRelInputValue, setAttributes ] );
- function onCloseSettingsSheet() {
+ const onCloseSettingsSheet = useCallback( () => {
onSetAttributes();
if ( onClose ) {
onClose();
}
- }
+ }, [ onClose, onSetAttributes ] );
- function onChangeOpenInNewTab( value ) {
- const newLinkTarget = value ? '_blank' : undefined;
+ const onChangeOpenInNewTab = useCallback(
+ ( value ) => {
+ const newLinkTarget = value ? '_blank' : undefined;
- let updatedRel = linkRelInputValue;
- if ( newLinkTarget && ! linkRelInputValue ) {
- updatedRel = NEW_TAB_REL;
- } else if ( ! newLinkTarget && linkRelInputValue === NEW_TAB_REL ) {
- updatedRel = undefined;
- }
+ let updatedRel = linkRelInputValue;
+ if ( newLinkTarget && ! linkRelInputValue ) {
+ updatedRel = NEW_TAB_REL;
+ } else if ( ! newLinkTarget && linkRelInputValue === NEW_TAB_REL ) {
+ updatedRel = undefined;
+ }
- setAttributes( {
- linkTarget: newLinkTarget,
- rel: updatedRel,
- } );
- }
+ setAttributes( {
+ linkTarget: newLinkTarget,
+ rel: updatedRel,
+ } );
+ },
+ [ linkRelInputValue ]
+ );
- function onChangeLinkRel( value ) {
+ const onChangeLinkRel = useCallback( ( value ) => {
setLinkRelInputValue( value );
- }
+ }, [] );
async function getURLFromClipboard() {
const clipboardText = await Clipboard.getString();
diff --git a/packages/components/src/mobile/link-settings/link-settings-navigation.native.js b/packages/components/src/mobile/link-settings/link-settings-navigation.native.js
index 1ca459f5cb5023..11b1cb136084c0 100644
--- a/packages/components/src/mobile/link-settings/link-settings-navigation.native.js
+++ b/packages/components/src/mobile/link-settings/link-settings-navigation.native.js
@@ -1,3 +1,7 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
@@ -10,7 +14,7 @@ const linkSettingsScreens = {
linkPicker: 'linkPicker',
};
-function LinkSettingsNavigation( props ) {
+const LinkSettingsNavigation = React.memo( ( props ) => {
if ( ! props.withBottomSheet ) {
return ;
}
@@ -39,6 +43,6 @@ function LinkSettingsNavigation( props ) {
);
-}
+} );
export default LinkSettingsNavigation;
diff --git a/packages/components/src/mobile/link-settings/link-settings-screen.native.js b/packages/components/src/mobile/link-settings/link-settings-screen.native.js
index c66892c9926c40..b83a5796942f60 100644
--- a/packages/components/src/mobile/link-settings/link-settings-screen.native.js
+++ b/packages/components/src/mobile/link-settings/link-settings-screen.native.js
@@ -15,7 +15,7 @@ import LinkSettings from './';
const LinkSettingsScreen = ( props ) => {
const navigation = useNavigation();
const route = useRoute();
- const { url = '' } = props.attributes || {};
+ const { url = '' } = props || {};
const { inputValue = url } = route.params || {};
const onLinkCellPressed = () => {
diff --git a/packages/components/src/mobile/picker/index.android.js b/packages/components/src/mobile/picker/index.android.js
index 2f727b2b92a9b3..1644776cade590 100644
--- a/packages/components/src/mobile/picker/index.android.js
+++ b/packages/components/src/mobile/picker/index.android.js
@@ -10,7 +10,7 @@ import { View } from 'react-native';
import { __ } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
-import { PanelBody } from '@wordpress/components';
+import { PanelBody, TextControl } from '@wordpress/components';
/**
* Internal dependencies
@@ -52,8 +52,27 @@ export default class Picker extends Component {
this.onClose();
}
+ getOptions() {
+ const { options, leftAlign } = this.props;
+
+ return options.map( ( option ) => (
+
+ { options.length > 1 && option.separated && }
+ this.onCellPress( option.value ) }
+ disabled={ option.disabled }
+ style={ option.disabled && styles.disabled }
+ />
+
+ ) );
+ }
+
render() {
- const { options, leftAlign, hideCancelButton, title } = this.props;
+ const { hideCancelButton, title } = this.props;
const { isVisible } = this.state;
return (
@@ -64,26 +83,9 @@ export default class Picker extends Component {
hideHeader
>
- { options.map( ( option ) => (
-
- { options.length > 1 && option.separated && (
-
- ) }
-
- this.onCellPress( option.value )
- }
- disabled={ option.disabled }
- style={ option.disabled && styles.disabled }
- />
-
- ) ) }
+ { this.getOptions() }
{ ! hideCancelButton && (
- {
+ return actions.map( ( { label, onPress } ) => {
+ return (
+
+ );
+ } );
+ }, [ actions ] );
+
return (
- { actions.map( ( { label, onPress } ) => {
- return (
-
- );
- } ) }
+ { mappedActions }
);
diff --git a/packages/components/src/query-controls/index.native.js b/packages/components/src/query-controls/index.native.js
index b9266e009151b1..22f65ce497c8b2 100644
--- a/packages/components/src/query-controls/index.native.js
+++ b/packages/components/src/query-controls/index.native.js
@@ -1,7 +1,12 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
+import { useCallback } from '@wordpress/element';
/**
* Internal dependencies
@@ -12,73 +17,81 @@ import CategorySelect from './category-select';
const DEFAULT_MIN_ITEMS = 1;
const DEFAULT_MAX_ITEMS = 100;
-export default function QueryControls( {
- categoriesList,
- selectedCategoryId,
- numberOfItems,
- order,
- orderBy,
- maxItems = DEFAULT_MAX_ITEMS,
- minItems = DEFAULT_MIN_ITEMS,
- onCategoryChange,
- onNumberOfItemsChange,
- onOrderChange,
- onOrderByChange,
-} ) {
- return [
- onOrderChange && onOrderByChange && (
- {
- const [ newOrderBy, newOrder ] = value.split( '/' );
- if ( newOrder !== order ) {
- onOrderChange( newOrder );
- }
- if ( newOrderBy !== orderBy ) {
- onOrderByChange( newOrderBy );
- }
- } }
- />
- ),
- onCategoryChange && (
-
- ),
- onNumberOfItemsChange && (
-
- ),
- ];
-}
+const options = [
+ {
+ label: __( 'Newest to oldest' ),
+ value: 'date/desc',
+ },
+ {
+ label: __( 'Oldest to newest' ),
+ value: 'date/asc',
+ },
+ {
+ /* translators: label for ordering posts by title in ascending order */
+ label: __( 'A → Z' ),
+ value: 'title/asc',
+ },
+ {
+ /* translators: label for ordering posts by title in descending order */
+ label: __( 'Z → A' ),
+ value: 'title/desc',
+ },
+];
+
+const QueryControls = React.memo(
+ ( {
+ categoriesList,
+ selectedCategoryId,
+ numberOfItems,
+ order,
+ orderBy,
+ maxItems = DEFAULT_MAX_ITEMS,
+ minItems = DEFAULT_MIN_ITEMS,
+ onCategoryChange,
+ onNumberOfItemsChange,
+ onOrderChange,
+ onOrderByChange,
+ } ) => {
+ const onChange = useCallback( ( value ) => {
+ const [ newOrderBy, newOrder ] = value.split( '/' );
+ if ( newOrder !== order ) {
+ onOrderChange( newOrder );
+ }
+ if ( newOrderBy !== orderBy ) {
+ onOrderByChange( newOrderBy );
+ }
+ }, [] );
+
+ return [
+ onOrderChange && onOrderByChange && (
+
+ ),
+ onCategoryChange && (
+
+ ),
+ onNumberOfItemsChange && (
+
+ ),
+ ];
+ }
+);
+
+export default QueryControls;
diff --git a/packages/components/src/range-control/index.native.js b/packages/components/src/range-control/index.native.js
index 9488fdad160879..96adbcecff895d 100644
--- a/packages/components/src/range-control/index.native.js
+++ b/packages/components/src/range-control/index.native.js
@@ -1,64 +1,70 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
import RangeCell from '../mobile/bottom-sheet/range-cell';
import StepperCell from '../mobile/bottom-sheet/stepper-cell';
-function RangeControl( {
- className,
- currentInput,
- label,
- value,
- instanceId,
- onChange,
- beforeIcon,
- afterIcon,
- help,
- allowReset,
- initialPosition,
- min,
- max,
- type,
- separatorType,
- ...props
-} ) {
- if ( type === 'stepper' ) {
+const RangeControl = React.memo(
+ ( {
+ className,
+ currentInput,
+ label,
+ value,
+ instanceId,
+ onChange,
+ beforeIcon,
+ afterIcon,
+ help,
+ allowReset,
+ initialPosition,
+ min,
+ max,
+ type,
+ separatorType,
+ ...props
+ } ) => {
+ if ( type === 'stepper' ) {
+ return (
+
+ );
+ }
+ const id = `inspector-range-control-${ instanceId }`;
+ const currentInputValue = currentInput === null ? value : currentInput;
+ const initialSliderValue = isFinite( currentInputValue )
+ ? currentInputValue
+ : initialPosition;
+
return (
-
);
}
- const id = `inspector-range-control-${ instanceId }`;
- const currentInputValue = currentInput === null ? value : currentInput;
- const initialSliderValue = isFinite( currentInputValue )
- ? currentInputValue
- : initialPosition;
-
- return (
-
- );
-}
+);
export default RangeControl;
diff --git a/packages/components/src/select-control/index.native.js b/packages/components/src/select-control/index.native.js
index 55b6064dfc1013..86ea11cdd50597 100644
--- a/packages/components/src/select-control/index.native.js
+++ b/packages/components/src/select-control/index.native.js
@@ -1,35 +1,41 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
import PickerCell from '../mobile/bottom-sheet/picker-cell';
-function SelectControl( {
- help,
- instanceId,
- label,
- multiple = false,
- onChange,
- options = [],
- className,
- hideLabelFromVision,
- ...props
-} ) {
- const id = `inspector-select-control-${ instanceId }`;
+const SelectControl = React.memo(
+ ( {
+ help,
+ instanceId,
+ label,
+ multiple = false,
+ onChange,
+ options = [],
+ className,
+ hideLabelFromVision,
+ ...props
+ } ) => {
+ const id = `inspector-select-control-${ instanceId }`;
- return (
-
- );
-}
+ return (
+
+ );
+ }
+);
export default SelectControl;
diff --git a/packages/components/src/text-control/index.native.js b/packages/components/src/text-control/index.native.js
index f490d70336e7c4..18a12fc6b1a7a6 100644
--- a/packages/components/src/text-control/index.native.js
+++ b/packages/components/src/text-control/index.native.js
@@ -1,35 +1,41 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
import Cell from '../mobile/bottom-sheet/cell';
-function TextControl( {
- label,
- hideLabelFromVision,
- value,
- help,
- className,
- instanceId,
- onChange,
- type = 'text',
- ...props
-} ) {
- const id = `inspector-text-control-${ instanceId }`;
+const TextControl = React.memo(
+ ( {
+ label,
+ hideLabelFromVision,
+ value,
+ help,
+ className,
+ instanceId,
+ onChange,
+ type = 'text',
+ ...props
+ } ) => {
+ const id = `inspector-text-control-${ instanceId }`;
- return (
- |
- );
-}
+ return (
+ |
+ );
+ }
+);
export default TextControl;
diff --git a/packages/components/src/toggle-control/index.native.js b/packages/components/src/toggle-control/index.native.js
index b6ed81df13748f..63cd25ee38a1d1 100644
--- a/packages/components/src/toggle-control/index.native.js
+++ b/packages/components/src/toggle-control/index.native.js
@@ -1,31 +1,29 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* Internal dependencies
*/
import SwitchCell from '../mobile/bottom-sheet/switch-cell';
-function ToggleControl( {
- label,
- checked,
- help,
- instanceId,
- className,
- onChange,
- ...props
-} ) {
- const id = `inspector-toggle-control-${ instanceId }`;
+const ToggleControl = React.memo(
+ ( { label, checked, help, instanceId, className, onChange, ...props } ) => {
+ const id = `inspector-toggle-control-${ instanceId }`;
- return (
-
- );
-}
+ return (
+
+ );
+ }
+);
export default ToggleControl;
diff --git a/packages/components/src/unit-control/index.native.js b/packages/components/src/unit-control/index.native.js
index 93355f7a34df09..66732e20086640 100644
--- a/packages/components/src/unit-control/index.native.js
+++ b/packages/components/src/unit-control/index.native.js
@@ -1,3 +1,7 @@
+/**
+ * External dependencies
+ */
+import React from 'react';
/**
* External dependencies
*/
@@ -20,46 +24,49 @@ import { CSS_UNITS } from './utils';
/**
* WordPress dependencies
*/
-import { useRef } from '@wordpress/element';
+import { useRef, useCallback } from '@wordpress/element';
import { withPreferredColorScheme } from '@wordpress/compose';
import { __, sprintf } from '@wordpress/i18n';
-function UnitControl( {
- currentInput,
- label,
- value,
- onChange,
- onUnitChange,
- initialPosition,
- min,
- max,
- separatorType,
- units = CSS_UNITS,
- unit,
- getStylesFromColorScheme,
- decimalNum,
- ...props
-} ) {
- const pickerRef = useRef();
- const anchorNodeRef = useRef();
+const UnitControl = React.memo(
+ ( {
+ currentInput,
+ label,
+ value,
+ onChange,
+ onUnitChange,
+ initialPosition,
+ min,
+ max,
+ separatorType,
+ units = CSS_UNITS,
+ unit,
+ getStylesFromColorScheme,
+ decimalNum,
+ ...props
+ } ) => {
+ const pickerRef = useRef();
+ const anchorNodeRef = useRef();
- function onPickerPresent() {
- if ( pickerRef?.current ) {
- pickerRef.current.presentPicker();
+ function onPickerPresent() {
+ if ( pickerRef?.current ) {
+ pickerRef.current.presentPicker();
+ }
}
- }
- const currentInputValue = currentInput === null ? value : currentInput;
- const initialControlValue = isFinite( currentInputValue )
- ? currentInputValue
- : initialPosition;
+ const currentInputValue = currentInput === null ? value : currentInput;
+ const initialControlValue = isFinite( currentInputValue )
+ ? currentInputValue
+ : initialPosition;
+
+ const unitButtonTextStyle = getStylesFromColorScheme(
+ styles.unitButtonText,
+ styles.unitButtonTextDark
+ );
- const unitButtonTextStyle = getStylesFromColorScheme(
- styles.unitButtonText,
- styles.unitButtonTextDark
- );
+ /* translators: accessibility text. Inform about current unit value. %s: Current unit value. */
+ const accessibilityLabel = sprintf( __( 'Current unit is %s' ), unit );
- const renderUnitButton = () => {
const accessibilityHint =
Platform.OS === 'ios'
? __( 'Double tap to open Action Sheet with available options' )
@@ -67,78 +74,77 @@ function UnitControl( {
'Double tap to open Bottom Sheet with available options'
);
- /* translators: accessibility text. Inform about current unit value. %s: Current unit value. */
- const accessibilityLabel = sprintf( __( 'Current unit is %s' ), unit );
+ const renderUnitButton = () => {
+ return (
+
+
+ { unit }
+
+
+ );
+ };
- return (
-
-
- { unit }
-
-
- );
- };
+ const getAnchor = () =>
+ anchorNodeRef?.current
+ ? findNodeHandle( anchorNodeRef?.current )
+ : undefined;
- const getAnchor = () =>
- anchorNodeRef?.current
- ? findNodeHandle( anchorNodeRef?.current )
- : undefined;
+ const renderUnitPicker = useCallback( () => {
+ return (
+
+ { renderUnitButton() }
+
+
+ );
+ }, [ pickerRef, units, onUnitChange, getAnchor ] );
- const renderUnitPicker = () => {
return (
-
- { renderUnitButton() }
-
-
+ <>
+ { unit !== '%' ? (
+
+ { renderUnitPicker() }
+
+ ) : (
+
+ { renderUnitPicker() }
+
+ ) }
+ >
);
- };
-
- return (
- <>
- { unit !== '%' ? (
-
- { renderUnitPicker() }
-
- ) : (
-
- { renderUnitPicker() }
-
- ) }
- >
- );
-}
+ }
+);
export default withPreferredColorScheme( UnitControl );
diff --git a/packages/rich-text/src/component/toolbar-button-with-options.native.js b/packages/rich-text/src/component/toolbar-button-with-options.native.js
index 3936bdd98c2872..cfef5060e57163 100644
--- a/packages/rich-text/src/component/toolbar-button-with-options.native.js
+++ b/packages/rich-text/src/component/toolbar-button-with-options.native.js
@@ -43,7 +43,7 @@ function ToolbarButtonWithOptions( { options } ) {
title={ firstOption.title }
icon={ }
onClick={ firstOption.onClick }
- onLongPress={ enablePicker && presentPicker }
+ onLongPress={ enablePicker ? presentPicker : null }
/>
{ enablePicker && (