PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.6.4.1
JetFormBuilder — Dynamic Blocks Form Builder v3.6.4.1
3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / modules / framework / blocks-style-manager / assets / src / components / control-component.jsx
jetformbuilder / modules / framework / blocks-style-manager / assets / src / components Last commit date
common 2 months ago controls 2 months ago control-component.jsx 2 months ago control-section.jsx 2 months ago control-stack.jsx 2 months ago
control-component.jsx
269 lines
1 import ControlText from './controls/text';
2 import ControlChoose from './controls/choose';
3 import ControlBorder from './controls/border';
4 import ControlColor from './controls/color';
5 import ControlTypography from './controls/typography';
6 import ControlDimensions from './controls/dimensions';
7 import ControlRange from './controls/range';
8 import ControlToggle from './controls/toggle';
9 import ControlHeading from './controls/heading';
10 import ControlsTabs from './common/controls-tabs';
11
12 import { useSelect } from '@wordpress/data';
13 import { getBreakpointsHierarchy } from '../helpers/breakpoints';
14 import { valueIsEmpty } from '../helpers/utils';
15 import { Tooltip } from '@wordpress/components';
16 import { isVisible, getContextFromProps } from '../helpers/conditions-checker';
17
18 /**
19 * Renders control depending on it's type and attach attributes handlers.
20 */
21 const ControlComponent = ( { control, props } ) => {
22
23 if ( control.condition && ! isVisible( control.condition, getContextFromProps( props ) ) ) {
24 return null;
25 }
26
27 const { attributes, setAttributes } = props;
28 const supportName = window.crocoStyleEditorData.support_name;
29
30 const prefixedName = ( name ) => {
31 return `__${ name.toLowerCase() }`
32 }
33
34 const device = useSelect(
35 ( select ) => {
36 const editPost = select( 'core/edit-post' );
37 let previewDevice = 'Desktop';
38
39 if ( editPost && typeof editPost.__experimentalGetPreviewDeviceType === 'function' ) {
40 previewDevice = editPost.__experimentalGetPreviewDeviceType();
41 }
42
43 return prefixedName( previewDevice );
44 }, []
45 );
46
47 const devicesHierarchy = getBreakpointsHierarchy();
48
49 // Check if the control has a value in the attributes
50 if ( ! attributes[ supportName ]?.[ control.id ] ) {
51 attributes[ supportName ][ control.id ] = control.defaultValue;
52 }
53
54 const findProp = ( obj, search ) => {
55
56 let result = null;
57
58 for ( const [ k, v ] of Object.entries( obj ) ) {
59 if ( v === search ) {
60 return k;
61 } else if ( 'object' === typeof v ) {
62 result = findProp( v, search );
63 if ( result ) {
64 break;
65 }
66 }
67 }
68
69 return result;
70 };
71
72 const maybeConvertFromReturnValue = ( value ) => {
73
74 if ( control.return_value ) {
75
76 let found = findProp( control.return_value, value );
77
78 if ( found ) {
79
80 value = found;
81
82 // convert string 'true'/'false' to boolean
83 if ( 'true' === value ) {
84 value = true;
85 } else if ( 'false' === value ) {
86 value = false;
87 }
88 }
89 }
90
91 return value;
92 };
93
94 const handleChange = ( value ) => {
95
96 if ( control.return_value ) {
97
98 if ( 'boolean' === typeof value ) {
99 if ( true === value ) {
100 value = control.return_value.true || null;
101 } else if ( false === value ) {
102 value = control.return_value.false || null;
103 } else {
104 value = null;
105 }
106 } else if ( 'string' === typeof value || 'number' === typeof value ) {
107 value = control.return_value?.[ value ] || null;
108 }
109 }
110
111 setStyleAttr( control.id, value );
112 };
113
114 const getResponsiveValue = ( attr ) => {
115 if ( '__desktop' === device ) {
116 return attributes[ supportName ][ attr ];
117 } else if ( attributes[ supportName ][ device ]?.[ attr ] ) {
118 return attributes[ supportName ][ device ][ attr ];
119 } else {
120
121 // If the value is not set for the current device - get previous device value
122 const currentDeviceIndex = devicesHierarchy.indexOf( device );
123 const prevDeviceIndex = currentDeviceIndex - 1;
124 const previousDevice = devicesHierarchy[ prevDeviceIndex ];
125
126 if ( prevDeviceIndex
127 && previousDevice
128 && attributes[ supportName ][ previousDevice ]?.[ attr ]
129 ) {
130 return attributes[ supportName ][ previousDevice ][ attr ];
131 }
132
133 // If no previous device value - return desktop value
134 return attributes[ supportName ][ attr ];
135 }
136 };
137
138 const usageMarker = () => {
139
140 const value = getResponsiveValue( control.id );
141
142 if ( control.default && control.default === value ) {
143 return null;
144 }
145
146 if ( valueIsEmpty( value ) ) {
147 return null;
148 }
149
150 let isUsedForCurrentDevice = false;
151 let tooltipText = 'Is inherited from the previous breakpoints';
152
153 // Check if the value is set for the current device
154 if ( '__desktop' === device
155 && ! valueIsEmpty( attributes[ supportName ][ control.id ] )
156 ) {
157 isUsedForCurrentDevice = true;
158 tooltipText = 'Explicitly set for the current device';
159 } else if ( ! valueIsEmpty( attributes[ supportName ]?.[ device ]?.[ control.id ] ) ) {
160 isUsedForCurrentDevice = true;
161 tooltipText = 'Explicitly set for the current device';
162 }
163
164 return (
165 <Tooltip
166 text={ tooltipText }
167 placement="top"
168 delay={ 300 }
169 >
170 <div className={ `crocoblock-style-manager__usage-marker is-${ isUsedForCurrentDevice ? 'used' : 'inherited' }` }></div>
171 </Tooltip>
172 );
173 }
174
175 const setStyleAttr = ( attr, value ) => {
176
177 let newStyles = {};
178
179 if ( '__desktop' === device ) {
180 newStyles = {
181 ...attributes[ supportName ],
182 [ attr ]: value,
183 };
184 } else {
185 newStyles = {
186 ...attributes[ supportName ],
187 [ device ]: {
188 ...attributes[ supportName ][ device ],
189 [ attr ]: value,
190 },
191 };
192 }
193
194 setAttributes( {
195 [ supportName ]: newStyles,
196 } );
197 };
198
199 const renderControl = () => {
200
201 const controlProps = {
202 control: control,
203 value: maybeConvertFromReturnValue( getResponsiveValue( control.id ) ),
204 handleChange: handleChange,
205 };
206
207 switch ( control.type ) {
208 case 'text':
209 return (
210 <ControlHeading { ...controlProps }/>
211 );
212 case 'input':
213 return (
214 <ControlText { ...controlProps }/>
215 );
216 case 'color-picker':
217 return (
218 <ControlColor { ...controlProps }/>
219 );
220 case 'toggle':
221 return (
222 <ControlToggle { ...controlProps }/>
223 );
224 case 'range':
225 return (
226 <ControlRange { ...controlProps }/>
227 );
228 case 'choose':
229 return (
230 <ControlChoose { ...controlProps }/>
231 );
232 case 'dimensions':
233 return (
234 <ControlDimensions { ...controlProps }/>
235 );
236 case 'border':
237 return (
238 <ControlBorder { ...controlProps }/>
239 );
240 case 'typography':
241 return (
242 <ControlTypography { ...controlProps }/>
243 );
244 case 'select':
245 return (
246 <></>
247 );
248 case 'tabs':
249 return (
250 <ControlsTabs
251 control={ control }
252 attributes={ attributes }
253 setAttributes={ setAttributes }
254 />
255 );
256 default:
257 return null;
258 }
259 };
260
261 return (
262 <div className={ `crocoblock-style-manager__control is-control--${ control.type }` }>
263 { usageMarker() }
264 { renderControl() }
265 </div>
266 );
267 };
268
269 export default ControlComponent;