From 3db67b45ecec9604ae8349cd47322044622f2283 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 13 Oct 2026 16:39:24 +0000 Subject: [PATCH] feat(certificates): required form fields as their own list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settings → Certificates keeps the layout tags and, apart, a table of the fields every certificate form must have (name, label, type; default name, cpf_rf, email). Email cannot be removed. {{auth_code}} stays forced; {{schedule}} is asked only of a form with an Event Schedule. A new form starts with the table's fields; in the builder their name, type and required flag are locked, and a form missing one offers an "Add the required fields" button. The save handler forces the table's type. An install that never saved the table derives it from the old tag list, and keeps the schedule check until the tab is saved again. Refs #1741 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018srx5hc431EYmG4MHUr2KA --- CHANGELOG.md | 1 + assets/css/ffc-admin-settings.css | 14 ++ assets/css/ffc-admin-settings.min.css | 2 +- assets/js/ffc-admin-field-builder.js | 60 ++++++- assets/js/ffc-admin-field-builder.min.js | 2 +- assets/js/ffc-certificate-settings.js | 36 ++++ assets/js/ffc-certificate-settings.min.js | 2 + .../admin/class-ffc-admin-assets-manager.php | 1 + includes/admin/class-ffc-admin-ui.php | 4 +- .../class-ffc-form-editor-builder-metabox.php | 100 +++++++---- .../class-ffc-form-editor-save-handler.php | 17 +- .../class-ffc-form-editor-save-validator.php | 89 +++++----- includes/admin/class-ffc-form-editor.php | 23 +-- .../admin/class-ffc-settings-save-handler.php | 38 +++++ .../settings/class-ffc-settings-reader.php | 160 +++++++++++++++++- .../tabs/class-ffc-tab-certificates.php | 10 +- .../documentation/feature-certificates.php | 2 +- .../documentation/forms-dynamic-fields.php | 6 +- .../settings/views/ffc-tab-certificates.php | 92 +++++++++- languages/ffcertificate-pt_BR.l10n.php | 4 +- languages/ffcertificate-pt_BR.mo | Bin 971353 -> 972519 bytes languages/ffcertificate-pt_BR.po | 104 +++++++----- languages/ffcertificate.pot | 104 +++++++----- tests/Unit/FormEditorBuilderMetaboxTest.php | 72 +++++++- tests/Unit/FormEditorSaveHandlerTest.php | 21 ++- tests/Unit/RequiredCertificateFieldsTest.php | 57 +++++-- tests/Unit/SettingsReaderTest.php | 98 ++++++++++- tests/Unit/SettingsSaveHandlerTest.php | 40 +++++ .../undeclared-settings-keys-baseline.php | 1 + tests/js/admin-field-builder.test.js | 58 ++++++- tests/js/certificate-settings.test.js | 52 ++++++ 31 files changed, 1049 insertions(+), 221 deletions(-) create mode 100644 assets/js/ffc-certificate-settings.js create mode 100644 assets/js/ffc-certificate-settings.min.js create mode 100644 tests/js/certificate-settings.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 73932100d..75b9fe6d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format follows [Keep a Changelog] (https://keepachangelog.com/en/1.1.0/). - **The compiled `.l10n.php` is `wp i18n make-php`'s shape, byte for byte** (#1721). The compiler writes WP-CLI's `domain` and headers and an integer-like key bare, so a catalogue compiled here, saved from Loco or made by WP-CLI is the same file. - **Form fields follow the form's font, and Public Design offers Arial** (#1727). Fields, selects and buttons inherit the font the labels use instead of the browser's; the font choice is the theme's (default), the plugin's system font or Arial, as in Email Signature Generator and Institutional Email. - **Required certificate tags have their own Settings tab and protect their fields** (#1734). The list moved from Advanced to a new Certificates tab; the layout and template screens list the configured tags instead of a fixed three. A field a required tag calls for is amber, badged, always required, and cannot be renamed or removed; a form missing one is warned on save. +- **Required form fields are a list of their own** (#1741). Settings → Certificates keeps the layout tags and, apart, the fields every form needs with label and type (default `name`, `cpf_rf`, `email`; Email stays). New forms start with them, their type is locked, and the editor adds missing ones. ### Fixed diff --git a/assets/css/ffc-admin-settings.css b/assets/css/ffc-admin-settings.css index 910c4980f..1feae1371 100644 --- a/assets/css/ffc-admin-settings.css +++ b/assets/css/ffc-admin-settings.css @@ -1384,3 +1384,17 @@ html:has(.ffc-settings-back-to-top) { .widefat tfoot .ffc-location-new-field { padding: 0 var(--ffc-spacing-lg); } + +/* Settings → Certificates → Required Form Fields (#1741): the inputs fill + their cells instead of `.regular-text`'s fixed width, which pushed the + Type and Remove columns past the card. */ +.ffc-required-fields-table input[type="text"], +.ffc-required-fields-table select { + width: 100%; + max-width: none; +} + +.ffc-required-fields-table td:last-child { + width: 1%; + white-space: nowrap; +} diff --git a/assets/css/ffc-admin-settings.min.css b/assets/css/ffc-admin-settings.min.css index 711de51db..a5ff82081 100644 --- a/assets/css/ffc-admin-settings.min.css +++ b/assets/css/ffc-admin-settings.min.css @@ -1,2 +1,2 @@ -.ffc-settings-page,.ffc-settings-wrap{max-width:1500px}.card.ffc-danger-zone{border-left:4px solid var(--ffc-danger)}.card.ffc-danger-zone h2{color:var(--ffc-danger);border-bottom-color:var(--ffc-danger-light)}.ffc-settings-wrap .form-table{margin-top:0}.ffc-settings-wrap .form-table th{width:200px;padding:var(--ffc-spacing-xl) var(--ffc-spacing-md) var(--ffc-spacing-xl) 0;font-weight:600;vertical-align:top}.ffc-settings-wrap .form-table td{padding:var(--ffc-spacing-xl) var(--ffc-spacing-md)}.ffc-settings-wrap .form-table .description{margin-top:var(--ffc-spacing-sm);margin-bottom:0;font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted);line-height:1.5}.ffc-settings-wrap .form-table fieldset .description{margin-top:var(--ffc-spacing-2xs);margin-bottom:var(--ffc-spacing-xl);margin-left:25px}.ffc-settings-wrap .form-table .description.ffc-module-note{display:flex;align-items:flex-start;gap:var(--ffc-spacing-xs);margin-top:var(--ffc-spacing-xs);font-style:italic}.ffc-settings-wrap .form-table .description.ffc-module-note .ffc-icon-info{display:inline-flex;flex:0 0 auto}.ffc-settings-wrap .form-table .description.ffc-module-note .ffc-icon-info::before{margin-right:0}.ffc-stats-box{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary)}.ffc-stats-box table{width:100%;max-width:1000px;border-collapse:collapse}.ffc-stats-box tr{border-bottom:1px solid var(--ffc-border-light)}.ffc-stats-box tr:last-child{border-bottom:none}.ffc-stats-box tr.alternate{background:rgba(255,255,255,.6)}.ffc-stats-box td{padding:var(--ffc-spacing-lg) 0}.ffc-stats-box td:first-child{width:50%;font-weight:600}.ffc-stats-box .ffc-stat-value{font-family:'SF Mono',Monaco,Consolas,monospace}.ffc-stats-box .ffc-stat-value.ffc-stat-info{color:var(--ffc-primary);font-weight:600}.ffc-provider-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--ffc-spacing-xl);margin-top:var(--ffc-spacing-xl)}.ffc-provider-card{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary)}.ffc-provider-card.ffc-provider-gmail{border-left-color:var(--ffc-primary)}.ffc-provider-card.ffc-provider-outlook{border-left-color:#00a0d2}.ffc-provider-card.ffc-provider-sendgrid{border-left-color:#9b51e0}.ffc-provider-card h4{margin:0 0 var(--ffc-spacing-md) 0;font-size:var(--ffc-font-size-base);font-weight:600}.ffc-provider-card p{margin:var(--ffc-spacing-2xs) 0;font-size:var(--ffc-font-size-sm);line-height:1.4}.ffc-checkbox-group{margin:var(--ffc-spacing-xl) 0}.ffc-checkbox-group label{display:block;margin-bottom:var(--ffc-spacing-md)}.ffc-checkbox-group .ffc-checkbox-sublabel{color:var(--ffc-primary);font-weight:400;font-size:var(--ffc-font-size-sm);margin-left:var(--ffc-spacing-2xs)}.ffc-checkbox-group .description{margin-left:30px;margin-top:var(--ffc-spacing-2xs);font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted)}.ffc-collapsible-section{margin-top:var(--ffc-spacing-2xl)}.ffc-collapsible-content{padding:var(--ffc-spacing-xl)}.ffc-loglevel-table{border-collapse:collapse;margin:var(--ffc-spacing-2xs) 0 var(--ffc-spacing-sm)}.ffc-loglevel-table td{padding:0;border:1px solid var(--ffc-border-light);border-bottom:none}.ffc-loglevel-table tr:last-child td{border-bottom:1px solid var(--ffc-border-light)}.ffc-loglevel-label{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-xl);margin:0;cursor:pointer;min-width:320px}.ffc-loglevel-table tr:has( input[type=radio]:checked ),.ffc-loglevel-table tr:has( input[type=radio]:checked )~tr{background:var(--ffc-success-light)}.ffc-loglevel-table tr:has( input[type=radio]:checked ) .ffc-loglevel-name,.ffc-loglevel-table tr:has( input[type=radio]:checked )~tr .ffc-loglevel-name{color:var(--ffc-success);font-weight:600}.ffc-migration-card{margin-bottom:var(--ffc-spacing-2xl)}.ffc-migration-card .postbox-header{padding:var(--ffc-spacing-2xl) var(--ffc-spacing-2xl) var(--ffc-spacing-md)}.ffc-migration-card .postbox-header .hndle{margin:0;padding:0}.ffc-migration-card .inside{margin:0;padding:var(--ffc-spacing-xl) var(--ffc-spacing-2xl) var(--ffc-spacing-2xl)}.ffc-migration-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--ffc-spacing-xl);margin:var(--ffc-spacing-xl) 0}.ffc-migration-stat-label{font-size:var(--ffc-font-size-xs);color:var(--ffc-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:var(--ffc-spacing-2xs)}.ffc-migration-stat-value{font-size:var(--ffc-font-size-2xl);font-weight:700;font-family:'SF Mono',Monaco,Consolas,monospace;color:var(--ffc-text)}.ffc-migration-stat-value.ffc-migration-stat-success{color:var(--ffc-success)}.ffc-migration-stat-value.ffc-migration-stat-pending{color:var(--ffc-warning)}.ffc-migration-stat-value.ffc-migration-stat-info{color:var(--ffc-primary)}.ffc-migration-stat-note{font-size:var(--ffc-font-size-xs);color:var(--ffc-text-muted);margin-top:var(--ffc-spacing-2xs)}.ffc-migration-progress-bar{margin:var(--ffc-spacing-2xl) 0}.ffc-progress-bar-container{position:relative;width:100%;height:30px;background:var(--ffc-bg-alt);border-radius:15px;overflow:hidden}.ffc-progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--ffc-primary) 0,var(--ffc-primary-hover) 100%);transition:width .3s ease;position:relative}.ffc-progress-bar-fill.ffc-progress-complete{background:linear-gradient(90deg,var(--ffc-success) 0,var(--ffc-success-hover) 100%)}.ffc-progress-bar-fill.ffc-progress-pending{background:linear-gradient(90deg,var(--ffc-warning) 0,var(--ffc-warning-border) 100%)}.ffc-progress-bar-label{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-weight:600;font-size:var(--ffc-font-size-sm);white-space:nowrap}.ffc-progress-bar-label.ffc-progress-label-light{color:var(--ffc-text)}.ffc-progress-bar-label.ffc-progress-label-dark{color:var(--ffc-text-on-primary)}.ffc-migration-conflicts{margin-top:var(--ffc-spacing-lg);padding:var(--ffc-spacing-sm) var(--ffc-spacing-md);background:var(--ffc-warning-bg);border-left:3px solid var(--ffc-warning-border);border-radius:var(--ffc-radius-xs);color:var(--ffc-warning-text)}.ffc-migration-conflicts p{margin:0 0 var(--ffc-spacing-2xs)}.ffc-migration-conflicts p:last-child{margin-bottom:0}.ffc-migration-actions{margin-top:var(--ffc-spacing-2xl)}.ffc-migration-help{background:var(--ffc-bg-alt)}.ffc-rate-limit-wrap .card{margin-bottom:var(--ffc-spacing-2xl)}.ffc-rate-limit-wrap .card h2,.ffc-rate-limit-wrap h2{margin-top:0;margin-bottom:var(--ffc-spacing-md)}.ffc-rate-limit-wrap .card>p{margin-bottom:var(--ffc-spacing-xl)}.ffc-settings-wrap .button{margin-right:var(--ffc-spacing-md);margin-bottom:var(--ffc-spacing-2xs)}.ffc-settings-wrap .button:last-child{margin-right:0}@media screen and (max-width:782px){.ffc-migration-stats,.ffc-provider-grid{grid-template-columns:1fr}.ffc-settings-wrap .form-table th{width:auto;padding:var(--ffc-spacing-md) var(--ffc-spacing-md) 0 0;display:block}.ffc-settings-wrap .form-table td{padding:var(--ffc-spacing-md) 0;display:block}.ffc-stats-box table{font-size:var(--ffc-font-size-sm)}.ffc-migration-stat-value{font-size:var(--ffc-font-size-xl)}}@media screen and (max-width:1000px){.ffc-settings-wrap .card{padding:var(--ffc-spacing-xl)}.ffc-provider-card,.ffc-stats-box{padding:var(--ffc-spacing-xl)}}.ffc-admin-page .card,.ffc-collapsible-content,.ffc-progress-bar-fill,.ffc-provider-card{transition:all .2s cubic-bezier(.4, 0, .2, 1)}@media print{.ffc-settings-wrap .button{display:none}.ffc-admin-page .card{border:1px solid var(--ffc-text);box-shadow:none;break-inside:avoid}}.ffc-doc-toc{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary);margin:var(--ffc-spacing-2xl) 0}.ffc-doc-toc h3{margin-top:0;margin-bottom:var(--ffc-spacing-xl);color:var(--ffc-text)}.ffc-doc-toc input[type=search]{width:100%;max-width:100%;box-sizing:border-box}.ffc-doc-toc-list,.ffc-doc-toc-sublist{list-style:none;padding:0;margin:0}.ffc-doc-toc-list>li{margin:var(--ffc-spacing-3xs) 0}.ffc-doc-toc-sublist>li{margin:var(--ffc-spacing-3xs) 0}.ffc-doc-toc-sublist{padding-left:var(--ffc-spacing-xl);margin-left:var(--ffc-spacing-sm);border-left:1px solid var(--ffc-border-light)}.ffc-doc-toc-branch>details>summary{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg);cursor:pointer;border-radius:var(--ffc-radius-sm);background:var(--ffc-bg-card);border:1px solid var(--ffc-border);font-weight:500;color:var(--ffc-link);transition:background .15s ease,color .15s ease,border-color .15s ease;list-style:none;user-select:none}.ffc-doc-toc-branch>details>summary::-webkit-details-marker{display:none}.ffc-doc-toc-chevron{display:inline-flex;flex:0 0 auto;color:var(--ffc-text-muted)}.ffc-doc-toc-chevron::before{margin-right:0;transition:transform .15s ease}.ffc-doc-toc-branch>details[open]>summary .ffc-doc-toc-chevron::before{transform:rotate(90deg)}.ffc-doc-toc-branch>details>summary:hover{background:var(--ffc-primary);color:var(--ffc-text-on-primary);border-color:var(--ffc-primary)}.ffc-doc-toc-branch>details>summary:hover .ffc-doc-toc-chevron,.ffc-doc-toc-branch>details>summary:hover .ffc-doc-toc-icon{color:var(--ffc-text-on-primary)}.ffc-doc-toc-icon{display:inline-flex;flex:0 0 auto;font-size:var(--ffc-font-size-lg);line-height:1}.ffc-doc-toc-icon::before{margin-right:0}.ffc-doc-toc-branch>details>summary .ffc-doc-toc-icon{color:var(--ffc-primary)}.ffc-doc-toc-branch>details>summary .ffc-doc-toc-branch-label,.ffc-doc-toc-branch>details>summary a{color:inherit;text-decoration:none}.ffc-doc-toc-list li>a{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg);background:var(--ffc-bg-card);border-radius:var(--ffc-radius-sm);text-decoration:none;color:var(--ffc-link);font-weight:500;transition:background .15s ease,color .15s ease,border-color .15s ease;border:1px solid var(--ffc-border)}.ffc-doc-toc-list li>a .ffc-doc-toc-icon{color:var(--ffc-text-muted)}.ffc-doc-toc-list li>a:hover{background:var(--ffc-primary);color:var(--ffc-text-on-primary);border-color:var(--ffc-primary)}.ffc-doc-toc-list li>a:hover .ffc-doc-toc-icon{color:var(--ffc-text-on-primary)}.ffc-doc-example{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);margin:var(--ffc-spacing-2xl) 0;border-left:4px solid var(--ffc-success)}.ffc-doc-example h4{margin-top:0;margin-bottom:var(--ffc-spacing-md);color:var(--ffc-success);font-size:var(--ffc-font-size-base);font-weight:600}.ffc-doc-example pre{background:#1e1e1e;color:#d4d4d4;padding:var(--ffc-spacing-xl);border-radius:var(--ffc-radius-sm);overflow-x:auto;margin:var(--ffc-spacing-md) 0;font-family:'SF Mono',Monaco,Consolas,monospace;font-size:var(--ffc-font-size-sm);line-height:1.5}.ffc-doc-example code{background:0 0;color:inherit;padding:0}.ffc-doc-example ul{margin:var(--ffc-spacing-md) 0 0 var(--ffc-spacing-2xl)}.ffc-admin-page code{background:var(--ffc-bg-alt);padding:3px var(--ffc-spacing-xs);border-radius:var(--ffc-radius-xs);font-family:'SF Mono',Monaco,Consolas,monospace;font-size:var(--ffc-font-size-sm);color:var(--ffc-danger-text);border:1px solid var(--ffc-border-light)}.ffc-admin-page pre code{background:0 0;border:none;padding:0;color:inherit}.ffc-doc-list{list-style:none;padding:0}.ffc-doc-list li{padding:var(--ffc-spacing-md) 0 var(--ffc-spacing-md) 30px;border-bottom:1px solid var(--ffc-border-light);position:relative}.ffc-doc-list li:last-child{border-bottom:none}.ffc-doc-list li::before{content:"✓";position:absolute;left:0;color:var(--ffc-success);font-weight:700;font-size:var(--ffc-font-size-lg)}.ffc-alert{padding:var(--ffc-spacing-xl) var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);margin:var(--ffc-spacing-2xl) 0;border-left:4px solid}.ffc-alert p{margin:0}.ffc-alert-info{background:var(--ffc-info-bg);border-color:var(--ffc-info-border);color:var(--ffc-info-text)}.ffc-settings-wrap .widefat{border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm);overflow:hidden}.ffc-settings-wrap .widefat thead th{background:var(--ffc-bg-alt);font-weight:600;padding:var(--ffc-spacing-lg)}.ffc-settings-wrap .widefat tbody td{padding:var(--ffc-spacing-lg);border-bottom:1px solid var(--ffc-border-light)}.ffc-settings-wrap .widefat tbody tr:last-child td{border-bottom:none}.ffc-settings-wrap .widefat code{font-size:var(--ffc-font-size-xs)}.ffc-settings-wrap .card h3[id]{scroll-margin-top:20px}.ffc-settings-wrap .card h3[id]{--ffc-icon-tone:var(--ffc-primary)}.ffc-doc-topics .card td a{text-decoration:underline}@media screen and (max-width:782px){.ffc-doc-example pre{font-size:var(--ffc-font-size-xs);padding:var(--ffc-spacing-md)}}@media (prefers-reduced-motion:reduce){.ffc-admin-page .card,.ffc-collapsible-content,.ffc-doc-toc-branch>details>summary::before,.ffc-doc-toc-list li>a,.ffc-progress-bar-fill,.ffc-provider-card{transition:none}}.ffc-settings-tab-content{max-width:1500px}.ffc-settings-tabs{display:flex;align-items:stretch;margin-top:var(--ffc-spacing-2xl);background:var(--ffc-bg-card);border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm);box-shadow:var(--ffc-shadow-sm);overflow:clip}.ffc-settings-tabs__nav{flex:0 0 220px;margin:0;padding:0;list-style:none;background:var(--ffc-bg-alt);border-right:1px solid var(--ffc-border)}.ffc-settings-tabs__nav-item{margin:0}.ffc-settings-tabs__tab{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-lg) var(--ffc-spacing-xl);color:var(--ffc-text);text-decoration:none;border-left:4px solid transparent;line-height:1.3;transition:background .15s ease,color .15s ease,border-color .15s ease}.ffc-settings-tabs__tab:focus,.ffc-settings-tabs__tab:hover{background:var(--ffc-primary-light);color:var(--ffc-primary);box-shadow:none}.ffc-settings-tabs__tab:focus-visible{outline:2px solid var(--ffc-primary);outline-offset:-2px}.ffc-settings-tabs__tab.is-active{background:var(--ffc-bg-card);color:var(--ffc-primary);border-left-color:var(--ffc-primary);font-weight:600}.ffc-settings-tabs__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;filter:grayscale(1)}.ffc-settings-tabs__nav .ffc-settings-tabs__icon::before{margin-right:0}.ffc-settings-tabs__label{flex:1 1 auto}.ffc-settings-tabs__group{list-style:none}.ffc-settings-tabs__group-label{display:block;padding:var(--ffc-spacing-lg) var(--ffc-spacing-lg) var(--ffc-spacing-2xs);font-size:var(--ffc-font-size-2xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ffc-text-muted)}.ffc-settings-tabs__nav>.ffc-settings-tabs__group:first-child .ffc-settings-tabs__group-label{padding-top:var(--ffc-spacing-xs)}.ffc-settings-tabs__external{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;opacity:.55}.ffc-settings-tabs__panel{flex:1 1 auto;min-width:0;padding:var(--ffc-spacing-2xs) var(--ffc-spacing-2xl) var(--ffc-spacing-2xl);animation:ffc-tab-fade-in .2s ease-out}@keyframes ffc-tab-fade-in{from{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}@media screen and (max-width:782px){.ffc-settings-tabs{flex-direction:column}.ffc-settings-tabs__nav{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:0;border-right:none;border-bottom:1px solid var(--ffc-border)}.ffc-settings-tabs__tab{border-left:none;border-bottom:3px solid transparent;padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg)}.ffc-settings-tabs__tab.is-active{border-left:none;border-bottom-color:var(--ffc-primary)}.ffc-settings-tabs__group{flex:0 0 100%}.ffc-settings-tabs__group-label{padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg) 0}}@media (prefers-reduced-motion:reduce){.ffc-settings-tabs__panel,.ffc-settings-tabs__tab{transition:none;animation:none}}.ffc-settings-tabs__nav .ffc-settings-tabs__icon{font-size:20px;line-height:1}.ffc-settings-tabs__nav .ffc-settings-tabs__external::before,.ffc-settings-tabs__nav .ffc-settings-tabs__icon::before{margin-right:0}.ffc-settings-tabs__nav .ffc-settings-tabs__external{font-size:var(--ffc-font-size-sm)}@media screen and (min-width:1280px){.ffc-doc-layout{display:grid;grid-template-columns:280px minmax(0,1fr);column-gap:var(--ffc-spacing-2xl);align-items:start}.ffc-doc-toc{position:sticky;top:calc(var(--wp-admin--admin-bar--height,32px) + var(--ffc-spacing-xl));z-index:var(--ffc-z-sticky);max-height:calc(100vh - var(--wp-admin--admin-bar--height,32px) - 2 * var(--ffc-spacing-xl));overflow-y:auto}}.ffc-settings-back-to-top{position:fixed;right:24px;bottom:24px;z-index:9999;display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border-radius:var(--ffc-radius-full);background:var(--ffc-primary);color:var(--ffc-text-on-primary);text-decoration:none;box-shadow:var(--ffc-shadow-md);opacity:.85;transition:opacity .2s ease,transform .2s ease}.ffc-settings-back-to-top:focus,.ffc-settings-back-to-top:hover{opacity:1;color:var(--ffc-text-on-primary);transform:translateY(-2px)}.ffc-settings-back-to-top:focus-visible{outline:2px solid var(--ffc-border-focus);outline-offset:2px}.ffc-settings-back-to-top .ffc-icon-chevron-up{font-size:var(--ffc-font-size-xl);line-height:1}.ffc-settings-back-to-top .ffc-icon-chevron-up::before{margin-right:0}html:has(.ffc-settings-back-to-top){scroll-behavior:smooth}@media (prefers-reduced-motion:reduce){html:has(.ffc-settings-back-to-top){scroll-behavior:auto}.ffc-settings-back-to-top{transition:none}}.ffc-set-my-10{margin:var(--ffc-spacing-md) 0}.ffc-set-my-12{margin:var(--ffc-spacing-lg) 0}.ffc-set-mt-10{margin-top:var(--ffc-spacing-md)}.ffc-set-mt-18{margin-top:var(--ffc-spacing-xl)}.ffc-set-mr-8{margin-right:var(--ffc-spacing-sm)}.ffc-set-mb-10{margin-bottom:var(--ffc-spacing-md)}.ffc-set-mb-6{margin-bottom:var(--ffc-spacing-xs)}.ffc-set-w-80{width:80px}.ffc-set-w-90{width:90px}.ffc-set-w-100{width:100px}.ffc-set-w-120{width:120px}.ffc-set-w-110-right{width:110px;text-align:right}.ffc-set-text-right{text-align:right}.ffc-set-text-center{text-align:center}.ffc-set-filter-row{margin-bottom:var(--ffc-spacing-xs);display:flex;align-items:center;gap:var(--ffc-spacing-xs);flex-wrap:wrap}.ffc-settings-readonly-lock{border:0;margin:0;padding:0;min-width:0}.ffc-encryption-key-suggest{margin-top:var(--ffc-spacing-xl)}.ffc-key-suggest-widget{margin-top:var(--ffc-spacing-lg)}.ffc-rl-endpoint-heading{margin-top:1.5em}.ffc-signal-group-heading{margin-bottom:var(--ffc-spacing-3xs)}.ffc-signal-badge{display:inline-block;padding:1px 7px;border-radius:9px;font-size:var(--ffc-font-size-2xs);font-weight:600;vertical-align:middle}.ffc-gps-fallback-cases{margin-top:var(--ffc-spacing-lg);max-width:720px}.ffc-settings-divergence-notice{margin:var(--ffc-spacing-xl) 0;padding:var(--ffc-spacing-lg) var(--ffc-spacing-xl)}.ffc-settings-divergence-notice p{margin:0 0 var(--ffc-spacing-sm)}.ffc-settings-divergence-notice ul{margin:var(--ffc-spacing-xs) 0 0 var(--ffc-spacing-xl);list-style:disc}.ffc-email-body-hub__item{padding:var(--ffc-spacing-xl) 0;border-top:1px solid var(--ffc-border-light)}.ffc-email-body-hub__item:first-of-type{border-top:0;padding-top:var(--ffc-spacing-2xs)}.ffc-email-body-hub__item h3{margin:0 0 var(--ffc-spacing-md)}.ffc-debug-group-title{margin:var(--ffc-spacing-3xl) 0 var(--ffc-spacing-2xs);padding-top:var(--ffc-spacing-lg);border-top:1px solid var(--ffc-border-light);font-size:var(--ffc-font-size-base);font-weight:600;color:var(--ffc-primary)}.card .ffc-debug-group-title:first-of-type,.ffc-debug-group-title:first-child{border-top:0;padding-top:0}.ffc-debug-group-blurb{margin:0 0 var(--ffc-spacing-sm) 0;font-style:italic;color:var(--ffc-text-muted)}.ffc-url-shortener-types .ffc-col-center{text-align:center;width:6em}.ffc-inline-status{margin-left:var(--ffc-spacing-sm);font-style:italic;color:var(--ffc-text-muted)}.ffc-qr-design-layout{display:flex;flex-wrap:wrap;gap:var(--ffc-spacing-xl);align-items:flex-start}.ffc-qr-design-layout .ffc-sections{flex:1 1 28em;min-width:0}.ffc-qr-design-preview{flex:0 0 auto;width:240px;position:sticky;top:40px}.ffc-qr-design-preview__image{width:240px;min-height:240px;border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm)}.ffc-qr-design-preview__image svg{display:block;width:100%;height:auto}.ffc-qr-design-preview__checks{margin:var(--ffc-spacing-sm) 0 0;font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted)}.ffc-qr-design-preview__checks.is-warning{color:var(--ffc-warning-text)}.ffc-qr-design-preview__checks.is-error{color:var(--ffc-danger-text)}.widefat tfoot .ffc-location-new-field{padding:0 var(--ffc-spacing-lg)} +.ffc-settings-page,.ffc-settings-wrap{max-width:1500px}.card.ffc-danger-zone{border-left:4px solid var(--ffc-danger)}.card.ffc-danger-zone h2{color:var(--ffc-danger);border-bottom-color:var(--ffc-danger-light)}.ffc-settings-wrap .form-table{margin-top:0}.ffc-settings-wrap .form-table th{width:200px;padding:var(--ffc-spacing-xl) var(--ffc-spacing-md) var(--ffc-spacing-xl) 0;font-weight:600;vertical-align:top}.ffc-settings-wrap .form-table td{padding:var(--ffc-spacing-xl) var(--ffc-spacing-md)}.ffc-settings-wrap .form-table .description{margin-top:var(--ffc-spacing-sm);margin-bottom:0;font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted);line-height:1.5}.ffc-settings-wrap .form-table fieldset .description{margin-top:var(--ffc-spacing-2xs);margin-bottom:var(--ffc-spacing-xl);margin-left:25px}.ffc-settings-wrap .form-table .description.ffc-module-note{display:flex;align-items:flex-start;gap:var(--ffc-spacing-xs);margin-top:var(--ffc-spacing-xs);font-style:italic}.ffc-settings-wrap .form-table .description.ffc-module-note .ffc-icon-info{display:inline-flex;flex:0 0 auto}.ffc-settings-wrap .form-table .description.ffc-module-note .ffc-icon-info::before{margin-right:0}.ffc-stats-box{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary)}.ffc-stats-box table{width:100%;max-width:1000px;border-collapse:collapse}.ffc-stats-box tr{border-bottom:1px solid var(--ffc-border-light)}.ffc-stats-box tr:last-child{border-bottom:none}.ffc-stats-box tr.alternate{background:rgba(255,255,255,.6)}.ffc-stats-box td{padding:var(--ffc-spacing-lg) 0}.ffc-stats-box td:first-child{width:50%;font-weight:600}.ffc-stats-box .ffc-stat-value{font-family:'SF Mono',Monaco,Consolas,monospace}.ffc-stats-box .ffc-stat-value.ffc-stat-info{color:var(--ffc-primary);font-weight:600}.ffc-provider-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:var(--ffc-spacing-xl);margin-top:var(--ffc-spacing-xl)}.ffc-provider-card{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary)}.ffc-provider-card.ffc-provider-gmail{border-left-color:var(--ffc-primary)}.ffc-provider-card.ffc-provider-outlook{border-left-color:#00a0d2}.ffc-provider-card.ffc-provider-sendgrid{border-left-color:#9b51e0}.ffc-provider-card h4{margin:0 0 var(--ffc-spacing-md) 0;font-size:var(--ffc-font-size-base);font-weight:600}.ffc-provider-card p{margin:var(--ffc-spacing-2xs) 0;font-size:var(--ffc-font-size-sm);line-height:1.4}.ffc-checkbox-group{margin:var(--ffc-spacing-xl) 0}.ffc-checkbox-group label{display:block;margin-bottom:var(--ffc-spacing-md)}.ffc-checkbox-group .ffc-checkbox-sublabel{color:var(--ffc-primary);font-weight:400;font-size:var(--ffc-font-size-sm);margin-left:var(--ffc-spacing-2xs)}.ffc-checkbox-group .description{margin-left:30px;margin-top:var(--ffc-spacing-2xs);font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted)}.ffc-collapsible-section{margin-top:var(--ffc-spacing-2xl)}.ffc-collapsible-content{padding:var(--ffc-spacing-xl)}.ffc-loglevel-table{border-collapse:collapse;margin:var(--ffc-spacing-2xs) 0 var(--ffc-spacing-sm)}.ffc-loglevel-table td{padding:0;border:1px solid var(--ffc-border-light);border-bottom:none}.ffc-loglevel-table tr:last-child td{border-bottom:1px solid var(--ffc-border-light)}.ffc-loglevel-label{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-xl);margin:0;cursor:pointer;min-width:320px}.ffc-loglevel-table tr:has( input[type=radio]:checked ),.ffc-loglevel-table tr:has( input[type=radio]:checked )~tr{background:var(--ffc-success-light)}.ffc-loglevel-table tr:has( input[type=radio]:checked ) .ffc-loglevel-name,.ffc-loglevel-table tr:has( input[type=radio]:checked )~tr .ffc-loglevel-name{color:var(--ffc-success);font-weight:600}.ffc-migration-card{margin-bottom:var(--ffc-spacing-2xl)}.ffc-migration-card .postbox-header{padding:var(--ffc-spacing-2xl) var(--ffc-spacing-2xl) var(--ffc-spacing-md)}.ffc-migration-card .postbox-header .hndle{margin:0;padding:0}.ffc-migration-card .inside{margin:0;padding:var(--ffc-spacing-xl) var(--ffc-spacing-2xl) var(--ffc-spacing-2xl)}.ffc-migration-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--ffc-spacing-xl);margin:var(--ffc-spacing-xl) 0}.ffc-migration-stat-label{font-size:var(--ffc-font-size-xs);color:var(--ffc-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:var(--ffc-spacing-2xs)}.ffc-migration-stat-value{font-size:var(--ffc-font-size-2xl);font-weight:700;font-family:'SF Mono',Monaco,Consolas,monospace;color:var(--ffc-text)}.ffc-migration-stat-value.ffc-migration-stat-success{color:var(--ffc-success)}.ffc-migration-stat-value.ffc-migration-stat-pending{color:var(--ffc-warning)}.ffc-migration-stat-value.ffc-migration-stat-info{color:var(--ffc-primary)}.ffc-migration-stat-note{font-size:var(--ffc-font-size-xs);color:var(--ffc-text-muted);margin-top:var(--ffc-spacing-2xs)}.ffc-migration-progress-bar{margin:var(--ffc-spacing-2xl) 0}.ffc-progress-bar-container{position:relative;width:100%;height:30px;background:var(--ffc-bg-alt);border-radius:15px;overflow:hidden}.ffc-progress-bar-fill{height:100%;background:linear-gradient(90deg,var(--ffc-primary) 0,var(--ffc-primary-hover) 100%);transition:width .3s ease;position:relative}.ffc-progress-bar-fill.ffc-progress-complete{background:linear-gradient(90deg,var(--ffc-success) 0,var(--ffc-success-hover) 100%)}.ffc-progress-bar-fill.ffc-progress-pending{background:linear-gradient(90deg,var(--ffc-warning) 0,var(--ffc-warning-border) 100%)}.ffc-progress-bar-label{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-weight:600;font-size:var(--ffc-font-size-sm);white-space:nowrap}.ffc-progress-bar-label.ffc-progress-label-light{color:var(--ffc-text)}.ffc-progress-bar-label.ffc-progress-label-dark{color:var(--ffc-text-on-primary)}.ffc-migration-conflicts{margin-top:var(--ffc-spacing-lg);padding:var(--ffc-spacing-sm) var(--ffc-spacing-md);background:var(--ffc-warning-bg);border-left:3px solid var(--ffc-warning-border);border-radius:var(--ffc-radius-xs);color:var(--ffc-warning-text)}.ffc-migration-conflicts p{margin:0 0 var(--ffc-spacing-2xs)}.ffc-migration-conflicts p:last-child{margin-bottom:0}.ffc-migration-actions{margin-top:var(--ffc-spacing-2xl)}.ffc-migration-help{background:var(--ffc-bg-alt)}.ffc-rate-limit-wrap .card{margin-bottom:var(--ffc-spacing-2xl)}.ffc-rate-limit-wrap .card h2,.ffc-rate-limit-wrap h2{margin-top:0;margin-bottom:var(--ffc-spacing-md)}.ffc-rate-limit-wrap .card>p{margin-bottom:var(--ffc-spacing-xl)}.ffc-settings-wrap .button{margin-right:var(--ffc-spacing-md);margin-bottom:var(--ffc-spacing-2xs)}.ffc-settings-wrap .button:last-child{margin-right:0}@media screen and (max-width:782px){.ffc-migration-stats,.ffc-provider-grid{grid-template-columns:1fr}.ffc-settings-wrap .form-table th{width:auto;padding:var(--ffc-spacing-md) var(--ffc-spacing-md) 0 0;display:block}.ffc-settings-wrap .form-table td{padding:var(--ffc-spacing-md) 0;display:block}.ffc-stats-box table{font-size:var(--ffc-font-size-sm)}.ffc-migration-stat-value{font-size:var(--ffc-font-size-xl)}}@media screen and (max-width:1000px){.ffc-settings-wrap .card{padding:var(--ffc-spacing-xl)}.ffc-provider-card,.ffc-stats-box{padding:var(--ffc-spacing-xl)}}.ffc-admin-page .card,.ffc-collapsible-content,.ffc-progress-bar-fill,.ffc-provider-card{transition:all .2s cubic-bezier(.4, 0, .2, 1)}@media print{.ffc-settings-wrap .button{display:none}.ffc-admin-page .card{border:1px solid var(--ffc-text);box-shadow:none;break-inside:avoid}}.ffc-doc-toc{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);border-left:4px solid var(--ffc-primary);margin:var(--ffc-spacing-2xl) 0}.ffc-doc-toc h3{margin-top:0;margin-bottom:var(--ffc-spacing-xl);color:var(--ffc-text)}.ffc-doc-toc input[type=search]{width:100%;max-width:100%;box-sizing:border-box}.ffc-doc-toc-list,.ffc-doc-toc-sublist{list-style:none;padding:0;margin:0}.ffc-doc-toc-list>li{margin:var(--ffc-spacing-3xs) 0}.ffc-doc-toc-sublist>li{margin:var(--ffc-spacing-3xs) 0}.ffc-doc-toc-sublist{padding-left:var(--ffc-spacing-xl);margin-left:var(--ffc-spacing-sm);border-left:1px solid var(--ffc-border-light)}.ffc-doc-toc-branch>details>summary{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg);cursor:pointer;border-radius:var(--ffc-radius-sm);background:var(--ffc-bg-card);border:1px solid var(--ffc-border);font-weight:500;color:var(--ffc-link);transition:background .15s ease,color .15s ease,border-color .15s ease;list-style:none;user-select:none}.ffc-doc-toc-branch>details>summary::-webkit-details-marker{display:none}.ffc-doc-toc-chevron{display:inline-flex;flex:0 0 auto;color:var(--ffc-text-muted)}.ffc-doc-toc-chevron::before{margin-right:0;transition:transform .15s ease}.ffc-doc-toc-branch>details[open]>summary .ffc-doc-toc-chevron::before{transform:rotate(90deg)}.ffc-doc-toc-branch>details>summary:hover{background:var(--ffc-primary);color:var(--ffc-text-on-primary);border-color:var(--ffc-primary)}.ffc-doc-toc-branch>details>summary:hover .ffc-doc-toc-chevron,.ffc-doc-toc-branch>details>summary:hover .ffc-doc-toc-icon{color:var(--ffc-text-on-primary)}.ffc-doc-toc-icon{display:inline-flex;flex:0 0 auto;font-size:var(--ffc-font-size-lg);line-height:1}.ffc-doc-toc-icon::before{margin-right:0}.ffc-doc-toc-branch>details>summary .ffc-doc-toc-icon{color:var(--ffc-primary)}.ffc-doc-toc-branch>details>summary .ffc-doc-toc-branch-label,.ffc-doc-toc-branch>details>summary a{color:inherit;text-decoration:none}.ffc-doc-toc-list li>a{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg);background:var(--ffc-bg-card);border-radius:var(--ffc-radius-sm);text-decoration:none;color:var(--ffc-link);font-weight:500;transition:background .15s ease,color .15s ease,border-color .15s ease;border:1px solid var(--ffc-border)}.ffc-doc-toc-list li>a .ffc-doc-toc-icon{color:var(--ffc-text-muted)}.ffc-doc-toc-list li>a:hover{background:var(--ffc-primary);color:var(--ffc-text-on-primary);border-color:var(--ffc-primary)}.ffc-doc-toc-list li>a:hover .ffc-doc-toc-icon{color:var(--ffc-text-on-primary)}.ffc-doc-example{background:var(--ffc-bg-alt);padding:var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);margin:var(--ffc-spacing-2xl) 0;border-left:4px solid var(--ffc-success)}.ffc-doc-example h4{margin-top:0;margin-bottom:var(--ffc-spacing-md);color:var(--ffc-success);font-size:var(--ffc-font-size-base);font-weight:600}.ffc-doc-example pre{background:#1e1e1e;color:#d4d4d4;padding:var(--ffc-spacing-xl);border-radius:var(--ffc-radius-sm);overflow-x:auto;margin:var(--ffc-spacing-md) 0;font-family:'SF Mono',Monaco,Consolas,monospace;font-size:var(--ffc-font-size-sm);line-height:1.5}.ffc-doc-example code{background:0 0;color:inherit;padding:0}.ffc-doc-example ul{margin:var(--ffc-spacing-md) 0 0 var(--ffc-spacing-2xl)}.ffc-admin-page code{background:var(--ffc-bg-alt);padding:3px var(--ffc-spacing-xs);border-radius:var(--ffc-radius-xs);font-family:'SF Mono',Monaco,Consolas,monospace;font-size:var(--ffc-font-size-sm);color:var(--ffc-danger-text);border:1px solid var(--ffc-border-light)}.ffc-admin-page pre code{background:0 0;border:none;padding:0;color:inherit}.ffc-doc-list{list-style:none;padding:0}.ffc-doc-list li{padding:var(--ffc-spacing-md) 0 var(--ffc-spacing-md) 30px;border-bottom:1px solid var(--ffc-border-light);position:relative}.ffc-doc-list li:last-child{border-bottom:none}.ffc-doc-list li::before{content:"✓";position:absolute;left:0;color:var(--ffc-success);font-weight:700;font-size:var(--ffc-font-size-lg)}.ffc-alert{padding:var(--ffc-spacing-xl) var(--ffc-spacing-2xl);border-radius:var(--ffc-radius-sm);margin:var(--ffc-spacing-2xl) 0;border-left:4px solid}.ffc-alert p{margin:0}.ffc-alert-info{background:var(--ffc-info-bg);border-color:var(--ffc-info-border);color:var(--ffc-info-text)}.ffc-settings-wrap .widefat{border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm);overflow:hidden}.ffc-settings-wrap .widefat thead th{background:var(--ffc-bg-alt);font-weight:600;padding:var(--ffc-spacing-lg)}.ffc-settings-wrap .widefat tbody td{padding:var(--ffc-spacing-lg);border-bottom:1px solid var(--ffc-border-light)}.ffc-settings-wrap .widefat tbody tr:last-child td{border-bottom:none}.ffc-settings-wrap .widefat code{font-size:var(--ffc-font-size-xs)}.ffc-settings-wrap .card h3[id]{scroll-margin-top:20px}.ffc-settings-wrap .card h3[id]{--ffc-icon-tone:var(--ffc-primary)}.ffc-doc-topics .card td a{text-decoration:underline}@media screen and (max-width:782px){.ffc-doc-example pre{font-size:var(--ffc-font-size-xs);padding:var(--ffc-spacing-md)}}@media (prefers-reduced-motion:reduce){.ffc-admin-page .card,.ffc-collapsible-content,.ffc-doc-toc-branch>details>summary::before,.ffc-doc-toc-list li>a,.ffc-progress-bar-fill,.ffc-provider-card{transition:none}}.ffc-settings-tab-content{max-width:1500px}.ffc-settings-tabs{display:flex;align-items:stretch;margin-top:var(--ffc-spacing-2xl);background:var(--ffc-bg-card);border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm);box-shadow:var(--ffc-shadow-sm);overflow:clip}.ffc-settings-tabs__nav{flex:0 0 220px;margin:0;padding:0;list-style:none;background:var(--ffc-bg-alt);border-right:1px solid var(--ffc-border)}.ffc-settings-tabs__nav-item{margin:0}.ffc-settings-tabs__tab{display:flex;align-items:center;gap:var(--ffc-spacing-sm);padding:var(--ffc-spacing-lg) var(--ffc-spacing-xl);color:var(--ffc-text);text-decoration:none;border-left:4px solid transparent;line-height:1.3;transition:background .15s ease,color .15s ease,border-color .15s ease}.ffc-settings-tabs__tab:focus,.ffc-settings-tabs__tab:hover{background:var(--ffc-primary-light);color:var(--ffc-primary);box-shadow:none}.ffc-settings-tabs__tab:focus-visible{outline:2px solid var(--ffc-primary);outline-offset:-2px}.ffc-settings-tabs__tab.is-active{background:var(--ffc-bg-card);color:var(--ffc-primary);border-left-color:var(--ffc-primary);font-weight:600}.ffc-settings-tabs__icon{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;filter:grayscale(1)}.ffc-settings-tabs__nav .ffc-settings-tabs__icon::before{margin-right:0}.ffc-settings-tabs__label{flex:1 1 auto}.ffc-settings-tabs__group{list-style:none}.ffc-settings-tabs__group-label{display:block;padding:var(--ffc-spacing-lg) var(--ffc-spacing-lg) var(--ffc-spacing-2xs);font-size:var(--ffc-font-size-2xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ffc-text-muted)}.ffc-settings-tabs__nav>.ffc-settings-tabs__group:first-child .ffc-settings-tabs__group-label{padding-top:var(--ffc-spacing-xs)}.ffc-settings-tabs__external{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;opacity:.55}.ffc-settings-tabs__panel{flex:1 1 auto;min-width:0;padding:var(--ffc-spacing-2xs) var(--ffc-spacing-2xl) var(--ffc-spacing-2xl);animation:ffc-tab-fade-in .2s ease-out}@keyframes ffc-tab-fade-in{from{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}@media screen and (max-width:782px){.ffc-settings-tabs{flex-direction:column}.ffc-settings-tabs__nav{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:0;border-right:none;border-bottom:1px solid var(--ffc-border)}.ffc-settings-tabs__tab{border-left:none;border-bottom:3px solid transparent;padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg)}.ffc-settings-tabs__tab.is-active{border-left:none;border-bottom-color:var(--ffc-primary)}.ffc-settings-tabs__group{flex:0 0 100%}.ffc-settings-tabs__group-label{padding:var(--ffc-spacing-sm) var(--ffc-spacing-lg) 0}}@media (prefers-reduced-motion:reduce){.ffc-settings-tabs__panel,.ffc-settings-tabs__tab{transition:none;animation:none}}.ffc-settings-tabs__nav .ffc-settings-tabs__icon{font-size:20px;line-height:1}.ffc-settings-tabs__nav .ffc-settings-tabs__external::before,.ffc-settings-tabs__nav .ffc-settings-tabs__icon::before{margin-right:0}.ffc-settings-tabs__nav .ffc-settings-tabs__external{font-size:var(--ffc-font-size-sm)}@media screen and (min-width:1280px){.ffc-doc-layout{display:grid;grid-template-columns:280px minmax(0,1fr);column-gap:var(--ffc-spacing-2xl);align-items:start}.ffc-doc-toc{position:sticky;top:calc(var(--wp-admin--admin-bar--height,32px) + var(--ffc-spacing-xl));z-index:var(--ffc-z-sticky);max-height:calc(100vh - var(--wp-admin--admin-bar--height,32px) - 2 * var(--ffc-spacing-xl));overflow-y:auto}}.ffc-settings-back-to-top{position:fixed;right:24px;bottom:24px;z-index:9999;display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border-radius:var(--ffc-radius-full);background:var(--ffc-primary);color:var(--ffc-text-on-primary);text-decoration:none;box-shadow:var(--ffc-shadow-md);opacity:.85;transition:opacity .2s ease,transform .2s ease}.ffc-settings-back-to-top:focus,.ffc-settings-back-to-top:hover{opacity:1;color:var(--ffc-text-on-primary);transform:translateY(-2px)}.ffc-settings-back-to-top:focus-visible{outline:2px solid var(--ffc-border-focus);outline-offset:2px}.ffc-settings-back-to-top .ffc-icon-chevron-up{font-size:var(--ffc-font-size-xl);line-height:1}.ffc-settings-back-to-top .ffc-icon-chevron-up::before{margin-right:0}html:has(.ffc-settings-back-to-top){scroll-behavior:smooth}@media (prefers-reduced-motion:reduce){html:has(.ffc-settings-back-to-top){scroll-behavior:auto}.ffc-settings-back-to-top{transition:none}}.ffc-set-my-10{margin:var(--ffc-spacing-md) 0}.ffc-set-my-12{margin:var(--ffc-spacing-lg) 0}.ffc-set-mt-10{margin-top:var(--ffc-spacing-md)}.ffc-set-mt-18{margin-top:var(--ffc-spacing-xl)}.ffc-set-mr-8{margin-right:var(--ffc-spacing-sm)}.ffc-set-mb-10{margin-bottom:var(--ffc-spacing-md)}.ffc-set-mb-6{margin-bottom:var(--ffc-spacing-xs)}.ffc-set-w-80{width:80px}.ffc-set-w-90{width:90px}.ffc-set-w-100{width:100px}.ffc-set-w-120{width:120px}.ffc-set-w-110-right{width:110px;text-align:right}.ffc-set-text-right{text-align:right}.ffc-set-text-center{text-align:center}.ffc-set-filter-row{margin-bottom:var(--ffc-spacing-xs);display:flex;align-items:center;gap:var(--ffc-spacing-xs);flex-wrap:wrap}.ffc-settings-readonly-lock{border:0;margin:0;padding:0;min-width:0}.ffc-encryption-key-suggest{margin-top:var(--ffc-spacing-xl)}.ffc-key-suggest-widget{margin-top:var(--ffc-spacing-lg)}.ffc-rl-endpoint-heading{margin-top:1.5em}.ffc-signal-group-heading{margin-bottom:var(--ffc-spacing-3xs)}.ffc-signal-badge{display:inline-block;padding:1px 7px;border-radius:9px;font-size:var(--ffc-font-size-2xs);font-weight:600;vertical-align:middle}.ffc-gps-fallback-cases{margin-top:var(--ffc-spacing-lg);max-width:720px}.ffc-settings-divergence-notice{margin:var(--ffc-spacing-xl) 0;padding:var(--ffc-spacing-lg) var(--ffc-spacing-xl)}.ffc-settings-divergence-notice p{margin:0 0 var(--ffc-spacing-sm)}.ffc-settings-divergence-notice ul{margin:var(--ffc-spacing-xs) 0 0 var(--ffc-spacing-xl);list-style:disc}.ffc-email-body-hub__item{padding:var(--ffc-spacing-xl) 0;border-top:1px solid var(--ffc-border-light)}.ffc-email-body-hub__item:first-of-type{border-top:0;padding-top:var(--ffc-spacing-2xs)}.ffc-email-body-hub__item h3{margin:0 0 var(--ffc-spacing-md)}.ffc-debug-group-title{margin:var(--ffc-spacing-3xl) 0 var(--ffc-spacing-2xs);padding-top:var(--ffc-spacing-lg);border-top:1px solid var(--ffc-border-light);font-size:var(--ffc-font-size-base);font-weight:600;color:var(--ffc-primary)}.card .ffc-debug-group-title:first-of-type,.ffc-debug-group-title:first-child{border-top:0;padding-top:0}.ffc-debug-group-blurb{margin:0 0 var(--ffc-spacing-sm) 0;font-style:italic;color:var(--ffc-text-muted)}.ffc-url-shortener-types .ffc-col-center{text-align:center;width:6em}.ffc-inline-status{margin-left:var(--ffc-spacing-sm);font-style:italic;color:var(--ffc-text-muted)}.ffc-qr-design-layout{display:flex;flex-wrap:wrap;gap:var(--ffc-spacing-xl);align-items:flex-start}.ffc-qr-design-layout .ffc-sections{flex:1 1 28em;min-width:0}.ffc-qr-design-preview{flex:0 0 auto;width:240px;position:sticky;top:40px}.ffc-qr-design-preview__image{width:240px;min-height:240px;border:1px solid var(--ffc-border);border-radius:var(--ffc-radius-sm)}.ffc-qr-design-preview__image svg{display:block;width:100%;height:auto}.ffc-qr-design-preview__checks{margin:var(--ffc-spacing-sm) 0 0;font-size:var(--ffc-font-size-sm);color:var(--ffc-text-muted)}.ffc-qr-design-preview__checks.is-warning{color:var(--ffc-warning-text)}.ffc-qr-design-preview__checks.is-error{color:var(--ffc-danger-text)}.widefat tfoot .ffc-location-new-field{padding:0 var(--ffc-spacing-lg)}.ffc-required-fields-table input[type=text],.ffc-required-fields-table select{width:100%;max-width:none}.ffc-required-fields-table td:last-child{width:1%;white-space:nowrap} /*# sourceMappingURL=ffc-admin-settings.min.css.map */ \ No newline at end of file diff --git a/assets/js/ffc-admin-field-builder.js b/assets/js/ffc-admin-field-builder.js index 67c42bdda..cd5690bec 100644 --- a/assets/js/ffc-admin-field-builder.js +++ b/assets/js/ffc-admin-field-builder.js @@ -336,13 +336,71 @@ return $row; } + /** + * Lock a row the way the server renders a required field (#1741): the + * name, the type and the required flag cannot change, and the row + * cannot be removed. Only the label stays editable. + */ + function lockRequiredRow($row, field) { + var index = String($row.attr('data-index')); + var lockId = 'ffc_field_lock_' + index; + var $select = $row.find('.ffc-field-type-selector'); + + $row.addClass('ffc-field-row-required-tag'); + $row.find('input[name$="[label]"]').first().val(field.label || field.name); + $row.find('input[name$="[name]"]').first().val(field.name).prop('readonly', true).attr('aria-describedby', lockId); + + // A disabled select posts nothing, so the type travels in a hidden input. + $select.removeAttr('name').prop('disabled', true).attr('aria-describedby', lockId); + $('').attr('name', 'ffc_fields[' + index + '][type]').val(field.type).insertBefore($select); + + $row.find('.ffc-field-required').prop('checked', true).prop('disabled', true); + $row.find('.ffc-remove-field').prop('disabled', true).attr('aria-describedby', lockId); + + var $badge = $('').attr('id', lockId); + $badge.append(' '); + $badge.append(document.createTextNode(strings().requiredField || 'Required field')); + $row.find('.ffc-field-title').after($badge); + } + + /** + * Add every required field the form lacks, locked, and drop the notice. + */ + function addRequiredFields($button) { + var fields; + try { + fields = JSON.parse(String($button.attr('data-ffc-required-fields') || '[]')); + } catch (err) { + fields = []; + } + if (!Array.isArray(fields)) { + return; + } + fields.forEach(function(field) { + if (!field || !field.name) { + return; + } + var $row = addFieldToBuilder(field.type || 'text'); + if ($row) { + lockRequiredRow($row, field); + } + }); + $button.closest('.ffc-required-fields-missing').remove(); + } + + $(document).on('click', '.ffc-add-required-fields', function(e) { + e.preventDefault(); + addRequiredFields($(this)); + }); + window.FFC = window.FFC || {}; window.FFC.Admin = window.FFC.Admin || {}; window.FFC.Admin.FieldBuilder = { init: initFormBuilder, addField: addFieldToBuilder, applyType: applyType, - refreshQuiz: refreshQuiz + refreshQuiz: refreshQuiz, + addRequiredFields: addRequiredFields }; if (FFC && FFC.registerModule) { diff --git a/assets/js/ffc-admin-field-builder.min.js b/assets/js/ffc-admin-field-builder.min.js index 24b01adb2..a53191ff8 100644 --- a/assets/js/ffc-admin-field-builder.min.js +++ b/assets/js/ffc-admin-field-builder.min.js @@ -1,2 +1,2 @@ -!function(e,f){"use strict";var i=["select","radio","checkbox"],t=["text","textarea"],c=["number","date"],n=0;function o(){return"undefined"!=typeof ffc_ajax&&ffc_ajax.strings?ffc_ajax.strings:{}}function d(){return e("#ffc_quiz_enabled").is(":checked")}function l(f,t){var c="info"===t,n="embed"===t,o=-1!==i.indexOf(t);f.find(".ffc-content-field").toggleClass("ffc-hidden",!c),f.find(".ffc-embed-field").toggleClass("ffc-hidden",!n),f.find(".ffc-hidden-value-field").toggleClass("ffc-hidden","hidden"!==t),f.find(".ffc-standard-row").toggleClass("ffc-hidden",c||n),f.find(".ffc-options-field").toggleClass("ffc-hidden",!o),f.find("[data-ffc-types]").each(function(){var f=String(e(this).attr("data-ffc-types")).split(" ");e(this).toggleClass("ffc-hidden",-1===f.indexOf(t))}),f.find(".ffc-type-desc").text(function(e){return("undefined"!=typeof ffc_ajax&&ffc_ajax.fieldTypeDescriptions?ffc_ajax.fieldTypeDescriptions:{})[e]||""}(t)),a(f,t)}function a(f,n){n=n||String(f.find(".ffc-field-type-selector").val()||"");var o=f.find(".ffc-field-quiz"),l=-1!==String(o.attr("data-ffc-quiz-types")||"").split(" ").indexOf(n),a=d()&&l,s=a&&o.find(".ffc-quiz-scored").is(":checked"),u=-1!==i.indexOf(n),h=u?String(o.find(".ffc-quiz-mode").val()):"",p=-1!==t.indexOf(n)&&"none"===o.find(".ffc-quiz-text").val();o.toggleClass("ffc-hidden",!a),o.find(".ffc-field-quiz-body").toggleClass("ffc-hidden",!s),f.find(".ffc-choice-quiz").each(function(){e(this).toggleClass("ffc-hidden",!(s&&u&&e(this).attr("data-ffc-quiz-mode")===h))}),o.find(".ffc-quiz-points-setting").toggleClass("ffc-hidden",u&&"points"===h||p),o.find("[data-ffc-types]").each(function(){e(this).toggleClass("ffc-hidden",-1===String(e(this).attr("data-ffc-types")).split(" ").indexOf(n))}),o.find('[data-ffc-quiz-help="correct"]').toggleClass("ffc-hidden",!(u&&"correct"===h)),o.find('[data-ffc-quiz-help="points"]').toggleClass("ffc-hidden",!(u&&"points"===h)),o.find('[data-ffc-quiz-help="range"]').toggleClass("ffc-hidden",-1===c.indexOf(n)),r(f)}function r(e){var f=e.find('input[name$="[max_select]"]');if(f.length&&f[0].setCustomValidity){var i=String(e.find(".ffc-field-type-selector").val()||""),t=parseInt(f.val(),10),c=e.find(".ffc-choice-correct-value").filter(function(){return"1"===this.value}).length,n="";"checkbox"===i&&d()&&e.find(".ffc-quiz-scored").is(":checked")&&"correct"===e.find(".ffc-quiz-mode").val()&&t>0&&tf&&(f=i)}),Math.max(f+1,n)}function h(e,f){var i=e.children(".ffc-choice-row").first();if(!i.length)return null;var t=i.clone();return t.find(".ffc-choice-input").val(f||""),p(t),e.append(t),t}function p(e){e.find(".ffc-choice-correct-value").val("0"),e.find(".ffc-choice-correct-input").prop("checked",!1),e.find(".ffc-choice-points-input").val("")}function v(f){e.fn.sortable&&f.find(".ffc-choice-list").sortable({handle:".ffc-choice-handle",axis:"y"})}function g(f){var i=e(".ffc-field-template .ffc-field-row").first();if(!i.length)return null;var t=String(u());n=parseInt(t,10)+1;var c=i.clone();return c.attr("data-index",t),c.find("[name], [id], [for]").each(function(){var e=this;["name","id","for"].forEach(function(f){var i=e.getAttribute(f);i&&-1!==i.indexOf("TEMPLATE")&&e.setAttribute(f,i.split("TEMPLATE").join(t))})}),e("#ffc-fields-container").append(c),c.find(".ffc-field-type-selector").val(f),l(c,f),v(c),c.find('input[type="text"]').first().trigger("focus"),c}window.FFC=window.FFC||{},window.FFC.Admin=window.FFC.Admin||{},window.FFC.Admin.FieldBuilder={init:function(){var f=e("#ffc-fields-container");0!==f.length&&(n=0,n=u(),e(document).off("click.ffcFieldBuilder"),e(document).on("click.ffcFieldBuilder",".ffc-add-field",function(f){f.preventDefault(),function(f){e(".ffc-field-type-menu").remove();var i=e('
');i.append(e('
').text(o().chooseFieldType||"Choose Field Type:"));var t=e("
    ");("undefined"!=typeof ffc_ajax&&Array.isArray(ffc_ajax.fieldTypes)&&ffc_ajax.fieldTypes.length?ffc_ajax.fieldTypes:[{value:"checkbox",label:"Checkbox"},{value:"date",label:"Date"},{value:"select",label:"Dropdown Select"},{value:"email",label:"Email"},{value:"number",label:"Number"},{value:"radio",label:"Radio Buttons"},{value:"text",label:"Text"},{value:"textarea",label:"Textarea"},{value:"embed",label:"Embed (Media)"},{value:"hidden",label:"Hidden Field"},{value:"info",label:"Info Block"}]).forEach(function(f){var c=e('').attr("data-type",f.value).text(f.label);c.on("click",function(){g(f.value),i.remove()}),t.append(e("
  • ").append(c))}),i.append(t);var c=f.offset();i.css({position:"absolute",top:c.top+f.outerHeight()+5+"px",left:c.left+"px"}),e("body").append(i),i.find(".ffc-field-type-option").first().trigger("focus"),setTimeout(function(){e(document).one("click",function(){i.remove()})},100)}(e(this))}),e(document).on("click.ffcFieldBuilder",".ffc-remove-field",function(f){f.preventDefault(),confirm(o().confirmDeleteField||"Remove this field?")&&e(this).closest(".ffc-field-row").fadeOut(300,function(){e(this).remove()})}),f.on("change",".ffc-field-type-selector",function(){l(e(this).closest(".ffc-field-row"),e(this).val())}),f.on("click",".ffc-choice-add",function(f){f.preventDefault();var i=h(e(this).siblings(".ffc-choice-list"),"");i&&i.find(".ffc-choice-input").trigger("focus")}),f.on("click",".ffc-choice-remove",function(f){f.preventDefault();var i=e(this).closest(".ffc-choice-row"),t=i.closest(".ffc-field-row");i.siblings(".ffc-choice-row").length?i.remove():(i.find(".ffc-choice-input").val(""),p(i)),r(t)}),f.on("change",".ffc-choice-correct-input",function(){e(this).closest(".ffc-choice-row").find(".ffc-choice-correct-value").val(this.checked?"1":"0"),r(e(this).closest(".ffc-field-row"))}),f.on("change",".ffc-quiz-scored, .ffc-quiz-mode, .ffc-quiz-text",function(){a(e(this).closest(".ffc-field-row"))}),f.on("input change",'input[name$="[max_select]"]',function(){r(e(this).closest(".ffc-field-row"))}),e(document).off("change.ffcFieldBuilder"),e(document).on("change.ffcFieldBuilder","#ffc_quiz_enabled",s),s(),f.on("keydown",".ffc-choice-input",function(f){if("Enter"===f.key){f.preventDefault();var i=h(e(this).closest(".ffc-choice-list"),"");i&&(i.insertAfter(e(this).closest(".ffc-choice-row")),i.find(".ffc-choice-input").trigger("focus"))}}),e.fn.sortable&&f.sortable({handle:".ffc-sort-handle",placeholder:"ffc-field-placeholder"}),v(f))},addField:g,applyType:l,refreshQuiz:s},f&&f.registerModule&&f.registerModule("Admin.FieldBuilder",f.version)}(jQuery,window.FFC); +!function(e,f){"use strict";var i=["select","radio","checkbox"],t=["text","textarea"],c=["number","date"],n=0;function d(){return"undefined"!=typeof ffc_ajax&&ffc_ajax.strings?ffc_ajax.strings:{}}function a(){return e("#ffc_quiz_enabled").is(":checked")}function l(f,t){var c="info"===t,n="embed"===t,d=-1!==i.indexOf(t);f.find(".ffc-content-field").toggleClass("ffc-hidden",!c),f.find(".ffc-embed-field").toggleClass("ffc-hidden",!n),f.find(".ffc-hidden-value-field").toggleClass("ffc-hidden","hidden"!==t),f.find(".ffc-standard-row").toggleClass("ffc-hidden",c||n),f.find(".ffc-options-field").toggleClass("ffc-hidden",!d),f.find("[data-ffc-types]").each(function(){var f=String(e(this).attr("data-ffc-types")).split(" ");e(this).toggleClass("ffc-hidden",-1===f.indexOf(t))}),f.find(".ffc-type-desc").text(function(e){return("undefined"!=typeof ffc_ajax&&ffc_ajax.fieldTypeDescriptions?ffc_ajax.fieldTypeDescriptions:{})[e]||""}(t)),o(f,t)}function o(f,n){n=n||String(f.find(".ffc-field-type-selector").val()||"");var d=f.find(".ffc-field-quiz"),l=-1!==String(d.attr("data-ffc-quiz-types")||"").split(" ").indexOf(n),o=a()&&l,s=o&&d.find(".ffc-quiz-scored").is(":checked"),u=-1!==i.indexOf(n),p=u?String(d.find(".ffc-quiz-mode").val()):"",h=-1!==t.indexOf(n)&&"none"===d.find(".ffc-quiz-text").val();d.toggleClass("ffc-hidden",!o),d.find(".ffc-field-quiz-body").toggleClass("ffc-hidden",!s),f.find(".ffc-choice-quiz").each(function(){e(this).toggleClass("ffc-hidden",!(s&&u&&e(this).attr("data-ffc-quiz-mode")===p))}),d.find(".ffc-quiz-points-setting").toggleClass("ffc-hidden",u&&"points"===p||h),d.find("[data-ffc-types]").each(function(){e(this).toggleClass("ffc-hidden",-1===String(e(this).attr("data-ffc-types")).split(" ").indexOf(n))}),d.find('[data-ffc-quiz-help="correct"]').toggleClass("ffc-hidden",!(u&&"correct"===p)),d.find('[data-ffc-quiz-help="points"]').toggleClass("ffc-hidden",!(u&&"points"===p)),d.find('[data-ffc-quiz-help="range"]').toggleClass("ffc-hidden",-1===c.indexOf(n)),r(f)}function r(e){var f=e.find('input[name$="[max_select]"]');if(f.length&&f[0].setCustomValidity){var i=String(e.find(".ffc-field-type-selector").val()||""),t=parseInt(f.val(),10),c=e.find(".ffc-choice-correct-value").filter(function(){return"1"===this.value}).length,n="";"checkbox"===i&&a()&&e.find(".ffc-quiz-scored").is(":checked")&&"correct"===e.find(".ffc-quiz-mode").val()&&t>0&&tf&&(f=i)}),Math.max(f+1,n)}function p(e,f){var i=e.children(".ffc-choice-row").first();if(!i.length)return null;var t=i.clone();return t.find(".ffc-choice-input").val(f||""),h(t),e.append(t),t}function h(e){e.find(".ffc-choice-correct-value").val("0"),e.find(".ffc-choice-correct-input").prop("checked",!1),e.find(".ffc-choice-points-input").val("")}function v(f){e.fn.sortable&&f.find(".ffc-choice-list").sortable({handle:".ffc-choice-handle",axis:"y"})}function g(f){var i=e(".ffc-field-template .ffc-field-row").first();if(!i.length)return null;var t=String(u());n=parseInt(t,10)+1;var c=i.clone();return c.attr("data-index",t),c.find("[name], [id], [for]").each(function(){var e=this;["name","id","for"].forEach(function(f){var i=e.getAttribute(f);i&&-1!==i.indexOf("TEMPLATE")&&e.setAttribute(f,i.split("TEMPLATE").join(t))})}),e("#ffc-fields-container").append(c),c.find(".ffc-field-type-selector").val(f),l(c,f),v(c),c.find('input[type="text"]').first().trigger("focus"),c}function m(f){var i;try{i=JSON.parse(String(f.attr("data-ffc-required-fields")||"[]"))}catch(e){i=[]}Array.isArray(i)&&(i.forEach(function(f){if(f&&f.name){var i=g(f.type||"text");i&&function(f,i){var t=String(f.attr("data-index")),c="ffc_field_lock_"+t,n=f.find(".ffc-field-type-selector");f.addClass("ffc-field-row-required-tag"),f.find('input[name$="[label]"]').first().val(i.label||i.name),f.find('input[name$="[name]"]').first().val(i.name).prop("readonly",!0).attr("aria-describedby",c),n.removeAttr("name").prop("disabled",!0).attr("aria-describedby",c),e('').attr("name","ffc_fields["+t+"][type]").val(i.type).insertBefore(n),f.find(".ffc-field-required").prop("checked",!0).prop("disabled",!0),f.find(".ffc-remove-field").prop("disabled",!0).attr("aria-describedby",c);var a=e('').attr("id",c);a.append(' '),a.append(document.createTextNode(d().requiredField||"Required field")),f.find(".ffc-field-title").after(a)}(i,f)}}),f.closest(".ffc-required-fields-missing").remove())}e(document).on("click",".ffc-add-required-fields",function(f){f.preventDefault(),m(e(this))}),window.FFC=window.FFC||{},window.FFC.Admin=window.FFC.Admin||{},window.FFC.Admin.FieldBuilder={init:function(){var f=e("#ffc-fields-container");0!==f.length&&(n=0,n=u(),e(document).off("click.ffcFieldBuilder"),e(document).on("click.ffcFieldBuilder",".ffc-add-field",function(f){f.preventDefault(),function(f){e(".ffc-field-type-menu").remove();var i=e('
    ');i.append(e('
    ').text(d().chooseFieldType||"Choose Field Type:"));var t=e("
      ");("undefined"!=typeof ffc_ajax&&Array.isArray(ffc_ajax.fieldTypes)&&ffc_ajax.fieldTypes.length?ffc_ajax.fieldTypes:[{value:"checkbox",label:"Checkbox"},{value:"date",label:"Date"},{value:"select",label:"Dropdown Select"},{value:"email",label:"Email"},{value:"number",label:"Number"},{value:"radio",label:"Radio Buttons"},{value:"text",label:"Text"},{value:"textarea",label:"Textarea"},{value:"embed",label:"Embed (Media)"},{value:"hidden",label:"Hidden Field"},{value:"info",label:"Info Block"}]).forEach(function(f){var c=e('').attr("data-type",f.value).text(f.label);c.on("click",function(){g(f.value),i.remove()}),t.append(e("
    • ").append(c))}),i.append(t);var c=f.offset();i.css({position:"absolute",top:c.top+f.outerHeight()+5+"px",left:c.left+"px"}),e("body").append(i),i.find(".ffc-field-type-option").first().trigger("focus"),setTimeout(function(){e(document).one("click",function(){i.remove()})},100)}(e(this))}),e(document).on("click.ffcFieldBuilder",".ffc-remove-field",function(f){f.preventDefault(),confirm(d().confirmDeleteField||"Remove this field?")&&e(this).closest(".ffc-field-row").fadeOut(300,function(){e(this).remove()})}),f.on("change",".ffc-field-type-selector",function(){l(e(this).closest(".ffc-field-row"),e(this).val())}),f.on("click",".ffc-choice-add",function(f){f.preventDefault();var i=p(e(this).siblings(".ffc-choice-list"),"");i&&i.find(".ffc-choice-input").trigger("focus")}),f.on("click",".ffc-choice-remove",function(f){f.preventDefault();var i=e(this).closest(".ffc-choice-row"),t=i.closest(".ffc-field-row");i.siblings(".ffc-choice-row").length?i.remove():(i.find(".ffc-choice-input").val(""),h(i)),r(t)}),f.on("change",".ffc-choice-correct-input",function(){e(this).closest(".ffc-choice-row").find(".ffc-choice-correct-value").val(this.checked?"1":"0"),r(e(this).closest(".ffc-field-row"))}),f.on("change",".ffc-quiz-scored, .ffc-quiz-mode, .ffc-quiz-text",function(){o(e(this).closest(".ffc-field-row"))}),f.on("input change",'input[name$="[max_select]"]',function(){r(e(this).closest(".ffc-field-row"))}),e(document).off("change.ffcFieldBuilder"),e(document).on("change.ffcFieldBuilder","#ffc_quiz_enabled",s),s(),f.on("keydown",".ffc-choice-input",function(f){if("Enter"===f.key){f.preventDefault();var i=p(e(this).closest(".ffc-choice-list"),"");i&&(i.insertAfter(e(this).closest(".ffc-choice-row")),i.find(".ffc-choice-input").trigger("focus"))}}),e.fn.sortable&&f.sortable({handle:".ffc-sort-handle",placeholder:"ffc-field-placeholder"}),v(f))},addField:g,applyType:l,refreshQuiz:s,addRequiredFields:m},f&&f.registerModule&&f.registerModule("Admin.FieldBuilder",f.version)}(jQuery,window.FFC); //# sourceMappingURL=ffc-admin-field-builder.min.js.map \ No newline at end of file diff --git a/assets/js/ffc-certificate-settings.js b/assets/js/ffc-certificate-settings.js new file mode 100644 index 000000000..1dbcb0482 --- /dev/null +++ b/assets/js/ffc-certificate-settings.js @@ -0,0 +1,36 @@ +/** + * Settings → Certificates: the required-field table (#1741). + * + * Adds a row from the