PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.8.2
GenerateBlocks v1.8.2
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 / extend / inspector-control / controls / borders / index.js
generateblocks / src / extend / inspector-control / controls / borders Last commit date
components 2 years ago BorderCSS.js 2 years ago attributes.js 2 years ago editor.scss 2 years ago index.js 2 years ago
index.js
243 lines
1 import { __ } from '@wordpress/i18n';
2 import PanelArea from '../../../../components/panel-area';
3 import getIcon from '../../../../utils/get-icon';
4 import { useContext, useState, useEffect } from '@wordpress/element';
5 import ControlsContext from '../../../../block-context';
6 import getDeviceType from '../../../../utils/get-device-type';
7 import useDeviceAttributes from '../../../../hooks/useDeviceAttributes';
8 import getResponsivePlaceholder from '../../../../utils/get-responsive-placeholder';
9 import DimensionsControl from '../../../../components/dimensions';
10 import { BaseControl, Tooltip, Button } from '@wordpress/components';
11 import FlexControl from '../../../../components/flex-control';
12 import UnitControl from '../../../../components/unit-control';
13 import './editor.scss';
14 import ColorPicker from '../../../../components/color-picker';
15 import StyleDropdown from './components/style-dropdown';
16 import { link, linkOff } from '@wordpress/icons';
17 import isNumeric from '../../../../utils/is-numeric';
18 import { isEqual, isEmpty } from 'lodash';
19
20 export default function Borders( { attributes, setAttributes } ) {
21 const device = getDeviceType();
22 const { id, supports: { borders: bordersPanel } } = useContext( ControlsContext );
23 const [ deviceAttributes, setDeviceAttributes ] = useDeviceAttributes( attributes, setAttributes );
24 const borderRadiusAttributes = [ 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomLeftRadius', 'borderBottomRightRadius' ];
25 const borderAreas = [ 'borderTop', 'borderRight', 'borderBottom', 'borderLeft' ];
26 const borderLabels = {
27 borderTop: __( 'Top', 'generateblocks' ),
28 borderRight: __( 'Right', 'generateblocks' ),
29 borderBottom: __( 'Bottom', 'generateblocks' ),
30 borderLeft: __( 'Left', 'generateblocks' ),
31 };
32 const [ sync, setSync ] = useState( false );
33
34 useEffect( () => {
35 const allValues = borderAreas.map( ( area ) => {
36 return Object.entries( deviceAttributes.borders ).reduce( ( newObject, [ key, value ] ) => {
37 if ( key.startsWith( area ) && value ) {
38 const newKey = key.replace( area, '' );
39
40 newObject = {
41 ...newObject,
42 [ newKey ]: value,
43 };
44 }
45
46 return newObject;
47 }, {} );
48 } );
49
50 if (
51 4 === allValues.length &&
52 allValues.every( ( obj ) => ! isEmpty( obj ) && isEqual( obj, allValues[ 0 ] ) )
53 ) {
54 setSync( true );
55 }
56 }, [] );
57
58 function manualSync() {
59 const areasWithWidth = borderAreas.filter( ( area ) => deviceAttributes.borders[ area + 'Width' ] || isNumeric( deviceAttributes.borders[ area + 'Width' ] ) );
60
61 if ( ! areasWithWidth.length ) {
62 return;
63 }
64
65 const firstArea = areasWithWidth[ 0 ];
66
67 const valuesToSync = Object.entries( deviceAttributes.borders ).reduce( ( newObject, [ key, value ] ) => {
68 if ( key.startsWith( firstArea ) ) {
69 const newKey = key.replace( firstArea, '' );
70 newObject[ newKey ] = value;
71 }
72
73 return newObject;
74 }, {} );
75
76 const newDeviceAttributes = Object.entries( valuesToSync ).reduce( ( newObject, [ key, value ] ) => {
77 borderAreas.forEach( ( area ) => {
78 newObject[ area + key ] = value;
79 } );
80
81 return newObject;
82 }, {} );
83
84 setDeviceAttributes( newDeviceAttributes, 'borders' );
85 }
86
87 return (
88 <PanelArea
89 title={ __( 'Borders', 'generateblocks' ) }
90 initialOpen={ false }
91 icon={ getIcon( 'borders' ) }
92 className="gblocks-panel-label"
93 id={ `${ id }Borders` }
94 >
95 { ( bordersPanel.borderTop || bordersPanel.borderRight || bordersPanel.borderBottom || bordersPanel.borderLeft ) &&
96 <BaseControl
97 label={ __( 'Border', 'generateblocks' ) }
98 id={ 'gblocks-borderTop-width' }
99 className="gblocks-border-row"
100 >
101 <Tooltip text={ !! sync ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) } >
102 <Button
103 className="components-gblocks-dimensions-control_sync"
104 aria-label={ !! sync ? __( 'Unlink Sides', 'generateblocks' ) : __( 'Link Sides', 'generateblocks' ) }
105 variant={ !! sync ? 'primary' : '' }
106 aria-pressed={ !! sync }
107 onClick={ () => {
108 setSync( ! sync );
109
110 if ( ! sync ) {
111 manualSync();
112 }
113 } }
114 >
115 { !! sync ? link : linkOff }
116 </Button>
117 </Tooltip>
118
119 { borderAreas.map( ( borderArea, areaIndex ) => {
120 if ( ! bordersPanel[ borderArea ] ) {
121 return null;
122 }
123
124 if ( sync && areaIndex > 0 ) {
125 return null;
126 }
127
128 const iconBorderStyle = !! sync
129 ? 'borderAll'
130 : borderArea;
131
132 return (
133 <FlexControl key={ borderArea }>
134 <Tooltip text={ !! sync ? __( 'All sides', 'generateblocks' ) : borderLabels[ borderArea ] }>
135 <div className={ 'gblocks-border-icon ' + iconBorderStyle } style={ { borderStyle: attributes.borders[ borderArea + 'Style' ] } }></div>
136 </Tooltip>
137
138 <UnitControl
139 id={ 'gblocks-' + borderArea + '-width' }
140 value={ deviceAttributes.borders[ borderArea + 'Width' ] || '' }
141 placeholder={ getResponsivePlaceholder( borderArea + 'Width', attributes.borders, device ) }
142 onChange={ ( value ) => {
143 const newAttributes = {
144 [ borderArea + 'Width' ]: value,
145 };
146
147 if ( sync ) {
148 newAttributes.borderRightWidth = value;
149 newAttributes.borderBottomWidth = value;
150 newAttributes.borderLeftWidth = value;
151 }
152
153 if ( ! value ) {
154 newAttributes[ borderArea + 'Style' ] = '';
155
156 if ( sync ) {
157 newAttributes.borderRightStyle = '';
158 newAttributes.borderBottomStyle = '';
159 newAttributes.borderLeftStyle = '';
160 }
161 } else if ( ! attributes.borders[ borderArea + 'Style' ] ) {
162 newAttributes[ borderArea + 'Style' ] = 'solid';
163
164 if ( sync ) {
165 newAttributes.borderRightStyle = 'solid';
166 newAttributes.borderBottomStyle = 'solid';
167 newAttributes.borderLeftStyle = 'solid';
168 }
169 }
170
171 setDeviceAttributes( newAttributes, 'borders' );
172 } }
173 />
174
175 <StyleDropdown
176 value={ deviceAttributes.borders[ borderArea + 'Style' ] || getResponsivePlaceholder( borderArea + 'Style', attributes.borders, device ) }
177 onChange={ ( value ) => {
178 const newAttributes = {
179 [ borderArea + 'Style' ]: value,
180 };
181
182 if ( sync ) {
183 newAttributes.borderRightStyle = value;
184 newAttributes.borderBottomStyle = value;
185 newAttributes.borderLeftStyle = value;
186 }
187
188 setDeviceAttributes( newAttributes, 'borders' );
189 } }
190 />
191
192 { !! bordersPanel.borderColors.length && 'Desktop' === device &&
193 <div className="gblocks-border-colors">
194 { bordersPanel.borderColors.map( ( borderColor, index ) => {
195 return (
196 <ColorPicker
197 key={ 'border' + index }
198 tooltip={ borderColor?.tooltip }
199 value={ attributes.borders[ borderArea + 'Color' + borderColor.state ] || '' }
200 alpha={ borderColor.alpha || false }
201 onChange={ ( nextBackgroundColor ) => {
202 const newAttributes = {
203 [ borderArea + 'Color' + borderColor.state ]: nextBackgroundColor,
204 };
205
206 if ( sync ) {
207 newAttributes[ 'borderRightColor' + borderColor.state ] = nextBackgroundColor;
208 newAttributes[ 'borderBottomColor' + borderColor.state ] = nextBackgroundColor;
209 newAttributes[ 'borderLeftColor' + borderColor.state ] = nextBackgroundColor;
210 }
211
212 setAttributes( {
213 borders: {
214 ...newAttributes,
215 },
216 } );
217 } }
218 />
219 );
220 } ) }
221 </div>
222 }
223 </FlexControl>
224 );
225 } ) }
226 </BaseControl>
227 }
228
229 { bordersPanel.borderRadius &&
230 <DimensionsControl
231 label={ __( 'Border Radius', 'generateblocks' ) }
232 attributeNames={ borderRadiusAttributes }
233 values={ deviceAttributes.borders }
234 placeholders={ borderRadiusAttributes.reduce( ( o, key ) => (
235 { ...o, [ key ]: getResponsivePlaceholder( key, attributes.borders, device, '' ) }
236 ), {} ) }
237 onChange={ ( values ) => setDeviceAttributes( values, 'borders' ) }
238 />
239 }
240 </PanelArea>
241 );
242 }
243