Skip to content

Commit 326d4d8

Browse files
authored
TinyMCE per block: Adding transform block API (#204)
- I implemented text,quote,heading transformations for now
1 parent 5f809c9 commit 326d4d8

File tree

24 files changed

+281
-87
lines changed

24 files changed

+281
-87
lines changed

tinymce-per-block/build/app.js

+14-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tinymce-per-block/src/assets/stylesheets/main.scss

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@import '~renderers/block/block-list/style';
1212
@import '~renderers/html/html-editor/style';
1313
@import '~controls/editable-format-toolbar/style';
14+
@import '~controls/transform-block-toolbar/style';
1415
@import '~inserter/style';
1516

1617
* {

tinymce-per-block/src/blocks/embed-block/form.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default class EmbedBlockForm extends Component {
2424

2525
render() {
2626
const { block, isSelected, change, moveCursorUp, moveCursorDown,
27-
remove, focusConfig, focus, moveBlockUp, moveBlockDown, appendBlock } = this.props;
27+
remove, focusConfig, focus, moveBlockUp, moveBlockDown, appendBlock, unselect } = this.props;
2828

2929
const removePrevious = () => {
3030
if ( ! block.url ) {
@@ -81,7 +81,10 @@ export default class EmbedBlockForm extends Component {
8181
moveCursorDown={ moveCursorDown }
8282
splitValue={ splitValue }
8383
value={ block.caption }
84-
onChange={ ( value ) => change( { caption: value } ) }
84+
onChange={ ( value ) => {
85+
change( { caption: value } );
86+
unselect();
87+
} }
8588
placeholder="Write caption"
8689
focusConfig={ focusConfig }
8790
onFocusChange={ focus }

tinymce-per-block/src/blocks/heading-block/form.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import InlineTextBlockForm from '../inline-text-block/form';
1313
import EditableFormatToolbar from 'controls/editable-format-toolbar';
1414
import BlockArrangement from 'controls/block-arrangement';
15+
import TransformBlockToolbar from 'controls/transform-block-toolbar';
1516

1617
export default class HeadingBlockForm extends Component {
1718
bindForm = ( ref ) => {
@@ -32,7 +33,7 @@ export default class HeadingBlockForm extends Component {
3233
};
3334

3435
render() {
35-
const { block, isSelected, moveBlockUp, moveBlockDown } = this.props;
36+
const { block, isSelected, moveBlockUp, moveBlockDown, select, transform } = this.props;
3637
const sizes = [
3738
{ id: 'h1', icon: EditorHeading1Icon },
3839
{ id: 'h2', icon: EditorHeading2Icon },
@@ -45,6 +46,9 @@ export default class HeadingBlockForm extends Component {
4546
moveBlockUp={ moveBlockUp } moveBlockDown={ moveBlockDown } /> }
4647
{ isSelected && (
4748
<div className="block-list__block-controls">
49+
<div className="block-list__block-controls-group">
50+
<TransformBlockToolbar blockType="heading" onTransform={ transform } />
51+
</div>
4852
<div className="block-list__block-controls-group">
4953
{ sizes.map( ( { id, icon: Icon } ) =>
5054
<button
@@ -64,7 +68,7 @@ export default class HeadingBlockForm extends Component {
6468
</div>
6569
</div>
6670
) }
67-
<div className={ `heading-block__form ${ block.size }` }>
71+
<div className={ `heading-block__form ${ block.size }` } onClick={ select }>
6872
<InlineTextBlockForm
6973
ref={ this.bindForm }
7074
{ ...this.props }

tinymce-per-block/src/blocks/heading-block/index.js

+15-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ import { EditorHeadingIcon } from 'dashicons';
99
*/
1010
import form from './form';
1111

12+
const createHeadingBlockWithContent = ( content = '' ) => {
13+
return {
14+
blockType: 'heading',
15+
size: 'h2',
16+
content
17+
};
18+
};
19+
1220
registerBlock( 'heading', {
1321
title: 'Heading',
1422
form: form,
@@ -40,11 +48,11 @@ registerBlock( 'heading', {
4048
rawContent
4149
};
4250
},
43-
create: () => {
44-
return {
45-
blockType: 'heading',
46-
content: '',
47-
size: 'h2'
48-
};
49-
}
51+
create: createHeadingBlockWithContent,
52+
transformations: [
53+
{
54+
blocks: [ 'text', 'quote' ],
55+
transform: ( block ) => createHeadingBlockWithContent( block.content )
56+
}
57+
]
5058
} );

tinymce-per-block/src/blocks/html-block/form.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default class HtmlBlockForm extends Component {
4040

4141
render() {
4242
const { block, isSelected, change, moveCursorUp, moveCursorDown, appendBlock,
43-
mergeWithPrevious, remove, focusConfig, focus, moveBlockUp, moveBlockDown } = this.props;
43+
mergeWithPrevious, remove, focusConfig, focus, moveBlockUp, moveBlockDown, select, unselect } = this.props;
4444
const splitValue = ( left, right ) => {
4545
change( { content: left } );
4646
if ( right ) {
@@ -72,7 +72,7 @@ export default class HtmlBlockForm extends Component {
7272
</div>
7373
</div>
7474
) }
75-
<div className="html-block__form" style={ style }>
75+
<div className="html-block__form" style={ style } onClick={ select }>
7676
<EditableComponent
7777
ref={ this.bindEditable }
7878
content={ block.content }
@@ -85,6 +85,7 @@ export default class HtmlBlockForm extends Component {
8585
onChange={ ( value ) => change( { content: value } ) }
8686
focusConfig={ focusConfig }
8787
onFocusChange={ focus }
88+
onType={ unselect }
8889
/>
8990
</div>
9091
</div>

tinymce-per-block/src/blocks/image-block/form.js

+24-19
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default class ImageBlockForm extends Component {
2020

2121
render() {
2222
const { block, change, moveCursorDown, moveCursorUp, remove, appendBlock,
23-
isSelected, focusConfig, focus, moveBlockUp, moveBlockDown } = this.props;
23+
isSelected, focusConfig, focus, moveBlockUp, moveBlockDown, select, unselect } = this.props;
2424
const removePrevious = () => {
2525
if ( ! block.caption ) {
2626
remove();
@@ -45,25 +45,30 @@ export default class ImageBlockForm extends Component {
4545
</div>
4646
</div>
4747
}
48-
<img
49-
src={ block.src }
50-
className="image-block__display"
51-
onClick={ () => {
52-
! focusConfig && focus();
53-
} }
54-
/>
55-
<div className="image-block__caption">
56-
<EnhancedInputComponent
57-
moveCursorUp={ moveCursorUp }
58-
removePrevious={ removePrevious }
59-
moveCursorDown={ moveCursorDown }
60-
splitValue={ splitValue }
61-
value={ block.caption }
62-
onChange={ ( value ) => change( { caption: value } ) }
63-
placeholder="Write caption"
64-
focusConfig={ focusConfig }
65-
onFocusChange={ focus }
48+
<div onClick={ select }>
49+
<img
50+
src={ block.src }
51+
className="image-block__display"
52+
onClick={ () => {
53+
! focusConfig && focus();
54+
} }
6655
/>
56+
<div className="image-block__caption">
57+
<EnhancedInputComponent
58+
moveCursorUp={ moveCursorUp }
59+
removePrevious={ removePrevious }
60+
moveCursorDown={ moveCursorDown }
61+
splitValue={ splitValue }
62+
value={ block.caption }
63+
onChange={ ( value ) => {
64+
change( { caption: value } );
65+
unselect();
66+
} }
67+
placeholder="Write caption"
68+
focusConfig={ focusConfig }
69+
onFocusChange={ focus }
70+
/>
71+
</div>
6772
</div>
6873
</div>
6974
);

tinymce-per-block/src/blocks/inline-text-block/form.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default class InlineTextBlockForm extends Component {
3737

3838
render() {
3939
const { block, change, moveCursorUp, moveCursorDown, appendBlock,
40-
mergeWithPrevious, remove, setToolbarState, focus, focusConfig } = this.props;
40+
mergeWithPrevious, remove, setToolbarState, focus, focusConfig, unselect } = this.props;
4141

4242
const splitValue = ( left, right ) => {
4343
change( { content: left } );
@@ -65,6 +65,7 @@ export default class InlineTextBlockForm extends Component {
6565
setToolbarState={ setToolbarState }
6666
focusConfig={ focusConfig }
6767
onFocusChange={ focus }
68+
onType={ unselect }
6869
inline
6970
single
7071
/>

tinymce-per-block/src/blocks/quote-block/form.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
*/
44
import { createElement, Component } from 'wp-elements';
55

6-
import { EditableComponent, EnhancedInputComponent } from 'wp-blocks';
7-
import { serialize } from 'serializers/block';
8-
import { parse } from 'parsers/block';
6+
/**
7+
* Internal dependencies
8+
*/
9+
import { EditableComponent } from 'wp-blocks';
910
import EditableFormatToolbar from 'controls/editable-format-toolbar';
1011
import BlockArrangement from 'controls/block-arrangement';
12+
import TransformBlockToolbar from 'controls/transform-block-toolbar';
1113

1214
export default class QuoteBlockForm extends Component {
1315
bindContent = ( ref ) => {
@@ -59,7 +61,7 @@ export default class QuoteBlockForm extends Component {
5961
render() {
6062
const { block, change, moveCursorUp, moveCursorDown, remove,
6163
mergeWithPrevious, appendBlock, isSelected, focusConfig, focus,
62-
moveBlockUp, moveBlockDown } = this.props;
64+
moveBlockUp, moveBlockDown, select, unselect, transform } = this.props;
6365
const splitValue = ( left, right ) => {
6466
change( { cite: left } );
6567
appendBlock( {
@@ -78,13 +80,17 @@ export default class QuoteBlockForm extends Component {
7880
moveBlockUp={ moveBlockUp } moveBlockDown={ moveBlockDown } /> }
7981
{ isSelected &&
8082
<div className="block-list__block-controls">
83+
<div className="block-list__block-controls-group">
84+
<TransformBlockToolbar blockType="quote" onTransform={ transform } />
85+
</div>
86+
8187
<div className="block-list__block-controls-group">
8288
<EditableFormatToolbar editable={ focusInput === 'content' ? this.content : this.cite } ref={ this.bindFormatToolbar } />
8389
</div>
8490
</div>
8591
}
8692

87-
<div className="quote-block__form">
93+
<div className="quote-block__form" onClick={ select }>
8894
<div className="quote-block__content">
8995
<EditableComponent
9096
ref={ this.bindContent }
@@ -97,6 +103,7 @@ export default class QuoteBlockForm extends Component {
97103
setToolbarState={ focusInput === 'content' ? this.setToolbarState : undefined }
98104
focusConfig={ focusInput === 'content' ? focusConfig : null }
99105
onFocusChange={ ( config ) => focus( Object.assign( { input: 'content' }, config ) ) }
106+
onType={ unselect }
100107
inline
101108
/>
102109
</div>
@@ -113,6 +120,7 @@ export default class QuoteBlockForm extends Component {
113120
setToolbarState={ focusInput === 'cite' ? this.setToolbarState : undefined }
114121
focusConfig={ focusInput === 'cite' ? focusConfig : null }
115122
onFocusChange={ ( config ) => focus( Object.assign( { input: 'cite' }, config ) ) }
123+
onType={ unselect }
116124
inline
117125
single
118126
/>

tinymce-per-block/src/blocks/quote-block/index.js

+15-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ import {
1111
*/
1212
import form from './form';
1313

14+
const createQuoteBlockWithContent = ( content = '' ) => {
15+
return {
16+
blockType: 'quote',
17+
cite: '',
18+
content
19+
};
20+
};
21+
1422
registerBlock( 'quote', {
1523
title: 'Quote',
1624
form: form,
@@ -55,11 +63,11 @@ registerBlock( 'quote', {
5563
rawContent
5664
};
5765
},
58-
create: () => {
59-
return {
60-
blockType: 'quote',
61-
cite: '',
62-
content: ''
63-
};
64-
}
66+
create: createQuoteBlockWithContent,
67+
transformations: [
68+
{
69+
blocks: [ 'text', 'heading' ],
70+
transform: ( block ) => createQuoteBlockWithContent( block.content )
71+
}
72+
]
6573
} );

tinymce-per-block/src/blocks/text-block/form.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createElement, Component } from 'wp-elements';
66
import EditableFormatToolbar from 'controls/editable-format-toolbar';
77
import AlignmentToolbar from 'controls/alignment-toolbar';
88
import BlockArrangement from 'controls/block-arrangement';
9+
import TransformBlockToolbar from 'controls/transform-block-toolbar';
910
import InlineTextBlockForm from 'blocks/inline-text-block/form';
1011
import InserterButton from 'inserter/button';
1112

@@ -28,7 +29,7 @@ export default class TextBlockForm extends Component {
2829
};
2930

3031
render() {
31-
const { block, isSelected, focusConfig, moveBlockUp, moveBlockDown, replace } = this.props;
32+
const { block, isSelected, focusConfig, moveBlockUp, moveBlockDown, replace, select, transform } = this.props;
3233
const selectedTextAlign = block.align || 'left';
3334
const style = {
3435
textAlign: selectedTextAlign
@@ -40,6 +41,10 @@ export default class TextBlockForm extends Component {
4041
moveBlockUp={ moveBlockUp } moveBlockDown={ moveBlockDown } /> }
4142
{ isSelected &&
4243
<div className="block-list__block-controls">
44+
<div className="block-list__block-controls-group">
45+
<TransformBlockToolbar blockType="text" onTransform={ transform } />
46+
</div>
47+
4348
<div className="block-list__block-controls-group">
4449
<AlignmentToolbar value={ block.align } onChange={ this.setAlignment } />
4550
</div>
@@ -50,7 +55,7 @@ export default class TextBlockForm extends Component {
5055
</div>
5156
}
5257

53-
<div className="text-block__form" style={ style }>
58+
<div className="text-block__form" style={ style } onClick={ select }>
5459
{ ! block.content.trim() && ! isSelected && focusConfig &&
5560
<InserterButton onAdd={ ( id ) => replace( id ) } />
5661
}

tinymce-per-block/src/blocks/text-block/index.js

+15-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ import { EditorParagraphIcon } from 'dashicons';
99
*/
1010
import form from './form';
1111

12+
const createTextBlockWithContent = ( content = '' ) => {
13+
return {
14+
blockType: 'text',
15+
align: 'no-align',
16+
content
17+
};
18+
};
19+
1220
registerBlock( 'text', {
1321
title: 'Text',
1422
form: form,
@@ -44,11 +52,11 @@ registerBlock( 'text', {
4452
rawContent
4553
};
4654
},
47-
create: () => {
48-
return {
49-
blockType: 'text',
50-
content: '',
51-
align: 'no-align'
52-
};
53-
}
55+
create: () => createTextBlockWithContent,
56+
transformations: [
57+
{
58+
blocks: [ 'heading', 'quote' ],
59+
transform: ( block ) => createTextBlockWithContent( block.content )
60+
}
61+
]
5462
} );

tinymce-per-block/src/controls/block-arrangement.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,14 @@ import { ArrowDownAlt2Icon, ArrowUpAlt2Icon } from 'dashicons';
88
export default function BlockArrangement( { block, moveBlockUp, moveBlockDown } ) {
99
const blockDefinition = getBlock( block.blockType );
1010
const Icon = blockDefinition.icon;
11-
const onMoveUp = ( event ) => {
12-
event.stopPropagation();
13-
moveBlockUp();
14-
};
15-
const onMoveDown = ( event ) => {
16-
event.stopPropagation();
17-
moveBlockDown();
18-
};
1911

2012
return (
2113
<div className="block-list__block-arrangement">
2214
<div className="block-list__movement-controls">
23-
<button className="block-list__block-arrange-control" onClick={ onMoveUp }>
15+
<button className="block-list__block-arrange-control" onClick={ moveBlockUp }>
2416
<ArrowUpAlt2Icon />
2517
</button>
26-
<button className="block-list__block-arrange-control" onClick={ onMoveDown }>
18+
<button className="block-list__block-arrange-control" onClick={ moveBlockDown }>
2719
<ArrowDownAlt2Icon />
2820
</button>
2921
</div>

0 commit comments

Comments
 (0)