PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.6.0
GenerateBlocks v1.6.0
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
attributes.js 4 years ago editor.scss 4 years ago index.js 4 years ago
index.js
260 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 = Math.max.apply( null, numbers ).toString();
94
95 setAttributes( {
96 [ value ]: ! attributes[ value ],
97 [ attributeNames.top ]: syncValue,
98 [ attributeNames.right ]: syncValue,
99 [ attributeNames.bottom ]: syncValue,
100 [ attributeNames.left ]: syncValue,
101 } );
102 };
103
104 return (
105 <BaseControl className="components-gblocks-dimensions-control">
106 <UnitPicker
107 label={ label }
108 value={ 'undefined' !== typeof attributes[ attributeNames.unit ] ? attributes[ attributeNames.unit ] : 'px' }
109 units={ units }
110 onClick={ ( value ) => onChangeUnits( value ) }
111 />
112
113 <div className="components-gblocks-dimensions-control__inputs">
114 <div>
115 <input
116 id={ attributeNames.top }
117 className="components-gblocks-dimensions-control__number"
118 placeholder={ getResponsivePlaceholder(
119 attributeNames.top,
120 attributes,
121 device,
122 'margin' === type && 'px' === attributes.marginUnit
123 ? computedStyles.marginTop
124 : ''
125 ) }
126 type="number"
127 onChange={ ( event ) => {
128 let value = event.target.value;
129
130 if ( 'margin' !== type ) {
131 // No negative values allowed here.
132 value = value.toString().replace( /-/g, '' );
133 }
134
135 if ( attributes[ attributeNames.sync ] ) {
136 onChangeAll( value );
137 } else {
138 onChangeTop( value );
139 }
140 } }
141 /* translators: Dimension label (padding, margin, border) */
142 aria-label={ sprintf( __( '%s Top', 'generateblocks' ), label ) }
143 value={ attributes[ attributeNames.top ] || '' }
144 min={ 'margin' !== type ? 0 : undefined }
145 />
146
147 <label htmlFor={ attributeNames.top } className="gblocks-dimensions-control__label">{ labels.top }</label>
148 </div>
149
150 <div>
151 <input
152 id={ attributeNames.right }
153 className="components-gblocks-dimensions-control__number"
154 placeholder={ getResponsivePlaceholder( attributeNames.right, attributes, device, '' ) }
155 type="number"
156 onChange={ ( event ) => {
157 let value = event.target.value;
158
159 if ( 'margin' !== type ) {
160 // No negative values allowed here.
161 value = value.toString().replace( /-/g, '' );
162 }
163
164 if ( attributes[ attributeNames.sync ] ) {
165 onChangeAll( value );
166 } else {
167 onChangeRight( value );
168 }
169 } }
170 /* translators: Dimension label (padding, margin, border) */
171 aria-label={ sprintf( __( '%s Right', 'generateblocks' ), label ) }
172 value={ attributes[ attributeNames.right ] || '' }
173 min={ 'margin' !== type ? 0 : undefined }
174 />
175
176 <label htmlFor={ attributeNames.right } className="gblocks-dimensions-control__label">{ labels.right }</label>
177 </div>
178
179 <div>
180 <input
181 id={ attributeNames.bottom }
182 className="components-gblocks-dimensions-control__number"
183 placeholder={ getResponsivePlaceholder(
184 attributeNames.bottom,
185 attributes,
186 device,
187 'margin' === type && 'px' === attributes.marginUnit
188 ? computedStyles.marginBottom
189 : ''
190 ) }
191 type="number"
192 onChange={ ( event ) => {
193 let value = event.target.value;
194
195 if ( 'margin' !== type ) {
196 // No negative values allowed here.
197 value = value.toString().replace( /-/g, '' );
198 }
199
200 if ( attributes[ attributeNames.sync ] ) {
201 onChangeAll( value );
202 } else {
203 onChangeBottom( value );
204 }
205 } }
206 /* translators: Dimension label (padding, margin, border) */
207 aria-label={ sprintf( __( '%s Bottom', 'generateblocks' ), label ) }
208 value={ attributes[ attributeNames.bottom ] || '' }
209 min={ 'margin' !== type ? 0 : undefined }
210 />
211
212 <label htmlFor={ attributeNames.bottom } className="gblocks-dimensions-control__label">{ labels.bottom }</label>
213 </div>
214
215 <div>
216 <input
217 id={ attributeNames.left }
218 className="components-gblocks-dimensions-control__number"
219 placeholder={ getResponsivePlaceholder( attributeNames.left, attributes, device, '' ) }
220 type="number"
221 onChange={ ( event ) => {
222 let value = event.target.value;
223
224 if ( 'margin' !== type ) {
225 // No negative values allowed here.
226 value = value.toString().replace( /-/g, '' );
227 }
228
229 if ( attributes[ attributeNames.sync ] ) {
230 onChangeAll( value );
231 } else {
232 onChangeLeft( value );
233 }
234 } }
235 /* translators: Dimension label (padding, margin, border) */
236 aria-label={ sprintf( __( '%s Left', 'generateblocks' ), label ) }
237 value={ attributes[ attributeNames.left ] || '' }
238 min={ 'margin' !== type ? 0 : undefined }
239 />
240
241 <label htmlFor={ attributeNames.left } className="gblocks-dimensions-control__label">{ labels.left }</label>
242 </div>
243
244 <Tooltip text={ !! attributes[ attributeNames.sync ] ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) } >
245 <Button
246 className="components-gblocks-dimensions-control_sync"
247 aria-label={ !! attributes[ attributeNames.sync ] ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) }
248 isPrimary={ attributes[ attributeNames.sync ] ? attributes[ attributeNames.sync ] : false }
249 aria-pressed={ attributes[ attributeNames.sync ] ? attributes[ attributeNames.sync ] : false }
250 onClick={ () => syncUnits( attributeNames.sync ) }
251 isSmall
252 >
253 { !! attributes[ attributeNames.sync ] ? link : linkOff }
254 </Button>
255 </Tooltip>
256 </div>
257 </BaseControl>
258 );
259 }
260