PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.7.1
GenerateBlocks v1.7.1
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / components / dimensions / index.js
generateblocks / src / components / dimensions Last commit date
editor.scss 3 years ago index.js 3 years ago
index.js
278 lines
1 /**
2 * External dependencies
3 */
4 import { __, _x, sprintf } from '@wordpress/i18n';
5 import { BaseControl, Button, Tooltip } from '@wordpress/components';
6 import { link, linkOff } from '@wordpress/icons';
7
8 /**
9 * Internal dependencies
10 */
11 import './editor.scss';
12 import UnitPicker from '../unit-picker';
13 import getResponsivePlaceholder from '../../utils/get-responsive-placeholder';
14
15 export default function Dimensions( props ) {
16 const {
17 setAttributes,
18 attributes,
19 label = __( 'Padding', 'generateblocks' ),
20 type = 'padding',
21 labelTop = __( 'Top', 'generateblocks' ),
22 labelRight = __( 'Right', 'generateblocks' ),
23 labelBottom = __( 'Bottom', 'generateblocks' ),
24 labelLeft = __( 'Left', 'generateblocks' ),
25 device,
26 units,
27 computedStyles = {},
28 } = props;
29
30 const attributeNames = {
31 top: type + 'Top',
32 right: type + 'Right',
33 bottom: type + 'Bottom',
34 left: type + 'Left',
35 unit: type + 'Unit',
36 sync: type + 'SyncUnits',
37 };
38
39 const labels = {
40 top: labelTop,
41 right: labelRight,
42 bottom: labelBottom,
43 left: labelLeft,
44 };
45
46 if ( 'borderRadius' === type ) {
47 attributeNames.top = 'borderRadiusTopLeft';
48 attributeNames.right = 'borderRadiusTopRight';
49 attributeNames.bottom = 'borderRadiusBottomRight';
50 attributeNames.left = 'borderRadiusBottomLeft';
51
52 labels.top = _x( 'T-Left', 'short for Top Left', 'generateblocks' );
53 labels.right = _x( 'T-Right', 'short for Top Right', 'generateblocks' );
54 labels.bottom = _x( 'B-Right', 'short for Bottom Right', 'generateblocks' );
55 labels.left = _x( 'B-Left', 'short for Bottom Left', 'generateblocks' );
56 }
57
58 if ( 'Desktop' !== device ) {
59 attributeNames.top += device;
60 attributeNames.right += device;
61 attributeNames.bottom += device;
62 attributeNames.left += device;
63 }
64
65 const onChangeTop = ( value ) => setAttributes( { [ attributeNames.top ]: value } );
66 const onChangeRight = ( value ) => setAttributes( { [ attributeNames.right ]: value } );
67 const onChangeBottom = ( value ) => setAttributes( { [ attributeNames.bottom ]: value } );
68 const onChangeLeft = ( value ) => setAttributes( { [ attributeNames.left ]: value } );
69 const onChangeUnits = ( value ) => setAttributes( { [ [ attributeNames.unit ] ]: value } );
70 const onChangeAll = ( value ) => setAttributes( {
71 [ attributeNames.top ]: value,
72 [ attributeNames.right ]: value,
73 [ attributeNames.bottom ]: value,
74 [ attributeNames.left ]: value,
75 } );
76
77 const syncUnits = ( value ) => {
78 const numbers = [
79 attributes[ attributeNames.top ],
80 attributes[ attributeNames.right ],
81 attributes[ attributeNames.bottom ],
82 attributes[ attributeNames.left ],
83 ].filter( ( number ) => '' !== number );
84
85 if ( numbers.length === 0 ) {
86 setAttributes( {
87 [ value ]: ! attributes[ value ],
88 } );
89
90 return;
91 }
92
93 const syncValue = numbers.includes( 'auto' )
94 ? 'auto'
95 : Math.max.apply( null, numbers ).toString();
96
97 setAttributes( {
98 [ value ]: ! attributes[ value ],
99 [ attributeNames.top ]: syncValue,
100 [ attributeNames.right ]: syncValue,
101 [ attributeNames.bottom ]: syncValue,
102 [ attributeNames.left ]: syncValue,
103 } );
104 };
105
106 return (
107 <BaseControl className="components-gblocks-dimensions-control">
108 <UnitPicker
109 label={ label }
110 value={ 'undefined' !== typeof attributes[ attributeNames.unit ] ? attributes[ attributeNames.unit ] : 'px' }
111 units={ units }
112 onClick={ ( value ) => onChangeUnits( value ) }
113 />
114
115 <div className="components-gblocks-dimensions-control__inputs">
116 <div>
117 <input
118 id={ attributeNames.top }
119 className="components-gblocks-dimensions-control__number"
120 placeholder={ getResponsivePlaceholder(
121 attributeNames.top,
122 attributes,
123 device,
124 'margin' === type && 'px' === attributes.marginUnit
125 ? computedStyles.marginTop
126 : ''
127 ) }
128 type={ 'margin' === type ? 'text' : 'number' }
129 onChange={ ( event ) => {
130 let value = event.target.value;
131
132 if ( 'margin' !== type ) {
133 // No negative values allowed here.
134 value = value.toString().replace( /-/g, '' );
135 }
136
137 if ( 'margin' === type && value ) {
138 value = value.toString().toLowerCase();
139 }
140
141 if ( attributes[ attributeNames.sync ] ) {
142 onChangeAll( value );
143 } else {
144 onChangeTop( value );
145 }
146 } }
147 /* translators: Dimension label (padding, margin, border) */
148 aria-label={ sprintf( __( '%s Top', 'generateblocks' ), label ) }
149 value={ attributes[ attributeNames.top ] || '' }
150 min={ 'margin' !== type ? 0 : undefined }
151 />
152
153 <label htmlFor={ attributeNames.top } className="gblocks-dimensions-control__label">{ labels.top }</label>
154 </div>
155
156 <div>
157 <input
158 id={ attributeNames.right }
159 className="components-gblocks-dimensions-control__number"
160 placeholder={ getResponsivePlaceholder( attributeNames.right, attributes, device, '' ) }
161 type={ 'margin' === type ? 'text' : 'number' }
162 onChange={ ( event ) => {
163 let value = event.target.value;
164
165 if ( 'margin' !== type ) {
166 // No negative values allowed here.
167 value = value.toString().replace( /-/g, '' );
168 }
169
170 if ( 'margin' === type && value ) {
171 value = value.toString().toLowerCase();
172 }
173
174 if ( attributes[ attributeNames.sync ] ) {
175 onChangeAll( value );
176 } else {
177 onChangeRight( value );
178 }
179 } }
180 /* translators: Dimension label (padding, margin, border) */
181 aria-label={ sprintf( __( '%s Right', 'generateblocks' ), label ) }
182 value={ attributes[ attributeNames.right ] || '' }
183 min={ 'margin' !== type ? 0 : undefined }
184 />
185
186 <label htmlFor={ attributeNames.right } className="gblocks-dimensions-control__label">{ labels.right }</label>
187 </div>
188
189 <div>
190 <input
191 id={ attributeNames.bottom }
192 className="components-gblocks-dimensions-control__number"
193 placeholder={ getResponsivePlaceholder(
194 attributeNames.bottom,
195 attributes,
196 device,
197 'margin' === type && 'px' === attributes.marginUnit
198 ? computedStyles.marginBottom
199 : ''
200 ) }
201 type={ 'margin' === type ? 'text' : 'number' }
202 onChange={ ( event ) => {
203 let value = event.target.value;
204
205 if ( 'margin' !== type ) {
206 // No negative values allowed here.
207 value = value.toString().replace( /-/g, '' );
208 }
209
210 if ( 'margin' === type && value ) {
211 value = value.toString().toLowerCase();
212 }
213
214 if ( attributes[ attributeNames.sync ] ) {
215 onChangeAll( value );
216 } else {
217 onChangeBottom( value );
218 }
219 } }
220 /* translators: Dimension label (padding, margin, border) */
221 aria-label={ sprintf( __( '%s Bottom', 'generateblocks' ), label ) }
222 value={ attributes[ attributeNames.bottom ] || '' }
223 min={ 'margin' !== type ? 0 : undefined }
224 />
225
226 <label htmlFor={ attributeNames.bottom } className="gblocks-dimensions-control__label">{ labels.bottom }</label>
227 </div>
228
229 <div>
230 <input
231 id={ attributeNames.left }
232 className="components-gblocks-dimensions-control__number"
233 placeholder={ getResponsivePlaceholder( attributeNames.left, attributes, device, '' ) }
234 type={ 'margin' === type ? 'text' : 'number' }
235 onChange={ ( event ) => {
236 let value = event.target.value;
237
238 if ( 'margin' !== type ) {
239 // No negative values allowed here.
240 value = value.toString().replace( /-/g, '' );
241 }
242
243 if ( 'margin' === type && value ) {
244 value = value.toString().toLowerCase();
245 }
246
247 if ( attributes[ attributeNames.sync ] ) {
248 onChangeAll( value );
249 } else {
250 onChangeLeft( value );
251 }
252 } }
253 /* translators: Dimension label (padding, margin, border) */
254 aria-label={ sprintf( __( '%s Left', 'generateblocks' ), label ) }
255 value={ attributes[ attributeNames.left ] || '' }
256 min={ 'margin' !== type ? 0 : undefined }
257 />
258
259 <label htmlFor={ attributeNames.left } className="gblocks-dimensions-control__label">{ labels.left }</label>
260 </div>
261
262 <Tooltip text={ !! attributes[ attributeNames.sync ] ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) } >
263 <Button
264 className="components-gblocks-dimensions-control_sync"
265 aria-label={ !! attributes[ attributeNames.sync ] ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) }
266 isPrimary={ attributes[ attributeNames.sync ] ? attributes[ attributeNames.sync ] : false }
267 aria-pressed={ attributes[ attributeNames.sync ] ? attributes[ attributeNames.sync ] : false }
268 onClick={ () => syncUnits( attributeNames.sync ) }
269 isSmall
270 >
271 { !! attributes[ attributeNames.sync ] ? link : linkOff }
272 </Button>
273 </Tooltip>
274 </div>
275 </BaseControl>
276 );
277 }
278