diff --git a/src/widget.js b/src/widget.js
index 7c8cff5f..e05924a4 100644
--- a/src/widget.js
+++ b/src/widget.js
@@ -154,6 +154,8 @@ export default class Widget extends Plugin {
wasHandled = this._handleArrowKeys( isForward );
} else if ( isSelectAllKeyCode( domEventData ) ) {
wasHandled = this._selectAllNestedEditableContent() || this._selectAllContent();
+ } else if ( keyCode === keyCodes.enter ) {
+ wasHandled = this._handleEnterKey( domEventData.shiftKey );
}
if ( wasHandled ) {
@@ -207,6 +209,7 @@ export default class Widget extends Plugin {
/**
* Handles arrow keys.
*
+ * @private
* @param {Boolean} isForward Set to true if arrow key should be handled in forward direction.
* @returns {Boolean|undefined} Returns `true` if keys were handled correctly.
*/
@@ -246,6 +249,34 @@ export default class Widget extends Plugin {
}
}
+ /**
+ * Handles the enter key, giving users and access to positions in the editable directly before
+ * (Shift+Enter) or after (Enter) the selected widget.
+ * It improves the UX, mainly when the widget is the first or last child of the root editable
+ * and there's no other way to type after or before it.
+ *
+ * @private
+ * @param {Boolean} isBackwards Set to true if the new paragraph is to be inserted before
+ * the selected widget (Shift+Enter).
+ * @returns {Boolean|undefined} Returns `true` if keys were handled correctly.
+ */
+ _handleEnterKey( isBackwards ) {
+ const model = this.editor.model;
+ const modelSelection = model.document.selection;
+ const objectElement = modelSelection.getSelectedElement();
+
+ if ( objectElement && model.schema.isObject( objectElement ) ) {
+ model.change( writer => {
+ const paragraph = writer.createElement( 'paragraph' );
+
+ writer.insert( paragraph, objectElement, isBackwards ? 'before' : 'after' );
+ writer.setSelection( paragraph, 'in' );
+ } );
+
+ return true;
+ }
+ }
+
/**
* Extends the {@link module:engine/model/selection~Selection document's selection} to span the entire
* content of the nested editable if already anchored in one.
diff --git a/tests/widget.js b/tests/widget.js
index 3f4c54d7..6511f343 100644
--- a/tests/widget.js
+++ b/tests/widget.js
@@ -681,6 +681,50 @@ describe( 'Widget', () => {
);
} );
+ describe( 'enter', () => {
+ test(
+ 'should insert a paragraph after the selected widget upon Enter',
+ '[]',
+ keyCodes.enter,
+ '[]'
+ );
+
+ test(
+ 'should insert a paragraph before the selected widget upon Shift+Enter',
+ '[]',
+ { keyCode: keyCodes.enter, shiftKey: true },
+ '[]'
+ );
+
+ test(
+ 'should insert a paragraph when not a first-child of the root',
+ '[]foo',
+ keyCodes.enter,
+ '[]foo'
+ );
+
+ test(
+ 'should insert a paragraph when not a last-child of the root',
+ 'foo[]',
+ { keyCode: keyCodes.enter, shiftKey: true },
+ 'foo[]'
+ );
+
+ test(
+ 'should insert a paragraph only when an entire widget is selected (#1)',
+ '[foo] bar',
+ keyCodes.enter,
+ '[] bar'
+ );
+
+ test(
+ 'should insert a paragraph only when an entire widget is selected (#2)',
+ 'f[oob]ar',
+ keyCodes.enter,
+ 'f[]ar'
+ );
+ } );
+
function test( name, data, keyCodeOrMock, expected, expectedView ) {
it( name, () => {
const domEventDataMock = ( typeof keyCodeOrMock == 'object' ) ? keyCodeOrMock : {