diff --git a/src/components/advanced-text-control/index.js b/src/components/advanced-text-control/index.js
index b679de26d4..83d3e33234 100644
--- a/src/components/advanced-text-control/index.js
+++ b/src/components/advanced-text-control/index.js
@@ -1,6 +1,7 @@
/**
* Internal dependencies
*/
+import { useInternalValue } from '~stackable/hooks'
import AdvancedControl, { extractControlProps } from '../base-control2'
import { useControlHandlers } from '../base-control2/hooks'
import { ResetButton } from '../base-control2/reset-button'
@@ -40,6 +41,15 @@ const AdvancedTextControl = memo( props => {
isFormatType,
} )
+ // Track the value internally, because if not the value will be updated on
+ // every render and will make the cursor jump to the end.
+ const [ internalValue, setInternalValue ] = useInternalValue( typeof props.value === 'undefined' ? value : props.value )
+ const _onChange = typeof props.onChange === 'undefined' ? onChange : props.onChange
+ const internalOnChange = value => {
+ setInternalValue( value )
+ _onChange( value )
+ }
+
const TextInput = isMultiline ? TextareaControl : TextControl
return (
@@ -54,16 +64,16 @@ const AdvancedTextControl = memo( props => {
>
diff --git a/src/components/image-alt-control/index.js b/src/components/image-alt-control/index.js
index 759853c644..c2cf04d768 100644
--- a/src/components/image-alt-control/index.js
+++ b/src/components/image-alt-control/index.js
@@ -8,19 +8,28 @@ import { i18n } from 'stackable'
*/
import { TextareaControl, ExternalLink } from '@wordpress/components'
import { __ } from '@wordpress/i18n'
-import { Fragment } from '@wordpress/element'
+import { useInternalValue } from '~stackable/hooks'
const ImageAltControl = props => {
+ // Keep track of the internal value because we will move the cursor to the
+ // end of the text when the user types.
+ const [ internalValue, setInternalValue ] = useInternalValue( props.value )
+
return (
{
+ setInternalValue( value )
+ props.onChange( value )
+ } }
help={
-
+ <>
{ __( 'Describe the purpose of the image', i18n ) }
{ __( 'Leave empty if the image is purely decorative.', i18n ) }
-
+ >
}
/>
)
diff --git a/src/hooks/index.js b/src/hooks/index.js
index 3f567939a3..0954c6c47c 100644
--- a/src/hooks/index.js
+++ b/src/hooks/index.js
@@ -9,6 +9,7 @@ export * from './use-saved-default-block-style'
export * from './use-font-loader'
export * from './use-attribute-edit-handlers'
export * from './use-attribute-name'
+export * from './use-internal-value'
export * from './use-linking'
export * from './use-block-hover-state'
export * from './use-on-screen'
diff --git a/src/hooks/use-internal-value.js b/src/hooks/use-internal-value.js
new file mode 100644
index 0000000000..968b80e6ee
--- /dev/null
+++ b/src/hooks/use-internal-value.js
@@ -0,0 +1,26 @@
+// This files is based on
+// https://github.com/WordPress/gutenberg/blob/trunk/packages/block-editor/src/components/link-control/use-internal-value.js
+// This is a hook that keeps track of the internal value of a component, and
+// updates the value only when the value changes.
+
+/**
+ * WordPress dependencies
+ */
+import { useState } from '@wordpress/element'
+
+/**
+ * External dependencies
+ */
+import fastDeepEqual from 'fast-deep-equal'
+
+export const useInternalValue = value => {
+ const [ internalValue, setInternalValue ] = useState( value )
+ const [ previousValue, setPreviousValue ] = useState( value )
+
+ if ( ! fastDeepEqual( value, previousValue ) ) {
+ setPreviousValue( value )
+ setInternalValue( value )
+ }
+
+ return [ internalValue, setInternalValue ]
+}