diff --git a/packages/block-editor/src/components/plain-text/index.native.js b/packages/block-editor/src/components/plain-text/index.native.js
index 13d2bbf851837b..6c8259ceae1600 100644
--- a/packages/block-editor/src/components/plain-text/index.native.js
+++ b/packages/block-editor/src/components/plain-text/index.native.js
@@ -7,7 +7,7 @@ import { TextInput, Platform, Dimensions } from 'react-native';
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
-import { getPxFromCssUnit } from '@wordpress/block-editor';
+import { RichText, getPxFromCssUnit } from '@wordpress/block-editor';
/**
* Internal dependencies
@@ -18,6 +18,9 @@ export default class PlainText extends Component {
constructor() {
super( ...arguments );
this.isAndroid = Platform.OS === 'android';
+
+ this.onChangeTextInput = this.onChangeTextInput.bind( this );
+ this.onChangeRichText = this.onChangeRichText.bind( this );
}
componentDidMount() {
@@ -44,7 +47,7 @@ export default class PlainText extends Component {
componentDidUpdate( prevProps ) {
if ( ! this.props.isSelected && prevProps.isSelected ) {
- this._input.blur();
+ this._input?.blur();
}
}
@@ -55,11 +58,11 @@ export default class PlainText extends Component {
}
focus() {
- this._input.focus();
+ this._input?.focus();
}
blur() {
- this._input.blur();
+ this._input?.blur();
}
getFontSize() {
@@ -79,20 +82,73 @@ export default class PlainText extends Component {
};
}
+ replaceLineBreakTags( value ) {
+ return value?.replace( RegExp( '
', 'gim' ), '\n' );
+ }
+
+ onChangeTextInput( event ) {
+ const { onChange } = this.props;
+ onChange( event.nativeEvent.text );
+ }
+
+ onChangeRichText( value ) {
+ const { onChange } = this.props;
+ // The
tags have to be replaced with new line characters
+ // as the content of plain text shouldn't contain HTML tags.
+ onChange( this.replaceLineBreakTags( value ) );
+ }
+
render() {
- const { style } = this.props;
+ const {
+ style,
+ __experimentalVersion,
+ onFocus,
+ ...otherProps
+ } = this.props;
const textStyles = [
style || styles[ 'block-editor-plain-text' ],
this.getFontSize(),
];
+ if ( __experimentalVersion === 2 ) {
+ const disableFormattingProps = {
+ withoutInteractiveFormatting: true,
+ disableEditingMenu: true,
+ __unstableDisableFormats: true,
+ disableSuggestions: true,
+ };
+
+ const forcePlainTextProps = {
+ preserveWhiteSpace: true,
+ __unstablePastePlainText: true,
+ multiline: false,
+ };
+
+ const fontProps = {
+ fontFamily: style?.fontFamily,
+ fontSize: style?.fontSize,
+ fontWeight: style?.fontWeight,
+ };
+
+ return (
+
+ );
+ }
+
return (
( this._input = x ) }
- onChange={ ( event ) => {
- this.props.onChange( event.nativeEvent.text );
- } }
+ onChange={ this.onChangeTextInput }
onFocus={ this.props.onFocus } // Always assign onFocus as a props.
onBlur={ this.props.onBlur } // Always assign onBlur as a props.
fontFamily={
diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js
index d30fa8eae5e92d..eacd225eeb091e 100644
--- a/packages/block-editor/src/components/rich-text/index.js
+++ b/packages/block-editor/src/components/rich-text/index.js
@@ -76,6 +76,8 @@ function removeNativeProps( props ) {
'minWidth',
'maxWidth',
'setRef',
+ 'disableSuggestions',
+ 'disableAutocorrection',
] );
}
diff --git a/packages/block-editor/src/components/rich-text/index.native.js b/packages/block-editor/src/components/rich-text/index.native.js
index 2c24022c8e9749..0232b68a2a671c 100644
--- a/packages/block-editor/src/components/rich-text/index.native.js
+++ b/packages/block-editor/src/components/rich-text/index.native.js
@@ -111,6 +111,8 @@ function RichTextWrapper(
maxWidth,
onBlur,
setRef,
+ disableSuggestions,
+ disableAutocorrection,
...props
},
forwardedRef
@@ -635,6 +637,8 @@ function RichTextWrapper(
maxWidth={ maxWidth }
onBlur={ onBlur }
setRef={ setRef }
+ disableSuggestions={ disableSuggestions }
+ disableAutocorrection={ disableAutocorrection }
// Props to be set on the editable container are destructured on the
// element itself for web (see below), but passed through rich text
// for native.
diff --git a/packages/block-library/src/shortcode/edit.native.js b/packages/block-library/src/shortcode/edit.native.js
index 778254784682f1..044ad1d23877f8 100644
--- a/packages/block-library/src/shortcode/edit.native.js
+++ b/packages/block-library/src/shortcode/edit.native.js
@@ -9,6 +9,7 @@ import { View, Text } from 'react-native';
import { __ } from '@wordpress/i18n';
import { PlainText } from '@wordpress/block-editor';
import { withPreferredColorScheme } from '@wordpress/compose';
+import { useCallback } from '@wordpress/element';
/**
* Internal dependencies
@@ -23,11 +24,16 @@ export function ShortcodeEdit( props ) {
onFocus,
onBlur,
getStylesFromColorScheme,
+ blockWidth,
} = props;
const titleStyle = getStylesFromColorScheme(
styles.blockTitle,
styles.blockTitleDark
);
+ const shortcodeContainerStyle = getStylesFromColorScheme(
+ styles.blockShortcodeContainer,
+ styles.blockShortcodeContainerDark
+ );
const shortcodeStyle = getStylesFromColorScheme(
styles.blockShortcode,
styles.blockShortcodeDark
@@ -37,24 +43,32 @@ export function ShortcodeEdit( props ) {
styles.placeholderDark
);
+ const maxWidth =
+ blockWidth -
+ shortcodeContainerStyle.paddingLeft +
+ shortcodeContainerStyle.paddingRight;
+
+ const onChange = useCallback( ( text ) => setAttributes( { text } ), [
+ setAttributes,
+ ] );
+
return (
{ __( 'Shortcode' ) }
- setAttributes( { text } ) }
- placeholder={ __( 'Add a shortcode…' ) }
- aria-label={ __( 'Shortcode' ) }
- isSelected={ props.isSelected }
- onFocus={ onFocus }
- onBlur={ onBlur }
- autoCorrect={ false }
- autoComplete="off"
- placeholderTextColor={ placeholderStyle.color }
- />
+
+
+
);
}
diff --git a/packages/block-library/src/shortcode/style.native.scss b/packages/block-library/src/shortcode/style.native.scss
index ed7d235960abdd..b828e7ff28f7a9 100644
--- a/packages/block-library/src/shortcode/style.native.scss
+++ b/packages/block-library/src/shortcode/style.native.scss
@@ -11,18 +11,25 @@
color: $gray-50;
}
+.blockShortcodeContainer {
+ padding: 12px;
+ border-radius: 4px;
+ background-color: $gray-light;
+}
+
+.blockShortcodeContainerDark {
+ background-color: $gray-100;
+}
+
.blockShortcode {
font-family: $default-monospace-font;
font-weight: 400;
font-size: 14px;
- padding: 12px;
- border-radius: 4px;
- background-color: $gray-light;
+ color: $gray-900;
}
.blockShortcodeDark {
color: $white;
- background-color: $gray-100;
}
.placeholder {
diff --git a/packages/block-library/src/shortcode/test/__snapshots__/edit.native.js.snap b/packages/block-library/src/shortcode/test/__snapshots__/edit.native.js.snap
new file mode 100644
index 00000000000000..12d5722a68c39d
--- /dev/null
+++ b/packages/block-library/src/shortcode/test/__snapshots__/edit.native.js.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Shortcode block edits content 1`] = `
+"
+[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]
+"
+`;
+
+exports[`Shortcode block inserts block 1`] = `""`;
diff --git a/packages/block-library/src/shortcode/test/edit.native.js b/packages/block-library/src/shortcode/test/edit.native.js
index c6aa9261b6d9f5..f6c9ce705f5ad3 100644
--- a/packages/block-library/src/shortcode/test/edit.native.js
+++ b/packages/block-library/src/shortcode/test/edit.native.js
@@ -1,58 +1,76 @@
/**
* External dependencies
*/
-import renderer from 'react-test-renderer';
-import { TextInput } from 'react-native';
+import {
+ getEditorHtml,
+ initializeEditor,
+ fireEvent,
+ waitFor,
+} from 'test/helpers';
/**
* WordPress dependencies
*/
-import { BlockEdit } from '@wordpress/block-editor';
-import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
+import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
+import { registerCoreBlocks } from '@wordpress/block-library';
-/**
- * Internal dependencies
- */
-import { metadata, settings, name } from '../index';
+beforeAll( () => {
+ // Register all core blocks
+ registerCoreBlocks();
+} );
+
+afterAll( () => {
+ // Clean up registered blocks
+ getBlockTypes().forEach( ( block ) => {
+ unregisterBlockType( block.name );
+ } );
+} );
+
+describe( 'Shortcode block', () => {
+ it( 'inserts block', async () => {
+ const {
+ getByA11yLabel,
+ getByTestId,
+ getByText,
+ } = await initializeEditor();
-const Shortcode = ( { clientId, ...props } ) => (
-
-);
+ fireEvent.press( getByA11yLabel( 'Add block' ) );
-describe( 'Shortcode', () => {
- beforeAll( () => {
- registerBlockType( name, {
- ...metadata,
- ...settings,
+ const blockList = getByTestId( 'InserterUI-Blocks' );
+ // onScroll event used to force the FlatList to render all items
+ fireEvent.scroll( blockList, {
+ nativeEvent: {
+ contentOffset: { y: 0, x: 0 },
+ contentSize: { width: 100, height: 100 },
+ layoutMeasurement: { width: 100, height: 100 },
+ },
} );
- } );
- afterAll( () => {
- unregisterBlockType( name );
- } );
+ fireEvent.press( await waitFor( () => getByText( 'Shortcode' ) ) );
- it( 'renders without crashing', () => {
- const component = renderer.create(
-
- );
- const rendered = component.toJSON();
- expect( rendered ).toBeTruthy();
+ expect( getByA11yLabel( /Shortcode Block\. Row 1/ ) ).toBeVisible();
+ expect( getEditorHtml() ).toMatchSnapshot();
} );
- it( 'renders given text without crashing', () => {
- const component = renderer.create(
-
- );
- const testInstance = component.root;
- const textInput = testInstance.findByType( TextInput );
- expect( textInput ).toBeTruthy();
- expect( textInput.props.value ).toBe(
- '[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]'
+ it( 'edits content', async () => {
+ const { getByA11yLabel, getByPlaceholderText } = await initializeEditor(
+ {
+ initialHtml: '',
+ }
);
+ const shortcodeBlock = getByA11yLabel( /Shortcode Block\. Row 1/ );
+ fireEvent.press( shortcodeBlock );
+
+ const textField = getByPlaceholderText( 'Add a shortcode…' );
+ fireEvent( textField, 'focus' );
+ fireEvent( textField, 'onChange', {
+ nativeEvent: {
+ eventCount: 1,
+ target: undefined,
+ text: '[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]',
+ },
+ } );
+
+ expect( getEditorHtml() ).toMatchSnapshot();
} );
} );
diff --git a/packages/react-native-aztec/android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecManager.java b/packages/react-native-aztec/android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecManager.java
index 52dac695bc9973..1e3e90c3a48442 100644
--- a/packages/react-native-aztec/android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecManager.java
+++ b/packages/react-native-aztec/android/src/main/java/org/wordpress/mobile/ReactNativeAztec/ReactAztecManager.java
@@ -13,6 +13,7 @@
import android.os.Handler;
import android.os.Looper;
import android.text.Editable;
+import android.text.InputType;
import android.text.Layout;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -617,6 +618,16 @@ public void setShouldDeleteEnter(final ReactAztecText view, boolean shouldDelete
view.shouldDeleteEnter = shouldDeleteEnter;
}
+ @ReactProp(name = "disableAutocorrection", defaultBoolean = false)
+ public void disableAutocorrection(final ReactAztecText view, boolean disable) {
+ if (disable) {
+ view.setInputType((view.getInputType() & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ }
+ else {
+ view.setInputType((view.getInputType() & ~InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
+ }
+ }
+
@Override
public Map getCommandsMap() {
return MapBuilder.builder()
diff --git a/packages/react-native-aztec/ios/RNTAztecView/RCTAztecView.swift b/packages/react-native-aztec/ios/RNTAztecView/RCTAztecView.swift
index 5413041b6ac6ff..cc87ef29e9704b 100644
--- a/packages/react-native-aztec/ios/RNTAztecView/RCTAztecView.swift
+++ b/packages/react-native-aztec/ios/RNTAztecView/RCTAztecView.swift
@@ -31,6 +31,12 @@ class RCTAztecView: Aztec.TextView {
}
}
+ @objc var disableAutocorrection: Bool = false {
+ didSet {
+ autocorrectionType = disableAutocorrection ? .no : .default
+ }
+ }
+
override var textAlignment: NSTextAlignment {
set {
super.textAlignment = newValue
diff --git a/packages/react-native-aztec/ios/RNTAztecView/RCTAztecViewManager.m b/packages/react-native-aztec/ios/RNTAztecView/RCTAztecViewManager.m
index bad6dd8abf7680..e8038ab17a7044 100644
--- a/packages/react-native-aztec/ios/RNTAztecView/RCTAztecViewManager.m
+++ b/packages/react-native-aztec/ios/RNTAztecView/RCTAztecViewManager.m
@@ -31,6 +31,7 @@ @interface RCT_EXTERN_MODULE(RCTAztecViewManager, NSObject)
RCT_EXPORT_VIEW_PROPERTY(lineHeight, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(disableEditingMenu, BOOL)
+RCT_EXPORT_VIEW_PROPERTY(disableAutocorrection, BOOL)
RCT_REMAP_VIEW_PROPERTY(textAlign, textAlignment, NSTextAlignment)
RCT_REMAP_VIEW_PROPERTY(selectionColor, tintColor, UIColor)
diff --git a/packages/rich-text/src/component/index.native.js b/packages/rich-text/src/component/index.native.js
index f460019df8b3ce..4fadc90b8d4baa 100644
--- a/packages/rich-text/src/component/index.native.js
+++ b/packages/rich-text/src/component/index.native.js
@@ -1050,6 +1050,7 @@ export class RichText extends Component {
baseGlobalStyles,
selectionStart,
selectionEnd,
+ disableSuggestions,
} = this.props;
const { currentFontSize } = this.state;
@@ -1220,6 +1221,7 @@ export class RichText extends Component {
minWidth={ minWidth }
id={ this.props.id }
selectionColor={ this.props.selectionColor }
+ disableAutocorrection={ this.props.disableAutocorrection }
/>
{ isSelected && (
<>
@@ -1230,11 +1232,13 @@ export class RichText extends Component {
onChange={ this.onFormatChange }
onFocus={ () => {} }
/>
-
-
-
+ { ! disableSuggestions && (
+
+
+
+ ) }
>
) }
@@ -1249,10 +1253,17 @@ RichText.defaultProps = {
};
const withFormatTypes = ( WrappedComponent ) => ( props ) => {
+ const {
+ clientId,
+ identifier,
+ withoutInteractiveFormatting,
+ allowedFormats,
+ } = props;
const { formatTypes } = useFormatTypes( {
- clientId: props.clientId,
- identifier: props.identifier,
- withoutInteractiveFormatting: props.withoutInteractiveFormatting,
+ clientId,
+ identifier,
+ withoutInteractiveFormatting,
+ allowedFormats,
} );
return ;
diff --git a/test/native/__mocks__/styleMock.js b/test/native/__mocks__/styleMock.js
index 4723663203954f..11f58d79b1afcd 100644
--- a/test/native/__mocks__/styleMock.js
+++ b/test/native/__mocks__/styleMock.js
@@ -162,4 +162,7 @@ module.exports = {
'dropping-insertion-point': {
height: 3,
},
+ blockShortcodeContainer: {
+ padding: 12,
+ },
};