From 1ad3f18001b32f2aec25ae935cbdeb3beafb81db Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 10 Feb 2021 18:43:06 +0100 Subject: [PATCH 01/20] add component logic --- .../src/edit-in-place-control/index.js | 102 ++++++++++++++++++ .../src/edit-in-place-control/style.scss | 16 +++ packages/components/src/index.js | 1 + packages/components/src/style.scss | 1 + 4 files changed, 120 insertions(+) create mode 100644 packages/components/src/edit-in-place-control/index.js create mode 100644 packages/components/src/edit-in-place-control/style.scss diff --git a/packages/components/src/edit-in-place-control/index.js b/packages/components/src/edit-in-place-control/index.js new file mode 100644 index 00000000000000..47baaa51ec4f3b --- /dev/null +++ b/packages/components/src/edit-in-place-control/index.js @@ -0,0 +1,102 @@ +/** + * External dependencies + */ +import { noop, negate, isUndefined } from 'lodash'; + +/** + * WordPress dependencies + */ +import { useState, useRef, useEffect } from '@wordpress/element'; +/** + * Internal dependencies + */ +import Button from '../button'; + +const baseInputCssClass = 'components-edit-in-place-control__input'; +const beforeTransitionInputCssClass = 'small'; +const afterTransitionInputCssClass = 'large'; +const withoutTransitionCssClass = `${ baseInputCssClass } ${ beforeTransitionInputCssClass }`; +const withTransitionCssClass = `${ baseInputCssClass } ${ afterTransitionInputCssClass }`; +const cancelEvent = ( event ) => ( + event.preventDefault(), event.stopPropagation() +); + +function EditInPlaceControl( { + initialValue = '', + onClick = noop, + onUpdate = noop, + switchToEditModeButtonLabel, + inputValidator = negate( isUndefined ), + editNameInputLabel = initialValue, +} ) { + const [ isEdit, setIsEdit ] = useState( false ); + const [ value, setValue ] = useState( initialValue ); + const [ inputCssClasses, setInputCssClasses ] = useState( + withoutTransitionCssClass + ); + + const inputRef = useRef(); + const buttonRef = useRef(); + + useEffect( () => { + if ( isEdit ) { + inputRef.current.focus(); + inputRef.current.select(); + } else { + buttonRef.current.focus(); + } + }, [ isEdit ] ); + + return ( + <> + { isEdit ? ( + { + setValue( event.target.value ); + } } + onFocus={ () => + setInputCssClasses( withTransitionCssClass ) + } + onBlur={ () => { + setIsEdit( false ); + onUpdate( value ); + setInputCssClasses( withoutTransitionCssClass ); + } } + onKeyDown={ ( event ) => { + if ( 'Enter' === event.key ) { + cancelEvent( event ); + if ( inputValidator( value ) ) { + setIsEdit( false ); + onUpdate( value ); + } + } + if ( 'Escape' === event.key ) { + cancelEvent( event ); + setValue( initialValue ); + setIsEdit( false ); + event.target.blur(); + } + } } + /> + ) : ( + + ) } + + ); +} + +export default EditInPlaceControl; diff --git a/packages/components/src/edit-in-place-control/style.scss b/packages/components/src/edit-in-place-control/style.scss new file mode 100644 index 00000000000000..eeb8d36a1cfdbf --- /dev/null +++ b/packages/components/src/edit-in-place-control/style.scss @@ -0,0 +1,16 @@ +.components-edit-in-place-control__label { + padding: $grid-unit-30; + width: auto; +} +.components-edit-in-place-control__input { + margin-bottom: 1px; + text-indent: $grid-unit; + &.large { + width: 100%; + transition: width 0.3s; + } + &.small { + width: 50%; + transition: width 0.3s; + } +} diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 84d87495b37c21..1266183bfc0690 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -77,6 +77,7 @@ export { default as GuidePage } from './guide/page'; export { default as Icon } from './icon'; export { default as IconButton } from './button/deprecated'; export { default as __experimentalInputControl } from './input-control'; +export { default as __experimentalEditInPlaceControl } from './edit-in-place-control'; export { default as KeyboardShortcuts } from './keyboard-shortcuts'; export { default as MenuGroup } from './menu-group'; export { default as MenuItem } from './menu-item'; diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index a7b92c1192b13d..992e277f3fd005 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -16,6 +16,7 @@ @import "./drop-zone/style.scss"; @import "./dropdown/style.scss"; @import "./dropdown-menu/style.scss"; +@import "./edit-in-place-control/style.scss"; @import "./font-size-picker/style.scss"; @import "./form-toggle/style.scss"; @import "./form-token-field/style.scss"; From 3c1191fbd9fc52f5c85d0745f4d3de89b58f4369 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Sun, 14 Feb 2021 13:36:53 +0100 Subject: [PATCH 02/20] add missing callbacks: onKedyDown and onChange --- packages/components/src/edit-in-place-control/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/components/src/edit-in-place-control/index.js b/packages/components/src/edit-in-place-control/index.js index 47baaa51ec4f3b..e28f07bdb3ac6f 100644 --- a/packages/components/src/edit-in-place-control/index.js +++ b/packages/components/src/edit-in-place-control/index.js @@ -28,6 +28,8 @@ function EditInPlaceControl( { switchToEditModeButtonLabel, inputValidator = negate( isUndefined ), editNameInputLabel = initialValue, + onChange = noop, + onKeyDown = noop, } ) { const [ isEdit, setIsEdit ] = useState( false ); const [ value, setValue ] = useState( initialValue ); @@ -56,7 +58,9 @@ function EditInPlaceControl( { className={ inputCssClasses } value={ value } onChange={ ( event ) => { + const _value = event.target.value; setValue( event.target.value ); + onChange( _value, event ); } } onFocus={ () => setInputCssClasses( withTransitionCssClass ) @@ -80,6 +84,7 @@ function EditInPlaceControl( { setIsEdit( false ); event.target.blur(); } + onKeyDown( event ); } } /> ) : ( From 6d554cab499247547fd29853d9acf2878014ed3c Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 16 Feb 2021 12:04:35 +0100 Subject: [PATCH 03/20] component story added --- .../edit-in-place-control/stories/index.js | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 packages/components/src/edit-in-place-control/stories/index.js diff --git a/packages/components/src/edit-in-place-control/stories/index.js b/packages/components/src/edit-in-place-control/stories/index.js new file mode 100644 index 00000000000000..e82eb31698818f --- /dev/null +++ b/packages/components/src/edit-in-place-control/stories/index.js @@ -0,0 +1,69 @@ +/** + * External dependencies + */ +import { text } from '@storybook/addon-knobs'; +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import EditInPlaceControl from '../'; +import { isUndefined, negate } from 'lodash'; + +export default { + title: 'Components/EditInPlaceControl', + component: EditInPlaceControl, +}; + +export const _default = () => { + const [ onClickCallbacks, setOnClickCallbacks ] = useState( 0 ); + const [ onUpdateCallbacks, setOnUpdateCallbacks ] = useState( 0 ); + const [ onChangeCallbacks, setOnChangeCallbacks ] = useState( 0 ); + const [ onKeydownCallbacks, setOnKeydownCallbacks ] = useState( 0 ); + + const incrementOnClickCallbacks = () => + setOnClickCallbacks( 1 + onClickCallbacks ); + const incrementOnUpdateCallbacks = () => + setOnUpdateCallbacks( 1 + onUpdateCallbacks ); + const incrementOnChangeCallbacks = () => + setOnChangeCallbacks( 1 + onChangeCallbacks ); + const incrementOnKeydownCallbacks = () => + setOnKeydownCallbacks( 1 + onKeydownCallbacks ); + + const initialValue = text( 'Initial value', 'Input initial value' ); + const switchToEditModeButtonLabel = text( + 'Aria label informing user, the button will switch to edit mode on click', + 'Edit mode' + ); + const inputLabel = text( + 'Aria label attached to input (when on edit mdoe)', + 'Input text' + ); + + const props = { + initialValue, + onClick: incrementOnClickCallbacks, + onUpdate: incrementOnUpdateCallbacks, + switchToEditModeButtonLabel, + inputValidator: negate( isUndefined ), + inputLabel, + onChange: incrementOnChangeCallbacks, + onKeyDown: incrementOnKeydownCallbacks, + }; + + return ( + <> + +
    +
  • onClick callbacks: { onClickCallbacks }
  • +
  • onUpdate callbacks: { onUpdateCallbacks }
  • +
  • onChange callback: { onChangeCallbacks }
  • +
  • onKeyDown callback: { onKeydownCallbacks }
  • +
  • inputValidator: is defined
  • +
+ + ); +}; From 044cac40a7a68770bf948bff73443ff66876893f Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 16 Feb 2021 12:08:11 +0100 Subject: [PATCH 04/20] remove input styles for now --- .../components/src/edit-in-place-control/index.js | 14 +------------- .../src/edit-in-place-control/style.scss | 12 ------------ 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/packages/components/src/edit-in-place-control/index.js b/packages/components/src/edit-in-place-control/index.js index e28f07bdb3ac6f..a48cfb9d434836 100644 --- a/packages/components/src/edit-in-place-control/index.js +++ b/packages/components/src/edit-in-place-control/index.js @@ -12,11 +12,6 @@ import { useState, useRef, useEffect } from '@wordpress/element'; */ import Button from '../button'; -const baseInputCssClass = 'components-edit-in-place-control__input'; -const beforeTransitionInputCssClass = 'small'; -const afterTransitionInputCssClass = 'large'; -const withoutTransitionCssClass = `${ baseInputCssClass } ${ beforeTransitionInputCssClass }`; -const withTransitionCssClass = `${ baseInputCssClass } ${ afterTransitionInputCssClass }`; const cancelEvent = ( event ) => ( event.preventDefault(), event.stopPropagation() ); @@ -33,9 +28,6 @@ function EditInPlaceControl( { } ) { const [ isEdit, setIsEdit ] = useState( false ); const [ value, setValue ] = useState( initialValue ); - const [ inputCssClasses, setInputCssClasses ] = useState( - withoutTransitionCssClass - ); const inputRef = useRef(); const buttonRef = useRef(); @@ -55,20 +47,16 @@ function EditInPlaceControl( { { const _value = event.target.value; setValue( event.target.value ); onChange( _value, event ); } } - onFocus={ () => - setInputCssClasses( withTransitionCssClass ) - } onBlur={ () => { setIsEdit( false ); onUpdate( value ); - setInputCssClasses( withoutTransitionCssClass ); } } onKeyDown={ ( event ) => { if ( 'Enter' === event.key ) { diff --git a/packages/components/src/edit-in-place-control/style.scss b/packages/components/src/edit-in-place-control/style.scss index eeb8d36a1cfdbf..6e6d6e71875bae 100644 --- a/packages/components/src/edit-in-place-control/style.scss +++ b/packages/components/src/edit-in-place-control/style.scss @@ -2,15 +2,3 @@ padding: $grid-unit-30; width: auto; } -.components-edit-in-place-control__input { - margin-bottom: 1px; - text-indent: $grid-unit; - &.large { - width: 100%; - transition: width 0.3s; - } - &.small { - width: 50%; - transition: width 0.3s; - } -} From 18ef7affcef09517a564106364fa621c2cf382c4 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Wed, 17 Feb 2021 11:09:11 +0100 Subject: [PATCH 05/20] size property added --- packages/components/src/edit-in-place-control/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/edit-in-place-control/index.js b/packages/components/src/edit-in-place-control/index.js index a48cfb9d434836..578e3ad70ef8a1 100644 --- a/packages/components/src/edit-in-place-control/index.js +++ b/packages/components/src/edit-in-place-control/index.js @@ -49,6 +49,7 @@ function EditInPlaceControl( { ref={ inputRef } className={ 'components-edit-in-place-control__input' } value={ value } + size={ String( value ).length } onChange={ ( event ) => { const _value = event.target.value; setValue( event.target.value ); From 9793a56a916af4f7deae4c49f327a1c242db0d3d Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Mon, 22 Feb 2021 13:49:47 +0100 Subject: [PATCH 06/20] edit in place changed to hook --- .../src/edit-in-place-control/index.js | 96 ------------------ .../edit-in-place-control/stories/index.js | 73 ++++++++------ .../edit-in-place-control/use-inline-edit.js | 97 +++++++++++++++++++ 3 files changed, 141 insertions(+), 125 deletions(-) delete mode 100644 packages/components/src/edit-in-place-control/index.js create mode 100644 packages/components/src/edit-in-place-control/use-inline-edit.js diff --git a/packages/components/src/edit-in-place-control/index.js b/packages/components/src/edit-in-place-control/index.js deleted file mode 100644 index 578e3ad70ef8a1..00000000000000 --- a/packages/components/src/edit-in-place-control/index.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * External dependencies - */ -import { noop, negate, isUndefined } from 'lodash'; - -/** - * WordPress dependencies - */ -import { useState, useRef, useEffect } from '@wordpress/element'; -/** - * Internal dependencies - */ -import Button from '../button'; - -const cancelEvent = ( event ) => ( - event.preventDefault(), event.stopPropagation() -); - -function EditInPlaceControl( { - initialValue = '', - onClick = noop, - onUpdate = noop, - switchToEditModeButtonLabel, - inputValidator = negate( isUndefined ), - editNameInputLabel = initialValue, - onChange = noop, - onKeyDown = noop, -} ) { - const [ isEdit, setIsEdit ] = useState( false ); - const [ value, setValue ] = useState( initialValue ); - - const inputRef = useRef(); - const buttonRef = useRef(); - - useEffect( () => { - if ( isEdit ) { - inputRef.current.focus(); - inputRef.current.select(); - } else { - buttonRef.current.focus(); - } - }, [ isEdit ] ); - - return ( - <> - { isEdit ? ( - { - const _value = event.target.value; - setValue( event.target.value ); - onChange( _value, event ); - } } - onBlur={ () => { - setIsEdit( false ); - onUpdate( value ); - } } - onKeyDown={ ( event ) => { - if ( 'Enter' === event.key ) { - cancelEvent( event ); - if ( inputValidator( value ) ) { - setIsEdit( false ); - onUpdate( value ); - } - } - if ( 'Escape' === event.key ) { - cancelEvent( event ); - setValue( initialValue ); - setIsEdit( false ); - event.target.blur(); - } - onKeyDown( event ); - } } - /> - ) : ( - - ) } - - ); -} - -export default EditInPlaceControl; diff --git a/packages/components/src/edit-in-place-control/stories/index.js b/packages/components/src/edit-in-place-control/stories/index.js index e82eb31698818f..d73d27f5b4bcb0 100644 --- a/packages/components/src/edit-in-place-control/stories/index.js +++ b/packages/components/src/edit-in-place-control/stories/index.js @@ -10,59 +10,74 @@ import { useState } from '@wordpress/element'; /** * Internal dependencies */ -import EditInPlaceControl from '../'; -import { isUndefined, negate } from 'lodash'; +import { useInlineEdit } from '../use-inline-edit'; export default { title: 'Components/EditInPlaceControl', - component: EditInPlaceControl, + component: MyCustomEditInPlaceControl, }; +function MyCustomEditInPlaceControl( props = {} ) { + const { isEdit, amendInputProps, amendToggleProps, value } = useInlineEdit( + props + ); + + const buttonProps = { + onClick: ( _value ) => + // eslint-disable-next-line no-console + console.log( 'custom handle on click', _value ), + }; + const inputProps = { value }; + + return ( + <> + { isEdit ? ( + + ) : ( + + ) } + + ); +} + export const _default = () => { + const validate = ( _value ) => _value.length > 0; + const initialValue = text( 'Initial value', 'Input initial value' ); const [ onClickCallbacks, setOnClickCallbacks ] = useState( 0 ); - const [ onUpdateCallbacks, setOnUpdateCallbacks ] = useState( 0 ); const [ onChangeCallbacks, setOnChangeCallbacks ] = useState( 0 ); - const [ onKeydownCallbacks, setOnKeydownCallbacks ] = useState( 0 ); + const [ value, setValue ] = useState( initialValue ); + const [ isInputValid, setIsInputValid ] = useState( true ); const incrementOnClickCallbacks = () => setOnClickCallbacks( 1 + onClickCallbacks ); - const incrementOnUpdateCallbacks = () => - setOnUpdateCallbacks( 1 + onUpdateCallbacks ); + const incrementOnChangeCallbacks = () => setOnChangeCallbacks( 1 + onChangeCallbacks ); - const incrementOnKeydownCallbacks = () => - setOnKeydownCallbacks( 1 + onKeydownCallbacks ); - - const initialValue = text( 'Initial value', 'Input initial value' ); - const switchToEditModeButtonLabel = text( - 'Aria label informing user, the button will switch to edit mode on click', - 'Edit mode' - ); - const inputLabel = text( - 'Aria label attached to input (when on edit mdoe)', - 'Input text' - ); const props = { - initialValue, + value, + validate, onClick: incrementOnClickCallbacks, - onUpdate: incrementOnUpdateCallbacks, - switchToEditModeButtonLabel, - inputValidator: negate( isUndefined ), - inputLabel, - onChange: incrementOnChangeCallbacks, - onKeyDown: incrementOnKeydownCallbacks, + inputValidator: validate, + onChange: ( _value ) => ( + setValue( _value ), + incrementOnChangeCallbacks( _value ), + setIsInputValid( true ) + ), + onWrongInput: () => setIsInputValid( false ), }; return ( <> - +
  • onClick callbacks: { onClickCallbacks }
  • -
  • onUpdate callbacks: { onUpdateCallbacks }
  • onChange callback: { onChangeCallbacks }
  • -
  • onKeyDown callback: { onKeydownCallbacks }
  • +
  • value: { onChangeCallbacks }
  • inputValidator: is defined
  • +
  • is input valid: { isInputValid + '' }
); diff --git a/packages/components/src/edit-in-place-control/use-inline-edit.js b/packages/components/src/edit-in-place-control/use-inline-edit.js new file mode 100644 index 00000000000000..78074114433291 --- /dev/null +++ b/packages/components/src/edit-in-place-control/use-inline-edit.js @@ -0,0 +1,97 @@ +/** + * External dependencies + */ +import { isUndefined, negate, noop } from 'lodash'; +/** + * WordPress dependencies + */ +import { useEffect, useState, useRef } from '@wordpress/element'; + +const cancelEvent = ( event ) => ( + event.preventDefault(), event.stopPropagation() +); + +const mergeEvent = ( ...handlers ) => ( event ) => + handlers.forEach( ( handler = noop ) => handler( event ) ); + +export function useInlineEdit( { + validate = negate( isUndefined ), + onWrongInput = noop, + onChange: onInputChange = noop, + value: propValue, +} ) { + const [ isInEditMode, setIsInEditMode ] = useState( false ); + const [ editingValue, setEditingValue ] = useState( propValue ); + const inputRef = useRef(); + const toggleRef = useRef(); + + useEffect( () => { + setEditingValue( propValue ); + if ( ! validate( value ) ) onWrongInput( value ); + }, [ propValue ] ); + + useEffect( () => { + if ( isInEditMode ) { + inputRef.current.focus(); + inputRef.current.select(); + setEditingValue( propValue ); + } else { + toggleRef.current.focus(); + } + }, [ isInEditMode ] ); + + const handleOnCommit = ( event ) => { + const { value } = event.target; + cancelEvent( event ); + if ( validate( value ) ) { + setIsInEditMode( false ); + onInputChange( value ); + } else { + onWrongInput( value ); + } + }; + + const handleOnChange = ( event ) => { + setEditingValue( event.target.value ); + }; + + const handleOnKeyDown = ( event ) => { + if ( 'Enter' === event.key ) { + handleOnCommit( event ); + } + if ( 'Escape' === event.key ) { + cancelEvent( event ); + event.target.blur(); + } + }; + + const handleOnClick = () => setIsInEditMode( true ); + + const amendInputProps = ( { + onChange, + onKeyDown, + onBlur, + ...inputProps + } = {} ) => ( { + ref: inputRef, + onChange: mergeEvent( handleOnChange, onChange ), + onKeyDown: mergeEvent( handleOnKeyDown, onKeyDown ), + onBlur: mergeEvent( handleOnCommit, onBlur ), + ...inputProps, + } ); + + const amendToggleProps = ( { onClick, ...toggleProps } = {} ) => ( { + ref: toggleRef, + onClick: mergeEvent( handleOnClick, onClick ), + ...toggleProps, + } ); + + const value = isInEditMode ? editingValue : value; + + return { + isEdit: isInEditMode, + amendInputProps, + amendToggleProps, + value, + }; +} From 6b2a39b1b5bb094c343db4637de0dfaea88bfa0e Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 23 Feb 2021 22:15:30 +0100 Subject: [PATCH 07/20] component converted into hook --- .../src/edit-in-place-control/style.scss | 4 -- packages/components/src/index.js | 3 +- packages/components/src/inline-edit/README.MD | 6 +++ .../hook.js} | 47 ++++++++++--------- packages/components/src/inline-edit/index.js | 1 + .../stories/index.js | 32 +++++-------- packages/components/src/style.scss | 1 - 7 files changed, 47 insertions(+), 47 deletions(-) delete mode 100644 packages/components/src/edit-in-place-control/style.scss create mode 100644 packages/components/src/inline-edit/README.MD rename packages/components/src/{edit-in-place-control/use-inline-edit.js => inline-edit/hook.js} (59%) create mode 100644 packages/components/src/inline-edit/index.js rename packages/components/src/{edit-in-place-control => inline-edit}/stories/index.js (63%) diff --git a/packages/components/src/edit-in-place-control/style.scss b/packages/components/src/edit-in-place-control/style.scss deleted file mode 100644 index 6e6d6e71875bae..00000000000000 --- a/packages/components/src/edit-in-place-control/style.scss +++ /dev/null @@ -1,4 +0,0 @@ -.components-edit-in-place-control__label { - padding: $grid-unit-30; - width: auto; -} diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 1266183bfc0690..3a9ac943776182 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -77,7 +77,6 @@ export { default as GuidePage } from './guide/page'; export { default as Icon } from './icon'; export { default as IconButton } from './button/deprecated'; export { default as __experimentalInputControl } from './input-control'; -export { default as __experimentalEditInPlaceControl } from './edit-in-place-control'; export { default as KeyboardShortcuts } from './keyboard-shortcuts'; export { default as MenuGroup } from './menu-group'; export { default as MenuItem } from './menu-item'; @@ -165,3 +164,5 @@ export { __unstableWithNext, __unstableComponentSystemProvider, } from './__next/context'; + +export { useInlineEdit } from './inline-edit'; diff --git a/packages/components/src/inline-edit/README.MD b/packages/components/src/inline-edit/README.MD new file mode 100644 index 00000000000000..3a2f638ca1134c --- /dev/null +++ b/packages/components/src/inline-edit/README.MD @@ -0,0 +1,6 @@ +Hook providing with data to bend two elements. + +One of which sets 'isEdit' state to true upon clicking, second sets 'isEdit' state to false on 'Enter'/onBlur event and triggering onCommit callback with its value. + + +The hook was designed to be a component in the first place, but hook gives more flexibility. See more: https://github.com/WordPress/gutenberg/pull/28924 diff --git a/packages/components/src/edit-in-place-control/use-inline-edit.js b/packages/components/src/inline-edit/hook.js similarity index 59% rename from packages/components/src/edit-in-place-control/use-inline-edit.js rename to packages/components/src/inline-edit/hook.js index 78074114433291..a792396063bf40 100644 --- a/packages/components/src/edit-in-place-control/use-inline-edit.js +++ b/packages/components/src/inline-edit/hook.js @@ -1,33 +1,37 @@ /** * External dependencies */ -import { isUndefined, negate, noop } from 'lodash'; +import { isUndefined, negate, noop, flow } from 'lodash'; /** * WordPress dependencies */ import { useEffect, useState, useRef } from '@wordpress/element'; const cancelEvent = ( event ) => ( - event.preventDefault(), event.stopPropagation() + event.preventDefault(), event.stopPropagation(), event ); +const getEventValue = ( { target: { value } } ) => value; const mergeEvent = ( ...handlers ) => ( event ) => handlers.forEach( ( handler = noop ) => handler( event ) ); -export function useInlineEdit( { +export default function useInlineEdit({ validate = negate( isUndefined ), onWrongInput = noop, - onChange: onInputChange = noop, + onCommit = noop, value: propValue, } ) { const [ isInEditMode, setIsInEditMode ] = useState( false ); const [ editingValue, setEditingValue ] = useState( propValue ); const inputRef = useRef(); const toggleRef = useRef(); + const isInvalid = negate( validate ); + const changeToEditMode = () => setIsInEditMode( true ); + const changeToToggleMode = () => setIsInEditMode( false ); useEffect( () => { setEditingValue( propValue ); - if ( ! validate( value ) ) onWrongInput( value ); + if ( isInvalid( value ) ) onWrongInput( value ); }, [ propValue ] ); useEffect( () => { @@ -40,33 +44,31 @@ export function useInlineEdit( { } }, [ isInEditMode ] ); - const handleOnCommit = ( event ) => { + const commit = ( event ) => { const { value } = event.target; cancelEvent( event ); if ( validate( value ) ) { - setIsInEditMode( false ); - onInputChange( value ); + changeToToggleMode(); + onCommit( value ); } else { onWrongInput( value ); } }; - const handleOnChange = ( event ) => { - setEditingValue( event.target.value ); - }; - - const handleOnKeyDown = ( event ) => { + const handleInputActions = ( event ) => { if ( 'Enter' === event.key ) { - handleOnCommit( event ); + commit( event ); } if ( 'Escape' === event.key ) { cancelEvent( event ); event.target.blur(); + changeToToggleMode(); + } else { + const { value } = event.target; + setEditingValue( value ); } }; - const handleOnClick = () => setIsInEditMode( true ); - const amendInputProps = ( { onChange, onKeyDown, @@ -74,19 +76,22 @@ export function useInlineEdit( { ...inputProps } = {} ) => ( { ref: inputRef, - onChange: mergeEvent( handleOnChange, onChange ), - onKeyDown: mergeEvent( handleOnKeyDown, onKeyDown ), - onBlur: mergeEvent( handleOnCommit, onBlur ), + onChange: mergeEvent( + flow( [ getEventValue, setEditingValue ] ), + onChange + ), + onKeyDown: mergeEvent( handleInputActions, onKeyDown ), + onBlur: mergeEvent( commit, onBlur ), ...inputProps, } ); const amendToggleProps = ( { onClick, ...toggleProps } = {} ) => ( { ref: toggleRef, - onClick: mergeEvent( handleOnClick, onClick ), + onClick: mergeEvent( changeToEditMode, onClick ), ...toggleProps, } ); - const value = isInEditMode ? editingValue : value; + const value = isInEditMode ? editingValue : propValue; return { isEdit: isInEditMode, diff --git a/packages/components/src/inline-edit/index.js b/packages/components/src/inline-edit/index.js new file mode 100644 index 00000000000000..e757912862ddbd --- /dev/null +++ b/packages/components/src/inline-edit/index.js @@ -0,0 +1 @@ +export { default as useInlineEdit } from './hook'; diff --git a/packages/components/src/edit-in-place-control/stories/index.js b/packages/components/src/inline-edit/stories/index.js similarity index 63% rename from packages/components/src/edit-in-place-control/stories/index.js rename to packages/components/src/inline-edit/stories/index.js index d73d27f5b4bcb0..26ee2c76c79e37 100644 --- a/packages/components/src/edit-in-place-control/stories/index.js +++ b/packages/components/src/inline-edit/stories/index.js @@ -6,11 +6,12 @@ import { text } from '@storybook/addon-knobs'; * WordPress dependencies */ import { useState } from '@wordpress/element'; +import { pick } from 'lodash'; /** * Internal dependencies */ -import { useInlineEdit } from '../use-inline-edit'; +import useInlineEdit from '../hook'; export default { title: 'Components/EditInPlaceControl', @@ -21,20 +22,12 @@ function MyCustomEditInPlaceControl( props = {} ) { const { isEdit, amendInputProps, amendToggleProps, value } = useInlineEdit( props ); - - const buttonProps = { - onClick: ( _value ) => - // eslint-disable-next-line no-console - console.log( 'custom handle on click', _value ), - }; - const inputProps = { value }; - return ( <> { isEdit ? ( - + ) : ( - ) } @@ -43,27 +36,27 @@ function MyCustomEditInPlaceControl( props = {} ) { } export const _default = () => { - const validate = ( _value ) => _value.length > 0; + const validate = ( _value = '' ) => _value.length > 0; const initialValue = text( 'Initial value', 'Input initial value' ); const [ onClickCallbacks, setOnClickCallbacks ] = useState( 0 ); - const [ onChangeCallbacks, setOnChangeCallbacks ] = useState( 0 ); + const [ ocCommitCallbacks, setOnCommitCallbacks ] = useState( 0 ); const [ value, setValue ] = useState( initialValue ); const [ isInputValid, setIsInputValid ] = useState( true ); const incrementOnClickCallbacks = () => setOnClickCallbacks( 1 + onClickCallbacks ); - const incrementOnChangeCallbacks = () => - setOnChangeCallbacks( 1 + onChangeCallbacks ); + const incrementOnCommitCallbacks = () => + setOnCommitCallbacks( 1 + ocCommitCallbacks ); const props = { value, validate, onClick: incrementOnClickCallbacks, inputValidator: validate, - onChange: ( _value ) => ( + onCommit: ( _value ) => ( setValue( _value ), - incrementOnChangeCallbacks( _value ), + incrementOnCommitCallbacks(), setIsInputValid( true ) ), onWrongInput: () => setIsInputValid( false ), @@ -74,10 +67,9 @@ export const _default = () => {
  • onClick callbacks: { onClickCallbacks }
  • -
  • onChange callback: { onChangeCallbacks }
  • -
  • value: { onChangeCallbacks }
  • +
  • onCommit callback: { ocCommitCallbacks }
  • inputValidator: is defined
  • -
  • is input valid: { isInputValid + '' }
  • +
  • is commited input valid: { isInputValid + '' }
); diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index 992e277f3fd005..a7b92c1192b13d 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -16,7 +16,6 @@ @import "./drop-zone/style.scss"; @import "./dropdown/style.scss"; @import "./dropdown-menu/style.scss"; -@import "./edit-in-place-control/style.scss"; @import "./font-size-picker/style.scss"; @import "./form-toggle/style.scss"; @import "./form-token-field/style.scss"; From 3c30e6d00deae9a634f6ff4bfbb541de72af736e Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 23 Feb 2021 22:16:21 +0100 Subject: [PATCH 08/20] linter fix --- packages/components/src/inline-edit/hook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index a792396063bf40..ab627314856d5f 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -15,7 +15,7 @@ const getEventValue = ( { target: { value } } ) => value; const mergeEvent = ( ...handlers ) => ( event ) => handlers.forEach( ( handler = noop ) => handler( event ) ); -export default function useInlineEdit({ +export default function useInlineEdit( { validate = negate( isUndefined ), onWrongInput = noop, onCommit = noop, From 0841aa998d656919df9013ac31bde2291b5d5fe4 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Wed, 24 Feb 2021 12:19:08 +0100 Subject: [PATCH 09/20] Update packages/components/src/index.js useInlineEdit marked as ustable Co-authored-by: sarayourfriend --- packages/components/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 3a9ac943776182..27ef6fc072618b 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -165,4 +165,4 @@ export { __unstableComponentSystemProvider, } from './__next/context'; -export { useInlineEdit } from './inline-edit'; +export { useInlineEdit as __unstableUseInlineEdit } from './inline-edit'; From a584a1209a5e5d38795ea45451d2ba06cef197ae Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 9 Mar 2021 12:57:25 +0100 Subject: [PATCH 10/20] add anotations --- packages/components/src/inline-edit/hook.js | 13 +++++++++++++ packages/components/tsconfig.json | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index ab627314856d5f..1837f05fba07f2 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -1,3 +1,4 @@ +// @ts-nocheck /** * External dependencies */ @@ -15,6 +16,17 @@ const getEventValue = ( { target: { value } } ) => value; const mergeEvent = ( ...handlers ) => ( event ) => handlers.forEach( ( handler = noop ) => handler( event ) ); +/** + * @typedef Props + * @property {(value: string) => boolean} validate predicate + * @property {Function} onWrongInput called when a validate predicate fails + * @property {Function} onCommit called on enter/blur + * @property {string} value input value + */ + +/** + * @param {Props} props + */ export default function useInlineEdit( { validate = negate( isUndefined ), onWrongInput = noop, @@ -39,6 +51,7 @@ export default function useInlineEdit( { inputRef.current.focus(); inputRef.current.select(); setEditingValue( propValue ); + setEditingValue( propValue ); } else { toggleRef.current.focus(); } diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json index 9965ad27817733..875f201916e148 100644 --- a/packages/components/tsconfig.json +++ b/packages/components/tsconfig.json @@ -20,7 +20,8 @@ "src/utils/**/*", "src/view/**/*", "src/visually-hidden/**/*", - "src/text/**/*", + "src/text/**/*", + "src/inline-edit/**/*", "src/grid/**/*", "src/__next/**/*" ], From 533d7b70a92d09eff6d997169c3a1e2addf83d70 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Tue, 9 Mar 2021 13:03:10 +0100 Subject: [PATCH 11/20] remove mistakenly doubled line --- packages/components/src/inline-edit/hook.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 1837f05fba07f2..ce8cef1bf64907 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -51,7 +51,6 @@ export default function useInlineEdit( { inputRef.current.focus(); inputRef.current.select(); setEditingValue( propValue ); - setEditingValue( propValue ); } else { toggleRef.current.focus(); } From 5faf3cc001ca496509c6c6dd95c4fc6e48ed190c Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Thu, 11 Mar 2021 18:48:52 +0100 Subject: [PATCH 12/20] update types --- packages/components/src/inline-edit/README.MD | 7 ++- packages/components/src/inline-edit/hook.js | 44 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/packages/components/src/inline-edit/README.MD b/packages/components/src/inline-edit/README.MD index 3a2f638ca1134c..0805d7ca67f1d7 100644 --- a/packages/components/src/inline-edit/README.MD +++ b/packages/components/src/inline-edit/README.MD @@ -1,6 +1,5 @@ -Hook providing with data to bend two elements. +Hook providing with refs to bind two elements. -One of which sets 'isEdit' state to true upon clicking, second sets 'isEdit' state to false on 'Enter'/onBlur event and triggering onCommit callback with its value. +One ref is used to set 'isEdit' state to true upon clicking. The second is used to set 'isEdit' state to false on 'Enter'/onBlur event and triggering onCommit callback with its value. - -The hook was designed to be a component in the first place, but hook gives more flexibility. See more: https://github.com/WordPress/gutenberg/pull/28924 +The hook was designed to be a component in the first place, but a hook gives more flexibility. diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index ce8cef1bf64907..051b0a77daca64 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -1,4 +1,3 @@ -// @ts-nocheck /** * External dependencies */ @@ -8,13 +7,28 @@ import { isUndefined, negate, noop, flow } from 'lodash'; */ import { useEffect, useState, useRef } from '@wordpress/element'; +/** + * @param {Event} event + */ const cancelEvent = ( event ) => ( event.preventDefault(), event.stopPropagation(), event ); +/** + * @param {Event & { + target: HTMLButtonElement + }} event + */ const getEventValue = ( { target: { value } } ) => value; -const mergeEvent = ( ...handlers ) => ( event ) => - handlers.forEach( ( handler = noop ) => handler( event ) ); + +/** + * @param {Function[]} handlers + */ +const mergeEvent = ( ...handlers ) => + /** + * @param {Event} event + */ + ( event ) => handlers.forEach( ( handler = noop ) => handler( event ) ); /** * @typedef Props @@ -35,7 +49,9 @@ export default function useInlineEdit( { } ) { const [ isInEditMode, setIsInEditMode ] = useState( false ); const [ editingValue, setEditingValue ] = useState( propValue ); + /** @type {import('react').MutableRefObject} */ const inputRef = useRef(); + /** @type {import('react').MutableRefObject} */ const toggleRef = useRef(); const isInvalid = negate( validate ); const changeToEditMode = () => setIsInEditMode( true ); @@ -48,14 +64,19 @@ export default function useInlineEdit( { useEffect( () => { if ( isInEditMode ) { - inputRef.current.focus(); - inputRef.current.select(); + inputRef.current?.focus(); + inputRef.current?.select(); setEditingValue( propValue ); } else { - toggleRef.current.focus(); + toggleRef.current?.focus(); } }, [ isInEditMode ] ); + /** + * @param {Event & { + target: HTMLButtonElement + }} event + */ const commit = ( event ) => { const { value } = event.target; cancelEvent( event ); @@ -67,6 +88,9 @@ export default function useInlineEdit( { } }; + /** + * @param {Event & {key: string, target: HTMLButtonElement}} event + */ const handleInputActions = ( event ) => { if ( 'Enter' === event.key ) { commit( event ); @@ -82,9 +106,9 @@ export default function useInlineEdit( { }; const amendInputProps = ( { - onChange, - onKeyDown, - onBlur, + onChange = noop, + onKeyDown = noop, + onBlur = noop, ...inputProps } = {} ) => ( { ref: inputRef, @@ -97,7 +121,7 @@ export default function useInlineEdit( { ...inputProps, } ); - const amendToggleProps = ( { onClick, ...toggleProps } = {} ) => ( { + const amendToggleProps = ( { onClick = noop, ...toggleProps } = {} ) => ( { ref: toggleRef, onClick: mergeEvent( changeToEditMode, onClick ), ...toggleProps, From c8e1ef15093913ca2292d409b7ea2ae2b0db8a03 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Sat, 13 Mar 2021 14:13:26 +0100 Subject: [PATCH 13/20] add react synthetic events types --- packages/components/src/inline-edit/hook.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 051b0a77daca64..5ce5451edf0e8c 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -8,16 +8,14 @@ import { isUndefined, negate, noop, flow } from 'lodash'; import { useEffect, useState, useRef } from '@wordpress/element'; /** - * @param {Event} event + * @param {import("react").ChangeEvent} event */ const cancelEvent = ( event ) => ( event.preventDefault(), event.stopPropagation(), event ); /** - * @param {Event & { - target: HTMLButtonElement - }} event + * @param {import("react").ChangeEvent} event */ const getEventValue = ( { target: { value } } ) => value; @@ -26,7 +24,7 @@ const getEventValue = ( { target: { value } } ) => value; */ const mergeEvent = ( ...handlers ) => /** - * @param {Event} event + * @param {import("react").ChangeEvent} event */ ( event ) => handlers.forEach( ( handler = noop ) => handler( event ) ); @@ -73,9 +71,7 @@ export default function useInlineEdit( { }, [ isInEditMode ] ); /** - * @param {Event & { - target: HTMLButtonElement - }} event + * @param {import("react").ChangeEvent} event */ const commit = ( event ) => { const { value } = event.target; @@ -89,7 +85,7 @@ export default function useInlineEdit( { }; /** - * @param {Event & {key: string, target: HTMLButtonElement}} event + * @param {import("react").KeyboardEvent & import("react").ChangeEvent} event */ const handleInputActions = ( event ) => { if ( 'Enter' === event.key ) { From 0e19059adcfcc2ae22aa85929b0e04c2a10f2d69 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Mon, 15 Mar 2021 22:52:38 +0100 Subject: [PATCH 14/20] Update packages/components/src/inline-edit/hook.js Co-authored-by: sarayourfriend --- packages/components/src/inline-edit/hook.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 5ce5451edf0e8c..cb4fc7e8e95f41 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -47,10 +47,10 @@ export default function useInlineEdit( { } ) { const [ isInEditMode, setIsInEditMode ] = useState( false ); const [ editingValue, setEditingValue ] = useState( propValue ); - /** @type {import('react').MutableRefObject} */ - const inputRef = useRef(); - /** @type {import('react').MutableRefObject} */ - const toggleRef = useRef(); + /** @type {import('react').RefObject} */ + const inputRef = useRef( null ); + /** @type {import('react').RefObject} */ + const toggleRef = useRef( null ); const isInvalid = negate( validate ); const changeToEditMode = () => setIsInEditMode( true ); const changeToToggleMode = () => setIsInEditMode( false ); From 0fe91196293384049477776c3167272a98d1a895 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Mon, 15 Mar 2021 23:31:49 +0100 Subject: [PATCH 15/20] Update packages/components/src/inline-edit/hook.js Co-authored-by: sarayourfriend --- packages/components/src/inline-edit/hook.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index cb4fc7e8e95f41..2f8d09256c23a5 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -31,8 +31,8 @@ const mergeEvent = ( ...handlers ) => /** * @typedef Props * @property {(value: string) => boolean} validate predicate - * @property {Function} onWrongInput called when a validate predicate fails - * @property {Function} onCommit called on enter/blur + * @property {( value: string ) => void} onWrongInput called when a validate predicate fails + * @property {( value: string ) => void} onCommit called on enter/blur * @property {string} value input value */ From 5bf4f8e442794f91eb1d717fa7a085e414582138 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Fri, 19 Mar 2021 18:08:10 +0100 Subject: [PATCH 16/20] Update packages/components/src/inline-edit/hook.js Co-authored-by: Haz --- packages/components/src/inline-edit/hook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 2f8d09256c23a5..9f1e3d15b00f77 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -49,7 +49,7 @@ export default function useInlineEdit( { const [ editingValue, setEditingValue ] = useState( propValue ); /** @type {import('react').RefObject} */ const inputRef = useRef( null ); - /** @type {import('react').RefObject} */ + /** @type {import('react').RefObject} */ const toggleRef = useRef( null ); const isInvalid = negate( validate ); const changeToEditMode = () => setIsInEditMode( true ); From be806201b19260768b56e889645d2cf471d78136 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Fri, 19 Mar 2021 19:42:55 +0100 Subject: [PATCH 17/20] hooks logic simplified, validation called only on commit --- packages/components/src/inline-edit/hook.js | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 5ce5451edf0e8c..f37785a4621a1d 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -47,24 +47,20 @@ export default function useInlineEdit( { } ) { const [ isInEditMode, setIsInEditMode ] = useState( false ); const [ editingValue, setEditingValue ] = useState( propValue ); + const value = isInEditMode ? editingValue : propValue; /** @type {import('react').MutableRefObject} */ const inputRef = useRef(); /** @type {import('react').MutableRefObject} */ const toggleRef = useRef(); - const isInvalid = negate( validate ); const changeToEditMode = () => setIsInEditMode( true ); const changeToToggleMode = () => setIsInEditMode( false ); - useEffect( () => { - setEditingValue( propValue ); - if ( isInvalid( value ) ) onWrongInput( value ); - }, [ propValue ] ); + useEffect( () => { if ( isInEditMode ) { inputRef.current?.focus(); inputRef.current?.select(); - setEditingValue( propValue ); } else { toggleRef.current?.focus(); } @@ -74,13 +70,13 @@ export default function useInlineEdit( { * @param {import("react").ChangeEvent} event */ const commit = ( event ) => { - const { value } = event.target; + const { value: _value } = event.target; cancelEvent( event ); - if ( validate( value ) ) { + if ( validate( _value ) ) { changeToToggleMode(); - onCommit( value ); + onCommit( _value ); } else { - onWrongInput( value ); + onWrongInput( _value ); } }; @@ -96,8 +92,7 @@ export default function useInlineEdit( { event.target.blur(); changeToToggleMode(); } else { - const { value } = event.target; - setEditingValue( value ); + setEditingValue( event.target.value ); } }; @@ -123,8 +118,6 @@ export default function useInlineEdit( { ...toggleProps, } ); - const value = isInEditMode ? editingValue : propValue; - return { isEdit: isInEditMode, amendInputProps, From dfbe4d6b11c768b39ad531627fc48106b748f1b2 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Fri, 19 Mar 2021 19:45:52 +0100 Subject: [PATCH 18/20] hooks logic simplified, validation called only on commit --- packages/components/src/inline-edit/hook.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index f37785a4621a1d..f56795d8713b07 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -55,8 +55,6 @@ export default function useInlineEdit( { const changeToEditMode = () => setIsInEditMode( true ); const changeToToggleMode = () => setIsInEditMode( false ); - - useEffect( () => { if ( isInEditMode ) { inputRef.current?.focus(); From c9895d03b8c52d112462502204e738481e5abedd Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Fri, 19 Mar 2021 19:53:16 +0100 Subject: [PATCH 19/20] synch internal value on chnage from the outside --- packages/components/src/inline-edit/hook.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/src/inline-edit/hook.js b/packages/components/src/inline-edit/hook.js index 4cbc411cfe9151..56aebc3f0800f0 100644 --- a/packages/components/src/inline-edit/hook.js +++ b/packages/components/src/inline-edit/hook.js @@ -55,6 +55,10 @@ export default function useInlineEdit( { const changeToEditMode = () => setIsInEditMode( true ); const changeToToggleMode = () => setIsInEditMode( false ); + useEffect( () => { + setEditingValue( propValue ); + }, [ propValue ] ); + useEffect( () => { if ( isInEditMode ) { inputRef.current?.focus(); From c2cf6740ad3ec3cf73eaef9605ca17d6b57081b9 Mon Sep 17 00:00:00 2001 From: grzegorz_marzencki Date: Fri, 19 Mar 2021 19:56:36 +0100 Subject: [PATCH 20/20] update on initialValue change --- packages/components/src/inline-edit/stories/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/components/src/inline-edit/stories/index.js b/packages/components/src/inline-edit/stories/index.js index 26ee2c76c79e37..957b040b1397a9 100644 --- a/packages/components/src/inline-edit/stories/index.js +++ b/packages/components/src/inline-edit/stories/index.js @@ -5,7 +5,7 @@ import { text } from '@storybook/addon-knobs'; /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; +import { useEffect, useState } from '@wordpress/element'; import { pick } from 'lodash'; /** @@ -43,6 +43,10 @@ export const _default = () => { const [ value, setValue ] = useState( initialValue ); const [ isInputValid, setIsInputValid ] = useState( true ); + useEffect( () => { + setValue( initialValue ); + }, [ initialValue ] ); + const incrementOnClickCallbacks = () => setOnClickCallbacks( 1 + onClickCallbacks );