-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
index.js
163 lines (140 loc) · 3.75 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
* External dependencies
*/
import { times, property, omit } from 'lodash';
import classnames from 'classnames';
import memoize from 'memize';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, RangeControl } from '@wordpress/components';
import { Fragment } from '@wordpress/element';
import { createBlock } from '@wordpress/blocks';
import {
InspectorControls,
InnerBlocks,
} from '@wordpress/editor';
/**
* Allowed blocks constant is passed to InnerBlocks precisely as specified here.
* The contents of the array should never change.
* The array should contain the name of each block that is allowed.
* In columns block, the only block we allow is 'core/column'.
*
* @constant
* @type {string[]}
*/
const ALLOWED_BLOCKS = [ 'core/column' ];
/**
* Returns the layouts configuration for a given number of columns.
*
* @param {number} columns Number of columns.
*
* @return {Object[]} Columns layout configuration.
*/
const getColumnsTemplate = memoize( ( columns ) => {
return times( columns, () => [ 'core/column' ] );
} );
export const name = 'core/columns';
export const settings = {
title: __( 'Columns' ),
icon: <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z" /><g><path d="M21 4H3L2 5v14l1 1h18l1-1V5l-1-1zM8 18H4V6h4v12zm6 0h-4V6h4v12zm6 0h-4V6h4v12z" /></g></svg>,
category: 'layout',
attributes: {
columns: {
type: 'number',
default: 2,
},
},
description: __( 'Add a block that displays content in multiple columns, then add whatever content blocks you’d like.' ),
supports: {
align: [ 'wide', 'full' ],
},
deprecated: [
{
attributes: {
columns: {
type: 'number',
default: 2,
},
},
isEligible( attributes, innerBlocks ) {
return innerBlocks.some( property( [ 'attributes', 'layout' ] ) );
},
migrate( attributes, innerBlocks ) {
function withoutLayout( block ) {
return {
...block,
attributes: omit( block.attributes, [ 'layout' ] ),
};
}
const columns = innerBlocks.reduce( ( result, innerBlock ) => {
const { layout } = innerBlock.attributes;
let columnIndex, columnMatch;
if ( layout && ( columnMatch = layout.match( /^column-(\d+)$/ ) ) ) {
columnIndex = Number( columnMatch[ 1 ] ) - 1;
} else {
columnIndex = 0;
}
if ( ! result[ columnIndex ] ) {
result[ columnIndex ] = [];
}
result[ columnIndex ].push( withoutLayout( innerBlock ) );
return result;
}, [] );
const migratedInnerBlocks = columns.map( ( columnBlocks ) => (
createBlock( 'core/column', {}, columnBlocks )
) );
return [
attributes,
migratedInnerBlocks,
];
},
save( { attributes } ) {
const { columns } = attributes;
return (
<div className={ `has-${ columns }-columns` }>
<InnerBlocks.Content />
</div>
);
},
},
],
edit( { attributes, setAttributes, className } ) {
const { columns } = attributes;
const classes = classnames( className, `has-${ columns }-columns` );
return (
<Fragment>
<InspectorControls>
<PanelBody>
<RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ ( nextColumns ) => {
setAttributes( {
columns: nextColumns,
} );
} }
min={ 2 }
max={ 6 }
/>
</PanelBody>
</InspectorControls>
<div className={ classes }>
<InnerBlocks
template={ getColumnsTemplate( columns ) }
templateLock="all"
allowedBlocks={ ALLOWED_BLOCKS } />
</div>
</Fragment>
);
},
save( { attributes } ) {
const { columns } = attributes;
return (
<div className={ `has-${ columns }-columns` }>
<InnerBlocks.Content />
</div>
);
},
};