Skip to content

Commit

Permalink
Introduces RichText component for mobile and ports Para block for mob…
Browse files Browse the repository at this point in the history
…ile (#8231)

* Introduce RichText component for mobile, and port the Paragraph block by using the newly introduced RichText component.

* Fix lint

* Use an edit file to share more common code with the main Paragraph web code.

* Fix lint

* Remove log calls

* Revert renaming of custom-class-name.native.js → custom-class-name-native.js and relevant import statement.

* Cleaning the code / Refactoring by "nativizing" `utils.js` (& `index.js`) in raw-handling

* Remove any extra P.

* Replace <p> by <br>

* The RichText mobile component now returns plain HTML, and the transformation from HTML to React is made in the mobile paragraph block.

* Update code to work with the lastest master changes

* Correctly check if minHeight is undefined when setting the style of mobile paragraph block.

* Blocks: Extract phrasing content to its own file to allow reuse with React Native

* Remove method `setForceUpdate` that is not used. Also remove the conversion of value to boolean in if. JS does it itself.

* Remove `aria-label` that is not used in RichText mobile

* Convert private instance variable `lastContentSizeHeight`, to local method variable.

* Use built-in `forceUpdate` method call, instead of using a private boolean variable used to skip the rendering.

* Add comment for P replacement for BR
  • Loading branch information
daniloercoli authored Aug 1, 2018
1 parent 0a4b2a5 commit 1c966a9
Show file tree
Hide file tree
Showing 17 changed files with 495 additions and 271 deletions.
2 changes: 2 additions & 0 deletions core-blocks/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import {
*/
import * as code from './code';
import * as more from './more';
import * as paragraph from './paragraph';

export const registerCoreBlocks = () => {
[
paragraph,
code,
more,
].forEach( ( { name, settings } ) => {
Expand Down
243 changes: 243 additions & 0 deletions core-blocks/paragraph/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
Component,
Fragment,
} from '@wordpress/element';
import {
PanelBody,
ToggleControl,
withFallbackStyles,
} from '@wordpress/components';
import {
withColors,
AlignmentToolbar,
BlockControls,
ContrastChecker,
FontSizePicker,
InspectorControls,
PanelColorSettings,
RichText,
withFontSizes,
} from '@wordpress/editor';
import { createBlock } from '@wordpress/blocks';
import { compose } from '@wordpress/compose';

/**
* Internal dependencies
*/
import './style.scss';

const { getComputedStyle } = window;

const name = 'core/paragraph';

const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => {
const { textColor, backgroundColor, fontSize, customFontSize } = ownProps.attributes;
const editableNode = node.querySelector( '[contenteditable="true"]' );
//verify if editableNode is available, before using getComputedStyle.
const computedStyles = editableNode ? getComputedStyle( editableNode ) : null;
return {
fallbackBackgroundColor: backgroundColor || ! computedStyles ? undefined : computedStyles.backgroundColor,
fallbackTextColor: textColor || ! computedStyles ? undefined : computedStyles.color,
fallbackFontSize: fontSize || customFontSize || ! computedStyles ? undefined : parseInt( computedStyles.fontSize ) || undefined,
};
} );

class ParagraphBlock extends Component {
constructor() {
super( ...arguments );

this.onReplace = this.onReplace.bind( this );
this.toggleDropCap = this.toggleDropCap.bind( this );
this.splitBlock = this.splitBlock.bind( this );
}

onReplace( blocks ) {
const { attributes, onReplace } = this.props;
onReplace( blocks.map( ( block, index ) => (
index === 0 && block.name === name ?
{ ...block,
attributes: {
...attributes,
...block.attributes,
},
} :
block
) ) );
}

toggleDropCap() {
const { attributes, setAttributes } = this.props;
setAttributes( { dropCap: ! attributes.dropCap } );
}

getDropCapHelp( checked ) {
return checked ? __( 'Showing large initial letter.' ) : __( 'Toggle to show a large initial letter.' );
}

/**
* Split handler for RichText value, namely when content is pasted or the
* user presses the Enter key.
*
* @param {?Array} before Optional before value, to be used as content
* in place of what exists currently for the
* block. If undefined, the block is deleted.
* @param {?Array} after Optional after value, to be appended in a new
* paragraph block to the set of blocks passed
* as spread.
* @param {...WPBlock} blocks Optional blocks inserted between the before
* and after value blocks.
*/
splitBlock( before, after, ...blocks ) {
const {
attributes,
insertBlocksAfter,
setAttributes,
onReplace,
} = this.props;

if ( after ) {
// Append "After" content as a new paragraph block to the end of
// any other blocks being inserted after the current paragraph.
blocks.push( createBlock( name, { content: after } ) );
}

if ( blocks.length && insertBlocksAfter ) {
insertBlocksAfter( blocks );
}

const { content } = attributes;
if ( ! before ) {
// If before content is omitted, treat as intent to delete block.
onReplace( [] );
} else if ( content !== before ) {
// Only update content if it has in-fact changed. In case that user
// has created a new paragraph at end of an existing one, the value
// of before will be strictly equal to the current content.
setAttributes( { content: before } );
}
}

render() {
const {
attributes,
setAttributes,
mergeBlocks,
onReplace,
className,
backgroundColor,
textColor,
setBackgroundColor,
setTextColor,
fallbackBackgroundColor,
fallbackTextColor,
fallbackFontSize,
fontSize,
setFontSize,
} = this.props;

const {
align,
content,
dropCap,
placeholder,
} = attributes;

return (
<Fragment>
<BlockControls>
<AlignmentToolbar
value={ align }
onChange={ ( nextAlign ) => {
setAttributes( { align: nextAlign } );
} }
/>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Text Settings' ) } className="blocks-font-size">
<FontSizePicker
fallbackFontSize={ fallbackFontSize }
value={ fontSize.size }
onChange={ setFontSize }
/>
<ToggleControl
label={ __( 'Drop Cap' ) }
checked={ !! dropCap }
onChange={ this.toggleDropCap }
help={ this.getDropCapHelp }
/>
</PanelBody>
<PanelColorSettings
title={ __( 'Color Settings' ) }
initialOpen={ false }
colorSettings={ [
{
value: backgroundColor.value,
onChange: setBackgroundColor,
label: __( 'Background Color' ),
},
{
value: textColor.value,
onChange: setTextColor,
label: __( 'Text Color' ),
},
] }
>
<ContrastChecker
{ ...{
textColor: textColor.value,
backgroundColor: backgroundColor.value,
fallbackTextColor,
fallbackBackgroundColor,
} }
fontSize={ fontSize.size }
/>
</PanelColorSettings>
</InspectorControls>
<RichText
tagName="p"
className={ classnames( 'wp-block-paragraph', className, {
'has-background': backgroundColor.value,
'has-drop-cap': dropCap,
[ backgroundColor.class ]: backgroundColor.class,
[ textColor.class ]: textColor.class,
[ fontSize.class ]: fontSize.class,
} ) }
style={ {
backgroundColor: backgroundColor.value,
color: textColor.value,
fontSize: fontSize.size ? fontSize.size + 'px' : undefined,
textAlign: align,
} }
value={ content }
onChange={ ( nextContent ) => {
setAttributes( {
content: nextContent,
} );
} }
onSplit={ this.splitBlock }
onMerge={ mergeBlocks }
onReplace={ this.onReplace }
onRemove={ () => onReplace( [] ) }
placeholder={ placeholder || __( 'Add text or type / to add content' ) }
/>
</Fragment>
);
}
}

const ParagraphEdit = compose( [
withColors( 'backgroundColor', { textColor: 'color' } ),
withFontSizes( 'fontSize' ),
applyFallbackStyles,
] )( ParagraphBlock );

export default ParagraphEdit;
60 changes: 60 additions & 0 deletions core-blocks/paragraph/edit.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* External dependencies
*/
import { View } from 'react-native';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { parse } from '@wordpress/blocks';
import { RichText } from '@wordpress/editor';

const minHeight = 50;

class ParagraphEdit extends Component {
render() {
const {
attributes,
setAttributes,
style,
} = this.props;

const {
placeholder,
} = attributes;

return (
<View>
<RichText
content={ { contentTree: attributes.content, eventCount: attributes.eventCount } }
style={ {
...style,
minHeight: Math.max( minHeight, typeof attributes.aztecHeight === 'undefined' ? 0 : attributes.aztecHeight ),
} }
onChange={ ( event ) => {
// Create a React Tree from the new HTML
const newParaBlock = parse( '<!-- wp:paragraph --><p>' + event.content + '</p><!-- /wp:paragraph -->' )[ 0 ];
setAttributes( {
...this.props.attributes,
content: newParaBlock.attributes.content,
eventCount: event.eventCount,
} );
}
}
onContentSizeChange={ ( event ) => {
setAttributes( {
...this.props.attributes,
aztecHeight: event.aztecHeight,
} );
}
}
placeholder={ placeholder || __( 'Add text or type / to add content' ) }
/>
</View>
);
}
}

export default ParagraphEdit;
Loading

0 comments on commit 1c966a9

Please sign in to comment.