PluginProbe
Booking Calendar / 11.6.1
Booking Calendar v11.6.1
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / page-form-builder / form-settings / _src / settings_effects.js

settings_effects.js in Booking Calendar 11.6.1, at includes/page-form-builder/form-settings/_src/settings_effects.js

1,303 lines 50.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Applies effects in Canvas, after changing some settings in the right sidebar in BFB.
3 *
4 * @file ../includes/page-form-builder/form-settings/_src/settings_effects.js
5 */
6 (function (w, d) {
7 'use strict';
8
9 const Effects = (w.WPBC_BFB_Settings_Effects = w.WPBC_BFB_Settings_Effects || {});
10 const map = (Effects.map = Effects.map || Object.create( null ));
11
12 Effects.register = function (key, fn) {
13 if ( key && typeof fn === 'function' ) {
14 map[String( key )] = fn;
15 }
16 };
17
18 function get_canvas_root() {
19 return (
20 d.querySelector( '#wpbc_bfb__pages_container' ) ||
21 d.querySelector( '.wpbc_bfb__panel--preview' ) ||
22 d.getElementById( 'wpbc_bfb__preview' ) ||
23 d.body || d.documentElement
24 );
25 }
26
27 Effects.apply_one = function (key, value, ctx) {
28 const fn = map[String( key )];
29 if ( ! fn ) {
30 return;
31 }
32 try {
33 fn( value, Object.assign( { key, value, canvas: get_canvas_root() }, ctx || {} ) );
34 } catch ( e ) {
35 // keep silent in production if you prefer
36 console.error( 'WPBC Effects error:', key, e );
37 }
38 };
39
40 Effects.apply_all = function (options, ctx) {
41 if ( ! options || typeof options !== 'object' ) {
42 return;
43 }
44 Object.keys( options ).forEach( function (k) {
45 Effects.apply_one( k, options[k], Object.assign( { options: options }, ctx || {} ) );
46 } );
47 };
48
49 /**
50 * Normalize settings pack to the minimum required shape:
51 * { options: {}, css_vars: {} }
52 *
53 * @param {*} pack
54 * @return {{options:Object, css_vars:Object, bfb_options?:Object}|null}
55 */
56 Effects.normalize_pack = function (pack) {
57
58 if ( pack === null || typeof pack === 'undefined' || pack === '' ) {
59 return null;
60 }
61
62 // Parse JSON string if needed.
63 if ( typeof pack === 'string' ) {
64 try {
65 pack = JSON.parse( pack );
66 } catch ( _e ) {
67 return null;
68 }
69 }
70
71 if ( ! pack || typeof pack !== 'object' ) {
72 return null;
73 }
74
75 // If user passed just {key:value} options map, wrap it.
76 const has_shape =
77 Object.prototype.hasOwnProperty.call( pack, 'options' ) ||
78 Object.prototype.hasOwnProperty.call( pack, 'css_vars' ) ||
79 Object.prototype.hasOwnProperty.call( pack, 'bfb_options' );
80
81 if ( ! has_shape ) {
82 pack = { options: pack, css_vars: {} };
83 }
84
85 if ( ! pack.options || typeof pack.options !== 'object' ) {
86 pack.options = {};
87 }
88 if ( ! pack.css_vars || typeof pack.css_vars !== 'object' ) {
89 pack.css_vars = {};
90 }
91
92 // bfb_options is optional; keep if valid.
93 if ( pack.bfb_options && typeof pack.bfb_options !== 'object' ) {
94 delete pack.bfb_options;
95 }
96
97 return pack;
98 };
99
100 /**
101 * Re-apply settings effects after a canvas rebuild / structure load.
102 *
103 * This is needed because structure loading can replace DOM nodes that effects target.
104 *
105 * @param {*} settings_pack string|object settings_json pack (or plain options map)
106 * @param {Object} [ctx]
107 */
108 Effects.reapply_after_canvas = function (settings_pack, ctx) {
109
110 const pack = Effects.normalize_pack( settings_pack );
111 if ( ! pack ) {
112 return;
113 }
114
115 // Apply immediately (best effort).
116 Effects.apply_all( pack.options, Object.assign( { source: 'reapply_after_canvas' }, ctx || {} ) );
117 wpbc_bfb_global_form_style__apply( null, Object.assign( { source: 'reapply_after_canvas' }, ctx || {} ) );
118
119 // Some modules/hydration may run shortly after; do one more pass.
120 setTimeout( function () {
121 Effects.apply_all( pack.options, Object.assign( { source: 'reapply_after_canvas_delayed' }, ctx || {} ) );
122 wpbc_bfb_global_form_style__apply( null, Object.assign( { source: 'reapply_after_canvas_delayed' }, ctx || {} ) );
123 }, 60 );
124 };
125
126 // 1) Apply from AJAX load.
127 d.addEventListener( 'wpbc:bfb:form_settings:apply', function (e) {
128 const pack = e && e.detail ? e.detail.settings : null;
129 if ( pack && pack.options ) {
130 Effects.apply_all( pack.options, { source: 'apply' } );
131 }
132 wpbc_bfb_global_form_style__apply( null, { source: 'apply-global-style' } );
133 } );
134
135 // 2) Apply live from UI change (delegated).
136 function css_escape(value) {
137 const v = String( value == null ? '' : value );
138 if ( w.CSS && typeof w.CSS.escape === 'function' ) {
139 return w.CSS.escape( v );
140 }
141 return v.replace( /[^a-zA-Z0-9_\-]/g, '\\$&' );
142 }
143
144 function find_fs_root(el) {
145 if ( ! el || ! el.closest ) {
146 return null;
147 }
148
149 // 1) Direct: element or ancestor carries FS key (input/select/textarea writer, radio wrapper, etc.)
150 const direct = el.closest( '[data-wpbc-bfb-fs-key]' );
151 if ( direct ) {
152 return direct;
153 }
154
155 // 2) Length: event came from number/unit/range inside .wpbc_slider_len_group
156 const len_group = el.closest( '.wpbc_slider_len_group' );
157 if ( len_group ) {
158 return (
159 len_group.querySelector( 'input[data-wpbc_slider_len_writer][data-wpbc-bfb-fs-key]' ) ||
160 len_group.querySelector( 'input[data-wpbc-bfb-fs-type="length"][data-wpbc-bfb-fs-key]' ) ||
161 null
162 );
163 }
164
165 // 3) Spacing: event came from vertical/horizontal number inside .wpbc_spacing_group.
166 const spacing_group = el.closest( '.wpbc_spacing_group' );
167 if ( spacing_group ) {
168 return (
169 spacing_group.querySelector( 'input[data-wpbc_spacing_writer][data-wpbc-bfb-fs-key]' ) ||
170 spacing_group.querySelector( 'input[data-wpbc-bfb-fs-type="spacing"][data-wpbc-bfb-fs-key]' ) ||
171 null
172 );
173 }
174
175 // 4) Range: event came from range input inside .wpbc_slider_range_group
176 const range_group = el.closest( '.wpbc_slider_range_group' );
177 if ( range_group ) {
178 return (
179 range_group.querySelector( 'input[data-wpbc_slider_range_writer][data-wpbc-bfb-fs-key]' ) ||
180 range_group.querySelector( 'input[data-wpbc_slider_range_writer]' ) ||
181 null
182 );
183 }
184
185 return null;
186 }
187
188 function read_value_from_fs_root(fs_root, original_target) {
189 if ( ! fs_root ) {
190 return '';
191 }
192
193 const fs_type = String( fs_root.getAttribute( 'data-wpbc-bfb-fs-type' ) || '' );
194
195 // RADIO: read checked within wrapper.
196 if ( fs_type === 'radio' ) {
197 const control_id = fs_root.getAttribute( 'data-wpbc-bfb-fs-controlid' ) || '';
198 const selector = control_id
199 ? 'input[type="radio"][name="' + css_escape( control_id ) + '"]:checked'
200 : 'input[type="radio"]:checked';
201
202 const checked = fs_root.querySelector( selector );
203 return checked ? String( checked.value || '' ) : '';
204 }
205
206 if ( fs_type === 'spacing' ) {
207 const group = ( original_target && original_target.closest ) ? original_target.closest( '.wpbc_spacing_group' ) : fs_root.closest( '.wpbc_spacing_group' );
208 const vertical_input = group ? group.querySelector( 'input[data-wpbc_spacing_vertical]' ) : null;
209 const horizontal_input = group ? group.querySelector( 'input[data-wpbc_spacing_horizontal]' ) : null;
210 const writer = group ? group.querySelector( 'input[data-wpbc_spacing_writer]' ) : null;
211 const vertical = vertical_input ? String( vertical_input.value || '0' ) : '0';
212 const horizontal = horizontal_input ? String( horizontal_input.value || vertical ) : vertical;
213 const combined = wpbc_bfb_form_appearance__normalize_spacing_numbers( vertical, horizontal );
214
215 if ( writer ) {
216 writer.value = combined;
217 }
218
219 return combined;
220 }
221
222 // CHECKBOX / TOGGLE
223 if ( (original_target && original_target.type === 'checkbox') || fs_root.type === 'checkbox' ) {
224 const cb = (original_target && original_target.type === 'checkbox') ? original_target : fs_root;
225 return cb.checked ? 'On' : 'Off';
226 }
227
228 // DEFAULT: writer/input/textarea/select
229 if ( fs_root.value != null ) {
230 return String( fs_root.value );
231 }
232 if ( original_target && original_target.value != null ) {
233 return String( original_target.value );
234 }
235
236 return '';
237 }
238
239 function apply_change_from_target(target, event_type, event_source) {
240 if ( ! target ) { return; }
241
242 const fs_root = find_fs_root( target );
243 if ( ! fs_root ) { return; }
244
245
246 // Normalize events so each control produces exactly one effect call.
247 // - toggle/select/radio/checkbox => "change" only.
248 // - everything else => "input" only.
249 const fs_type = String( fs_root.getAttribute( 'data-wpbc-bfb-fs-type' ) || '' );
250 const tag = String( target.tagName || '' ).toLowerCase();
251 const type = String( target.type || '' ).toLowerCase();
252
253 const use_change = (fs_type === 'toggle') || (fs_type === 'select') || (fs_type === 'radio') || (type === 'checkbox') || (type === 'radio') || (tag === 'select');
254
255 if ( use_change && event_type !== 'change' ) { return; }
256 if ( ! use_change && event_type !== 'input' ) { return; }
257 // -------------------------------------------------------------------------------------------
258
259 const key = fs_root.getAttribute( 'data-wpbc-bfb-fs-key' );
260 if ( ! key ) { return; }
261
262 const scope = fs_root.getAttribute( 'data-wpbc-bfb-fs-scope' ) || '';
263 const value = read_value_from_fs_root( fs_root, target );
264
265 Effects.apply_one( key, value, { source: event_source || 'ui', scope: scope, control: target, fs_root: fs_root } );
266 }
267
268 function is_coloris_control(target) {
269 if ( ! target || ! target.matches ) {
270 return false;
271 }
272
273 return target.matches( '[data-wpbc-bfb-fs-type="color"], [data-inspector-type="color"], .wpbc_bfb_coloris' );
274 }
275
276 function on_change(ev) {
277 // Ignore generic synthetic events dispatched by code (apply/reapply, slider sync, etc.).
278 // Coloris dispatches synthetic input events while the user picks a color, so allow those color controls through.
279 if ( ev && ev.isTrusted === false && ! is_coloris_control( ev.target ) ) { return; }
280 apply_change_from_target( ev && ev.target, ev && ev.type, ( ev && ev.isTrusted === false ) ? 'coloris' : 'ui' );
281 }
282
283 d.addEventListener( 'input', on_change, false );
284 d.addEventListener( 'change', on_change, false );
285 function on_coloris_pick(ev) {
286 const detail = ev && ev.detail ? ev.detail : {};
287 const target = detail.currentEl || detail.el || detail.input || ev.target || null;
288
289 if ( ! is_coloris_control( target ) ) {
290 return;
291 }
292
293 if ( detail.color && target.value !== detail.color ) {
294 target.value = detail.color;
295 }
296
297 apply_change_from_target( target, 'input', 'coloris' );
298 }
299 d.addEventListener( 'coloris:pick', on_coloris_pick, false );
300 d.addEventListener( 'wpbc:bfb:coloris:change', on_coloris_pick, false );
301
302 })( window, document );
303
304 function wpbc_bfb_form_appearance__get_presets() {
305 return {
306 bordered: {
307 background : '#ffffff',
308 borderColor: '#cccccc',
309 borderWidth: '1px',
310 radius : '2px',
311 padding : '10px 30px',
312 shadow : 'rgba(0, 0, 0, 0.05) 0px 2px 6px 0px'
313 },
314 none : {
315 background : 'transparent',
316 borderColor: 'transparent',
317 borderWidth: '0px',
318 radius : '0px',
319 padding : '0px',
320 shadow : 'none'
321 },
322 soft : {
323 background : '#f9f9fa',
324 borderColor: '#fff',
325 borderWidth: '3px',
326 radius : '8px',
327 padding : '20px',
328 shadow : 'rgba(15, 23, 42, 0.06) 0px 4px 16px 0px'
329 }
330 };
331 }
332
333 function wpbc_bfb_form_appearance__is_dark_theme(options) {
334 options = options && typeof options === 'object' ? options : {};
335 return 'wpbc_theme_dark_1' === String( options.booking_form_theme || '' );
336 }
337
338 function wpbc_bfb_form_appearance__get_preset_for_options(style, options) {
339 const presets = wpbc_bfb_form_appearance__get_presets();
340
341 if ( ! wpbc_bfb_form_appearance__is_dark_theme( options ) ) {
342 return presets[style] || presets.bordered;
343 }
344
345 if ( 'soft' === style ) {
346 return {
347 background : '#1f2937',
348 borderColor: '#334155',
349 borderWidth: '3px',
350 radius : '8px',
351 padding : '20px',
352 shadow : 'rgba(0, 0, 0, 0.24) 0px 4px 16px 0px'
353 };
354 }
355
356 return presets[style] || presets.bordered;
357 }
358
359 function wpbc_bfb_form_appearance__sanitize_color(value, fallback) {
360 const v = String( value == null ? '' : value ).trim();
361 if ( /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test( v ) ) {
362 return v;
363 }
364 if ( v === 'transparent' ) {
365 return v;
366 }
367 return fallback;
368 }
369
370 function wpbc_bfb_form_appearance__sanitize_optional_color(value) {
371 return wpbc_bfb_form_appearance__sanitize_color( value, '' );
372 }
373
374 /**
375 * Resolve an opaque accent color with the PHP-localized installation default.
376 *
377 * The Form Style effects live outside the registration IIFE, so the default is
378 * deliberately read from the shared localized payload at the point of use.
379 * Invalid requested and localized values return an empty string, allowing the
380 * caller to skip the accent overlay without throwing or producing invalid CSS.
381 *
382 * @param {*} value Requested accent color.
383 * @return {string} Valid three- or six-digit hexadecimal color, or an empty string.
384 */
385 function wpbc_bfb_global_form_style__sanitize_accent_color(value) {
386 const requested_color = String( value == null ? '' : value ).trim();
387 if ( /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test( requested_color ) ) {
388 return requested_color;
389 }
390
391 const settings_vars = window.wpbc_bfb_settings_vars && typeof window.wpbc_bfb_settings_vars === 'object'
392 ? window.wpbc_bfb_settings_vars
393 : {};
394 const accent_defaults = settings_vars.form_accent_defaults && typeof settings_vars.form_accent_defaults === 'object'
395 ? settings_vars.form_accent_defaults
396 : {};
397 const default_color = String( accent_defaults.booking_form_accent_color || '' ).trim();
398
399 return /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test( default_color ) ? default_color : '';
400 }
401
402 function wpbc_bfb_form_appearance__sanitize_length(value, fallback) {
403 const v = String( value == null ? '' : value ).trim();
404 if ( /^\d+(?:\.\d+)?(?:px|rem|em|%)$/i.test( v ) ) {
405 return v;
406 }
407 return fallback;
408 }
409
410 function wpbc_bfb_form_appearance__sanitize_spacing(value, fallback) {
411 const v = String( value == null ? '' : value ).trim().replace( /\s+/g, ' ' );
412 const parts = v ? v.split( ' ' ) : [];
413 if ( parts.length < 1 || parts.length > 4 ) {
414 return fallback;
415 }
416 for ( let i = 0; i < parts.length; i++ ) {
417 if ( ! /^\d+(?:\.\d+)?(?:px|rem|em|%)$/i.test( parts[i] ) ) {
418 return fallback;
419 }
420 }
421 return parts.join( ' ' );
422 }
423
424 function wpbc_bfb_form_appearance__normalize_spacing_numbers(vertical, horizontal) {
425 const v = String( vertical == null ? '' : vertical ).trim();
426 const h = String( horizontal == null ? '' : horizontal ).trim();
427 const vertical_num = /^\d+(?:\.\d+)?$/.test( v ) ? v : '0';
428 const horizontal_num = /^\d+(?:\.\d+)?$/.test( h ) ? h : vertical_num;
429
430 return vertical_num + 'px ' + horizontal_num + 'px';
431 }
432
433 function wpbc_bfb_form_appearance__collect_options(ctx, key, value) {
434 let options = (ctx && ctx.options && typeof ctx.options === 'object') ? Object.assign( {}, ctx.options ) : {};
435
436 if ( window.WPBC_BFB_FormSettings && typeof window.WPBC_BFB_FormSettings.collect === 'function' ) {
437 options = Object.assign( window.WPBC_BFB_FormSettings.collect( 'form' ) || {}, options );
438 }
439
440 if ( key ) {
441 options[String( key )] = value;
442 }
443
444 if ( wpbc_bfb_form_appearance__is_custom_control_key( key ) ) {
445 options.booking_form_container_style = 'custom';
446 wpbc_bfb_form_appearance__set_container_style_control( 'custom' );
447 }
448
449 return options;
450 }
451
452 function wpbc_bfb_form_appearance__get_custom_control_keys() {
453 return [
454 'booking_form_background_color',
455 'booking_form_border_color',
456 'booking_form_border_width',
457 'booking_form_border_radius',
458 'booking_form_padding',
459 'booking_form_text_color',
460 'booking_form_field_background_color',
461 'booking_form_field_text_color',
462 'booking_form_field_border_color'
463 ];
464 }
465
466 function wpbc_bfb_form_appearance__is_custom_control_key(key) {
467 return wpbc_bfb_form_appearance__get_custom_control_keys().indexOf( String( key || '' ) ) !== -1;
468 }
469
470 function wpbc_bfb_form_appearance__set_container_style_control(value) {
471 const control = document.querySelector( '[data-wpbc-bfb-fs-key="booking_form_container_style"]' );
472 if ( ! control || control.value === value ) {
473 return;
474 }
475
476 control.value = value;
477 }
478
479 function wpbc_bfb_form_appearance__set_radio_control(key, value) {
480 const row = document.querySelector( '.wpbc_bfb__form_setting[data-key="' + key + '"]' );
481 if ( ! row ) {
482 return;
483 }
484
485 const wrap = row.querySelector( '.wpbc_bfb__form_setting_radio[data-wpbc-bfb-fs-controlid]' );
486 const control_id = wrap ? String( wrap.getAttribute( 'data-wpbc-bfb-fs-controlid' ) || '' ) : '';
487 const radios = control_id
488 ? row.querySelectorAll( 'input[type="radio"][name="' + control_id + '"]' )
489 : row.querySelectorAll( 'input[type="radio"]' );
490
491 radios.forEach( function (radio) {
492 const should_check = ( String( radio.value ) === String( value == null ? '' : value ) );
493 radio.checked = should_check;
494
495 const choice = radio.closest ? radio.closest( '.wpbc_theme_choice' ) : null;
496 if ( choice ) {
497 choice.classList.toggle( 'is-selected', should_check );
498 }
499 } );
500 }
501
502 function wpbc_bfb_form_appearance__set_select_control(key, value) {
503 const control = document.querySelector( '[data-wpbc-bfb-fs-key="' + key + '"]' );
504 if ( control ) {
505 control.value = String( value == null ? '' : value );
506 }
507 }
508
509 function wpbc_bfb_form_appearance__get_current_options() {
510 return window.WPBC_BFB_FormSettings && typeof window.WPBC_BFB_FormSettings.collect === 'function'
511 ? window.WPBC_BFB_FormSettings.collect( 'form' ) || {}
512 : {};
513 }
514
515 function wpbc_bfb_form_appearance__get_style_value_from_options(options) {
516 options = options && typeof options === 'object' ? options : {};
517
518 const theme = String( options.booking_form_theme || '' );
519 const style = String( options.booking_form_container_style || 'inherit' );
520
521 if ( 'custom' === style ) {
522 return 'custom';
523 }
524 if ( 'inherit' === style || '' === style ) {
525 return 'inherit';
526 }
527
528 const prefix = ( 'wpbc_theme_dark_1' === theme ) ? 'dark' : 'light';
529 if ( [ 'bordered', 'none', 'soft' ].indexOf( style ) === -1 ) {
530 return prefix + '_bordered';
531 }
532
533 return prefix + '_' + style;
534 }
535
536 function wpbc_bfb_form_appearance__sync_form_style_control(options) {
537 wpbc_bfb_form_appearance__set_radio_control( 'booking_form_style', wpbc_bfb_form_appearance__get_style_value_from_options( options ) );
538 }
539
540 function wpbc_bfb_form_appearance__resolve_form_style_choice(value) {
541 const current_options = wpbc_bfb_form_appearance__get_current_options();
542 const current_theme = String( current_options.booking_form_theme || '' );
543 const choice = String( value || 'inherit' );
544
545 if ( 'custom' === choice ) {
546 return {
547 booking_form_theme : current_theme,
548 booking_form_container_style: 'custom'
549 };
550 }
551 if ( 'inherit' === choice || '' === choice ) {
552 return {
553 booking_form_theme : '',
554 booking_form_container_style: 'inherit'
555 };
556 }
557
558 const parts = choice.split( '_' );
559 const theme = ( 'dark' === parts[0] ) ? 'wpbc_theme_dark_1' : '';
560 const style = parts[1] || 'bordered';
561
562 return {
563 booking_form_theme : theme,
564 booking_form_container_style: ( [ 'bordered', 'none', 'soft' ].indexOf( style ) === -1 ) ? 'bordered' : style
565 };
566 }
567
568 function wpbc_bfb_form_appearance__is_user_theme_switch(ctx) {
569 const source = String( ctx && ctx.source ? ctx.source : '' );
570 return [ 'ui', 'coloris' ].indexOf( source ) !== -1;
571 }
572
573 function wpbc_bfb_form_appearance__is_custom_style(options) {
574 return String( options && options.booking_form_container_style ? options.booking_form_container_style : 'inherit' ) === 'custom';
575 }
576
577 function wpbc_bfb_form_appearance__sync_custom_controls(options) {
578 const is_custom = wpbc_bfb_form_appearance__is_custom_style( options );
579 const reset_row = document.querySelector( '[data-wpbc-bfb-custom-appearance-reset-row]' );
580 const base_theme_row = document.querySelector( '.wpbc_bfb__form_setting[data-key="booking_form_theme"]' );
581
582 wpbc_bfb_form_appearance__get_custom_control_keys().forEach( function (key) {
583 const row = document.querySelector( '.wpbc_bfb__form_setting[data-key="' + key + '"]' );
584 if ( ! row ) {
585 return;
586 }
587 row.hidden = ! is_custom;
588 row.setAttribute( 'aria-hidden', is_custom ? 'false' : 'true' );
589 row.classList.toggle( 'is-hidden', ! is_custom );
590 } );
591
592 if ( reset_row ) {
593 reset_row.hidden = ! is_custom;
594 reset_row.setAttribute( 'aria-hidden', is_custom ? 'false' : 'true' );
595 reset_row.classList.toggle( 'is-hidden', ! is_custom );
596 }
597
598 if ( base_theme_row ) {
599 base_theme_row.hidden = ! is_custom;
600 base_theme_row.setAttribute( 'aria-hidden', is_custom ? 'false' : 'true' );
601 base_theme_row.classList.toggle( 'is-hidden', ! is_custom );
602 }
603 }
604
605 function wpbc_bfb_form_appearance__resolve(options) {
606 let style = String( options.booking_form_container_style || 'inherit' );
607
608 if ( style === 'inherit' ) {
609 const global_options = window.wpbc_bfb_settings_vars && window.wpbc_bfb_settings_vars.global_appearance
610 ? window.wpbc_bfb_settings_vars.global_appearance
611 : {};
612 options = Object.assign( {}, global_options || {} );
613 style = String( options.booking_form_container_style || 'bordered' );
614 }
615
616 if ( style === 'bordered' ) {
617 return null;
618 }
619
620 if ( style !== 'custom' ) {
621 return wpbc_bfb_form_appearance__get_preset_for_options( style, options );
622 }
623
624 return {
625 background : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_background_color, '#ffffff' ),
626 borderColor: wpbc_bfb_form_appearance__sanitize_color( options.booking_form_border_color, '#cccccc' ),
627 borderWidth: wpbc_bfb_form_appearance__sanitize_length( options.booking_form_border_width, '1px' ),
628 radius : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_border_radius, '2px' ),
629 padding : wpbc_bfb_form_appearance__sanitize_spacing( options.booking_form_padding, '10px 30px' ),
630 shadow : 'rgba(0, 0, 0, 0.05) 0px 2px 6px 0px'
631 };
632 }
633
634 function wpbc_bfb_form_appearance__resolve_design_colors(options) {
635 options = options && typeof options === 'object' ? options : {};
636
637 if ( ! wpbc_bfb_form_appearance__is_custom_style( options ) ) {
638 if (
639 wpbc_bfb_form_appearance__is_dark_theme( options ) &&
640 'none' === String( options.booking_form_container_style || '' )
641 ) {
642 return {
643 textColor : '#1d2327',
644 fieldBackground: '',
645 fieldText : '',
646 fieldBorder : ''
647 };
648 }
649 return {
650 textColor : '',
651 fieldBackground: '',
652 fieldText : '',
653 fieldBorder : ''
654 };
655 }
656
657 return {
658 textColor : wpbc_bfb_form_appearance__sanitize_optional_color( options.booking_form_text_color ),
659 fieldBackground: wpbc_bfb_form_appearance__sanitize_optional_color( options.booking_form_field_background_color ),
660 fieldText : wpbc_bfb_form_appearance__sanitize_optional_color( options.booking_form_field_text_color ),
661 fieldBorder : wpbc_bfb_form_appearance__sanitize_optional_color( options.booking_form_field_border_color )
662 };
663 }
664
665 function wpbc_bfb_form_appearance__apply_vars(value, ctx) {
666 const options = wpbc_bfb_form_appearance__collect_options( ctx, ctx && ctx.key, value );
667 const resolved = wpbc_bfb_form_appearance__resolve( options );
668 const design = wpbc_bfb_form_appearance__resolve_design_colors( options );
669 const is_custom = wpbc_bfb_form_appearance__is_custom_style( options );
670 const root = ctx && ctx.canvas;
671
672 wpbc_bfb_form_appearance__sync_form_style_control( options );
673 wpbc_bfb_form_appearance__sync_custom_controls( options );
674
675 if ( ! root || ! root.querySelectorAll ) {
676 return;
677 }
678
679 const wraps = root.querySelectorAll( '.wpbc_bfb__form_preview_section_container, .wpbc_bfb_form' );
680 if ( ! wraps.length ) {
681 return;
682 }
683
684 wraps.forEach( function (wrap) {
685 if ( ! wrap || ! wrap.style ) {
686 return;
687 }
688 wrap.classList.toggle( 'wpbc_bfb_form_appearance_custom', is_custom );
689 if ( ! resolved ) {
690 wrap.style.removeProperty( '--wpbc-bfb-form-background' );
691 wrap.style.removeProperty( '--wpbc-bfb-form-border-color' );
692 wrap.style.removeProperty( '--wpbc-bfb-form-border-width' );
693 wrap.style.removeProperty( '--wpbc-bfb-form-border-radius' );
694 wrap.style.removeProperty( '--wpbc-bfb-form-padding' );
695 wrap.style.removeProperty( '--wpbc-bfb-form-box-shadow' );
696 } else {
697 wrap.style.setProperty( '--wpbc-bfb-form-background', resolved.background );
698 wrap.style.setProperty( '--wpbc-bfb-form-border-color', resolved.borderColor );
699 wrap.style.setProperty( '--wpbc-bfb-form-border-width', resolved.borderWidth );
700 wrap.style.setProperty( '--wpbc-bfb-form-border-radius', resolved.radius );
701 wrap.style.setProperty( '--wpbc-bfb-form-padding', resolved.padding );
702 wrap.style.setProperty( '--wpbc-bfb-form-box-shadow', resolved.shadow );
703 }
704
705 if ( design.textColor ) {
706 wrap.style.setProperty( '--wpbc_form-label-color', design.textColor );
707 wrap.style.setProperty( '--wpbc_form-label-sublabel-color', design.textColor );
708 } else {
709 wrap.style.removeProperty( '--wpbc_form-label-color' );
710 wrap.style.removeProperty( '--wpbc_form-label-sublabel-color' );
711 }
712
713 if ( design.fieldBackground ) {
714 wrap.style.setProperty( '--wpbc_form-field-background-color', design.fieldBackground );
715 wrap.style.setProperty( '--wpbc_form-field-menu-color', design.fieldBackground );
716 } else {
717 wrap.style.removeProperty( '--wpbc_form-field-background-color' );
718 wrap.style.removeProperty( '--wpbc_form-field-menu-color' );
719 }
720
721 if ( design.fieldText ) {
722 wrap.style.setProperty( '--wpbc_form-field-text-color', design.fieldText );
723 } else {
724 wrap.style.removeProperty( '--wpbc_form-field-text-color' );
725 }
726
727 if ( design.fieldBorder ) {
728 wrap.style.setProperty( '--wpbc_form-field-border-color', design.fieldBorder );
729 wrap.style.setProperty( '--wpbc_form-field-border-color-spare', design.fieldBorder );
730 } else {
731 wrap.style.removeProperty( '--wpbc_form-field-border-color' );
732 wrap.style.removeProperty( '--wpbc_form-field-border-color-spare' );
733 }
734 } );
735 }
736
737 function wpbc_bfb_global_form_style__get_vars() {
738 return window.wpbc_bfb_settings_vars || {};
739 }
740
741 function wpbc_bfb_global_form_style__get_presets() {
742 const vars = wpbc_bfb_global_form_style__get_vars();
743 return vars.form_style_presets && typeof vars.form_style_presets === 'object' ? vars.form_style_presets : {};
744 }
745
746 function wpbc_bfb_global_form_style__get_custom_keys() {
747 return [
748 'booking_form_custom_background_color',
749 'booking_form_custom_border_color',
750 'booking_form_custom_border_width',
751 'booking_form_custom_border_radius',
752 'booking_form_custom_padding_vertical',
753 'booking_form_custom_padding_horizontal',
754 'booking_form_custom_text_color',
755 'booking_form_custom_field_background_color',
756 'booking_form_custom_field_text_color',
757 'booking_form_custom_field_border_color',
758 'booking_form_custom_button_background_color',
759 'booking_form_custom_button_text_color',
760 'booking_form_custom_button_border_color',
761 'booking_form_custom_button_hover_background_color',
762 'booking_form_custom_button_hover_text_color',
763 'booking_form_custom_button_hover_border_color',
764 'booking_form_custom_secondary_button_background_color',
765 'booking_form_custom_secondary_button_text_color',
766 'booking_form_custom_secondary_button_border_color',
767 'booking_form_custom_secondary_button_hover_background_color',
768 'booking_form_custom_secondary_button_hover_text_color',
769 'booking_form_custom_secondary_button_hover_border_color',
770 'booking_form_custom_button_border_width',
771 'booking_form_custom_button_border_radius'
772 ];
773 }
774
775 function wpbc_bfb_global_form_style__get_custom_defaults() {
776 const vars = wpbc_bfb_global_form_style__get_vars();
777 const localized = vars.custom_form_style_defaults && typeof vars.custom_form_style_defaults === 'object'
778 ? vars.custom_form_style_defaults
779 : {};
780
781 return Object.assign( {
782 booking_form_custom_background_color : '#ffffff',
783 booking_form_custom_border_color : '#cccccc',
784 booking_form_custom_border_width : '1px',
785 booking_form_custom_border_radius : '2px',
786 booking_form_custom_padding_vertical : '10px',
787 booking_form_custom_padding_horizontal : '30px',
788 booking_form_custom_text_color : '#1d2327',
789 booking_form_custom_field_background_color : '#ffffff',
790 booking_form_custom_field_text_color : '#3c434a',
791 booking_form_custom_field_border_color : '#cccccc',
792 booking_form_custom_button_background_color: '#066aab',
793 booking_form_custom_button_text_color : '#ffffff',
794 booking_form_custom_button_border_color : '#066aab',
795 booking_form_custom_button_hover_background_color: '#055589',
796 booking_form_custom_button_hover_text_color: '#ffffff',
797 booking_form_custom_button_hover_border_color: '#055589',
798 booking_form_custom_secondary_button_background_color: '#fdfdfd',
799 booking_form_custom_secondary_button_text_color: '#444444',
800 booking_form_custom_secondary_button_border_color: '#eeeeee',
801 booking_form_custom_secondary_button_hover_background_color: '#fdfdfd',
802 booking_form_custom_secondary_button_hover_text_color: '#444444',
803 booking_form_custom_secondary_button_hover_border_color: '#4d91cd',
804 booking_form_custom_button_border_width : '1px',
805 booking_form_custom_button_border_radius : '3px'
806 }, localized );
807 }
808
809 function wpbc_bfb_global_form_style__get_current_options(ctx, key, value) {
810 const vars = wpbc_bfb_global_form_style__get_vars();
811 let options = vars.global_form_style && typeof vars.global_form_style === 'object'
812 ? Object.assign( {}, vars.global_form_style )
813 : {};
814
815 if ( window.WPBC_BFB_FormSettings && typeof window.WPBC_BFB_FormSettings.collect === 'function' ) {
816 options = Object.assign( options, window.WPBC_BFB_FormSettings.collect( 'global' ) || {} );
817 }
818
819 if ( ctx && ctx.options && typeof ctx.options === 'object' ) {
820 options = Object.assign( options, ctx.options );
821 }
822 if ( key ) {
823 options[String( key )] = value;
824 }
825 if ( ! options.booking_form_style ) {
826 options.booking_form_style = 'light_bordered';
827 }
828
829 return options;
830 }
831
832 function wpbc_bfb_global_form_style__mix_colors(color, target, amount) {
833 let source = wpbc_bfb_global_form_style__sanitize_accent_color( color ).replace( '#', '' );
834 const destination = wpbc_bfb_form_appearance__sanitize_color( target, '#000000' ).replace( '#', '' );
835 const channels = [];
836 if ( ! source ) {
837 return '';
838 }
839 if ( source.length === 3 ) {
840 source = source.replace( /./g, function (value) { return value + value; } );
841 }
842 for ( let index = 0; index < 3; index++ ) {
843 const source_channel = parseInt( source.substr( index * 2, 2 ), 16 );
844 const target_channel = parseInt( destination.substr( index * 2, 2 ), 16 );
845 channels.push( Math.round( source_channel + ( ( target_channel - source_channel ) * amount ) ) );
846 }
847 return '#' + channels.map( function (channel) { return ( '0' + channel.toString( 16 ) ).slice( -2 ); } ).join( '' );
848 }
849
850 function wpbc_bfb_global_form_style__get_luminance(color) {
851 let hex = wpbc_bfb_global_form_style__sanitize_accent_color( color ).replace( '#', '' );
852 if ( ! hex ) {
853 return 0;
854 }
855 if ( hex.length === 3 ) {
856 hex = hex.replace( /./g, function (value) { return value + value; } );
857 }
858 const channels = [ 0, 1, 2 ].map( function (index) {
859 const channel = parseInt( hex.substr( index * 2, 2 ), 16 ) / 255;
860 return channel <= 0.03928 ? channel / 12.92 : Math.pow( ( channel + 0.055 ) / 1.055, 2.4 );
861 } );
862 return ( 0.2126 * channels[0] ) + ( 0.7152 * channels[1] ) + ( 0.0722 * channels[2] );
863 }
864
865 /**
866 * Apply shared accent variables without masking explicit Custom button controls.
867 *
868 * @param {Object} css_vars Resolved base style variables.
869 * @param {Object} options Current global style options.
870 * @param {boolean} preserve_custom_button_colors Whether Custom button variables remain authoritative.
871 * @return {Object} Resolved variables with the optional accent overlay.
872 */
873 function wpbc_bfb_global_form_style__apply_accent(css_vars, options, preserve_custom_button_colors) {
874 if ( String( options.booking_form_accent_enabled || 'Off' ) !== 'On' ) {
875 return css_vars;
876 }
877 const accent = wpbc_bfb_global_form_style__sanitize_accent_color( options.booking_form_accent_color );
878 if ( ! accent ) {
879 return css_vars;
880 }
881 const luminance = wpbc_bfb_global_form_style__get_luminance( accent );
882 const contrast = luminance > 0.18 ? '#000000' : '#ffffff';
883 const hover_target = '#ffffff' === contrast ? '#000000' : '#ffffff';
884 const hover = wpbc_bfb_global_form_style__mix_colors( accent, hover_target, 0.10 );
885 const hover_contrast = contrast;
886
887 const accent_overlay = {
888 '--wpbc_form-accent-color': accent,
889 '--wpbc_form-accent-hover-color': hover,
890 '--wpbc_form-accent-contrast-color': contrast,
891 '--wpbc_form-field-focus-border-color': accent,
892 '--wpbc_form-field-focus-shadow-color': accent,
893 '--wpbc_form-choice-checked-border-color': accent,
894 '--wpbc_form-choice-checked-color': accent,
895 '--wpbc_form-choice-focus-color': accent,
896 '--wpbc_form-button-background-color': accent,
897 '--wpbc_form-button-background-color-alt': accent,
898 '--wpbc_form-button-border-color': accent,
899 '--wpbc_form-button-text-color': contrast,
900 '--wpbc_form-button-text-color-alt': contrast,
901 '--wpbc_form-button-hover-background-color': hover,
902 '--wpbc_form-button-hover-border-color': hover,
903 '--wpbc_form-button-hover-text-color': hover_contrast,
904 '--wpbc_form-button-light-hover-border-color': accent,
905 '--wpbc_form-button-primary-hover-border-color': hover,
906 '--wpbc_form-page-break-color': accent
907 };
908
909 if ( preserve_custom_button_colors ) {
910 [
911 '--wpbc_form-button-background-color',
912 '--wpbc_form-button-background-color-alt',
913 '--wpbc_form-button-border-color',
914 '--wpbc_form-button-text-color',
915 '--wpbc_form-button-text-color-alt',
916 '--wpbc_form-button-hover-background-color',
917 '--wpbc_form-button-hover-border-color',
918 '--wpbc_form-button-hover-text-color',
919 '--wpbc_form-button-light-hover-border-color',
920 '--wpbc_form-button-primary-hover-border-color'
921 ].forEach( function (css_var_name) {
922 delete accent_overlay[css_var_name];
923 } );
924 }
925
926 return Object.assign( {}, css_vars, accent_overlay );
927 }
928
929 function wpbc_bfb_global_form_style__resolve_css_vars(options) {
930 options = options && typeof options === 'object' ? options : {};
931 const style = String( options.booking_form_style || 'light_bordered' );
932 const presets = wpbc_bfb_global_form_style__get_presets();
933 const preset = presets[style] || presets.light_bordered || {};
934 const defaults = wpbc_bfb_global_form_style__get_custom_defaults();
935
936 if ( 'custom' !== style ) {
937 return wpbc_bfb_global_form_style__apply_accent( preset.css_vars && typeof preset.css_vars === 'object' ? Object.assign( {}, preset.css_vars ) : {}, options );
938 }
939
940 const css_vars = {
941 '--wpbc-bfb-form-background' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_background_color, defaults.booking_form_custom_background_color ),
942 '--wpbc-bfb-form-border-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_border_color, defaults.booking_form_custom_border_color ),
943 '--wpbc-bfb-form-border-width' : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_border_width, defaults.booking_form_custom_border_width ),
944 '--wpbc-bfb-form-border-radius' : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_border_radius, defaults.booking_form_custom_border_radius ),
945 '--wpbc-bfb-form-padding' : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_padding_vertical, defaults.booking_form_custom_padding_vertical ) + ' ' + wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_padding_horizontal, defaults.booking_form_custom_padding_horizontal ),
946 '--wpbc-bfb-form-box-shadow' : 'rgba(0, 0, 0, 0.05) 0px 2px 6px 0px',
947 '--wpbc_form-label-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_text_color, defaults.booking_form_custom_text_color ),
948 '--wpbc_form-label-sublabel-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_text_color, defaults.booking_form_custom_text_color ),
949 '--wpbc_form-label-error-color' : '#d63637',
950 '--wpbc_form-field-background-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_field_background_color, defaults.booking_form_custom_field_background_color ),
951 '--wpbc_form-field-menu-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_field_background_color, defaults.booking_form_custom_field_background_color ),
952 '--wpbc_form-field-text-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_field_text_color, defaults.booking_form_custom_field_text_color ),
953 '--wpbc_form-field-border-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_field_border_color, defaults.booking_form_custom_field_border_color ),
954 '--wpbc_form-field-border-color-spare': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_field_border_color, defaults.booking_form_custom_field_border_color ),
955 '--wpbc_form-field-focus-border-color': '#066aab',
956 '--wpbc_form-field-focus-shadow-color': '#066aab',
957 '--wpbc_form-field-disabled-color' : 'rgba(0, 0, 0, 0.2)',
958 '--wpbc_form-button-border-radius' : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_button_border_radius, defaults.booking_form_custom_button_border_radius ),
959 '--wpbc_form-button-border-style' : 'solid',
960 '--wpbc_form-button-border-size' : wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_button_border_width, defaults.booking_form_custom_button_border_width ),
961 '--wpbc_form-button-background-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_background_color, defaults.booking_form_custom_button_background_color ),
962 '--wpbc_form-button-background-color-alt': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_background_color, defaults.booking_form_custom_button_background_color ),
963 '--wpbc_form-button-border-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_border_color, defaults.booking_form_custom_button_border_color ),
964 '--wpbc_form-button-text-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_text_color, defaults.booking_form_custom_button_text_color ),
965 '--wpbc_form-button-text-color-alt' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_text_color, defaults.booking_form_custom_button_text_color ),
966 '--wpbc_form-button-hover-background-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_hover_background_color, defaults.booking_form_custom_button_hover_background_color ),
967 '--wpbc_form-button-hover-border-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_hover_border_color, defaults.booking_form_custom_button_hover_border_color ),
968 '--wpbc_form-button-hover-text-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_hover_text_color, defaults.booking_form_custom_button_hover_text_color ),
969 '--wpbc_form-choice-checked-border-color': '#066aab',
970 '--wpbc_form-choice-checked-color' : '#066aab',
971 '--wpbc_form-choice-focus-color' : '#066aab',
972 '--wpbc_form-button-light-background-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_background_color, defaults.booking_form_custom_secondary_button_background_color ),
973 '--wpbc_form-button-light-border-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_border_color, defaults.booking_form_custom_secondary_button_border_color ),
974 '--wpbc_form-button-light-border-size': wpbc_bfb_form_appearance__sanitize_length( options.booking_form_custom_button_border_width, defaults.booking_form_custom_button_border_width ),
975 '--wpbc_form-button-light-text-color' : wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_text_color, defaults.booking_form_custom_secondary_button_text_color ),
976 '--wpbc_form-button-light-box-shadow' : '0 2px 10px 2px #ffffff54',
977 '--wpbc_form-button-light-hover-background-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_hover_background_color, defaults.booking_form_custom_secondary_button_hover_background_color ),
978 '--wpbc_form-button-light-hover-border-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_hover_border_color, defaults.booking_form_custom_secondary_button_hover_border_color ),
979 '--wpbc_form-button-light-hover-text-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_secondary_button_hover_text_color, defaults.booking_form_custom_secondary_button_hover_text_color ),
980 '--wpbc_form-button-light-hover-box-shadow': '0 2px 10px 2px #ffffff54',
981 '--wpbc_form-button-primary-hover-border-color': wpbc_bfb_form_appearance__sanitize_color( options.booking_form_custom_button_hover_border_color, defaults.booking_form_custom_button_hover_border_color ),
982 '--wpbc_form-page-break-color' : '#066aab'
983 };
984
985 return wpbc_bfb_global_form_style__apply_accent( css_vars, options, true );
986 }
987
988 function wpbc_bfb_global_form_style__get_css_var_keys(options) {
989 const vars = wpbc_bfb_global_form_style__get_vars();
990 const localized = Array.isArray( vars.form_style_css_var_names ) ? vars.form_style_css_var_names : [];
991 const keys = [];
992 const presets = wpbc_bfb_global_form_style__get_presets();
993
994 if ( localized.length ) {
995 return localized;
996 }
997
998 Object.keys( presets ).forEach( function (preset_key) {
999 const preset = presets[preset_key] || {};
1000 const css_vars = preset.css_vars && typeof preset.css_vars === 'object' ? preset.css_vars : {};
1001
1002 Object.keys( css_vars ).forEach( function (var_name) {
1003 if ( keys.indexOf( var_name ) === -1 ) {
1004 keys.push( var_name );
1005 }
1006 } );
1007 } );
1008
1009 Object.keys( wpbc_bfb_global_form_style__resolve_css_vars( Object.assign( {}, options || {}, { booking_form_style: 'custom' } ) ) ).forEach( function (var_name) {
1010 if ( keys.indexOf( var_name ) === -1 ) {
1011 keys.push( var_name );
1012 }
1013 } );
1014
1015 return keys;
1016 }
1017
1018 function wpbc_bfb_global_form_style__sync_controls(options) {
1019 const is_custom = 'custom' === String( options && options.booking_form_style ? options.booking_form_style : '' );
1020 const accent_enabled = 'On' === String( options && options.booking_form_accent_enabled ? options.booking_form_accent_enabled : 'Off' );
1021 const reset_row = document.querySelector( '[data-wpbc-bfb-custom-appearance-reset-row]' );
1022
1023 wpbc_bfb_form_appearance__set_radio_control( 'booking_form_style', options.booking_form_style || 'light_bordered' );
1024
1025 document.querySelectorAll( '.wpbc_bfb__form_setting_global_custom_style' ).forEach( function (row) {
1026 row.hidden = ! is_custom;
1027 row.setAttribute( 'aria-hidden', is_custom ? 'false' : 'true' );
1028 row.classList.toggle( 'is-hidden', ! is_custom );
1029 } );
1030
1031 document.querySelectorAll( '.wpbc_bfb__form_setting_global_accent_dependent' ).forEach( function (row) {
1032 row.hidden = ! accent_enabled;
1033 row.setAttribute( 'aria-hidden', accent_enabled ? 'false' : 'true' );
1034 row.classList.toggle( 'is-hidden', ! accent_enabled );
1035 } );
1036
1037 if ( reset_row ) {
1038 reset_row.hidden = ! is_custom;
1039 reset_row.setAttribute( 'aria-hidden', is_custom ? 'false' : 'true' );
1040 reset_row.classList.toggle( 'is-hidden', ! is_custom );
1041 }
1042 }
1043
1044 function wpbc_bfb_global_form_style__apply(value, ctx) {
1045 const options = wpbc_bfb_global_form_style__get_current_options( ctx, ctx && ctx.key, value );
1046 const style = String( options.booking_form_style || 'light_bordered' );
1047 const presets = wpbc_bfb_global_form_style__get_presets();
1048 const preset = presets[style] || presets.light_bordered || {};
1049 const css_vars = wpbc_bfb_global_form_style__resolve_css_vars( options );
1050 // Form Style is global. Always start at the complete Builder theme scope so
1051 // inline Custom tokens on an outer wrapper cannot leak into a preset when a
1052 // field-level update provides only the inner canvas in ctx.canvas.
1053 const root = document.getElementById( 'wpbc_bfb__theme_scope' ) || ( ctx && ctx.canvas ) || document;
1054 const theme_classes = [];
1055 const css_var_keys = wpbc_bfb_global_form_style__get_css_var_keys( options );
1056
1057 wpbc_bfb_global_form_style__sync_controls( options );
1058
1059 Object.keys( presets ).forEach( function (preset_key) {
1060 const class_name = presets[preset_key] && presets[preset_key].theme_class ? String( presets[preset_key].theme_class ) : '';
1061 if ( class_name && theme_classes.indexOf( class_name ) === -1 ) {
1062 theme_classes.push( class_name );
1063 }
1064 } );
1065
1066 if ( ! root || ! root.querySelectorAll ) {
1067 return;
1068 }
1069
1070 const selector = '.wpbc_container.wpbc_form, .wpbc_bfb_form, .wpbc_bfb__pages_panel, .wpbc_bfb__form_preview_section_container';
1071 const wraps = [];
1072 if ( root.matches && root.matches( selector ) ) {
1073 wraps.push( root );
1074 }
1075 root.querySelectorAll( selector ).forEach( function (wrap) {
1076 wraps.push( wrap );
1077 } );
1078
1079 wraps.forEach( function (wrap) {
1080 if ( ! wrap || ! wrap.style ) {
1081 return;
1082 }
1083 theme_classes.forEach( function (class_name) {
1084 wrap.classList.remove( class_name );
1085 } );
1086 if ( preset.theme_class ) {
1087 wrap.classList.add( String( preset.theme_class ) );
1088 }
1089 wrap.classList.toggle( 'wpbc_bfb_form_appearance_custom', 'custom' === style );
1090
1091 css_var_keys.forEach( function (css_key) {
1092 wrap.style.removeProperty( css_key );
1093 } );
1094 Object.keys( css_vars ).forEach( function (css_key) {
1095 wrap.style.setProperty( css_key, css_vars[css_key] );
1096 } );
1097 } );
1098 }
1099
1100 [
1101 'booking_form_style',
1102 'booking_form_accent_enabled',
1103 'booking_form_accent_color',
1104 'booking_form_custom_background_color',
1105 'booking_form_custom_border_color',
1106 'booking_form_custom_border_width',
1107 'booking_form_custom_border_radius',
1108 'booking_form_custom_padding_vertical',
1109 'booking_form_custom_padding_horizontal',
1110 'booking_form_custom_text_color',
1111 'booking_form_custom_field_background_color',
1112 'booking_form_custom_field_text_color',
1113 'booking_form_custom_field_border_color',
1114 'booking_form_custom_button_background_color',
1115 'booking_form_custom_button_text_color',
1116 'booking_form_custom_button_border_color',
1117 'booking_form_custom_button_hover_background_color',
1118 'booking_form_custom_button_hover_text_color',
1119 'booking_form_custom_button_hover_border_color',
1120 'booking_form_custom_secondary_button_background_color',
1121 'booking_form_custom_secondary_button_text_color',
1122 'booking_form_custom_secondary_button_border_color',
1123 'booking_form_custom_secondary_button_hover_background_color',
1124 'booking_form_custom_secondary_button_hover_text_color',
1125 'booking_form_custom_secondary_button_hover_border_color',
1126 'booking_form_custom_button_border_width',
1127 'booking_form_custom_button_border_radius'
1128 ].forEach( function (key) {
1129 WPBC_BFB_Settings_Effects.register( key, function (value, ctx) {
1130 wpbc_bfb_global_form_style__apply( value, Object.assign( {}, ctx || {}, { key: key } ) );
1131 } );
1132 } );
1133
1134 function wpbc_bfb_form_appearance__sync_custom_controls_from_ui() {
1135 const options = wpbc_bfb_global_form_style__get_current_options();
1136 wpbc_bfb_global_form_style__sync_controls( options );
1137 wpbc_bfb_global_form_style__apply( null, { source: 'sync-global-style' } );
1138 }
1139
1140 wpbc_bfb_form_appearance__sync_custom_controls_from_ui();
1141 document.addEventListener( 'DOMContentLoaded', wpbc_bfb_form_appearance__sync_custom_controls_from_ui );
1142
1143
1144 // BOOKING_FORM_THEME.
1145 WPBC_BFB_Settings_Effects.register( 'booking_form_theme', function (value, ctx) {
1146 const root = (ctx && ctx.canvas) || document.getElementById( 'wpbc_bfb__theme_scope' ) || document;
1147 if ( ! root || ! root.querySelectorAll ) {
1148 return;
1149 }
1150
1151 if ( wpbc_bfb_form_appearance__is_user_theme_switch( ctx ) ) {
1152 const current_options = wpbc_bfb_form_appearance__get_current_options();
1153 if ( 'custom' === String( current_options.booking_form_container_style || '' ) ) {
1154 current_options.booking_form_theme = value;
1155 wpbc_bfb_form_appearance__sync_form_style_control( current_options );
1156 wpbc_bfb_form_appearance__apply_vars( 'custom', Object.assign( {}, ctx || {}, {
1157 key : 'booking_form_container_style',
1158 source : 'theme-base-custom',
1159 options: current_options
1160 } ) );
1161 } else {
1162 wpbc_bfb_form_appearance__set_container_style_control( 'bordered' );
1163 wpbc_bfb_form_appearance__apply_vars( 'bordered', Object.assign( {}, ctx || {}, { key: 'booking_form_container_style' } ) );
1164 }
1165 } else if ( ctx && ctx.options ) {
1166 wpbc_bfb_form_appearance__sync_form_style_control( ctx.options );
1167 }
1168
1169 const theme_selector = '.wpbc_container.wpbc_form, .wpbc_bfb_form, .wpbc_bfb__pages_panel';
1170 const wraps = [];
1171 if ( root.matches && root.matches( theme_selector ) ) {
1172 wraps.push( root );
1173 }
1174 root.querySelectorAll( theme_selector ).forEach( function (wrap) {
1175 wraps.push( wrap );
1176 } );
1177 if ( ! wraps.length ) {
1178 return;
1179 }
1180
1181 wraps.forEach( function (wrap) {
1182 // remove any previous theme classes (simple + future-proof).
1183 Array.from( wrap.classList ).forEach( function (cls) {
1184 if ( /^wpbc_theme_/.test( cls ) ) {
1185 wrap.classList.remove( cls );
1186 }
1187 } );
1188
1189 if ( value ) {
1190 wrap.classList.add( String( value ) );
1191 }
1192 } );
1193 } );
1194
1195
1196 // BOOKING_FORM_LAYOUT_WIDTH — Form width: applies combined "100%" / "600px" / "40rem" to the booking form containers.
1197 WPBC_BFB_Settings_Effects.register( 'booking_form_layout_width', function (value, ctx) {
1198 const root = ctx && ctx.canvas;
1199 if ( ! root || ! root.querySelectorAll ) {
1200 return;
1201 }
1202
1203 const wraps = root.querySelectorAll( '.wpbc_bfb__form_preview_section_container' );
1204 if ( ! wraps.length ) {
1205 return;
1206 }
1207
1208 const v = String( value == null ? '' : value ).trim();
1209
1210 // allow only "number + unit".
1211 if ( v && ! /^\d+(?:\.\d+)?(?:%|px|rem|em|vw|vh)$/.test( v ) ) {
1212 return;
1213 }
1214
1215 wraps.forEach(
1216 function (wrap) {
1217 if ( ! wrap || ! wrap.style ) {
1218 return;
1219 }
1220
1221 if ( ! v ) {
1222 wrap.style.removeProperty( '--wpbc-bfb-booking_form_layout_width' );
1223 } else {
1224 wrap.style.setProperty( '--wpbc-bfb-booking_form_layout_width', v );
1225 }
1226 }
1227 );
1228 } );
1229
1230
1231 // Debug Preview Mode.
1232 WPBC_BFB_Settings_Effects.register( 'booking_bfb_preview_mode', function (value, ctx) {
1233 const root = ctx.canvas;
1234 if ( ! root || ! root.querySelectorAll ) {
1235 return;
1236 }
1237
1238 const wraps = root.querySelectorAll( '.wpbc_container.wpbc_form' );
1239 if ( ! wraps.length ) {
1240 return;
1241 }
1242
1243 // Get builder async.
1244 wpbc_bfb_api.with_builder(
1245 function (Builder) {
1246
1247 /**
1248 * Capture active right sidebar tab and return restore handle.
1249 *
1250 * @return {{restore:function():void}|null}
1251 */
1252 function capture_right_sidebar_active_tab_restore_handle() {
1253
1254 var tablist_el = document.querySelector( '.wpbc_bfb__rightbar_tabs[role="tablist"]' );
1255 if ( ! tablist_el ) {
1256 return null;
1257 }
1258
1259 var active_tab_el = tablist_el.querySelector( '[role="tab"][aria-selected="true"]' );
1260
1261 if ( ! active_tab_el ) {
1262 active_tab_el = tablist_el.querySelector( '[role="tab"][aria-controls="wpbc_bfb__palette_add_new"]' );
1263 }
1264
1265 if ( ! active_tab_el || typeof active_tab_el.click !== 'function' ) {
1266 return null;
1267 }
1268
1269 return {
1270 restore: function () {
1271 try { active_tab_el.click(); } catch ( _e ) {}
1272 }
1273 };
1274 }
1275
1276 var tab_restore_handle = capture_right_sidebar_active_tab_restore_handle();
1277
1278 let restored = false;
1279 var EVS = window.WPBC_BFB_Core && window.WPBC_BFB_Core.WPBC_BFB_Events ? window.WPBC_BFB_Core.WPBC_BFB_Events : {};
1280 var EV_DONE = EVS.STRUCTURE_LOADED || EVS.CANVAS_REFRESHED || 'wpbc:bfb:structure-loaded';
1281
1282
1283 function do_restore() {
1284 if ( restored ) { return; }
1285 restored = true;
1286 try { Builder?.bus?.off?.( EV_DONE, do_restore ); } catch ( _ ) {}
1287 requestAnimationFrame( function () {
1288 if ( ! tab_restore_handle ) { return; }
1289 tab_restore_handle.restore();
1290 } );
1291 }
1292
1293 // Listen once (best), plus a fallback in case event isn't fired.
1294 try { Builder?.bus?.on?.( EV_DONE, do_restore ); } catch ( _ ) {}
1295
1296
1297 var enabled = ('On' === value);
1298 Builder.set_preview_mode( enabled, { rebuild: true, reinit: true, source: 'settings-effects' } );
1299 }
1300 );
1301
1302 } );
1303