diff --git a/packages/netlify-cms-widget-string/src/StringControl.js b/packages/netlify-cms-widget-string/src/StringControl.js index 3f7d3212..16694027 100644 --- a/packages/netlify-cms-widget-string/src/StringControl.js +++ b/packages/netlify-cms-widget-string/src/StringControl.js @@ -15,23 +15,44 @@ export default class StringControl extends React.Component { value: '', }; + // The selection to maintain for the input element + _sel = 0; + + // The input element ref + _el = null; + + // NOTE: This prevents the cursor from jumping to the end of the text for + // nested inputs. In other words, this is not an issue on top-level text + // fields such as the `title` of a collection post. However, it becomes an + // issue on fields nested within other components, namely widgets nested + // within a `markdown` widget. For example, the alt text on a block image + // within markdown. + // SEE: https://github.com/netlify/netlify-cms/issues/4539 + // SEE: https://github.com/netlify/netlify-cms/issues/3578 + componentDidUpdate() { + if (this._el && this._el.selectionStart !== this._sel) { + this._el.setSelectionRange(this._sel, this._sel); + } + } + + handleChange = e => { + this._sel = e.target.selectionStart; + this.props.onChange(e.target.value); + }; + render() { - const { - forID, - value, - onChange, - classNameWrapper, - setActiveStyle, - setInactiveStyle, - } = this.props; + const { forID, value, classNameWrapper, setActiveStyle, setInactiveStyle } = this.props; return ( { + this._el = el; + }} type="text" id={forID} className={classNameWrapper} value={value || ''} - onChange={e => onChange(e.target.value)} + onChange={this.handleChange} onFocus={setActiveStyle} onBlur={setInactiveStyle} />