Changeset 3471571
- Timestamp:
- 02/28/2026 11:05:25 AM (11 days ago)
- Location:
- griffinforms-form-builder/trunk
- Files:
-
- 13 edited
-
admin/app/html/widgets/presentationarea/formcontrols/inputaddress.php (modified) (1 diff)
-
admin/css/app/griffinforms-app-formlayout.css (modified) (2 diffs)
-
admin/css/griffinforms-lists.css (modified) (1 diff)
-
admin/html/modals/deletelistitem.php (modified) (5 diffs)
-
admin/language/forms.php (modified) (2 diffs)
-
admin/language/lists.php (modified) (1 diff)
-
admin/language/messages.php (modified) (1 diff)
-
admin/language/submissions.php (modified) (1 diff)
-
admin/sql/format.php (modified) (1 diff)
-
blocks/gutenberg/index.js (modified) (6 diffs)
-
config.php (modified) (1 diff)
-
griffinforms.php (modified) (1 diff)
-
readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
griffinforms-form-builder/trunk/admin/app/html/widgets/presentationarea/formcontrols/inputaddress.php
r3394319 r3471571 48 48 echo '<div class="input-group gf-address-admin-city-postal">'; 49 49 echo '<div class="form-floating flex-grow-1">'; 50 echo '<input type="text" id="' . esc_attr($this->getFieldControlId('city')) . '" class="form-control gf-address-admin-city"' . $text_attributes . ' placeholder=" ">';50 echo '<input type="text" id="' . esc_attr($this->getFieldControlId('city')) . '" class="form-control gf-address-admin-city"' . $text_attributes . ' style="border-top-right-radius:0 !important;border-bottom-right-radius:0 !important;" placeholder=" ">'; 51 51 echo '<label>' . esc_html__('City', 'griffinforms-form-builder') . '</label>'; 52 52 echo '</div>'; 53 53 echo '<div class="form-floating gf-address-admin-postal">'; 54 echo '<input type="text" id="' . esc_attr($this->getFieldControlId('postal-code')) . '" class="form-control"' . $text_attributes . ' placeholder=" ">';54 echo '<input type="text" id="' . esc_attr($this->getFieldControlId('postal-code')) . '" class="form-control"' . $text_attributes . ' style="border-top-left-radius:0 !important;border-bottom-left-radius:0 !important;" placeholder=" ">'; 55 55 echo '<label>' . esc_html__('Postal Code', 'griffinforms-form-builder') . '</label>'; 56 56 echo '</div>'; -
griffinforms-form-builder/trunk/admin/css/app/griffinforms-app-formlayout.css
r3456321 r3471571 459 459 /* Adds animation to newly added form elements to make them standout. */ 460 460 .griffinforms-new-formelement { 461 animation: new-fe 2s ease-out; 462 } 463 464 @keyframes new-fe { 465 from {opacity: 0;} 466 to{opacity: 1;} 461 transform-origin: center top; 462 animation: gf-element-insert 560ms cubic-bezier(0.2, 0.85, 0.25, 1) both; 463 will-change: transform, opacity, box-shadow; 464 } 465 466 @keyframes gf-element-insert { 467 0% { 468 opacity: 0; 469 transform: translateY(8px) scale(0.97); 470 box-shadow: 0 0 0 0 var(--gf-color-primary-rgba-18); 471 } 472 45% { 473 opacity: 1; 474 transform: translateY(-2px) scale(1.01); 475 box-shadow: 0 0 0 3px var(--gf-color-primary-rgba-18); 476 } 477 100% { 478 opacity: 1; 479 transform: translateY(0) scale(1); 480 box-shadow: 0 0 0 0 var(--gf-color-primary-rgba-18); 481 } 482 } 483 484 @media (prefers-reduced-motion: reduce) { 485 .griffinforms-new-formelement { 486 animation: gf-element-insert-reduced 160ms ease-out both; 487 } 488 } 489 490 @keyframes gf-element-insert-reduced { 491 from { 492 opacity: 0; 493 } 494 to { 495 opacity: 1; 496 } 467 497 } 468 498 … … 743 773 .gf-address-admin-city-postal { 744 774 gap: 0; 745 } 746 747 .gf-address-admin-city-postal .gf-address-admin-city { 775 align-items: stretch; 776 } 777 778 .gf-address-admin-city-postal > .form-floating.flex-grow-1 > .gf-address-admin-city { 779 border-top-left-radius: var(--bs-border-radius, 0.375rem) !important; 780 border-bottom-left-radius: var(--bs-border-radius, 0.375rem) !important; 748 781 border-top-right-radius: 0 !important; 749 782 border-bottom-right-radius: 0 !important; 750 783 } 751 784 752 .gf-address-admin-city-postal .gf-address-admin-postal {785 .gf-address-admin-city-postal > .form-floating.gf-address-admin-postal { 753 786 flex: 0 0 200px; 754 787 } 755 788 756 .gf-address-admin-city-postal .gf-address-admin-postal.form-control {789 .gf-address-admin-city-postal > .form-floating.gf-address-admin-postal > .form-control { 757 790 border-top-left-radius: 0 !important; 758 791 border-bottom-left-radius: 0 !important; 792 border-top-right-radius: var(--bs-border-radius, 0.375rem) !important; 793 border-bottom-right-radius: var(--bs-border-radius, 0.375rem) !important; 794 } 795 796 .gf-address-admin-city-postal > .form-floating > .form-control:focus { 797 position: relative; 798 z-index: 2; 759 799 } 760 800 -
griffinforms-form-builder/trunk/admin/css/griffinforms-lists.css
r3394319 r3471571 29 29 .griffinforms-container .error a { 30 30 text-decoration: none !important; 31 } 32 33 .gf-delete-modal-alert { 34 border: 1px solid #f1aeb5; 35 background: #f8d7da; 36 color: #842029; 37 padding: 8px 10px; 38 border-radius: 6px; 39 font-size: 12px; 40 } 41 42 .gf-delete-modal-warning { 43 display: flex; 44 align-items: flex-start; 45 gap: 8px; 46 border: 1px solid #f1aeb5; 47 background: #fff5f5; 48 color: #842029; 49 border-radius: 8px; 50 padding: 10px; 51 } 52 53 .gf-delete-modal-warning .dashicons { 54 margin-top: 1px; 55 } 56 57 .gf-delete-modal-warning-title { 58 font-weight: 600; 59 line-height: 1.2; 60 } 61 62 .gf-delete-modal-warning-description { 63 margin-top: 2px; 64 font-size: 12px; 65 color: #8a3a44; 66 } 67 68 .gf-delete-modal-message { 69 color: #1d2327; 70 } 71 72 .gf-delete-modal-content label[for="gf-also-delete-entries"] { 73 display: inline-flex; 74 align-items: flex-start; 75 gap: 8px; 76 } 77 78 .gf-delete-modal-content #gf-also-delete-entries { 79 margin-top: 3px; 31 80 } 32 81 -
griffinforms-form-builder/trunk/admin/html/modals/deletelistitem.php
r3299683 r3471571 19 19 protected function modalContent() 20 20 { 21 echo '<div class="p-3 ">';21 echo '<div class="p-3 gf-delete-modal-content">'; 22 22 23 echo '<div class="mb- 2">';24 echo '<div class="modal-alert text-danger small mt-2" style="display:none;"></div>';23 echo '<div class="mb-3">'; 24 echo '<div class="modal-alert gf-delete-modal-alert" role="alert" style="display:none;"></div>'; 25 25 echo '</div>'; 26 26 27 echo '<div class="mb-2 fw-bold">'; 27 echo '<div class="gf-delete-modal-warning mb-3">'; 28 echo '<span class="dashicons dashicons-warning"></span>'; 29 echo '<div class="gf-delete-modal-warning-copy">'; 30 echo '<div class="gf-delete-modal-warning-title">' . esc_html__('This action cannot be undone.', 'griffinforms-form-builder') . '</div>'; 31 echo '<div class="gf-delete-modal-warning-description">' . esc_html__('Please confirm you want to continue.', 'griffinforms-form-builder') . '</div>'; 32 echo '</div>'; 33 echo '</div>'; 34 35 echo '<div class="mb-2 fw-semibold gf-delete-modal-message">'; 28 36 $this->confirmationText(); 29 37 echo '</div>'; 30 38 31 echo '<div class=" ">';39 echo '<div class="mt-3">'; 32 40 $this->additionalOptions(); 33 41 echo '</div>'; … … 53 61 echo '<div class="modal-footer border-top-0">'; 54 62 $this->cancelBtn(); 55 $this->ActionBtn('delete', ' primary');63 $this->ActionBtn('delete', 'danger'); 56 64 echo '</div>'; 57 65 } … … 66 74 67 75 modal.addEventListener("show.bs.modal", function (event) { 76 $(".modal-alert").hide().text(""); 68 77 $("#<?php echo esc_attr($this->action_btn_id); ?>").attr("data-bs-dismiss", ""); 69 78 const triggerElement = event.relatedTarget; 70 let itemId = parseInt(triggerElement.getAttribute("data-gf-id")); 79 if (!triggerElement) { 80 return; 81 } 82 let itemId = parseInt(triggerElement.getAttribute("data-gf-id"), 10); 71 83 $("#<?php echo esc_attr($this->action_btn_id); ?>").attr("data-gf-itemid", itemId); 72 84 … … 74 86 75 87 $("#<?php echo esc_js($this->action_btn_id); ?>").click(function() { 88 const $actionBtn = $(this); 89 if ($actionBtn.prop("disabled")) { 90 return; 91 } 92 $actionBtn.prop("disabled", true).text("<?php echo esc_js(__('Deleting...', 'griffinforms-form-builder')); ?>"); 76 93 let alsoDeleteSubmissions = 0; 77 94 … … 95 112 } else { 96 113 $(".modal-alert").text("<?php echo esc_js($this->lang->getText('delete_failed', 'modal_text')); ?>").show(); 114 $actionBtn.prop("disabled", false).text("<?php echo esc_js($this->lang->getText('delete', 'action_btn')); ?>"); 97 115 } 98 116 }).fail(function() { 99 117 $(".modal-alert").text("<?php echo esc_js($this->lang->getText('ajax_request_failed', 'modal_text')); ?>").show(); 118 $actionBtn.prop("disabled", false).text("<?php echo esc_js($this->lang->getText('delete', 'action_btn')); ?>"); 100 119 }); 101 120 }); -
griffinforms-form-builder/trunk/admin/language/forms.php
r3446601 r3471571 167 167 protected function deleteFormSubmissionsModalText() 168 168 { 169 return __('Also deletesubmissions for this form?', 'griffinforms-form-builder');169 return __('Also permanently delete all submissions for this form?', 'griffinforms-form-builder'); 170 170 } 171 171 … … 177 177 protected function deleteListItemModalText() 178 178 { 179 return __('D o you wish to delete this form? This action is irreversible.', 'griffinforms-form-builder');179 return __('Delete this form permanently? This action cannot be undone.', 'griffinforms-form-builder'); 180 180 } 181 181 -
griffinforms-form-builder/trunk/admin/language/lists.php
r3303055 r3471571 105 105 protected function deleteListItemModalText() 106 106 { 107 return __('D o you wish to delete this item? This action is irreversible.', 'griffinforms-form-builder');107 return __('Delete this item permanently? This action cannot be undone.', 'griffinforms-form-builder'); 108 108 } 109 109 -
griffinforms-form-builder/trunk/admin/language/messages.php
r3299683 r3471571 34 34 protected function deleteListItemModalText() 35 35 { 36 return __('D o you wish to delete this message? This action is irreversible.', 'griffinforms-form-builder');36 return __('Delete this message permanently? This action cannot be undone.', 'griffinforms-form-builder'); 37 37 } 38 38 -
griffinforms-form-builder/trunk/admin/language/submissions.php
r3455761 r3471571 132 132 protected function deleteListItemModalText() 133 133 { 134 return __('D o you wish to delete this form submission? This action is irreversible.', 'griffinforms-form-builder');134 return __('Delete this submission permanently? This action cannot be undone.', 'griffinforms-form-builder'); 135 135 } 136 136 -
griffinforms-form-builder/trunk/admin/sql/format.php
r3461374 r3471571 138 138 $update = $wpdb->update($table, $data, $where); 139 139 return $update; 140 } 141 142 /** 143 * Remove a child ID from a parent's serialized children column. 144 * 145 * Shared by delete cascade methods (formpage -> pagerow -> rowcolumn -> field). 146 * 147 * @param string $parent_type Parent item type/table key. 148 * @param int $parent_id Parent item ID. 149 * @param string $children_type Parent column that stores child IDs. 150 * @param int $child_id Child ID to remove from the list. 151 * @return bool True when relation is synchronized or parent is unavailable. 152 */ 153 protected function updateChildren($parent_type, $parent_id, $children_type, $child_id) 154 { 155 $parent_id = absint($parent_id); 156 $child_id = absint($child_id); 157 158 // When parent context is unavailable, nothing to sync. 159 if ($parent_id < 1) { 160 return true; 161 } 162 163 $children_ids_raw = $this->getItemValue($parent_id, $children_type, $parent_type); 164 $children_ids = $this->maybeDecode($children_ids_raw); 165 166 if (!is_array($children_ids)) { 167 $children_ids = array(); 168 } 169 170 $children_ids = array_values(array_filter(array_map('absint', $children_ids), static function ($id) { 171 return $id > 0; 172 })); 173 174 $updated_children = array_values(array_filter($children_ids, static function ($id) use ($child_id) { 175 return $id !== $child_id; 176 })); 177 178 $result = $this->updateItemValue($parent_type, $parent_id, $children_type, maybe_serialize($updated_children)); 179 return $result !== false; 140 180 } 141 181 -
griffinforms-form-builder/trunk/blocks/gutenberg/index.js
r3450618 r3471571 54 54 }; 55 55 56 const buildPreviewHtml = (structure, customSubmitLabel, activePage) => { 56 const scopeThemeCss = (themeCss, previewScopeClass) => { 57 if (!themeCss || !previewScopeClass) { 58 return themeCss || ''; 59 } 60 61 const scopedSelector = '.' + String(previewScopeClass); 62 return String(themeCss).replace(/\.griffinforms-block-preview\b/g, scopedSelector); 63 }; 64 65 const buildPreviewHtml = (structure, customSubmitLabel, activePage, previewScopeClass) => { 57 66 if (!structure || typeof structure !== 'object') { 58 67 return ''; … … 227 236 228 237 const formStyle = structure.form_style_css ? ' style="' + esc(structure.form_style_css) + '"' : ''; 229 const previewClass = 'griffinforms-block-preview' + (structure.theme_css ? ' gf-bp-theme' : ' gf-bp-no-theme') ;238 const previewClass = 'griffinforms-block-preview' + (structure.theme_css ? ' gf-bp-theme' : ' gf-bp-no-theme') + (previewScopeClass ? ' ' + previewScopeClass : ''); 230 239 let html = '<div class="' + previewClass + '"' + formStyle + '>'; 231 240 232 241 if (structure.theme_css) { 233 html += '<style class="gf-bp-theme">' + s tructure.theme_css+ '</style>';242 html += '<style class="gf-bp-theme">' + scopeThemeCss(structure.theme_css, previewScopeClass) + '</style>'; 234 243 } 235 244 … … 362 371 363 372 const FormBlockEdit = (props) => { 364 const { attributes, setAttributes } = props;373 const { attributes, setAttributes, clientId } = props; 365 374 const [forms, setForms] = useState([]); 366 375 const [loadingForms, setLoadingForms] = useState(true); … … 371 380 const [activePage, setActivePage] = useState(0); 372 381 const previewRef = useRef(null); 382 const previewScopeClass = 'gf-bp-scope-' + String(clientId || '').replace(/[^a-zA-Z0-9_-]/g, ''); 373 383 374 384 const blockProps = useBlockProps({ className: 'griffinforms-block-editor' }); … … 393 403 if (structure) { 394 404 const pageIndex = Math.min(activePage, Math.max(0, (structure.pages || []).length - 1)); 395 setPreviewHtml(buildPreviewHtml(structure, null, pageIndex ));405 setPreviewHtml(buildPreviewHtml(structure, null, pageIndex, previewScopeClass)); 396 406 ensureThemeFonts(structure.theme_fonts || []); 397 407 } 398 }, [structure, activePage ]);408 }, [structure, activePage, previewScopeClass]); 399 409 400 410 // Wire up navigation clicks inside the preview markup … … 448 458 setStructure(resp); 449 459 setActivePage(0); 450 setPreviewHtml(buildPreviewHtml(resp, null, 0 ));460 setPreviewHtml(buildPreviewHtml(resp, null, 0, previewScopeClass)); 451 461 const selected = (forms || []).find((f) => parseInt(f.id, 10) === parseInt(formId, 10)); 452 462 setAttributes({ -
griffinforms-form-builder/trunk/config.php
r3461374 r3471571 5 5 class Config 6 6 { 7 public const VERSION = '2.3. 2.0';8 public const DB_VER = '2.3. 2.0';7 public const VERSION = '2.3.3.0'; 8 public const DB_VER = '2.3.3.0'; 9 9 public const PHP_REQUIRED = '8.2'; 10 10 public const WP_REQUIRED = '6.2'; -
griffinforms-form-builder/trunk/griffinforms.php
r3461374 r3471571 4 4 * Plugin URI: https://griffinforms.com/ 5 5 * Description: A powerful and flexible form builder for WordPress. Create multi-page forms with drag-and-drop ease, custom validations, and full submission management. 6 * Version: 2.3. 2.06 * Version: 2.3.3.0 7 7 * Requires at least: 6.6 8 8 * Requires PHP: 8.2 -
griffinforms-form-builder/trunk/readme.txt
r3461374 r3471571 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.2 7 Stable tag: 2.3. 2.07 Stable tag: 2.3.3.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 174 174 == Changelog == 175 175 176 = 2.3.3.0 – 2026-02-28 = 177 * Fix: Isolated Gutenberg block preview theme CSS per block instance so multiple GriffinForms blocks on one page keep independent theme rendering. 178 * Fix: Corrected address field city/postal joined-input corner behavior in builder preview so adjoining borders remain square. 179 * Improvement: Refined list delete confirmation modals with clearer destructive-action hierarchy and improved guard/error behavior. 180 * Fix: Resolved bulk form delete fatal error by adding shared child-relation sync support used by delete cascades. 181 * Improvement: Replaced passive builder new-element fade with a clearer insertion animation and reduced-motion fallback. 182 176 183 = 2.3.2.0 – 2026-02-14 = 177 184 * Fix: Added themed/no-theme validation parity so invalid controls are clearly highlighted in themed frontend forms. … … 211 218 212 219 == Upgrade Notice == 220 221 = 2.3.3.0 = 222 Focused quality patch for Gutenberg multi-block theme isolation, address field joined-input edge consistency, delete-flow reliability, and clearer builder insertion feedback. Recommended update. 213 223 214 224 = 2.3.2.0 =
Note: See TracChangeset
for help on using the changeset viewer.