Plugin Directory

Changeset 3748403


Ignore:
Timestamp:
10/15/2026 12:10:58 PM (3 weeks ago)
Author:
4wpdev
Message:

Update trunk to 2.6.5

Location:
4wp-faq/trunk
Files:
2 added
33 edited

Legend:

Unmodified
Added
Removed
  • 4wp-faq/trunk/4wp-faq.php

    r3704354 r3748403  
    44 * Plugin URI:        https://github.com/4wpdev/4wp-faq
    55 * Description: FAQ wrapper for core Accordion: JSON-LD, optional registry you can edit or add from (writes back onto pages), hub blocks, usage context. Site content stays the source of truth.
    6  * Version:           2.6.1
     6 * Version:           2.6.5
    77 * Requires at least: 6.6
    88 * Requires PHP:      7.4
    … …  
    2020}
    2121
    22 define( 'FORWP_FAQ_VERSION', '2.6.1' );
     22define( 'FORWP_FAQ_VERSION', '2.6.5' );
    2323define( 'FORWP_FAQ_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    2424define( 'FORWP_FAQ_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
  • 4wp-faq/trunk/assets/admin-dashboard.css

    r3685374 r3748403  
    22 * Classic FAQ dashboard widgets (wp-admin dashboard pattern).
    33 */
    4 
    5 /* Square postboxes — native wp-admin, not the rounded dashboard CSS. */
    6 body.forwp-faq-dashboard-page #dashboard-widgets .postbox,
    7 body.forwp-faq-dashboard-page #dashboard-widgets .postbox-container .empty-container,
    8 body.forwp-faq-dashboard-page.is-dragging-metaboxes #dashboard-widgets .meta-box-sortables {
    9         border-radius: 0;
    10 }
    114
    125/* Keep 3-col and 33/66 radios visible below 1500px (core dashboard.css hides them). */
    … …  
    1710
    1811@media screen and (min-width: 800px) {
    19         /* 2 columns: 50 / 50 */
    20         body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 .postbox-container,
    21         body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-1,
    22         body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-2,
    23         body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-3,
    24         body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-4 {
    25                 width: 50%;
     12        /* 2 columns: same split as the WordPress dashboard, so the third column stacks on the right. */
     13        body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-1 {
     14                float: left;
     15                width: 49.5%;
    2616        }
    2717
    … …  
    3020        body.forwp-faq-dashboard-page #wpbody-content #dashboard-widgets.columns-2 #postbox-container-4 {
    3121                float: right;
     22                clear: right;
     23                width: 50.5%;
    3224        }
    3325
    … …  
    173165}
    174166
    175 #dashboard-widgets #forwp_faq_status .inside {
    176         margin: 0;
    177         padding: 0;
     167#dashboard-widgets #forwp_faq_status .inside,
     168#dashboard-widgets #forwp_faq_home .inside {
     169        margin: 0;
     170        padding: 0;
     171}
     172
     173#dashboard-widgets .forwp-faq-stats {
     174        display: grid;
     175        grid-template-columns: 1fr 1fr;
     176}
     177
     178#dashboard-widgets .forwp-faq-stat-cell {
     179        display: block;
     180        padding: 16px 8px;
     181        border-top: 1px solid #f0f0f1;
     182        text-align: center;
     183        text-decoration: none;
     184}
     185
     186#dashboard-widgets .forwp-faq-stat-cell:nth-child(-n + 2) {
     187        border-top: 0;
     188}
     189
     190#dashboard-widgets .forwp-faq-stat-cell:nth-child(odd) {
     191        border-right: 1px solid #f0f0f1;
     192}
     193
     194#dashboard-widgets .forwp-faq-stat-cell:hover,
     195#dashboard-widgets .forwp-faq-stat-cell:focus {
     196        background: #f6f7f7;
     197}
     198
     199#dashboard-widgets .forwp-faq-stat-cell__value {
     200        display: block;
     201        color: #1d2327;
     202        font-size: 28px;
     203        font-weight: 600;
     204        line-height: 1;
     205}
     206
     207#dashboard-widgets .forwp-faq-stat-cell__label {
     208        display: block;
     209        margin-top: 4px;
     210        color: #646970;
     211        font-size: 13px;
     212        line-height: 1.3;
    178213}
    179214
    … …  
    371406        border-top: 1px solid #f0f0f1;
    372407}
     408
     409#dashboard-widgets .forwp-faq-dash-lang {
     410        margin: 0;
     411        padding: 8px 12px;
     412        border-bottom: 1px solid #f0f0f1;
     413        color: #50575e;
     414        font-size: 12px;
     415}
     416
     417#dashboard-widgets .forwp-faq-dash-langs {
     418        margin: 0;
     419        border-width: 0 0 1px;
     420}
     421
     422#dashboard-widgets .forwp-faq-dash-langs th:first-child,
     423#dashboard-widgets .forwp-faq-dash-langs td:first-child {
     424        padding-left: 12px;
     425}
     426
     427#dashboard-widgets .forwp-faq-dash-langs th,
     428#dashboard-widgets .forwp-faq-dash-langs td {
     429        padding: 4px 8px;
     430        font-size: 12px;
     431}
  • 4wp-faq/trunk/assets/faq-view.js

    r3691205 r3748403  
    3030};
    3131
     32const normalizePath = ( path ) =>
     33        ( path || '' ).replace( /\/+$/, '' ) || '/';
     34
     35/**
     36 * Category from ?faq_cat= or a pretty /hub/term-slug/ URL.
     37 * Match the full nav href path — never the host page slug alone
     38 * (e.g. /4wp-faq/ must not activate category "4wp-faq").
     39 */
    3240const categoryFromLocation = () => {
    3341        const params = new URLSearchParams( window.location.search || '' );
    … …  
    3745        }
    3846
    39         const currentPath = ( window.location.pathname || '' ).replace( /\/+$/, '' );
    40         const last = currentPath.split( '/' ).filter( Boolean ).pop() || '';
    41         if ( ! last ) {
    42                 return '';
    43         }
    44 
     47        const currentPath = normalizePath( window.location.pathname || '' );
    4548        const links = document.querySelectorAll(
    4649                '.forwp-faq-categories__link[data-faq-cat]'
    … …  
    4851        let match = '';
    4952        links.forEach( ( link ) => {
    50                 const slug = link.getAttribute( 'data-faq-cat' ) || '';
    51                 if ( slug && slug === last ) {
    52                         match = slug;
     53                const slug = ( link.getAttribute( 'data-faq-cat' ) || '' ).trim();
     54                if ( ! slug || match ) {
     55                        return;
     56                }
     57                const href = link.getAttribute( 'href' ) || '';
     58                if ( ! href || href === '#' ) {
     59                        return;
     60                }
     61                try {
     62                        const linkPath = normalizePath(
     63                                new URL( href, window.location.origin ).pathname || ''
     64                        );
     65                        if ( linkPath === currentPath ) {
     66                                match = slug;
     67                        }
     68                } catch ( e ) {
     69                        // Ignore malformed hrefs.
    5370                }
    5471        } );
    … …  
    6784};
    6885
     86// Without a search the badge shows the category nav totals, not the cards on screen (preview limit).
     87const currentCount = () => {
     88        if ( ! String( state.search || '' ).trim() ) {
     89                const total = state.totals?.[ state.category || '' ];
     90                if ( typeof total === 'number' ) {
     91                        return total;
     92                }
     93        }
     94        return countVisibleCards();
     95};
     96
    6997const { state } = store( 'forwp/faq', {
    7098        state: {
    … …  
    94122                        return ! state.isBranchOpen;
    95123                },
     124                get isMenuOpen() {
     125                        return !! state.menuOpen;
     126                },
     127                get hasNoResults() {
     128                        return (
     129                                !! String( state.search || '' ).trim() && state.visibleCount === 0
     130                        );
     131                },
    96132                get isGroupVisible() {
    97133                        const ctx = getContext() || {};
    98                         if ( ! state.category ) {
    99                                 return true;
    100                         }
    101                         if ( ( ctx.slug || '' ) === state.category ) {
    102                                 return true;
    103                         }
    104                         const ancestors = ( ctx.ancestors || '' ).split( /\s+/ ).filter( Boolean );
    105                         return ancestors.indexOf( state.category ) !== -1;
     134                        if ( state.category ) {
     135                                const slug = ctx.slug || '';
     136                                const ancestors = ( ctx.ancestors || '' )
     137                                        .split( /\s+/ )
     138                                        .filter( Boolean );
     139                                const isSelf = slug === state.category;
     140                                const isDescendant =
     141                                        ancestors.indexOf( state.category ) !== -1;
     142                                // Keep parents of the active category visible (nested list HTML).
     143                                const isAncestor =
     144                                        ( state.categoryAncestors || [] ).indexOf( slug ) !== -1;
     145                                if ( ! isSelf && ! isDescendant && ! isAncestor ) {
     146                                        return false;
     147                                }
     148                        }
     149                        const query = ( state.search || '' ).trim().toLowerCase();
     150                        if ( query && ( ctx.searchText || '' ).indexOf( query ) === -1 ) {
     151                                return false;
     152                        }
     153                        return true;
    106154                },
    107155                get isItemVisible() {
    … …  
    119167        },
    120168        actions: {
     169                toggleMenu( event ) {
     170                        if ( event && typeof event.preventDefault === 'function' ) {
     171                                event.preventDefault();
     172                        }
     173                        state.menuOpen = ! state.menuOpen;
     174                },
    121175                toggleBranch: withSyncEvent( ( event ) => {
    122176                        if ( event && typeof event.preventDefault === 'function' ) {
    … …  
    149203                                event.preventDefault();
    150204                        }
    151                         state.category = ctx.slug || '';
     205                        applyCategory( ctx.slug || '', ctx.ancestors || '' );
    152206                        window.requestAnimationFrame( () => {
    153                                 state.visibleCount = countVisibleCards();
     207                                state.visibleCount = currentCount();
    154208                        } );
    155209                },
    … …  
    159213                                target && typeof target.value === 'string' ? target.value : '';
    160214                        window.requestAnimationFrame( () => {
    161                                 state.visibleCount = countVisibleCards();
     215                                state.visibleCount = currentCount();
    162216                        } );
    163217                },
    … …  
    169223        },
    170224} );
     225
     226const ancestorsForSlug = ( slug ) => {
     227        if ( ! slug ) {
     228                return [];
     229        }
     230        const groups = document.querySelectorAll( '.forwp-faq-list__group' );
     231        for ( let i = 0; i < groups.length; i++ ) {
     232                const raw = groups[ i ].getAttribute( 'data-wp-context' );
     233                if ( ! raw ) {
     234                        continue;
     235                }
     236                try {
     237                        const ctx = JSON.parse( raw );
     238                        if ( ( ctx.slug || '' ) === slug ) {
     239                                return String( ctx.ancestors || '' )
     240                                        .split( /\s+/ )
     241                                        .filter( Boolean );
     242                        }
     243                } catch ( e ) {
     244                        // Ignore malformed context.
     245                }
     246        }
     247        return [];
     248};
     249
     250const applyCategory = ( slug, ancestorsRaw ) => {
     251        state.category = slug || '';
     252        if ( ! slug ) {
     253                state.categoryAncestors = [];
     254                return;
     255        }
     256        if ( typeof ancestorsRaw === 'string' && ancestorsRaw.trim() ) {
     257                state.categoryAncestors = ancestorsRaw.split( /\s+/ ).filter( Boolean );
     258                return;
     259        }
     260        state.categoryAncestors = ancestorsForSlug( slug );
     261};
    171262
    172263if ( ! state.category ) {
    173264        const fromUrl = categoryFromLocation();
    174265        if ( fromUrl ) {
    175                 state.category = fromUrl;
    176         }
     266                applyCategory( fromUrl );
     267        }
     268} else if ( ! Array.isArray( state.categoryAncestors ) ) {
     269        state.categoryAncestors = ancestorsForSlug( state.category );
    177270}
    178271
    … …  
    182275
    183276if ( typeof state.visibleCount !== 'number' ) {
    184         state.visibleCount = countVisibleCards();
     277        state.visibleCount = currentCount();
    185278}
    186279
    187280window.addEventListener( 'popstate', () => {
    188         state.category = categoryFromLocation();
    189         state.visibleCount = countVisibleCards();
     281        applyCategory( categoryFromLocation() );
     282        state.visibleCount = currentCount();
    190283} );
  • 4wp-faq/trunk/blocks/faq-card/block.json

    r3698640 r3748403  
    3030                        "default": "Used in"
    3131                },
     32                "sourcesSeparator": {
     33                        "type": "string",
     34                        "default": ", "
     35                },
    3236                "showPostType": {
    3337                        "type": "boolean",
  • 4wp-faq/trunk/blocks/faq-categories/block.json

    r3698640 r3748403  
    5757                                "type": "number"
    5858                        }
     59                },
     60                "allItemFontSize": {
     61                        "type": "string",
     62                        "default": ""
     63                },
     64                "itemFontSize": {
     65                        "type": "string",
     66                        "default": ""
     67                },
     68                "itemGap": {
     69                        "type": "string",
     70                        "default": ""
    5971                }
    6072        },
  • 4wp-faq/trunk/blocks/faq-list/block.json

    r3698640 r3748403  
    4646                        "default": "Used in"
    4747                },
     48                "cardSourcesSeparator": {
     49                        "type": "string",
     50                        "default": ", "
     51                },
    4852                "cardShowPostType": {
    4953                        "type": "boolean",
    … …  
    5559                },
    5660                "cardAnswerStyle": {
     61                        "type": "object",
     62                        "default": {}
     63                },
     64                "groupTitleStyle": {
    5765                        "type": "object",
    5866                        "default": {}
  • 4wp-faq/trunk/build/admin/index.asset.php

    r3702258 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '73eae73b8f871db33b20');
     1<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'b6827ecaf8c95084b4cb');
  • 4wp-faq/trunk/build/admin/index.js

    r3702258 r3748403  
    1 (()=>{"use strict";var e,t={476(e,t,a){const n=window.React,l=window.wp.element,r=window.wp.i18n,o=window.wp.apiFetch;var s=a.n(o);const i=window.wp.components,c="/forwp-faq/v1/settings";function p({label:e,value:t,hint:a}){return(0,n.createElement)("div",{className:"forwp-faq-stat"},(0,n.createElement)("span",{className:"forwp-faq-stat__value"},t),(0,n.createElement)("span",{className:"forwp-faq-stat__label"},e),a?(0,n.createElement)("span",{className:"forwp-faq-stat__hint"},a):null)}function u({stats:e,setupComplete:t,lastScan:a}){return e?(0,n.createElement)(i.Card,{className:"forwp-faq-stats-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Overview","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("div",{className:"forwp-faq-stats-grid"},(0,n.createElement)(p,{label:(0,r.__)("Questions","4wp-faq"),value:t?e.total_questions:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Categories","4wp-faq"),value:t?e.faq_categories:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Reused","4wp-faq"),value:t?e.reused_questions:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Items in content","4wp-faq"),value:e.faq_items_in_content}),(0,n.createElement)(p,{label:(0,r.__)("Pages with FAQ","4wp-faq"),value:e.pages_with_faq})),a?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,r.sprintf)(/* translators: %s: date/time */ /* translators: %s: date/time */
    2 (0,r.__)("Last scan: %s","4wp-faq"),a)):null)):null}function d(){const[e,t]=(0,l.useState)(!0),[a,o]=(0,l.useState)(!1),[p,d]=(0,l.useState)(!1),[f,m]=(0,l.useState)(!1),[_,w]=(0,l.useState)(!1),[g,h]=(0,l.useState)(null),[q,E]=(0,l.useState)(null),[y,b]=(0,l.useState)(""),[v,A]=(0,l.useState)(""),[C,k]=(0,l.useState)(!1),N=(0,l.useCallback)(()=>(t(!0),b(""),Promise.all([s()({path:c}),s()({path:"/forwp-faq/v1/registry"})]).then(([e,t])=>{E(e),h(t)}).catch(e=>{b(e?.message||(0,r.__)("Could not load settings.","4wp-faq"))}).finally(()=>t(!1))),[]);if((0,l.useEffect)(()=>{!function(){if("undefined"==typeof window||!window.forwpFaqAdmin||window.forwpFaqAdmin.__middlewareApplied)return;const{restRoot:e,nonce:t}=window.forwpFaqAdmin,a=e.endsWith("/")?e:`${e}/`;s().use(s().createRootURLMiddleware(a)),s().use(s().createNonceMiddleware(t)),window.forwpFaqAdmin.__middlewareApplied=!0}(),N()},[N]),e)return(0,n.createElement)("div",{className:"forwp-faq-tab-loading"},(0,n.createElement)(i.Spinner,null));const O=g?.setup_complete,S=!0===q?.output_json_ld,F=q?.preview_per_category||5,P=!0===q?.seo_urls,Q=!0===q?.ai_available,L=!0===q?.ai_field_markup;return(0,n.createElement)("div",{className:"forwp-faq-settings-layout"},v?(0,n.createElement)(i.Notice,{status:"success",isDismissible:!0,onRemove:()=>A("")},v):null,y?(0,n.createElement)(i.Notice,{status:"error",isDismissible:!1},y):null,(0,n.createElement)(u,{stats:g?.stats,setupComplete:O,lastScan:g?.last_scan_label}),(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Settings","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("div",{className:"forwp-faq-actions-row"},(0,n.createElement)(i.Button,{variant:"primary",onClick:()=>{o(!0),A(""),b(""),s()({path:"/forwp-faq/v1/registry/scan",method:"POST"}).then(e=>{h(e),A((0,r.__)("Registry scan completed.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Scan failed. Please try again.","4wp-faq"))}).finally(()=>o(!1))},isBusy:a,disabled:a||!O},a?(0,r.__)("Scanning…","4wp-faq"):(0,r.__)("Rescan registry","4wp-faq")),!O&&g?.setup_url?(0,n.createElement)(i.ExternalLink,{href:g.setup_url},(0,r.__)("Complete setup to enable scan","4wp-faq")):null),O&&g?.last_scan_label?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,r.sprintf)(/* translators: %s: date/time */ /* translators: %s: date/time */
    3 (0,r.__)("Last scan: %s","4wp-faq"),g.last_scan_label)):null,(0,n.createElement)("hr",{className:"forwp-faq-actions-divider"}),(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("FAQPage JSON-LD","4wp-faq"),help:(0,r.__)("On: schema for questions actually shown. Per-block override still applies.","4wp-faq"),checked:S,disabled:p,onChange:e=>{d(!0),b(""),s()({path:c,method:"POST",data:{output_json_ld:e}}).then(t=>{E(t),A(e?(0,r.__)("JSON-LD enabled site-wide.","4wp-faq"):(0,r.__)("JSON-LD disabled site-wide.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save SEO setting.","4wp-faq"))}).finally(()=>d(!1))}}),(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("Pretty category URLs","4wp-faq"),help:(0,r.__)("Allows /page/term-slug/. Also enable it on the Categories block. Off: in-place filter, URL unchanged.","4wp-faq"),checked:P,disabled:p,onChange:e=>{d(!0),b(""),s()({path:c,method:"POST",data:{seo_urls:e}}).then(t=>{E(t),A(e?(0,r.__)("Pretty category URLs enabled. Turn on SEO-friendly category URLs in the 4WP FAQ Categories block on each hub page.","4wp-faq"):(0,r.__)("Pretty category URLs disabled. Category clicks filter in place and the page URL stays unchanged.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save SEO setting.","4wp-faq"))}).finally(()=>d(!1))}}),(0,n.createElement)(i.RangeControl,{label:(0,r.__)("Questions per group (All view)","4wp-faq"),help:(0,r.__)("Preview count on All categories. Category URLs still list every question.","4wp-faq"),value:F,onChange:e=>{const t="number"==typeof e?e:5;d(!0),b(""),s()({path:c,method:"POST",data:{preview_per_category:t}}).then(e=>{E(e),A((0,r.__)("Preview count saved.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save setting.","4wp-faq"))}).finally(()=>d(!1))},min:1,max:20,disabled:p}),O?(0,n.createElement)(n.Fragment,null,(0,n.createElement)("hr",{className:"forwp-faq-actions-divider"}),(0,n.createElement)("p",{className:"forwp-faq-reset-intro"},(0,r.__)("Reset setup to change CPT/taxonomy slugs. Categories are removed.","4wp-faq")),(0,n.createElement)(i.Button,{variant:"secondary",isDestructive:!0,onClick:()=>k(!0)},(0,r.__)("Reset setup","4wp-faq"))):null)),(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("AI","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("p",null,(0,r.__)("Uses WordPress Connectors. One prompt fills mapped fields on FAQ category edit. Apply writes into the form; Update still saves.","4wp-faq")),Q?null:(0,n.createElement)(i.Notice,{status:"warning",isDismissible:!1},(0,r.__)("WordPress Connectors are not available yet. Configure a text provider, then enable the option below.","4wp-faq"),q?.ai_connectors_url?(0,n.createElement)(n.Fragment,null," ",(0,n.createElement)(i.ExternalLink,{href:q.ai_connectors_url},(0,r.__)("Open Connectors","4wp-faq"))):null),(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("Allow predefined field markup","4wp-faq"),help:Q?(0,r.__)("On: show Generate with AI on category screens. Off: keep the panel hidden.","4wp-faq"):(0,r.__)("Turn on after WordPress Connectors support text generation.","4wp-faq"),checked:Q&&L,disabled:f||!Q,onChange:e=>{m(!0),b(""),s()({path:c,method:"POST",data:{ai_field_markup:e}}).then(t=>{E(t),A(e?(0,r.__)("Predefined field markup enabled. Generate with AI can fill mapped category fields.","4wp-faq"):(0,r.__)("Predefined field markup disabled. The AI panel stays hidden on category screens.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save AI setting.","4wp-faq"))}).finally(()=>m(!1))}}),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Description","4wp-faq"))," — ",(0,r.__)("Core category Description.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Display title","4wp-faq"))," — ",(0,r.__)("On-page title on pretty category URLs.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO title","4wp-faq"))," — ",(0,r.__)("Document title. No site name suffix.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO description","4wp-faq"))," — ",(0,r.__)("Meta description on category URLs.","4wp-faq"))),q?.ai_connectors_url?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,n.createElement)(i.ExternalLink,{href:q.ai_connectors_url},(0,r.__)("WordPress Connectors","4wp-faq"))):null)),(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Category titles","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("p",null,(0,r.__)("On pretty category URLs (/page/term-slug/). Edit fields on each FAQ category.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("On-page title","4wp-faq"))," — ",(0,r.__)("Display title (empty: category name). Put a core Title (post-title), Query Title / Archive title (query-title), or Term Name (term-name). Heading level is the template’s choice. Heading blocks are not swapped.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("On-page description","4wp-faq"))," — ",(0,r.__)("Category Description field. Put a core Excerpt (post-excerpt) or Term Description (term-description). Empty description: WordPress output is left as-is.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Document title","4wp-faq"))," — ",(0,r.__)("SEO title as-is if filled (no site-name suffix). Empty: on-page title + “ – {site name}”.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Meta description","4wp-faq"))," — ",(0,r.__)("SEO description. Empty: hub page default.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Canonical","4wp-faq"))," — ",(0,r.__)("The category URL (/page/term-slug/), not the hub.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO image","4wp-faq"))," — ",(0,r.__)("Open Graph / Twitter image on the category. Empty: hub page image.","4wp-faq"))))),C?(0,n.createElement)(i.Modal,{title:(0,r.__)("Reset FAQ setup?","4wp-faq"),onRequestClose:()=>!_&&k(!1),shouldCloseOnClickOutside:!_,shouldCloseOnEsc:!_},(0,n.createElement)("p",null,(0,r.__)("You can choose new registry slugs in the setup wizard, but all FAQ categories will be removed. Registry entries stay on the previous post type until you complete setup and run a new scan.","4wp-faq")),(0,n.createElement)("div",{className:"forwp-faq-modal-actions"},(0,n.createElement)(i.Button,{variant:"secondary",onClick:()=>k(!1),disabled:_},(0,r.__)("Cancel","4wp-faq")),(0,n.createElement)(i.Button,{variant:"primary",isDestructive:!0,isBusy:_,disabled:_,onClick:()=>{w(!0),b(""),s()({path:"/forwp-faq/v1/setup/reset",method:"POST"}).then(e=>{k(!1),e?.redirect&&(window.location.href=e.redirect)}).catch(e=>{b(e?.message||(0,r.__)("Reset failed. Please try again.","4wp-faq")),k(!1)}).finally(()=>w(!1))}},(0,r.__)("Reset setup","4wp-faq")))):null)}function f({title:e,children:t}){return(0,n.createElement)(i.Card,{className:"forwp-faq-doc-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,e)),(0,n.createElement)(i.CardBody,{className:"forwp-faq-doc-card__body"},t))}function m(){return(0,n.createElement)("div",{className:"forwp-faq-docs-layout"},(0,n.createElement)(f,{title:(0,r.__)("Overview","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("4WP FAQ is a thin wrapper around WordPress core Accordion. It does not replace your blocks or theme styles. It adds an intelligence layer: FAQPage JSON-LD on the front end, optional aggregation into a FAQ registry post type, and usage statistics in the admin.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Your questions and answers live in page content (Accordion items). That is the source of truth. The registry is a scan of unique questions. Edit a registry record and Update: the plugin writes the new Q/A onto every Used In page. Add FAQ to place a new item. Delete the registry or reinstall: a scan rebuilds it from the site.","4wp-faq"))),(0,n.createElement)(f,{title:(0,r.__)("Convert to FAQ","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("You can convert an existing Accordion, Accordion Item, Accordion Group, Details, List, or heading + paragraph pairs into a 4WP FAQ block without rebuilding the layout.","4wp-faq")),(0,n.createElement)("ol",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Select a core Accordion, Accordion Item, Accordion Group, Details, or List in the editor. You can select several Details or Accordion Items at once.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("In the block toolbar, click Convert to 4WP FAQ, or use Transform to → 4WP FAQ.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("The plugin wraps your markup in forwp/faq. Inner Accordion or Details blocks and styling stay the same on the front end.","4wp-faq"))),(0,n.createElement)("p",null,(0,r.__)("Each Accordion Item (or legacy Details block) inside the wrapper counts as one FAQ question for JSON-LD and for the registry scan.","4wp-faq"))),(0,n.createElement)(f,{title:(0,r.__)("Block structure","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Recommended pattern (WordPress 6.x core Accordion):","4wp-faq")),(0,n.createElement)("pre",{className:"forwp-faq-doc-pre"},(0,n.createElement)("code",null,"forwp/faq                    ← 4WP FAQ wrapper\n└── core/accordion           ← container\n    └── core/accordion-item  ← one Q&A\n        ├── accordion heading\n        └── accordion panel")),(0,n.createElement)("p",null,(0,r.__)("Legacy core/details blocks inside forwp/faq are still supported. Prefer Accordion + Accordion Item for new pages.","4wp-faq"))),(0,n.createElement)(f,{title:(0,r.__)("Blocks for pages","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Use these blocks when building a FAQ hub or in-page FAQs:","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq")," — ",(0,r.__)("Wrapper around core Accordion or Details for JSON-LD and registry scan. Convert / Transform to 4WP FAQ in the editor.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-list")," — ",(0,r.__)("Registry glossary (grouped or flat). Place on a page or template after setup + scan.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-card")," — ",(0,r.__)("Inner template of the List (not in the inserter). Accordion or heading + answer; optional sources.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-categories")," — ",(0,r.__)("Category nav. Include/exclude stay in sync with the List on the same page.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-count")," — ",(0,r.__)("Live number for All / current category / current search. Same as [forwp_faq_count].","4wp-faq"))),(0,n.createElement)("pre",{className:"forwp-faq-doc-pre"},(0,n.createElement)("code",null,"forwp/faq-categories         ← nav (optional)\nforwp/faq-list               ← registry questions\n└── forwp/faq-card\ncore/search                  ← optional filter\nforwp/faq-count              ← optional count"))),(0,n.createElement)(f,{title:(0,r.__)("Core Search block","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Add a core Search block on the same page as 4WP FAQ List. In the block sidebar open 4WP FAQ and turn on Filter 4WP FAQ List.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Typing filters visible FAQ cards through the Interactivity store. The form does not submit a WordPress search.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("FAQ Count follows the same search query when the filter is on.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Leave the toggle off if the Search should behave as a normal site search.","4wp-faq")))),(0,n.createElement)(f,{title:(0,r.__)("JSON-LD (SEO)","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("On singular posts and pages, the plugin can output FAQPage structured data (JSON-LD) in the document head when FAQ blocks are present.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Site-wide default: Settings → FAQPage JSON-LD (off by default).","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("When enabled site-wide: every forwp/faq block outputs schema unless you set JSON-LD on front end → Off for this block in the block sidebar.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("When disabled site-wide: no schema by default; enable per block with On for this block in the sidebar.","4wp-faq"))),(0,n.createElement)("p",{className:"forwp-faq-doc-muted"},(0,r.__)("JSON-LD does not require the FAQ registry. Blocks and schema work even if you never complete registry setup.","4wp-faq"))),(0,n.createElement)(f,{title:(0,r.__)("FAQ registry (optional)","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("After you complete setup (Settings → 4WP FAQ Setup), the plugin registers a custom post type and taxonomy (default slugs: faq and faq-category).","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("A scan walks content, finds forwp/faq blocks, and creates or updates registry posts—one per unique question—with usage, categories, and answer snapshots.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Where the question is used (pages, posts, other types)","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("How many times it appears (reuse count)","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Collected answer text and HTML snapshots","4wp-faq"))),(0,n.createElement)("p",null,(0,r.__)("Edit a registry FAQ (title + answer) and Update. The plugin finds that accordion item on every Used In page. If you change the question, it matches the previous title.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Add FAQ: write the question and answer. FAQ categories in the sidebar append the item to every forwp/faq block with those terms. One page (optional) writes only to that post/page. Neither: the row stays in the list until a scan, then it is dropped because it is not on the site.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("A new answer reuses the wrapper of a sibling accordion item on that page (same heading/panel markup) and fills in your text. After save, that wrapped HTML is stored on the registry record.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Run Rescan after you change FAQ content on pages. Registry Update also writes back to those pages, then a scan is scheduled. Scans also run when relevant posts are saved.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Reset setup (Settings tab) lets you change registry slugs in the wizard again but removes all FAQ categories; existing registry entries stay on the previous post type until you complete setup and scan again.","4wp-faq"))),(0,n.createElement)(f,{title:(0,r.__)("Typical workflow","4wp-faq")},(0,n.createElement)("ol",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Add or convert Accordion blocks to forwp/faq on your pages.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Enable JSON-LD on the Settings tab if you want structured data site-wide.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Optional: complete FAQ registry setup and run a scan. Then you can edit a registry FAQ (pushes to Used In pages) or Add FAQ onto category pages / one page.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Review Dashboard stats and open All FAQs under the FAQ admin menu.","4wp-faq")))))}const _=document.getElementById("forwp-faq-admin-root");_&&(0,l.createRoot)(_).render((0,n.createElement)(function(){const[e,t]=(0,l.useState)("settings");return(0,n.createElement)("div",{className:"forwp-faq-admin-app"},(0,n.createElement)("div",{className:"forwp-faq-tab-panel components-tab-panel"},(0,n.createElement)("div",{className:"components-tab-panel__tabs",role:"tablist","aria-label":(0,r.__)("4WP FAQ","4wp-faq")},(0,n.createElement)("button",{type:"button",role:"tab",id:"forwp-faq-tab-settings",className:"components-button components-tab-panel__tabs-item forwp-faq-tab-settings"+("settings"===e?" is-active":""),"aria-selected":"settings"===e,"aria-controls":"forwp-faq-panel-settings",tabIndex:"settings"===e?0:-1,onClick:()=>t("settings")},(0,r.__)("Settings","4wp-faq")),(0,n.createElement)("button",{type:"button",role:"tab",id:"forwp-faq-tab-documentation",className:"components-button components-tab-panel__tabs-item forwp-faq-tab-docs"+("documentation"===e?" is-active":""),"aria-selected":"documentation"===e,"aria-controls":"forwp-faq-panel-documentation",tabIndex:"documentation"===e?0:-1,onClick:()=>t("documentation")},(0,r.__)("Documentation","4wp-faq"))),(0,n.createElement)("div",{id:"forwp-faq-panel-settings",role:"tabpanel","aria-labelledby":"forwp-faq-tab-settings",className:"components-tab-panel__tab-content",hidden:"settings"!==e},(0,n.createElement)(d,null)),(0,n.createElement)("div",{id:"forwp-faq-panel-documentation",role:"tabpanel","aria-labelledby":"forwp-faq-tab-documentation",className:"components-tab-panel__tab-content",hidden:"documentation"!==e},(0,n.createElement)(m,null))))},null))}},a={};function n(e){var l=a[e];if(void 0!==l)return l.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,n),r.exports}n.m=t,e=[],n.O=(t,a,l,r)=>{if(!a){var o=1/0;for(p=0;p<e.length;p++){for(var[a,l,r]=e[p],s=!0,i=0;i<a.length;i++)(!1&r||o>=r)&&Object.keys(n.O).every(e=>n.O[e](a[i]))?a.splice(i--,1):(s=!1,r<o&&(o=r));if(s){e.splice(p--,1);var c=l();void 0!==c&&(t=c)}}return t}r=r||0;for(var p=e.length;p>0&&e[p-1][2]>r;p--)e[p]=e[p-1];e[p]=[a,l,r]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={773:0,641:0};n.O.j=t=>0===e[t];var t=(t,a)=>{var l,r,[o,s,i]=a,c=0;if(o.some(t=>0!==e[t])){for(l in s)n.o(s,l)&&(n.m[l]=s[l]);if(i)var p=i(n)}for(t&&t(a);c<o.length;c++)r=o[c],n.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return n.O(p)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var l=n.O(void 0,[641],()=>n(476));l=n.O(l)})();
     1(()=>{"use strict";var e,t={476(e,t,a){const n=window.React,l=window.wp.element,r=window.wp.i18n,s=window.wp.apiFetch;var o=a.n(s);const i=window.wp.components,c="/forwp-faq/v1/settings";function p({label:e,value:t,hint:a}){return(0,n.createElement)("div",{className:"forwp-faq-stat"},(0,n.createElement)("span",{className:"forwp-faq-stat__value"},t),(0,n.createElement)("span",{className:"forwp-faq-stat__label"},e),a?(0,n.createElement)("span",{className:"forwp-faq-stat__hint"},a):null)}function f({stats:e,setupComplete:t,lastScan:a}){return e?(0,n.createElement)(i.Card,{className:"forwp-faq-stats-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Overview","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("div",{className:"forwp-faq-stats-grid"},(0,n.createElement)(p,{label:(0,r.__)("Questions","4wp-faq"),value:t?e.total_questions:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Categories","4wp-faq"),value:t?e.faq_categories:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Reused","4wp-faq"),value:t?e.reused_questions:"—"}),(0,n.createElement)(p,{label:(0,r.__)("Items in content","4wp-faq"),value:e.faq_items_in_content}),(0,n.createElement)(p,{label:(0,r.__)("Pages with FAQ","4wp-faq"),value:e.pages_with_faq})),a?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,r.sprintf)(/* translators: %s: date/time */ /* translators: %s: date/time */
     2(0,r.__)("Last scan: %s","4wp-faq"),a)):null)):null}function u(){const[e,t]=(0,l.useState)(!0),[a,s]=(0,l.useState)(!1),[p,u]=(0,l.useState)(!1),[d,m]=(0,l.useState)(!1),[_,w]=(0,l.useState)(!1),[q,g]=(0,l.useState)(null),[h,E]=(0,l.useState)(null),[y,b]=(0,l.useState)(""),[v,A]=(0,l.useState)(""),[C,N]=(0,l.useState)(!1),[O,k]=(0,l.useState)(null),S=(0,l.useCallback)(()=>(t(!0),b(""),Promise.all([o()({path:c}),o()({path:"/forwp-faq/v1/registry"})]).then(([e,t])=>{E(e),g(t)}).catch(e=>{b(e?.message||(0,r.__)("Could not load settings.","4wp-faq"))}).finally(()=>t(!1))),[]);if((0,l.useEffect)(()=>{!function(){if("undefined"==typeof window||!window.forwpFaqAdmin||window.forwpFaqAdmin.__middlewareApplied)return;const{restRoot:e,nonce:t}=window.forwpFaqAdmin,a=e.endsWith("/")?e:`${e}/`;o().use(o().createRootURLMiddleware(a)),o().use(o().createNonceMiddleware(t)),window.forwpFaqAdmin.__middlewareApplied=!0}(),S()},[S]),e)return(0,n.createElement)("div",{className:"forwp-faq-tab-loading"},(0,n.createElement)(i.Spinner,null));const F=q?.setup_complete,P=!0===h?.output_json_ld,Q=h?.preview_per_category||5,L=!0===h?.seo_urls,R=!0===h?.ai_available,D=!0===h?.ai_field_markup;return(0,n.createElement)("div",{className:"forwp-faq-settings-layout"},v?(0,n.createElement)(i.Notice,{status:"success",isDismissible:!0,onRemove:()=>A("")},v):null,y?(0,n.createElement)(i.Notice,{status:"error",isDismissible:!1},y):null,O?(0,n.createElement)(i.Button,{className:"forwp-faq-section-back",variant:"tertiary",onClick:()=>k(null)},(0,r.__)("Overview","4wp-faq")):(0,n.createElement)(n.Fragment,null,(0,n.createElement)(f,{stats:q?.stats,setupComplete:F,lastScan:q?.last_scan_label}),(0,n.createElement)("div",{className:"forwp-faq-overview-grid"},(0,n.createElement)("button",{type:"button",className:"forwp-faq-overview-card",onClick:()=>k("registry")},(0,n.createElement)("span",{className:"forwp-faq-overview-card__title"},(0,r.__)("Registry","4wp-faq")),(0,n.createElement)("span",{className:"forwp-faq-overview-card__summary"},F?q?.last_scan_label?(0,r.sprintf)(/* translators: %s: date/time */ /* translators: %s: date/time */
     3(0,r.__)("Last scan: %s","4wp-faq"),q.last_scan_label):(0,r.__)("Not scanned yet.","4wp-faq"):(0,r.__)("Setup is not complete.","4wp-faq"))),(0,n.createElement)("button",{type:"button",className:"forwp-faq-overview-card",onClick:()=>k("seo")},(0,n.createElement)("span",{className:"forwp-faq-overview-card__title"},(0,r.__)("SEO","4wp-faq")),(0,n.createElement)("span",{className:"forwp-faq-overview-card__summary"},(0,r.sprintf)(/* translators: 1: on/off, 2: on/off, 3: count */ /* translators: 1: on/off, 2: on/off, 3: count */
     4(0,r.__)("JSON-LD %1$s · Pretty URLs %2$s · %3$d per group","4wp-faq"),P?(0,r.__)("On","4wp-faq"):(0,r.__)("Off","4wp-faq"),L?(0,r.__)("On","4wp-faq"):(0,r.__)("Off","4wp-faq"),Q))),(0,n.createElement)("button",{type:"button",className:"forwp-faq-overview-card",onClick:()=>k("ai")},(0,n.createElement)("span",{className:"forwp-faq-overview-card__title"},(0,r.__)("AI","4wp-faq")),(0,n.createElement)("span",{className:"forwp-faq-overview-card__summary"},R?D?(0,r.__)("Field markup is on.","4wp-faq"):(0,r.__)("Field markup is off.","4wp-faq"):(0,r.__)("WordPress Connectors are not available.","4wp-faq"))),(0,n.createElement)("button",{type:"button",className:"forwp-faq-overview-card",onClick:()=>k("titles")},(0,n.createElement)("span",{className:"forwp-faq-overview-card__title"},(0,r.__)("Category titles","4wp-faq")),(0,n.createElement)("span",{className:"forwp-faq-overview-card__summary"},(0,r.__)("On-page title, document title, meta description, and image.","4wp-faq"))))),"registry"===O?(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Registry","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("div",{className:"forwp-faq-actions-row"},(0,n.createElement)(i.Button,{variant:"primary",onClick:()=>{s(!0),A(""),b(""),o()({path:"/forwp-faq/v1/registry/scan",method:"POST"}).then(e=>{g(e),A((0,r.__)("Registry scan completed.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Scan failed. Please try again.","4wp-faq"))}).finally(()=>s(!1))},isBusy:a,disabled:a||!F},a?(0,r.__)("Scanning…","4wp-faq"):(0,r.__)("Rescan registry","4wp-faq")),!F&&q?.setup_url?(0,n.createElement)(i.ExternalLink,{href:q.setup_url},(0,r.__)("Complete setup to enable scan","4wp-faq")):null),F&&q?.last_scan_label?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,r.sprintf)(/* translators: %s: date/time */ /* translators: %s: date/time */
     5(0,r.__)("Last scan: %s","4wp-faq"),q.last_scan_label)):null,F?(0,n.createElement)(n.Fragment,null,(0,n.createElement)("hr",{className:"forwp-faq-actions-divider"}),(0,n.createElement)("p",{className:"forwp-faq-reset-intro"},(0,r.__)("Reset setup to change CPT/taxonomy slugs. Categories are removed.","4wp-faq")),(0,n.createElement)(i.Button,{variant:"secondary",isDestructive:!0,onClick:()=>N(!0)},(0,r.__)("Reset setup","4wp-faq"))):null)):null,"seo"===O?(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("SEO","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("FAQPage JSON-LD","4wp-faq"),help:(0,r.__)("On: schema for questions actually shown. Per-block override still applies.","4wp-faq"),checked:P,disabled:p,onChange:e=>{u(!0),b(""),o()({path:c,method:"POST",data:{output_json_ld:e}}).then(t=>{E(t),A(e?(0,r.__)("JSON-LD enabled site-wide.","4wp-faq"):(0,r.__)("JSON-LD disabled site-wide.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save SEO setting.","4wp-faq"))}).finally(()=>u(!1))}}),(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("Pretty category URLs","4wp-faq"),help:(0,r.__)("Allows /page/term-slug/. Also enable it on the Categories block. Off: in-place filter, URL unchanged.","4wp-faq"),checked:L,disabled:p,onChange:e=>{u(!0),b(""),o()({path:c,method:"POST",data:{seo_urls:e}}).then(t=>{E(t),A(e?(0,r.__)("Pretty category URLs enabled. Turn on SEO-friendly category URLs in the 4WP FAQ Categories block on each hub page.","4wp-faq"):(0,r.__)("Pretty category URLs disabled. Category clicks filter in place and the page URL stays unchanged.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save SEO setting.","4wp-faq"))}).finally(()=>u(!1))}}),(0,n.createElement)(i.RangeControl,{label:(0,r.__)("Questions per group (All view)","4wp-faq"),help:(0,r.__)("Preview count on All categories. Category URLs still list every question.","4wp-faq"),value:Q,onChange:e=>{const t="number"==typeof e?e:5;u(!0),b(""),o()({path:c,method:"POST",data:{preview_per_category:t}}).then(e=>{E(e),A((0,r.__)("Preview count saved.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save setting.","4wp-faq"))}).finally(()=>u(!1))},min:1,max:20,disabled:p}))):null,"ai"===O?(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("AI","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("p",null,(0,r.__)("Uses WordPress Connectors. One prompt fills mapped fields on FAQ category edit. Apply writes into the form; Update still saves.","4wp-faq")),R?null:(0,n.createElement)(i.Notice,{status:"warning",isDismissible:!1},(0,r.__)("WordPress Connectors are not available yet. Configure a text provider, then enable the option below.","4wp-faq"),h?.ai_connectors_url?(0,n.createElement)(n.Fragment,null," ",(0,n.createElement)(i.ExternalLink,{href:h.ai_connectors_url},(0,r.__)("Open Connectors","4wp-faq"))):null),(0,n.createElement)(i.ToggleControl,{label:(0,r.__)("Allow predefined field markup","4wp-faq"),help:R?(0,r.__)("On: show Generate with AI on category screens. Off: keep the panel hidden.","4wp-faq"):(0,r.__)("Turn on after WordPress Connectors support text generation.","4wp-faq"),checked:R&&D,disabled:d||!R,onChange:e=>{m(!0),b(""),o()({path:c,method:"POST",data:{ai_field_markup:e}}).then(t=>{E(t),A(e?(0,r.__)("Predefined field markup enabled. Generate with AI can fill mapped category fields.","4wp-faq"):(0,r.__)("Predefined field markup disabled. The AI panel stays hidden on category screens.","4wp-faq"))}).catch(e=>{b(e?.message||(0,r.__)("Could not save AI setting.","4wp-faq"))}).finally(()=>m(!1))}}),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Description","4wp-faq"))," — ",(0,r.__)("Core category Description.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Display title","4wp-faq"))," — ",(0,r.__)("On-page title on pretty category URLs.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO title","4wp-faq"))," — ",(0,r.__)("Document title. No site name suffix.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO description","4wp-faq"))," — ",(0,r.__)("Meta description on category URLs.","4wp-faq"))),h?.ai_connectors_url?(0,n.createElement)("p",{className:"forwp-faq-actions-card__meta"},(0,n.createElement)(i.ExternalLink,{href:h.ai_connectors_url},(0,r.__)("WordPress Connectors","4wp-faq"))):null)):null,"titles"===O?(0,n.createElement)(i.Card,{className:"forwp-faq-actions-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,(0,r.__)("Category titles","4wp-faq"))),(0,n.createElement)(i.CardBody,null,(0,n.createElement)("p",null,(0,r.__)("On pretty category URLs (/page/term-slug/). Edit fields on each FAQ category.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("On-page title","4wp-faq"))," — ",(0,r.__)("Display title (empty: category name). Put a core Title (post-title), Query Title / Archive title (query-title), or Term Name (term-name). Heading level is the template’s choice. Heading blocks are not swapped.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("On-page description","4wp-faq"))," — ",(0,r.__)("Category Description field. Put a core Excerpt (post-excerpt) or Term Description (term-description). Empty description: WordPress output is left as-is.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Document title","4wp-faq"))," — ",(0,r.__)("SEO title as-is if filled (no site-name suffix). Empty: on-page title + “ – {site name}”.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Meta description","4wp-faq"))," — ",(0,r.__)("SEO description. Empty: hub page default.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("Canonical","4wp-faq"))," — ",(0,r.__)("The category URL (/page/term-slug/), not the hub.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,(0,r.__)("SEO image","4wp-faq"))," — ",(0,r.__)("Open Graph / Twitter image on the category. Empty: hub page image.","4wp-faq"))))):null,C?(0,n.createElement)(i.Modal,{title:(0,r.__)("Reset FAQ setup?","4wp-faq"),onRequestClose:()=>!_&&N(!1),shouldCloseOnClickOutside:!_,shouldCloseOnEsc:!_},(0,n.createElement)("p",null,(0,r.__)("You can choose new registry slugs in the setup wizard, but all FAQ categories will be removed. Registry entries stay on the previous post type until you complete setup and run a new scan.","4wp-faq")),(0,n.createElement)("div",{className:"forwp-faq-modal-actions"},(0,n.createElement)(i.Button,{variant:"secondary",onClick:()=>N(!1),disabled:_},(0,r.__)("Cancel","4wp-faq")),(0,n.createElement)(i.Button,{variant:"primary",isDestructive:!0,isBusy:_,disabled:_,onClick:()=>{w(!0),b(""),o()({path:"/forwp-faq/v1/setup/reset",method:"POST"}).then(e=>{N(!1),e?.redirect&&(window.location.href=e.redirect)}).catch(e=>{b(e?.message||(0,r.__)("Reset failed. Please try again.","4wp-faq")),N(!1)}).finally(()=>w(!1))}},(0,r.__)("Reset setup","4wp-faq")))):null)}function d({title:e,children:t}){return(0,n.createElement)(i.Card,{className:"forwp-faq-doc-card"},(0,n.createElement)(i.CardHeader,null,(0,n.createElement)("h2",null,e)),(0,n.createElement)(i.CardBody,{className:"forwp-faq-doc-card__body"},t))}function m(){return(0,n.createElement)("div",{className:"forwp-faq-docs-layout"},(0,n.createElement)(d,{title:(0,r.__)("Overview","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("4WP FAQ is a thin wrapper around WordPress core Accordion. It does not replace your blocks or theme styles. It adds an intelligence layer: FAQPage JSON-LD on the front end, optional aggregation into a FAQ registry post type, and usage statistics in the admin.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Your questions and answers live in page content (Accordion items). That is the source of truth. The registry is a scan of unique questions. Edit a registry record and Update: the plugin writes the new Q/A onto every Used In page. Add FAQ to place a new item. Delete the registry or reinstall: a scan rebuilds it from the site.","4wp-faq"))),(0,n.createElement)(d,{title:(0,r.__)("Convert to FAQ","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("You can convert an existing Accordion, Accordion Item, Accordion Group, Details, List, or heading + paragraph pairs into a 4WP FAQ block without rebuilding the layout.","4wp-faq")),(0,n.createElement)("ol",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Select a core Accordion, Accordion Item, Accordion Group, Details, or List in the editor. You can select several Details or Accordion Items at once.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("In the block toolbar, click Convert to 4WP FAQ, or use Transform to → 4WP FAQ.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("The plugin wraps your markup in forwp/faq. Inner Accordion or Details blocks and styling stay the same on the front end.","4wp-faq"))),(0,n.createElement)("p",null,(0,r.__)("Each Accordion Item (or legacy Details block) inside the wrapper counts as one FAQ question for JSON-LD and for the registry scan.","4wp-faq"))),(0,n.createElement)(d,{title:(0,r.__)("Block structure","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Recommended pattern (WordPress 6.x core Accordion):","4wp-faq")),(0,n.createElement)("pre",{className:"forwp-faq-doc-pre"},(0,n.createElement)("code",null,"forwp/faq                    ← 4WP FAQ wrapper\n└── core/accordion           ← container\n    └── core/accordion-item  ← one Q&A\n        ├── accordion heading\n        └── accordion panel")),(0,n.createElement)("p",null,(0,r.__)("Legacy core/details blocks inside forwp/faq are still supported. Prefer Accordion + Accordion Item for new pages.","4wp-faq"))),(0,n.createElement)(d,{title:(0,r.__)("Blocks for pages","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Use these blocks when building a FAQ hub or in-page FAQs:","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq")," — ",(0,r.__)("Wrapper around core Accordion or Details for JSON-LD and registry scan. Convert / Transform to 4WP FAQ in the editor.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-list")," — ",(0,r.__)("Registry glossary (grouped or flat). Place on a page or template after setup + scan.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-card")," — ",(0,r.__)("Inner template of the List (not in the inserter). Accordion or heading + answer; optional sources.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-categories")," — ",(0,r.__)("Category nav. Include/exclude stay in sync with the List on the same page.","4wp-faq")),(0,n.createElement)("li",null,(0,n.createElement)("strong",null,"forwp/faq-count")," — ",(0,r.__)("Live number for All / current category / current search. Same as [forwp_faq_count].","4wp-faq"))),(0,n.createElement)("pre",{className:"forwp-faq-doc-pre"},(0,n.createElement)("code",null,"forwp/faq-categories         ← nav (optional)\nforwp/faq-list               ← registry questions\n└── forwp/faq-card\ncore/search                  ← optional filter\nforwp/faq-count              ← optional count"))),(0,n.createElement)(d,{title:(0,r.__)("Core Search block","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("Add a core Search block on the same page as 4WP FAQ List. In the block sidebar open 4WP FAQ and turn on Filter 4WP FAQ List.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Typing filters visible FAQ cards through the Interactivity store. The form does not submit a WordPress search.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("FAQ Count follows the same search query when the filter is on.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Leave the toggle off if the Search should behave as a normal site search.","4wp-faq")))),(0,n.createElement)(d,{title:(0,r.__)("JSON-LD (SEO)","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("On singular posts and pages, the plugin can output FAQPage structured data (JSON-LD) in the document head when FAQ blocks are present.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Site-wide default: Settings → FAQPage JSON-LD (off by default).","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("When enabled site-wide: every forwp/faq block outputs schema unless you set JSON-LD on front end → Off for this block in the block sidebar.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("When disabled site-wide: no schema by default; enable per block with On for this block in the sidebar.","4wp-faq"))),(0,n.createElement)("p",{className:"forwp-faq-doc-muted"},(0,r.__)("JSON-LD does not require the FAQ registry. Blocks and schema work even if you never complete registry setup.","4wp-faq"))),(0,n.createElement)(d,{title:(0,r.__)("FAQ registry (optional)","4wp-faq")},(0,n.createElement)("p",null,(0,r.__)("After you complete setup (Settings → 4WP FAQ Setup), the plugin registers a custom post type and taxonomy (default slugs: faq and faq-category).","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("A scan walks content, finds forwp/faq blocks, and creates or updates registry posts—one per unique question—with usage, categories, and answer snapshots.","4wp-faq")),(0,n.createElement)("ul",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Where the question is used (pages, posts, other types)","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("How many times it appears (reuse count)","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Collected answer text and HTML snapshots","4wp-faq"))),(0,n.createElement)("p",null,(0,r.__)("Edit a registry FAQ (title + answer) and Update. The plugin finds that accordion item on every Used In page. If you change the question, it matches the previous title.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Add FAQ: write the question and answer. FAQ categories in the sidebar append the item to every forwp/faq block with those terms. One page (optional) writes only to that post/page. Neither: the row stays in the list until a scan, then it is dropped because it is not on the site.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("A new answer reuses the wrapper of a sibling accordion item on that page (same heading/panel markup) and fills in your text. After save, that wrapped HTML is stored on the registry record.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Run Rescan after you change FAQ content on pages. Registry Update also writes back to those pages, then a scan is scheduled. Scans also run when relevant posts are saved.","4wp-faq")),(0,n.createElement)("p",null,(0,r.__)("Reset setup (Settings tab) lets you change registry slugs in the wizard again but removes all FAQ categories; existing registry entries stay on the previous post type until you complete setup and scan again.","4wp-faq"))),(0,n.createElement)(d,{title:(0,r.__)("Typical workflow","4wp-faq")},(0,n.createElement)("ol",{className:"forwp-faq-doc-list"},(0,n.createElement)("li",null,(0,r.__)("Add or convert Accordion blocks to forwp/faq on your pages.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Enable JSON-LD on the Settings tab if you want structured data site-wide.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Optional: complete FAQ registry setup and run a scan. Then you can edit a registry FAQ (pushes to Used In pages) or Add FAQ onto category pages / one page.","4wp-faq")),(0,n.createElement)("li",null,(0,r.__)("Review Dashboard stats and open All FAQs under the FAQ admin menu.","4wp-faq")))))}const _=document.getElementById("forwp-faq-admin-root");_&&(0,l.createRoot)(_).render((0,n.createElement)(function(){const[e,t]=(0,l.useState)("settings");return(0,n.createElement)("div",{className:"forwp-faq-admin-app"},(0,n.createElement)("div",{className:"forwp-faq-tab-panel components-tab-panel"},(0,n.createElement)("div",{className:"components-tab-panel__tabs",role:"tablist","aria-label":(0,r.__)("4WP FAQ","4wp-faq")},(0,n.createElement)("button",{type:"button",role:"tab",id:"forwp-faq-tab-settings",className:"components-button components-tab-panel__tabs-item forwp-faq-tab-settings"+("settings"===e?" is-active":""),"aria-selected":"settings"===e,"aria-controls":"forwp-faq-panel-settings",tabIndex:"settings"===e?0:-1,onClick:()=>t("settings")},(0,r.__)("Settings","4wp-faq")),(0,n.createElement)("button",{type:"button",role:"tab",id:"forwp-faq-tab-documentation",className:"components-button components-tab-panel__tabs-item forwp-faq-tab-docs"+("documentation"===e?" is-active":""),"aria-selected":"documentation"===e,"aria-controls":"forwp-faq-panel-documentation",tabIndex:"documentation"===e?0:-1,onClick:()=>t("documentation")},(0,r.__)("Documentation","4wp-faq"))),(0,n.createElement)("div",{id:"forwp-faq-panel-settings",role:"tabpanel","aria-labelledby":"forwp-faq-tab-settings",className:"components-tab-panel__tab-content",hidden:"settings"!==e},(0,n.createElement)(u,null)),(0,n.createElement)("div",{id:"forwp-faq-panel-documentation",role:"tabpanel","aria-labelledby":"forwp-faq-tab-documentation",className:"components-tab-panel__tab-content",hidden:"documentation"!==e},(0,n.createElement)(m,null))))},null))}},a={};function n(e){var l=a[e];if(void 0!==l)return l.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,n),r.exports}n.m=t,e=[],n.O=(t,a,l,r)=>{if(!a){var s=1/0;for(p=0;p<e.length;p++){for(var[a,l,r]=e[p],o=!0,i=0;i<a.length;i++)(!1&r||s>=r)&&Object.keys(n.O).every(e=>n.O[e](a[i]))?a.splice(i--,1):(o=!1,r<s&&(s=r));if(o){e.splice(p--,1);var c=l();void 0!==c&&(t=c)}}return t}r=r||0;for(var p=e.length;p>0&&e[p-1][2]>r;p--)e[p]=e[p-1];e[p]=[a,l,r]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var a in t)n.o(t,a)&&!n.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={773:0,641:0};n.O.j=t=>0===e[t];var t=(t,a)=>{var l,r,[s,o,i]=a,c=0;if(s.some(t=>0!==e[t])){for(l in o)n.o(o,l)&&(n.m[l]=o[l]);if(i)var p=i(n)}for(t&&t(a);c<s.length;c++)r=s[c],n.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return n.O(p)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var l=n.O(void 0,[641],()=>n(476));l=n.O(l)})();
  • 4wp-faq/trunk/build/admin/style-index-rtl.css

    r3698640 r3748403  
    1 .forwp-faq-admin-shell{max-width:1100px}.forwp-faq-admin-shell h1.forwp-faq-admin-heading{align-items:center;display:flex;font-size:1.6rem;font-weight:600;gap:10px;margin-bottom:.25rem}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon{align-items:center;color:var(--wp-admin-theme-color,#3858e9);display:inline-flex;flex-shrink:0;justify-content:center;line-height:0}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon svg{display:block}.forwp-faq-admin-shell .forwp-faq-admin-heading__text{line-height:1.25}.forwp-faq-admin-root{margin-top:1rem;padding-bottom:2rem}.forwp-faq-admin-app{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);overflow:hidden}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs{align-items:stretch;background:#fafafa;border-bottom:1px solid #e0e0e0;display:flex;flex-wrap:wrap;gap:0;margin:0;padding:0}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item{border:1px solid transparent;border-bottom:none;border-radius:0;box-shadow:none;font-weight:500;height:auto;margin:0!important;min-height:0;padding:10px 14px}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item.is-active{background:#fff;border-color:#e0e0e0 #e0e0e0 #fff;margin-bottom:-1px!important;position:relative;z-index:1}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tab-content{padding:1.25rem 1.5rem 1.5rem}.forwp-faq-tab-loading{display:flex;justify-content:center;padding:2rem}.forwp-faq-intro-card{border:1px solid #e8e8e8;margin-bottom:1rem}.forwp-faq-intro-card__title{font-size:1.05rem;margin:0 0 .5rem}.forwp-faq-intro-card__text{color:#50575e;line-height:1.55;margin:0 0 .75rem}.forwp-faq-intro-card__text:last-child{margin-bottom:0}.forwp-faq-settings-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-stats-card .forwp-faq-actions-card__meta{margin-top:1rem}.forwp-faq-stats-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}.forwp-faq-stat{background:#f6f7f7;border:1px solid #e8e8e8;border-radius:6px;display:flex;flex-direction:column;gap:.2rem;padding:.75rem}.forwp-faq-stat__value{color:#1d2327;font-size:1.5rem;font-weight:600;line-height:1.2}.forwp-faq-stat__label{color:#50575e;font-size:.8rem;line-height:1.35}.forwp-faq-stat__hint{color:#646970;font-size:.72rem}.forwp-faq-actions-card__meta{color:#646970;font-size:.9rem;margin:.35rem 0 0}.forwp-faq-doc-list+.forwp-faq-actions-card__meta{margin-top:.15rem}.forwp-faq-actions-row{align-items:center;display:flex;flex-wrap:wrap;gap:.75rem}.forwp-faq-actions-divider{border:none;border-top:1px solid #e8e8e8;margin:1.25rem 0}.forwp-faq-reset-intro{color:#50575e;margin:0 0 .75rem}.forwp-faq-modal-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1rem}.forwp-faq-registry-layout{max-width:720px}.forwp-faq-registry-card__meta{margin:0 0 .5rem}.forwp-faq-registry-card__meta--muted{color:#646970}.forwp-faq-registry-card__actions{margin-top:1rem}.forwp-faq-docs-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-doc-card__body p{color:#1d2327;line-height:1.55;margin:0 0 .85rem}.forwp-faq-doc-card__body p:last-child{margin-bottom:0}.forwp-faq-doc-card__body strong{font-weight:600}.forwp-faq-doc-list{line-height:1.55;margin:0 1.25rem .85rem 0;padding:0}.forwp-faq-doc-list li{margin-bottom:.35rem}.forwp-faq-doc-pre{background:#f6f7f7;border:1px solid #e0e0e0;border-radius:4px;font-size:12px;line-height:1.45;margin:0 0 .85rem;overflow-x:auto;padding:12px 14px}.forwp-faq-doc-pre code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre}.forwp-faq-doc-muted{color:#646970!important;font-size:.92em}.forwp-faq-guide{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);margin-top:1.25rem;max-width:640px;padding:1.25rem 1.5rem}.forwp-faq-guide__lead{color:#1d2327;font-size:1rem;line-height:1.5;margin:0 0 1rem}.forwp-faq-guide__steps{line-height:1.6;margin:0 1.25rem 1.25rem 0;padding:0}.forwp-faq-guide__steps li{margin-bottom:.5rem}.forwp-faq-guide__steps a{color:var(--wp-admin-theme-color,#3858e9)}.forwp-faq-guide__hub,.forwp-faq-guide__video{color:#50575e;line-height:1.5;margin:0 0 .75rem}.forwp-faq-guide__video{border-top:1px solid #e8e8e8;font-style:italic;margin-bottom:0;padding-top:.75rem}
     1.forwp-faq-admin-shell{max-width:1100px}.forwp-faq-admin-shell h1.forwp-faq-admin-heading{align-items:center;display:flex;font-size:1.6rem;font-weight:600;gap:10px;margin-bottom:.25rem}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon{align-items:center;color:var(--wp-admin-theme-color,#3858e9);display:inline-flex;flex-shrink:0;justify-content:center;line-height:0}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon svg{display:block}.forwp-faq-admin-shell .forwp-faq-admin-heading__text{line-height:1.25}.forwp-faq-admin-root{margin-top:1rem;padding-bottom:2rem}.forwp-faq-admin-app{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);overflow:hidden}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs{align-items:stretch;background:#fafafa;border-bottom:1px solid #e0e0e0;display:flex;flex-wrap:wrap;gap:0;margin:0;padding:0}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item{border:1px solid transparent;border-bottom:none;border-radius:0;box-shadow:none;font-weight:500;height:auto;margin:0!important;min-height:0;padding:10px 14px}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item.is-active{background:#fff;border-color:#e0e0e0 #e0e0e0 #fff;margin-bottom:-1px!important;position:relative;z-index:1}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tab-content{padding:1.25rem 1.5rem 1.5rem}.forwp-faq-tab-loading{display:flex;justify-content:center;padding:2rem}.forwp-faq-intro-card{border:1px solid #e8e8e8;margin-bottom:1rem}.forwp-faq-intro-card__title{font-size:1.05rem;margin:0 0 .5rem}.forwp-faq-intro-card__text{color:#50575e;line-height:1.55;margin:0 0 .75rem}.forwp-faq-intro-card__text:last-child{margin-bottom:0}.forwp-faq-settings-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-overview-grid{display:grid;gap:1rem;grid-template-columns:repeat(2,minmax(0,1fr))}.forwp-faq-overview-card{align-items:flex-start;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 2px rgba(0,0,0,.04);color:inherit;cursor:pointer;display:flex;flex-direction:column;font:inherit;gap:.35rem;margin:0;padding:1rem 1.1rem;text-align:right;width:100%}.forwp-faq-overview-card:focus,.forwp-faq-overview-card:hover{border-color:var(--wp-admin-theme-color,#3858e9);box-shadow:0 0 0 1px var(--wp-admin-theme-color,#3858e9);outline:none}.forwp-faq-overview-card__title{color:#1d2327;font-size:1rem;font-weight:600}.forwp-faq-overview-card__summary{color:#50575e;font-size:.85rem;line-height:1.45}.forwp-faq-section-back{align-self:flex-start}@media(max-width:600px){.forwp-faq-overview-grid{grid-template-columns:1fr}}.forwp-faq-stats-card .forwp-faq-actions-card__meta{margin-top:1rem}.forwp-faq-stats-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}.forwp-faq-stat{background:#f6f7f7;border:1px solid #e8e8e8;border-radius:6px;display:flex;flex-direction:column;gap:.2rem;padding:.75rem}.forwp-faq-stat__value{color:#1d2327;font-size:1.5rem;font-weight:600;line-height:1.2}.forwp-faq-stat__label{color:#50575e;font-size:.8rem;line-height:1.35}.forwp-faq-stat__hint{color:#646970;font-size:.72rem}.forwp-faq-settings-layout .components-card__body{padding:12px 14px}.forwp-faq-settings-layout .components-card__body>p{margin:0 0 10px}.forwp-faq-settings-layout .components-notice{margin:0 0 14px}.forwp-faq-actions-card__meta{color:#646970;font-size:.9rem;margin:.35rem 0 0}.forwp-faq-doc-list+.forwp-faq-actions-card__meta{margin-top:.15rem}.forwp-faq-actions-row{align-items:center;display:flex;flex-wrap:wrap;gap:.75rem}.forwp-faq-actions-divider{border:none;border-top:1px solid #e8e8e8;margin:1.25rem 0}.forwp-faq-reset-intro{color:#50575e;margin:0 0 .75rem}.forwp-faq-modal-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1rem}.forwp-faq-registry-layout{max-width:720px}.forwp-faq-registry-card__meta{margin:0 0 .5rem}.forwp-faq-registry-card__meta--muted{color:#646970}.forwp-faq-registry-card__actions{margin-top:1rem}.forwp-faq-docs-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-doc-card__body p{color:#1d2327;line-height:1.55;margin:0 0 .85rem}.forwp-faq-doc-card__body p:last-child{margin-bottom:0}.forwp-faq-doc-card__body strong{font-weight:600}.forwp-faq-doc-list{line-height:1.55;margin:0 1.25rem .85rem 0;padding:0}.forwp-faq-doc-list li{margin-bottom:.35rem}.forwp-faq-doc-pre{background:#f6f7f7;border:1px solid #e0e0e0;border-radius:4px;font-size:12px;line-height:1.45;margin:0 0 .85rem;overflow-x:auto;padding:12px 14px}.forwp-faq-doc-pre code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre}.forwp-faq-doc-muted{color:#646970!important;font-size:.92em}.forwp-faq-guide{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);margin-top:1.25rem;max-width:640px;padding:1.25rem 1.5rem}.forwp-faq-guide__lead{color:#1d2327;font-size:1rem;line-height:1.5;margin:0 0 1rem}.forwp-faq-guide__steps{line-height:1.6;margin:0 1.25rem 1.25rem 0;padding:0}.forwp-faq-guide__steps li{margin-bottom:.5rem}.forwp-faq-guide__steps a{color:var(--wp-admin-theme-color,#3858e9)}.forwp-faq-guide__hub,.forwp-faq-guide__video{color:#50575e;line-height:1.5;margin:0 0 .75rem}.forwp-faq-guide__video{border-top:1px solid #e8e8e8;font-style:italic;margin-bottom:0;padding-top:.75rem}
  • 4wp-faq/trunk/build/admin/style-index.css

    r3698640 r3748403  
    1 .forwp-faq-admin-shell{max-width:1100px}.forwp-faq-admin-shell h1.forwp-faq-admin-heading{align-items:center;display:flex;font-size:1.6rem;font-weight:600;gap:10px;margin-bottom:.25rem}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon{align-items:center;color:var(--wp-admin-theme-color,#3858e9);display:inline-flex;flex-shrink:0;justify-content:center;line-height:0}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon svg{display:block}.forwp-faq-admin-shell .forwp-faq-admin-heading__text{line-height:1.25}.forwp-faq-admin-root{margin-top:1rem;padding-bottom:2rem}.forwp-faq-admin-app{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);overflow:hidden}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs{align-items:stretch;background:#fafafa;border-bottom:1px solid #e0e0e0;display:flex;flex-wrap:wrap;gap:0;margin:0;padding:0}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item{border:1px solid transparent;border-bottom:none;border-radius:0;box-shadow:none;font-weight:500;height:auto;margin:0!important;min-height:0;padding:10px 14px}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item.is-active{background:#fff;border-color:#e0e0e0 #e0e0e0 #fff;margin-bottom:-1px!important;position:relative;z-index:1}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tab-content{padding:1.25rem 1.5rem 1.5rem}.forwp-faq-tab-loading{display:flex;justify-content:center;padding:2rem}.forwp-faq-intro-card{border:1px solid #e8e8e8;margin-bottom:1rem}.forwp-faq-intro-card__title{font-size:1.05rem;margin:0 0 .5rem}.forwp-faq-intro-card__text{color:#50575e;line-height:1.55;margin:0 0 .75rem}.forwp-faq-intro-card__text:last-child{margin-bottom:0}.forwp-faq-settings-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-stats-card .forwp-faq-actions-card__meta{margin-top:1rem}.forwp-faq-stats-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}.forwp-faq-stat{background:#f6f7f7;border:1px solid #e8e8e8;border-radius:6px;display:flex;flex-direction:column;gap:.2rem;padding:.75rem}.forwp-faq-stat__value{color:#1d2327;font-size:1.5rem;font-weight:600;line-height:1.2}.forwp-faq-stat__label{color:#50575e;font-size:.8rem;line-height:1.35}.forwp-faq-stat__hint{color:#646970;font-size:.72rem}.forwp-faq-actions-card__meta{color:#646970;font-size:.9rem;margin:.35rem 0 0}.forwp-faq-doc-list+.forwp-faq-actions-card__meta{margin-top:.15rem}.forwp-faq-actions-row{align-items:center;display:flex;flex-wrap:wrap;gap:.75rem}.forwp-faq-actions-divider{border:none;border-top:1px solid #e8e8e8;margin:1.25rem 0}.forwp-faq-reset-intro{color:#50575e;margin:0 0 .75rem}.forwp-faq-modal-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1rem}.forwp-faq-registry-layout{max-width:720px}.forwp-faq-registry-card__meta{margin:0 0 .5rem}.forwp-faq-registry-card__meta--muted{color:#646970}.forwp-faq-registry-card__actions{margin-top:1rem}.forwp-faq-docs-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-doc-card__body p{color:#1d2327;line-height:1.55;margin:0 0 .85rem}.forwp-faq-doc-card__body p:last-child{margin-bottom:0}.forwp-faq-doc-card__body strong{font-weight:600}.forwp-faq-doc-list{line-height:1.55;margin:0 0 .85rem 1.25rem;padding:0}.forwp-faq-doc-list li{margin-bottom:.35rem}.forwp-faq-doc-pre{background:#f6f7f7;border:1px solid #e0e0e0;border-radius:4px;font-size:12px;line-height:1.45;margin:0 0 .85rem;overflow-x:auto;padding:12px 14px}.forwp-faq-doc-pre code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre}.forwp-faq-doc-muted{color:#646970!important;font-size:.92em}.forwp-faq-guide{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);margin-top:1.25rem;max-width:640px;padding:1.25rem 1.5rem}.forwp-faq-guide__lead{color:#1d2327;font-size:1rem;line-height:1.5;margin:0 0 1rem}.forwp-faq-guide__steps{line-height:1.6;margin:0 0 1.25rem 1.25rem;padding:0}.forwp-faq-guide__steps li{margin-bottom:.5rem}.forwp-faq-guide__steps a{color:var(--wp-admin-theme-color,#3858e9)}.forwp-faq-guide__hub,.forwp-faq-guide__video{color:#50575e;line-height:1.5;margin:0 0 .75rem}.forwp-faq-guide__video{border-top:1px solid #e8e8e8;font-style:italic;margin-bottom:0;padding-top:.75rem}
     1.forwp-faq-admin-shell{max-width:1100px}.forwp-faq-admin-shell h1.forwp-faq-admin-heading{align-items:center;display:flex;font-size:1.6rem;font-weight:600;gap:10px;margin-bottom:.25rem}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon{align-items:center;color:var(--wp-admin-theme-color,#3858e9);display:inline-flex;flex-shrink:0;justify-content:center;line-height:0}.forwp-faq-admin-shell .forwp-faq-admin-heading__icon svg{display:block}.forwp-faq-admin-shell .forwp-faq-admin-heading__text{line-height:1.25}.forwp-faq-admin-root{margin-top:1rem;padding-bottom:2rem}.forwp-faq-admin-app{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);overflow:hidden}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs{align-items:stretch;background:#fafafa;border-bottom:1px solid #e0e0e0;display:flex;flex-wrap:wrap;gap:0;margin:0;padding:0}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item{border:1px solid transparent;border-bottom:none;border-radius:0;box-shadow:none;font-weight:500;height:auto;margin:0!important;min-height:0;padding:10px 14px}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tabs button.components-tab-panel__tabs-item.is-active{background:#fff;border-color:#e0e0e0 #e0e0e0 #fff;margin-bottom:-1px!important;position:relative;z-index:1}.forwp-faq-admin-app .forwp-faq-tab-panel .components-tab-panel__tab-content{padding:1.25rem 1.5rem 1.5rem}.forwp-faq-tab-loading{display:flex;justify-content:center;padding:2rem}.forwp-faq-intro-card{border:1px solid #e8e8e8;margin-bottom:1rem}.forwp-faq-intro-card__title{font-size:1.05rem;margin:0 0 .5rem}.forwp-faq-intro-card__text{color:#50575e;line-height:1.55;margin:0 0 .75rem}.forwp-faq-intro-card__text:last-child{margin-bottom:0}.forwp-faq-settings-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-overview-grid{display:grid;gap:1rem;grid-template-columns:repeat(2,minmax(0,1fr))}.forwp-faq-overview-card{align-items:flex-start;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 2px rgba(0,0,0,.04);color:inherit;cursor:pointer;display:flex;flex-direction:column;font:inherit;gap:.35rem;margin:0;padding:1rem 1.1rem;text-align:left;width:100%}.forwp-faq-overview-card:focus,.forwp-faq-overview-card:hover{border-color:var(--wp-admin-theme-color,#3858e9);box-shadow:0 0 0 1px var(--wp-admin-theme-color,#3858e9);outline:none}.forwp-faq-overview-card__title{color:#1d2327;font-size:1rem;font-weight:600}.forwp-faq-overview-card__summary{color:#50575e;font-size:.85rem;line-height:1.45}.forwp-faq-section-back{align-self:flex-start}@media(max-width:600px){.forwp-faq-overview-grid{grid-template-columns:1fr}}.forwp-faq-stats-card .forwp-faq-actions-card__meta{margin-top:1rem}.forwp-faq-stats-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}.forwp-faq-stat{background:#f6f7f7;border:1px solid #e8e8e8;border-radius:6px;display:flex;flex-direction:column;gap:.2rem;padding:.75rem}.forwp-faq-stat__value{color:#1d2327;font-size:1.5rem;font-weight:600;line-height:1.2}.forwp-faq-stat__label{color:#50575e;font-size:.8rem;line-height:1.35}.forwp-faq-stat__hint{color:#646970;font-size:.72rem}.forwp-faq-settings-layout .components-card__body{padding:12px 14px}.forwp-faq-settings-layout .components-card__body>p{margin:0 0 10px}.forwp-faq-settings-layout .components-notice{margin:0 0 14px}.forwp-faq-actions-card__meta{color:#646970;font-size:.9rem;margin:.35rem 0 0}.forwp-faq-doc-list+.forwp-faq-actions-card__meta{margin-top:.15rem}.forwp-faq-actions-row{align-items:center;display:flex;flex-wrap:wrap;gap:.75rem}.forwp-faq-actions-divider{border:none;border-top:1px solid #e8e8e8;margin:1.25rem 0}.forwp-faq-reset-intro{color:#50575e;margin:0 0 .75rem}.forwp-faq-modal-actions{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1rem}.forwp-faq-registry-layout{max-width:720px}.forwp-faq-registry-card__meta{margin:0 0 .5rem}.forwp-faq-registry-card__meta--muted{color:#646970}.forwp-faq-registry-card__actions{margin-top:1rem}.forwp-faq-docs-layout{display:flex;flex-direction:column;gap:1rem;max-width:820px}.forwp-faq-doc-card__body p{color:#1d2327;line-height:1.55;margin:0 0 .85rem}.forwp-faq-doc-card__body p:last-child{margin-bottom:0}.forwp-faq-doc-card__body strong{font-weight:600}.forwp-faq-doc-list{line-height:1.55;margin:0 0 .85rem 1.25rem;padding:0}.forwp-faq-doc-list li{margin-bottom:.35rem}.forwp-faq-doc-pre{background:#f6f7f7;border:1px solid #e0e0e0;border-radius:4px;font-size:12px;line-height:1.45;margin:0 0 .85rem;overflow-x:auto;padding:12px 14px}.forwp-faq-doc-pre code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre}.forwp-faq-doc-muted{color:#646970!important;font-size:.92em}.forwp-faq-guide{background:#fff;border:1px solid #e0e0e0;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,.06);margin-top:1.25rem;max-width:640px;padding:1.25rem 1.5rem}.forwp-faq-guide__lead{color:#1d2327;font-size:1rem;line-height:1.5;margin:0 0 1rem}.forwp-faq-guide__steps{line-height:1.6;margin:0 0 1.25rem 1.25rem;padding:0}.forwp-faq-guide__steps li{margin-bottom:.5rem}.forwp-faq-guide__steps a{color:var(--wp-admin-theme-color,#3858e9)}.forwp-faq-guide__hub,.forwp-faq-guide__video{color:#50575e;line-height:1.5;margin:0 0 .75rem}.forwp-faq-guide__video{border-top:1px solid #e8e8e8;font-style:italic;margin-bottom:0;padding-top:.75rem}
  • 4wp-faq/trunk/build/faq-card.asset.php

    r3685374 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-i18n'), 'version' => '070b7332a0d905de6e45');
     1<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'eb35a819a118ff7797e1');
  • 4wp-faq/trunk/build/faq-card.js

    r3685374 r3748403  
    1 (()=>{"use strict";var e,a={49(){const e=window.React,a=window.wp.blocks,t=window.wp.blockEditor,o=window.wp.components,l=window.wp.i18n,n=window.wp.data,r=e=>{const a=[],t=new Set,o=e=>{if(!e||"object"!=typeof e)return;const o="string"==typeof e.fontFamily?e.fontFamily:"",l="string"==typeof e.slug?e.slug:"",n=o||l;n&&!t.has(n)&&(t.add(n),a.push({name:"string"==typeof e.name&&e.name||l||o,slug:l||n.replace(/[^a-z0-9\-]+/gi,"-").toLowerCase(),fontFamily:o||(l?`var(--wp--preset--font-family--${l})`:"")}))};return Array.isArray(e)?(e.forEach(o),a):(e&&"object"==typeof e&&Object.values(e).forEach(e=>{Array.isArray(e)&&e.forEach(o)}),a)},i=e=>null==e||""===e?"":"number"==typeof e&&Number.isFinite(e)?`${e}px`:String(e),s=e=>{if(null==e||""===e)return"";const a=String(e).trim(),t=a.match(/^var:preset\|color\|([a-z0-9\-]+)$/i);return t?`var(--wp--preset--color--${t[1].toLowerCase()})`:a},p={fontSize:"",fontFamily:"",fontWeight:"",color:""},f={colors:[],gradients:[],disableCustomColors:!1,disableCustomGradients:!0,hasColorsOrGradients:!1};function c({value:a={},onChange:c,title:_,panelId:m,help:u=""}){const{fontSizes:w,fontFamilies:d}=(0,n.useSelect)(e=>{var a,t;const o=e("core/block-editor")?.getSettings?.()||{},l=o.__experimentalFeatures||{},n=null!==(a=null!==(t=l?.typography?.fontFamilies)&&void 0!==t?t:o.fontFamilies)&&void 0!==a?a:null;return{fontSizes:Array.isArray(o.fontSizes)?o.fontSizes:Array.isArray(l?.typography?.fontSizes)?l.typography.fontSizes:void 0,fontFamilies:r(n)}},[]),h=("function"==typeof t.__experimentalUseMultipleOriginColorsAndGradients?(0,t.__experimentalUseMultipleOriginColorsAndGradients)():null)||f,g=a&&"object"==typeof a?a:{},y=g.fontSize||"",q=g.fontFamily||"",b=g.fontWeight||"",v=g.color||"",S=e=>c({...g,...e}),C=()=>!!q,E=()=>!!b;return(0,e.createElement)(e.Fragment,null,u?(0,e.createElement)("p",{className:"forwp-faq-typography-help"},u):null,(0,e.createElement)(o.__experimentalToolsPanel,{label:_,resetAll:()=>c({...p}),panelId:m,hasInnerWrapper:!0},t.__experimentalColorGradientSettingsDropdown?(0,e.createElement)(t.__experimentalColorGradientSettingsDropdown,{__experimentalIsRenderedInSidebar:!0,settings:[{colorValue:v||void 0,label:(0,l.__)("Color","4wp-faq"),onColorChange:e=>S({color:s(e)}),isShownByDefault:!0,resetAllFilter:()=>S({color:""}),hasValue:()=>!!v,onDeselect:()=>S({color:""})}],panelId:m,...h}):null,d.length>0&&t.__experimentalFontFamilyControl?(0,e.createElement)(o.__experimentalToolsPanelItem,{hasValue:C,label:(0,l.__)("Font","4wp-faq"),onDeselect:()=>S({fontFamily:""}),isShownByDefault:!0,panelId:m},(0,e.createElement)(t.__experimentalFontFamilyControl,{fontFamilies:d,value:q,onChange:e=>S({fontFamily:e||""}),size:"__unstable-large",__nextHasNoMarginBottom:!0})):d.length>0?(0,e.createElement)(o.__experimentalToolsPanelItem,{hasValue:C,label:(0,l.__)("Font","4wp-faq"),onDeselect:()=>S({fontFamily:""}),isShownByDefault:!0,panelId:m},(0,e.createElement)(o.SelectControl,{label:(0,l.__)("Font","4wp-faq"),hideLabelFromVision:!0,value:q,options:[{label:(0,l.__)("Default","4wp-faq"),value:""},...d.map(e=>({label:e.name,value:e.fontFamily}))],onChange:e=>S({fontFamily:e||""}),__next40pxDefaultSize:!0,__nextHasNoMarginBottom:!0})):null,(0,e.createElement)(o.__experimentalToolsPanelItem,{hasValue:()=>!!y,label:(0,l.__)("Size","4wp-faq"),onDeselect:()=>S({fontSize:""}),isShownByDefault:!0,panelId:m},(0,e.createElement)(t.FontSizePicker,{fontSizes:w,value:y||void 0,onChange:e=>S({fontSize:i(e)}),withReset:!1,size:"__unstable-large",__next40pxDefaultSize:!0})),t.__experimentalFontAppearanceControl?(0,e.createElement)(o.__experimentalToolsPanelItem,{hasValue:E,label:(0,l.__)("Appearance","4wp-faq"),onDeselect:()=>S({fontWeight:""}),isShownByDefault:!0,panelId:m},(0,e.createElement)(t.__experimentalFontAppearanceControl,{value:{fontStyle:"normal",fontWeight:b||void 0},onChange:e=>S({fontWeight:e?.fontWeight?String(e.fontWeight):""}),hasFontStyles:!1,hasFontWeights:!0})):(0,e.createElement)(o.__experimentalToolsPanelItem,{hasValue:E,label:(0,l.__)("Appearance","4wp-faq"),onDeselect:()=>S({fontWeight:""}),isShownByDefault:!0,panelId:m},(0,e.createElement)(o.SelectControl,{label:(0,l.__)("Weight","4wp-faq"),hideLabelFromVision:!0,value:b,options:[{label:(0,l.__)("Default","4wp-faq"),value:""},{label:(0,l.__)("Normal","4wp-faq"),value:"400"},{label:(0,l.__)("Medium","4wp-faq"),value:"500"},{label:(0,l.__)("Semibold","4wp-faq"),value:"600"},{label:(0,l.__)("Bold","4wp-faq"),value:"700"}],onChange:e=>S({fontWeight:e||""}),__next40pxDefaultSize:!0,__nextHasNoMarginBottom:!0}))))}(0,a.registerBlockType)("forwp/faq-card",{edit:({attributes:a,setAttributes:n})=>{const{displayMode:r="accordion",showSources:i=!1,sourcesLabel:s=(0,l.__)("Used in","4wp-faq"),showPostType:p=!1,questionStyle:f={},answerStyle:_={}}=a,m=(0,t.useBlockProps)({className:`forwp-faq-card-editor is-display-${r}`,style:{...f?.fontSize?{"--forwp-faq-q-size":f.fontSize}:{},...f?.fontFamily?{"--forwp-faq-q-family":f.fontFamily}:{},...f?.fontWeight?{"--forwp-faq-q-weight":f.fontWeight}:{},...f?.color?{"--forwp-faq-q-color":f.color}:{},..._?.fontSize?{"--forwp-faq-a-size":_.fontSize}:{},..._?.fontFamily?{"--forwp-faq-a-family":_.fontFamily}:{},..._?.fontWeight?{"--forwp-faq-a-weight":_.fontWeight}:{},..._?.color?{"--forwp-faq-a-color":_.color}:{}}});return(0,e.createElement)("div",{...m},(0,e.createElement)(t.InspectorControls,null,(0,e.createElement)(o.PanelBody,{title:(0,l.__)("Card","4wp-faq"),initialOpen:!0},(0,e.createElement)(o.RadioControl,{label:(0,l.__)("Display","4wp-faq"),selected:r,options:[{label:(0,l.__)("Accordion","4wp-faq"),value:"accordion"},{label:(0,l.__)("Heading and description","4wp-faq"),value:"heading"}],onChange:e=>n({displayMode:e||"accordion"})}),(0,e.createElement)(o.ToggleControl,{label:(0,l.__)("Show source links","4wp-faq"),checked:!!i,onChange:e=>n({showSources:!!e})}),i?(0,e.createElement)(e.Fragment,null,(0,e.createElement)(o.TextControl,{label:(0,l.__)("Sources label","4wp-faq"),placeholder:(0,l.__)("Used in","4wp-faq"),help:(0,l.__)("Placeholder above the source links. Leave empty to hide the label.","4wp-faq"),value:s,onChange:e=>n({sourcesLabel:e})}),(0,e.createElement)(o.ToggleControl,{label:(0,l.__)("Show CPT type","4wp-faq"),help:(0,l.__)("Show the source post type next to each link.","4wp-faq"),checked:!!p,onChange:e=>n({showPostType:!!e})})):null)),(0,e.createElement)(t.InspectorControls,{group:"styles"},(0,e.createElement)(c,{panelId:"forwp-faq-card-question-style",title:(0,l.__)("Question","4wp-faq"),help:(0,l.__)("Empty values inherit from the theme or parent block.","4wp-faq"),value:f,onChange:e=>n({questionStyle:e})}),(0,e.createElement)(c,{panelId:"forwp-faq-card-answer-style",title:(0,l.__)("Answer","4wp-faq"),help:(0,l.__)("Empty values inherit from the theme or parent block.","4wp-faq"),value:_,onChange:e=>n({answerStyle:e})})),"heading"===r?(0,e.createElement)("div",{className:"forwp-faq-card-editor__heading"},(0,e.createElement)("strong",{className:"forwp-faq-card-editor__question"},(0,l.__)("Question","4wp-faq")),(0,e.createElement)("p",{className:"forwp-faq-card-editor__answer"},(0,l.__)("Answer","4wp-faq"))):(0,e.createElement)("details",{className:"forwp-faq-card-editor__details",open:!0},(0,e.createElement)("summary",{className:"forwp-faq-card-editor__question"},(0,l.__)("Question","4wp-faq")),(0,e.createElement)("p",{className:"forwp-faq-card-editor__answer"},(0,l.__)("Answer","4wp-faq"))),i?(0,e.createElement)("p",{className:"forwp-faq-card-editor__sources"},s,p?(s?" · ":"")+(0,l.__)("CPT type","4wp-faq"):""):null)},save:()=>null})}},t={};function o(e){var l=t[e];if(void 0!==l)return l.exports;var n=t[e]={exports:{}};return a[e](n,n.exports,o),n.exports}o.m=a,e=[],o.O=(a,t,l,n)=>{if(!t){var r=1/0;for(f=0;f<e.length;f++){for(var[t,l,n]=e[f],i=!0,s=0;s<t.length;s++)(!1&n||r>=n)&&Object.keys(o.O).every(e=>o.O[e](t[s]))?t.splice(s--,1):(i=!1,n<r&&(r=n));if(i){e.splice(f--,1);var p=l();void 0!==p&&(a=p)}}return a}n=n||0;for(var f=e.length;f>0&&e[f-1][2]>n;f--)e[f]=e[f-1];e[f]=[t,l,n]},o.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),(()=>{var e={296:0,289:0};o.O.j=a=>0===e[a];var a=(a,t)=>{var l,n,[r,i,s]=t,p=0;if(r.some(a=>0!==e[a])){for(l in i)o.o(i,l)&&(o.m[l]=i[l]);if(s)var f=s(o)}for(a&&a(t);p<r.length;p++)n=r[p],o.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return o.O(f)},t=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];t.forEach(a.bind(null,0)),t.push=a.bind(null,t.push.bind(t))})();var l=o.O(void 0,[289],()=>o(49));l=o.O(l)})();
     1(()=>{"use strict";var e,t={532(){const e=window.React,t=window.wp.blocks,a=window.wp.blockEditor,o=window.wp.components,n=window.wp.i18n,l=window.wp.compose,r=window.wp.data,i=window.wp.element,s={},c={popoverProps:{placement:"left-start",offset:259}},p=e=>{const t=[],a=new Set,o=e=>{if(!e||"object"!=typeof e)return;const o="string"==typeof e.fontFamily?e.fontFamily:"",n="string"==typeof e.slug?e.slug:"",l=o||n;l&&!a.has(l)&&(a.add(l),t.push({name:"string"==typeof e.name&&e.name||n||o,slug:n||l.replace(/[^a-z0-9\-]+/gi,"-").toLowerCase(),fontFamily:o||(n?`var(--wp--preset--font-family--${n})`:"")}))};return Array.isArray(e)?(e.forEach(o),t):(e&&"object"==typeof e&&Object.values(e).forEach(e=>{Array.isArray(e)&&e.forEach(o)}),t)},f=e=>null==e||""===e?"":"number"==typeof e&&Number.isFinite(e)?`${e}px`:String(e),m=e=>{if(null==e||""===e)return"";const t=String(e).trim(),a=t.match(/^var:preset\|color\|([a-z0-9\-]+)$/i);return a?`var(--wp--preset--color--${a[1].toLowerCase()})`:t},_={color:"",fontFamily:"",fontSize:"",fontStyle:"",fontWeight:"",lineHeight:"",letterSpacing:"",textDecoration:"",textTransform:""},u={fontSize:"size",fontFamily:"family",fontWeight:"weight",fontStyle:"style",lineHeight:"line",letterSpacing:"spacing",textDecoration:"decoration",textTransform:"transform",color:"color"},d=(e,t)=>{const a={};return t&&"object"==typeof t?(Object.entries(u).forEach(([o,n])=>{t[o]&&(a[`--forwp-faq-${e}-${n}`]=t[o])}),a):a},h={colors:[],gradients:[],disableCustomColors:!1,disableCustomGradients:!0,hasColorsOrGradients:!1};function w({value:t={},onChange:u,title:d,panelId:w}){const{fontSizes:g,fontFamilies:y}=(0,r.useSelect)(e=>{var t,a;const o=e("core/block-editor")?.getSettings?.()||{},n=o.__experimentalFeatures||{},l=null!==(t=null!==(a=n?.typography?.fontFamilies)&&void 0!==a?a:o.fontFamilies)&&void 0!==t?t:null;return{fontSizes:Array.isArray(o.fontSizes)?o.fontSizes:Array.isArray(n?.typography?.fontSizes)?n.typography.fontSizes:void 0,fontFamilies:p(l)}},[]),S=(()=>{const e=(0,l.useViewportMatch)("medium","<");return(0,i.useMemo)(()=>e?s:c,[e])})(),v=("function"==typeof a.__experimentalUseMultipleOriginColorsAndGradients?(0,a.__experimentalUseMultipleOriginColorsAndGradients)():null)||h,b=t&&"object"==typeof t?t:{},q=e=>u({...b,...e}),C=e=>()=>!!b[e],E=(...e)=>()=>q(Object.fromEntries(e.map(e=>[e,""])));return(0,e.createElement)(o.__experimentalToolsPanel,{label:d,resetAll:()=>u({..._}),panelId:w,__experimentalFirstVisibleItemClass:"first",dropdownMenuProps:S},(0,e.createElement)(a.__experimentalColorGradientSettingsDropdown,{__experimentalIsRenderedInSidebar:!0,settings:[{colorValue:b.color||void 0,label:(0,n.__)("Color","4wp-faq"),onColorChange:e=>q({color:m(e)}),isShownByDefault:!0,resetAllFilter:()=>q({color:""}),hasValue:C("color"),onDeselect:E("color")}],panelId:w,...v}),y.length>0?(0,e.createElement)(o.__experimentalToolsPanelItem,{label:(0,n.__)("Font","4wp-faq"),hasValue:C("fontFamily"),onDeselect:E("fontFamily"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.__experimentalFontFamilyControl,{fontFamilies:y,value:b.fontFamily||"",onChange:e=>q({fontFamily:e||""})})):null,(0,e.createElement)(o.__experimentalToolsPanelItem,{label:(0,n.__)("Size","4wp-faq"),hasValue:C("fontSize"),onDeselect:E("fontSize"),isShownByDefault:!0,panelId:w},(0,e.createElement)(o.FontSizePicker,{fontSizes:g,value:b.fontSize||void 0,onChange:e=>q({fontSize:f(e)}),withReset:!1,withSlider:!0})),(0,e.createElement)(o.__experimentalToolsPanelItem,{label:(0,n.__)("Appearance","4wp-faq"),hasValue:()=>!!b.fontWeight||!!b.fontStyle,onDeselect:E("fontWeight","fontStyle"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.__experimentalFontAppearanceControl,{value:{fontStyle:b.fontStyle||void 0,fontWeight:b.fontWeight||void 0},onChange:e=>q({fontStyle:e?.fontStyle?String(e.fontStyle):"",fontWeight:e?.fontWeight?String(e.fontWeight):""}),hasFontStyles:!0,hasFontWeights:!0})),(0,e.createElement)(o.__experimentalToolsPanelItem,{className:"single-column",label:(0,n.__)("Line height","4wp-faq"),hasValue:C("lineHeight"),onDeselect:E("lineHeight"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.LineHeightControl,{__unstableInputWidth:"auto",value:b.lineHeight||void 0,onChange:e=>q({lineHeight:e?String(e):""})})),(0,e.createElement)(o.__experimentalToolsPanelItem,{className:"single-column",label:(0,n.__)("Letter spacing","4wp-faq"),hasValue:C("letterSpacing"),onDeselect:E("letterSpacing"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.__experimentalLetterSpacingControl,{__unstableInputWidth:"auto",value:b.letterSpacing||void 0,onChange:e=>q({letterSpacing:e||""})})),(0,e.createElement)(o.__experimentalToolsPanelItem,{label:(0,n.__)("Decoration","4wp-faq"),hasValue:C("textDecoration"),onDeselect:E("textDecoration"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.__experimentalTextDecorationControl,{value:b.textDecoration||void 0,onChange:e=>q({textDecoration:e||""})})),(0,e.createElement)(o.__experimentalToolsPanelItem,{label:(0,n.__)("Letter case","4wp-faq"),hasValue:C("textTransform"),onDeselect:E("textTransform"),isShownByDefault:!0,panelId:w},(0,e.createElement)(a.__experimentalTextTransformControl,{value:b.textTransform||void 0,onChange:e=>q({textTransform:e||""})})))}(0,t.registerBlockType)("forwp/faq-card",{edit:({attributes:t,setAttributes:l})=>{const{displayMode:r="accordion",showSources:i=!1,sourcesLabel:s=(0,n.__)("Used in","4wp-faq"),sourcesSeparator:c=", ",showPostType:p=!1,questionStyle:f={},answerStyle:m={}}=t,_=(0,a.useBlockProps)({className:`forwp-faq-card-editor is-display-${r}`,style:{...d("q",f),...d("a",m)}});return(0,e.createElement)("div",{..._},(0,e.createElement)(a.InspectorControls,null,(0,e.createElement)(o.PanelBody,{title:(0,n.__)("Card","4wp-faq"),initialOpen:!0},(0,e.createElement)(o.RadioControl,{label:(0,n.__)("Display","4wp-faq"),selected:r,options:[{label:(0,n.__)("Accordion","4wp-faq"),value:"accordion"},{label:(0,n.__)("Heading and description","4wp-faq"),value:"heading"}],onChange:e=>l({displayMode:e||"accordion"})}),(0,e.createElement)(o.ToggleControl,{label:(0,n.__)("Show source links","4wp-faq"),checked:!!i,onChange:e=>l({showSources:!!e})}),i?(0,e.createElement)(e.Fragment,null,(0,e.createElement)(o.TextControl,{label:(0,n.__)("Sources label","4wp-faq"),placeholder:(0,n.__)("Used in","4wp-faq"),help:(0,n.__)("Placeholder above the source links. Leave empty to hide the label.","4wp-faq"),value:s,onChange:e=>l({sourcesLabel:e})}),(0,e.createElement)(o.TextControl,{label:(0,n.__)("Separator","4wp-faq"),help:(0,n.__)("Enter character(s) used to separate source links.","4wp-faq"),value:c,onChange:e=>l({sourcesSeparator:e})}),(0,e.createElement)(o.ToggleControl,{label:(0,n.__)("Show CPT type","4wp-faq"),help:(0,n.__)("Show the source post type next to each link.","4wp-faq"),checked:!!p,onChange:e=>l({showPostType:!!e})})):null)),(0,e.createElement)(a.InspectorControls,{group:"styles"},(0,e.createElement)(w,{panelId:"forwp-faq-card-question-style",title:(0,n.__)("Question","4wp-faq"),value:f,onChange:e=>l({questionStyle:e})}),(0,e.createElement)(w,{panelId:"forwp-faq-card-answer-style",title:(0,n.__)("Answer","4wp-faq"),value:m,onChange:e=>l({answerStyle:e})})),"heading"===r?(0,e.createElement)("div",{className:"forwp-faq-card-editor__heading"},(0,e.createElement)("strong",{className:"forwp-faq-card-editor__question"},(0,n.__)("Question","4wp-faq")),(0,e.createElement)("p",{className:"forwp-faq-card-editor__answer"},(0,n.__)("Answer","4wp-faq"))):(0,e.createElement)("details",{className:"forwp-faq-card-editor__details",open:!0},(0,e.createElement)("summary",{className:"forwp-faq-card-editor__question"},(0,n.__)("Question","4wp-faq")),(0,e.createElement)("p",{className:"forwp-faq-card-editor__answer"},(0,n.__)("Answer","4wp-faq"))),i?(0,e.createElement)("p",{className:"forwp-faq-card-editor__sources"},s?`${s}: `:"",[(0,n.__)("Page","4wp-faq"),(0,n.__)("Post","4wp-faq")].map(e=>p?`${e} (${(0,n.__)("CPT type","4wp-faq")})`:e).join(c)):null)},save:()=>null})}},a={};function o(e){var n=a[e];if(void 0!==n)return n.exports;var l=a[e]={exports:{}};return t[e](l,l.exports,o),l.exports}o.m=t,e=[],o.O=(t,a,n,l)=>{if(!a){var r=1/0;for(p=0;p<e.length;p++){for(var[a,n,l]=e[p],i=!0,s=0;s<a.length;s++)(!1&l||r>=l)&&Object.keys(o.O).every(e=>o.O[e](a[s]))?a.splice(s--,1):(i=!1,l<r&&(r=l));if(i){e.splice(p--,1);var c=n();void 0!==c&&(t=c)}}return t}l=l||0;for(var p=e.length;p>0&&e[p-1][2]>l;p--)e[p]=e[p-1];e[p]=[a,n,l]},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={296:0,289:0};o.O.j=t=>0===e[t];var t=(t,a)=>{var n,l,[r,i,s]=a,c=0;if(r.some(t=>0!==e[t])){for(n in i)o.o(i,n)&&(o.m[n]=i[n]);if(s)var p=s(o)}for(t&&t(a);c<r.length;c++)l=r[c],o.o(e,l)&&e[l]&&e[l][0](),e[l]=0;return o.O(p)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var n=o.O(void 0,[289],()=>o(532));n=o.O(n)})();
  • 4wp-faq/trunk/build/faq-categories.asset.php

    r3691205 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '1557c7631ebb76b5d5d1');
     1<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '0f4acf9458cbc2f67151');
  • 4wp-faq/trunk/build/faq-categories.js

    r3691205 r3748403  
    1 (()=>{"use strict";var e,t={884(e,t,a){const r=window.React,l=window.wp.blocks,n=window.wp.blockEditor,o=window.wp.components,i=window.wp.element,s=window.wp.i18n,c=window.wp.apiFetch;var d=a.n(c);const p=window.wp.serverSideRender;var u=a.n(p);const f=window.wp.data,g=["forwp/faq-list","forwp/faq-categories"],h=(e,t=[])=>((e||[]).forEach(e=>{g.includes(e.name)&&t.push(e),e.innerBlocks&&e.innerBlocks.length&&h(e.innerBlocks,t)}),t),m=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0).sort((e,t)=>e-t).join(","),w=()=>"undefined"!=typeof window&&window.forwpFaqDisplay?window.forwpFaqDisplay:{},_=(e,t)=>(e||[]).map(e=>t.find(t=>t.id===e)?.name).filter(Boolean),b=(e,t)=>(e||[]).map(e=>t.find(t=>t.name===e)?.id).filter(Boolean);(0,l.registerBlockType)("forwp/faq-categories",{edit:({attributes:e,setAttributes:t,clientId:a})=>{const{orientation:l="vertical",label:c=(0,s.__)("Categories","4wp-faq"),showAll:p=!0,allLabel:g=(0,s.__)("All categories","4wp-faq"),showCount:v=!0,collapseChildren:y=!0,seoUrls:E=!1,includeTermIds:q=[],excludeTermIds:T=[]}=e,{terms:C,loading:k,registryReady:I}=(()=>{const[e,t]=(0,i.useState)([]),[a,r]=(0,i.useState)(!1),l=w(),n=!!l.registrySetupComplete,o=l.categoriesPath||"/forwp-faq/v1/editor/categories";return(0,i.useEffect)(()=>{if(!n)return void t([]);let e=!1;return r(!0),d()({path:o}).then(a=>{e||t(Array.isArray(a?.terms)?a.terms:[])}).catch(()=>{e||t([])}).finally(()=>{e||r(!1)}),()=>{e=!0}},[n,o]),{terms:e,loading:a,registryReady:n}})();((e,t,a)=>{const{updateBlockAttributes:r}=(0,f.useDispatch)("core/block-editor"),l=(0,f.useSelect)(t=>h(t("core/block-editor").getBlocks()).filter(t=>t.clientId!==e).map(e=>`${e.clientId}:${m(e.attributes?.includeTermIds)}:${m(e.attributes?.excludeTermIds)}`).join("|"),[e]),n=(0,i.useRef)(!1);(0,i.useEffect)(()=>{const l=(e=>h((0,f.select)("core/block-editor").getBlocks()).filter(t=>t.clientId!==e))(e);if(!n.current){n.current=!0;const o=l.find(e=>(e.attributes?.includeTermIds||[]).length>0||(e.attributes?.excludeTermIds||[]).length>0),i=0===(t||[]).length&&0===(a||[]).length;return void(o&&i&&r(e,{includeTermIds:o.attributes.includeTermIds||[],excludeTermIds:o.attributes.excludeTermIds||[]}))}const o=t||[],i=a||[];l.forEach(e=>{m(e.attributes?.includeTermIds)===m(o)&&m(e.attributes?.excludeTermIds)===m(i)||r(e.clientId,{includeTermIds:o,excludeTermIds:i})})},[e,t,a,l,r])})(a,q,T);const x=(0,i.useMemo)(()=>C.map(e=>e.name),[C]),O=(0,n.useBlockProps)({className:"forwp-faq-categories-editor"});return(0,r.createElement)("div",{...O},(0,r.createElement)(n.InspectorControls,null,(0,r.createElement)(o.PanelBody,{title:(0,s.__)("Navigation","4wp-faq"),initialOpen:!0},(0,r.createElement)(o.RadioControl,{label:(0,s.__)("Orientation","4wp-faq"),selected:l,options:[{label:(0,s.__)("Vertical","4wp-faq"),value:"vertical"},{label:(0,s.__)("Horizontal","4wp-faq"),value:"horizontal"}],onChange:e=>t({orientation:e||"vertical"})}),(0,r.createElement)(o.TextControl,{label:(0,s.__)("Label","4wp-faq"),value:c,onChange:e=>t({label:e||""})}),(0,r.createElement)(o.ToggleControl,{label:(0,s.__)("Show “All categories”","4wp-faq"),help:(0,s.__)("Shows the full list using the same category filters as 4WP FAQ List.","4wp-faq"),checked:!!p,onChange:e=>t({showAll:!!e})}),p?(0,r.createElement)(o.TextControl,{label:(0,s.__)("All categories label","4wp-faq"),value:g,onChange:e=>t({allLabel:e||""})}):null,(0,r.createElement)(o.ToggleControl,{label:(0,s.__)("Show counts","4wp-faq"),checked:!!v,onChange:e=>t({showCount:!!e})}),(0,r.createElement)(o.ToggleControl,{label:(0,s.__)("Collapse subcategories","4wp-faq"),help:(0,s.__)("Parents start closed. Visitors can expand them; the browser remembers their choice. The branch for the current category stays open.","4wp-faq"),checked:!1!==y,onChange:e=>t({collapseChildren:!!e})})),(0,r.createElement)(o.PanelBody,{title:(0,s.__)("Categories","4wp-faq"),initialOpen:!0},I?k?(0,r.createElement)(o.Spinner,null):(0,r.createElement)(r.Fragment,null,(0,r.createElement)(o.FormTokenField,{label:(0,s.__)("Include categories","4wp-faq"),value:_(q,C),suggestions:x,onChange:e=>t({includeTermIds:b(e,C)}),__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),(0,r.createElement)("p",{className:"forwp-faq-categories-editor__help"},(0,s.__)("Shared with 4WP FAQ List on this page. Leave empty to include all categories.","4wp-faq")),(0,r.createElement)(o.FormTokenField,{label:(0,s.__)("Exclude categories","4wp-faq"),value:_(T,C),suggestions:x,onChange:e=>t({excludeTermIds:b(e,C)}),__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0})):(0,r.createElement)(o.Notice,{status:"warning",isDismissible:!1},(0,s.__)("Complete FAQ registry setup to filter by category.","4wp-faq"))),(0,r.createElement)(o.PanelBody,{title:(0,s.__)("SEO","4wp-faq"),initialOpen:!1},w().seoUrlsEnabled?null:(0,r.createElement)(o.Notice,{status:"warning",isDismissible:!1},(0,s.__)("Pretty category URLs are off in 4WP FAQ Settings. Turn them on there first, then enable this toggle. Until then, clicks filter the list in place and the page URL stays unchanged.","4wp-faq")),(0,r.createElement)(o.ToggleControl,{label:(0,s.__)("SEO-friendly category URLs","4wp-faq"),help:(0,s.__)("Adds /term-slug/ after this page when Settings → SEO: pretty category URLs is also on. That URL uses the category Display title as H1 and the category SEO title/description as document meta. Off here: filter in place, URL unchanged.","4wp-faq"),checked:!!E,onChange:e=>t({seoUrls:!!e})}))),(0,r.createElement)(o.Disabled,null,(0,r.createElement)(u(),{block:"forwp/faq-categories",attributes:e})))},save:()=>null})}},a={};function r(e){var l=a[e];if(void 0!==l)return l.exports;var n=a[e]={exports:{}};return t[e](n,n.exports,r),n.exports}r.m=t,e=[],r.O=(t,a,l,n)=>{if(!a){var o=1/0;for(d=0;d<e.length;d++){for(var[a,l,n]=e[d],i=!0,s=0;s<a.length;s++)(!1&n||o>=n)&&Object.keys(r.O).every(e=>r.O[e](a[s]))?a.splice(s--,1):(i=!1,n<o&&(o=n));if(i){e.splice(d--,1);var c=l();void 0!==c&&(t=c)}}return t}n=n||0;for(var d=e.length;d>0&&e[d-1][2]>n;d--)e[d]=e[d-1];e[d]=[a,l,n]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={30:0,715:0};r.O.j=t=>0===e[t];var t=(t,a)=>{var l,n,[o,i,s]=a,c=0;if(o.some(t=>0!==e[t])){for(l in i)r.o(i,l)&&(r.m[l]=i[l]);if(s)var d=s(r)}for(t&&t(a);c<o.length;c++)n=o[c],r.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return r.O(d)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var l=r.O(void 0,[715],()=>r(884));l=r.O(l)})();
     1(()=>{"use strict";var e,t={382(e,t,a){const r=window.React,l=window.wp.blocks,n=window.wp.blockEditor,o=window.wp.components,i=window.wp.data,s=window.wp.element,c=window.wp.i18n,p=window.wp.apiFetch;var u=a.n(p);const d=window.wp.serverSideRender;var f=a.n(d);const m=["forwp/faq-list","forwp/faq-categories"],g=(e,t=[])=>((e||[]).forEach(e=>{m.includes(e.name)&&t.push(e),e.innerBlocks&&e.innerBlocks.length&&g(e.innerBlocks,t)}),t),w=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0).sort((e,t)=>e-t).join(","),h=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0),_=(e,t,a,r)=>{const l=w(e),n=(0,s.useMemo)(()=>((e,t)=>(e||[]).map(e=>{const a=Number(e);return t.find(e=>Number(e.id)===a)?.name}).filter(Boolean))(e,t),[l,t]),o=(0,s.useCallback)(e=>{const n=((e,t)=>(e||[]).map(e=>t.find(t=>t.name===e)?.id).map(e=>Number(e)).filter(e=>e>0))(e,t);w(n)!==l&&a({[r]:n})},[r,a,t,l]);return{value:n,onChange:o}},b=window.wp.compose,y={},v={popoverProps:{placement:"left-start",offset:259}},S=e=>{const t=[],a=new Set,r=e=>{if(!e||"object"!=typeof e)return;const r="string"==typeof e.fontFamily?e.fontFamily:"",l="string"==typeof e.slug?e.slug:"",n=r||l;n&&!a.has(n)&&(a.add(n),t.push({name:"string"==typeof e.name&&e.name||l||r,slug:l||n.replace(/[^a-z0-9\-]+/gi,"-").toLowerCase(),fontFamily:r||(l?`var(--wp--preset--font-family--${l})`:"")}))};return Array.isArray(e)?(e.forEach(r),t):(e&&"object"==typeof e&&Object.values(e).forEach(e=>{Array.isArray(e)&&e.forEach(r)}),t)},E=e=>null==e||""===e?"":"number"==typeof e&&Number.isFinite(e)?`${e}px`:String(e),q=()=>"undefined"!=typeof window&&window.forwpFaqDisplay?window.forwpFaqDisplay:{};(0,l.registerBlockType)("forwp/faq-categories",{edit:({attributes:e,setAttributes:t,clientId:a})=>{const{orientation:l="vertical",label:p=(0,c.__)("Categories","4wp-faq"),showAll:d=!0,allLabel:m=(0,c.__)("All categories","4wp-faq"),showCount:C=!0,collapseChildren:I=!0,seoUrls:F=!1,includeTermIds:T=[],excludeTermIds:x=[],allItemFontSize:k="",itemFontSize:z="",itemGap:A=""}=e,{terms:O,loading:P,registryReady:B}=(()=>{const[e,t]=(0,s.useState)([]),[a,r]=(0,s.useState)(!1),l=q(),n=!!l.registrySetupComplete,o=l.categoriesPath||"/forwp-faq/v1/editor/categories",c=(0,i.useSelect)(e=>e("core/editor")?.getCurrentPostId?.(),[]),p="number"==typeof c&&c>0?`?post_id=${c}`:"";return(0,s.useEffect)(()=>{if(!n)return void t([]);let e=!1;return r(!0),u()({path:`${o}${p}`}).then(a=>{e||t(Array.isArray(a?.terms)?a.terms:[])}).catch(()=>{e||t([])}).finally(()=>{e||r(!1)}),()=>{e=!0}},[n,o,p]),{terms:e,loading:a,registryReady:n}})(),{fontSizes:R}=(0,i.useSelect)(e=>{var t,a;const r=e("core/block-editor")?.getSettings?.()||{},l=r.__experimentalFeatures||{},n=null!==(t=null!==(a=l?.typography?.fontFamilies)&&void 0!==a?a:r.fontFamilies)&&void 0!==t?t:null;return{fontSizes:Array.isArray(r.fontSizes)?r.fontSizes:Array.isArray(l?.typography?.fontSizes)?l.typography.fontSizes:void 0,fontFamilies:S(n)}},[]),D=(()=>{const e=(0,b.useViewportMatch)("medium","<");return(0,s.useMemo)(()=>e?y:v,[e])})();((e,t,a)=>{const{updateBlockAttributes:r}=(0,i.useDispatch)("core/block-editor"),l=w(t),n=w(a),o=`${l}|${n}`,c=(0,s.useRef)(""),p=(0,s.useRef)(!1),u=(0,i.useSelect)(t=>g(t("core/block-editor").getBlocks()).filter(t=>t.clientId!==e).map(e=>`${w(e.attributes?.includeTermIds)}:${w(e.attributes?.excludeTermIds)}`).join("|"),[e]);(0,s.useEffect)(()=>{const s=(e=>g((0,i.select)("core/block-editor").getBlocks()).filter(t=>t.clientId!==e))(e),u=h(t),d=h(a);if(!p.current){p.current=!0;const t=s.find(e=>(e.attributes?.includeTermIds||[]).length>0||(e.attributes?.excludeTermIds||[]).length>0);if(t&&!l&&!n){const a=h(t.attributes.includeTermIds),l=h(t.attributes.excludeTermIds);return c.current=`${w(a)}|${w(l)}`,void r(e,{includeTermIds:a,excludeTermIds:l})}return void(c.current=o)}c.current!==o&&(c.current=o,s.forEach(e=>{w(e.attributes?.includeTermIds)===l&&w(e.attributes?.excludeTermIds)===n||r(e.clientId,{includeTermIds:u,excludeTermIds:d})}))},[e,l,n,o,u,r])})(a,T,x);const N=_(T,O,t,"includeTermIds"),L=_(x,O,t,"excludeTermIds"),$=(0,s.useMemo)(()=>O.map(e=>e.name),[O]),M=(0,n.useBlockProps)({className:"forwp-faq-categories-editor"});return(0,r.createElement)("div",{...M},(0,r.createElement)(n.InspectorControls,null,(0,r.createElement)(o.PanelBody,{title:(0,c.__)("Navigation","4wp-faq"),initialOpen:!0},(0,r.createElement)(o.RadioControl,{label:(0,c.__)("Orientation","4wp-faq"),selected:l,options:[{label:(0,c.__)("Vertical","4wp-faq"),value:"vertical"},{label:(0,c.__)("Horizontal","4wp-faq"),value:"horizontal"}],onChange:e=>t({orientation:e||"vertical"})}),(0,r.createElement)(o.TextControl,{label:(0,c.__)("Label","4wp-faq"),value:p,onChange:e=>t({label:e||""})}),(0,r.createElement)(o.ToggleControl,{label:(0,c.__)("Show “All categories”","4wp-faq"),help:(0,c.__)("Shows the full list using the same category filters as 4WP FAQ List.","4wp-faq"),checked:!!d,onChange:e=>t({showAll:!!e})}),d?(0,r.createElement)(o.TextControl,{label:(0,c.__)("All categories label","4wp-faq"),value:m,onChange:e=>t({allLabel:e||""})}):null,(0,r.createElement)(o.ToggleControl,{label:(0,c.__)("Show counts","4wp-faq"),checked:!!C,onChange:e=>t({showCount:!!e})}),(0,r.createElement)(o.ToggleControl,{label:(0,c.__)("Collapse subcategories","4wp-faq"),help:(0,c.__)("Parents start closed. Visitors can expand them; the browser remembers their choice. The branch for the current category stays open.","4wp-faq"),checked:!1!==I,onChange:e=>t({collapseChildren:!!e})})),(0,r.createElement)(o.PanelBody,{title:(0,c.__)("Categories","4wp-faq"),initialOpen:!0},B?P?(0,r.createElement)(o.Spinner,null):(0,r.createElement)(r.Fragment,null,(0,r.createElement)(o.FormTokenField,{label:(0,c.__)("Include categories","4wp-faq"),value:N.value,suggestions:$,onChange:N.onChange,__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),(0,r.createElement)("p",{className:"forwp-faq-categories-editor__help"},(0,c.__)("Shared with 4WP FAQ List on this page. Leave empty to include all categories.","4wp-faq")),(0,r.createElement)(o.FormTokenField,{label:(0,c.__)("Exclude categories","4wp-faq"),value:L.value,suggestions:$,onChange:L.onChange,__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0})):(0,r.createElement)(o.Notice,{status:"warning",isDismissible:!1},(0,c.__)("Complete FAQ registry setup to filter by category.","4wp-faq"))),(0,r.createElement)(o.PanelBody,{title:(0,c.__)("SEO","4wp-faq"),initialOpen:!1},q().seoUrlsEnabled?null:(0,r.createElement)(o.Notice,{status:"warning",isDismissible:!1},(0,c.__)("Pretty category URLs are off in 4WP FAQ Settings. Turn them on there first, then enable this toggle. Until then, clicks filter the list in place and the page URL stays unchanged.","4wp-faq")),(0,r.createElement)(o.ToggleControl,{label:(0,c.__)("SEO-friendly category URLs","4wp-faq"),help:(0,c.__)("Adds /term-slug/ after this page when Settings → SEO: pretty category URLs is also on. That URL uses the category Display title as H1 and the category SEO title/description as document meta. Off here: filter in place, URL unchanged.","4wp-faq"),checked:!!F,onChange:e=>t({seoUrls:!!e})}))),(0,r.createElement)(n.InspectorControls,{group:"styles"},(0,r.createElement)(o.__experimentalToolsPanel,{label:(0,c.__)("Sizes","4wp-faq"),panelId:"forwp-faq-categories-sizes",__experimentalFirstVisibleItemClass:"first",dropdownMenuProps:D,resetAll:()=>t({allItemFontSize:"",itemFontSize:"",itemGap:""})},(0,r.createElement)(o.__experimentalToolsPanelItem,{label:(0,c.__)("All questions","4wp-faq"),hasValue:()=>!!k,onDeselect:()=>t({allItemFontSize:""}),isShownByDefault:!0,panelId:"forwp-faq-categories-sizes"},(0,r.createElement)(o.FontSizePicker,{fontSizes:R,value:k||void 0,onChange:e=>t({allItemFontSize:E(e)}),withReset:!1,withSlider:!0})),(0,r.createElement)(o.__experimentalToolsPanelItem,{label:(0,c.__)("Headings","4wp-faq"),hasValue:()=>!!z,onDeselect:()=>t({itemFontSize:""}),isShownByDefault:!0,panelId:"forwp-faq-categories-sizes"},(0,r.createElement)(o.FontSizePicker,{fontSizes:R,value:z||void 0,onChange:e=>t({itemFontSize:E(e)}),withReset:!1,withSlider:!0})),(0,r.createElement)(o.__experimentalToolsPanelItem,{label:(0,c.__)("Space between items","4wp-faq"),hasValue:()=>!!A,onDeselect:()=>t({itemGap:""}),isShownByDefault:!0,panelId:"forwp-faq-categories-sizes"},(0,r.createElement)(o.RangeControl,{label:(0,c.__)("Space between items","4wp-faq"),value:A?parseFloat(A):void 0,onChange:e=>t({itemGap:null==e?"":`${e}px`}),min:0,max:48,step:1,allowReset:!0,resetFallbackValue:void 0,__next40pxDefaultSize:!0,__nextHasNoMarginBottom:!0})))),(0,r.createElement)(o.Disabled,null,(0,r.createElement)(f(),{block:"forwp/faq-categories",attributes:e,httpMethod:"POST"})))},save:()=>null})}},a={};function r(e){var l=a[e];if(void 0!==l)return l.exports;var n=a[e]={exports:{}};return t[e](n,n.exports,r),n.exports}r.m=t,e=[],r.O=(t,a,l,n)=>{if(!a){var o=1/0;for(p=0;p<e.length;p++){for(var[a,l,n]=e[p],i=!0,s=0;s<a.length;s++)(!1&n||o>=n)&&Object.keys(r.O).every(e=>r.O[e](a[s]))?a.splice(s--,1):(i=!1,n<o&&(o=n));if(i){e.splice(p--,1);var c=l();void 0!==c&&(t=c)}}return t}n=n||0;for(var p=e.length;p>0&&e[p-1][2]>n;p--)e[p]=e[p-1];e[p]=[a,l,n]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={30:0,715:0};r.O.j=t=>0===e[t];var t=(t,a)=>{var l,n,[o,i,s]=a,c=0;if(o.some(t=>0!==e[t])){for(l in i)r.o(i,l)&&(r.m[l]=i[l]);if(s)var p=s(r)}for(t&&t(a);c<o.length;c++)n=o[c],r.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return r.O(p)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var l=r.O(void 0,[715],()=>r(382));l=r.O(l)})();
  • 4wp-faq/trunk/build/faq-count.asset.php

    r3678667 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-server-side-render'), 'version' => '494659158c6e9ef14549');
     1<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-server-side-render'), 'version' => '923cdb1cababc7a90d8f');
  • 4wp-faq/trunk/build/faq-count.js

    r3678667 r3748403  
    1 (()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,o=window.wp.blocks,r=window.wp.blockEditor,n=window.wp.components,a=window.wp.i18n,l=window.wp.serverSideRender;var c=e.n(l);(0,o.registerBlockType)("forwp/faq-count",{edit:()=>{const e=(0,r.useBlockProps)({className:"forwp-faq-count-editor"});return(0,t.createElement)("div",{...e},(0,t.createElement)(r.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,a.__)("Count","4wp-faq"),initialOpen:!0},(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,a.__)("Shows how many questions are on the page: all categories (preview), the current category URL, or the current search.","4wp-faq")))),(0,t.createElement)(n.Disabled,null,(0,t.createElement)(c(),{block:"forwp/faq-count"})))},save:()=>null})})();
     1(()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,o=window.wp.blocks,r=window.wp.blockEditor,n=window.wp.components,a=window.wp.i18n,l=window.wp.serverSideRender;var c=e.n(l);(0,o.registerBlockType)("forwp/faq-count",{edit:()=>{const e=(0,r.useBlockProps)({className:"forwp-faq-count-editor"});return(0,t.createElement)("div",{...e},(0,t.createElement)(r.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,a.__)("Count","4wp-faq"),initialOpen:!0},(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,a.__)("Shows how many questions are on the page: all categories (preview), the current category URL, or the current search.","4wp-faq")))),(0,t.createElement)(n.Disabled,null,(0,t.createElement)(c(),{block:"forwp/faq-count",httpMethod:"POST"})))},save:()=>null})})();
  • 4wp-faq/trunk/build/faq-list.asset.php

    r3685374 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'fe2efc8ef2bd970504d6');
     1<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '7f14cd6eefac1c3d83b7');
  • 4wp-faq/trunk/build/faq-list.js

    r3685374 r3748403  
    1 (()=>{"use strict";var e,t={970(e,t,a){const o=window.React,l=window.wp.blocks,r=window.wp.blockEditor,n=window.wp.components,s=window.wp.data,i=window.wp.element,c=window.wp.i18n,p=window.wp.apiFetch;var u=a.n(p);const d=window.wp.serverSideRender;var f=a.n(d);const m=["forwp/faq-list","forwp/faq-categories"],y=(e,t=[])=>((e||[]).forEach(e=>{m.includes(e.name)&&t.push(e),e.innerBlocks&&e.innerBlocks.length&&y(e.innerBlocks,t)}),t),w=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0).sort((e,t)=>e-t).join(","),_=e=>{const t=[],a=new Set,o=e=>{if(!e||"object"!=typeof e)return;const o="string"==typeof e.fontFamily?e.fontFamily:"",l="string"==typeof e.slug?e.slug:"",r=o||l;r&&!a.has(r)&&(a.add(r),t.push({name:"string"==typeof e.name&&e.name||l||o,slug:l||r.replace(/[^a-z0-9\-]+/gi,"-").toLowerCase(),fontFamily:o||(l?`var(--wp--preset--font-family--${l})`:"")}))};return Array.isArray(e)?(e.forEach(o),t):(e&&"object"==typeof e&&Object.values(e).forEach(e=>{Array.isArray(e)&&e.forEach(o)}),t)},h=e=>null==e||""===e?"":"number"==typeof e&&Number.isFinite(e)?`${e}px`:String(e),b=e=>{if(null==e||""===e)return"";const t=String(e).trim(),a=t.match(/^var:preset\|color\|([a-z0-9\-]+)$/i);return a?`var(--wp--preset--color--${a[1].toLowerCase()})`:t},g={fontSize:"",fontFamily:"",fontWeight:"",color:""},S={colors:[],gradients:[],disableCustomColors:!1,disableCustomGradients:!0,hasColorsOrGradients:!1};function v({value:e={},onChange:t,title:a,panelId:l,help:i=""}){const{fontSizes:p,fontFamilies:u}=(0,s.useSelect)(e=>{var t,a;const o=e("core/block-editor")?.getSettings?.()||{},l=o.__experimentalFeatures||{},r=null!==(t=null!==(a=l?.typography?.fontFamilies)&&void 0!==a?a:o.fontFamilies)&&void 0!==t?t:null;return{fontSizes:Array.isArray(o.fontSizes)?o.fontSizes:Array.isArray(l?.typography?.fontSizes)?l.typography.fontSizes:void 0,fontFamilies:_(r)}},[]),d=("function"==typeof r.__experimentalUseMultipleOriginColorsAndGradients?(0,r.__experimentalUseMultipleOriginColorsAndGradients)():null)||S,f=e&&"object"==typeof e?e:{},m=f.fontSize||"",y=f.fontFamily||"",w=f.fontWeight||"",v=f.color||"",q=e=>t({...f,...e}),E=()=>!!y,F=()=>!!w;return(0,o.createElement)(o.Fragment,null,i?(0,o.createElement)("p",{className:"forwp-faq-typography-help"},i):null,(0,o.createElement)(n.__experimentalToolsPanel,{label:a,resetAll:()=>t({...g}),panelId:l,hasInnerWrapper:!0},r.__experimentalColorGradientSettingsDropdown?(0,o.createElement)(r.__experimentalColorGradientSettingsDropdown,{__experimentalIsRenderedInSidebar:!0,settings:[{colorValue:v||void 0,label:(0,c.__)("Color","4wp-faq"),onColorChange:e=>q({color:b(e)}),isShownByDefault:!0,resetAllFilter:()=>q({color:""}),hasValue:()=>!!v,onDeselect:()=>q({color:""})}],panelId:l,...d}):null,u.length>0&&r.__experimentalFontFamilyControl?(0,o.createElement)(n.__experimentalToolsPanelItem,{hasValue:E,label:(0,c.__)("Font","4wp-faq"),onDeselect:()=>q({fontFamily:""}),isShownByDefault:!0,panelId:l},(0,o.createElement)(r.__experimentalFontFamilyControl,{fontFamilies:u,value:y,onChange:e=>q({fontFamily:e||""}),size:"__unstable-large",__nextHasNoMarginBottom:!0})):u.length>0?(0,o.createElement)(n.__experimentalToolsPanelItem,{hasValue:E,label:(0,c.__)("Font","4wp-faq"),onDeselect:()=>q({fontFamily:""}),isShownByDefault:!0,panelId:l},(0,o.createElement)(n.SelectControl,{label:(0,c.__)("Font","4wp-faq"),hideLabelFromVision:!0,value:y,options:[{label:(0,c.__)("Default","4wp-faq"),value:""},...u.map(e=>({label:e.name,value:e.fontFamily}))],onChange:e=>q({fontFamily:e||""}),__next40pxDefaultSize:!0,__nextHasNoMarginBottom:!0})):null,(0,o.createElement)(n.__experimentalToolsPanelItem,{hasValue:()=>!!m,label:(0,c.__)("Size","4wp-faq"),onDeselect:()=>q({fontSize:""}),isShownByDefault:!0,panelId:l},(0,o.createElement)(r.FontSizePicker,{fontSizes:p,value:m||void 0,onChange:e=>q({fontSize:h(e)}),withReset:!1,size:"__unstable-large",__next40pxDefaultSize:!0})),r.__experimentalFontAppearanceControl?(0,o.createElement)(n.__experimentalToolsPanelItem,{hasValue:F,label:(0,c.__)("Appearance","4wp-faq"),onDeselect:()=>q({fontWeight:""}),isShownByDefault:!0,panelId:l},(0,o.createElement)(r.__experimentalFontAppearanceControl,{value:{fontStyle:"normal",fontWeight:w||void 0},onChange:e=>q({fontWeight:e?.fontWeight?String(e.fontWeight):""}),hasFontStyles:!1,hasFontWeights:!0})):(0,o.createElement)(n.__experimentalToolsPanelItem,{hasValue:F,label:(0,c.__)("Appearance","4wp-faq"),onDeselect:()=>q({fontWeight:""}),isShownByDefault:!0,panelId:l},(0,o.createElement)(n.SelectControl,{label:(0,c.__)("Weight","4wp-faq"),hideLabelFromVision:!0,value:w,options:[{label:(0,c.__)("Default","4wp-faq"),value:""},{label:(0,c.__)("Normal","4wp-faq"),value:"400"},{label:(0,c.__)("Medium","4wp-faq"),value:"500"},{label:(0,c.__)("Semibold","4wp-faq"),value:"600"},{label:(0,c.__)("Bold","4wp-faq"),value:"700"}],onChange:e=>q({fontWeight:e||""}),__next40pxDefaultSize:!0,__nextHasNoMarginBottom:!0}))))}const q=[["forwp/faq-card",{}]],E=(e,t)=>JSON.stringify(e&&"object"==typeof e?e:{})===JSON.stringify(t&&"object"==typeof t?t:{}),F=(e,t)=>(e||[]).map(e=>t.find(t=>t.id===e)?.name).filter(Boolean),I=(e,t)=>(e||[]).map(e=>t.find(t=>t.name===e)?.id).filter(Boolean);(0,l.registerBlockType)("forwp/faq-list",{edit:({attributes:e,setAttributes:t,clientId:a})=>{const{layout:l="grouped",includeTermIds:p=[],excludeTermIds:d=[],cardDisplayMode:m="accordion",cardShowSources:_=!1,cardSourcesLabel:h="Used in",cardShowPostType:b=!1,cardQuestionStyle:g={},cardAnswerStyle:S={}}=e,{terms:x,loading:C,registryReady:k}=(()=>{const[e,t]=(0,i.useState)([]),[a,o]=(0,i.useState)(!1),l="undefined"!=typeof window&&window.forwpFaqDisplay?window.forwpFaqDisplay:{},r=!!l.registrySetupComplete,n=l.categoriesPath||"/forwp-faq/v1/editor/categories";return(0,i.useEffect)(()=>{if(!r)return void t([]);let e=!1;return o(!0),u()({path:n}).then(a=>{e||t(Array.isArray(a?.terms)?a.terms:[])}).catch(()=>{e||t([])}).finally(()=>{e||o(!1)}),()=>{e=!0}},[r,n]),{terms:e,loading:a,registryReady:r}})();((e,t,a)=>{const{updateBlockAttributes:o}=(0,s.useDispatch)("core/block-editor"),l=(0,s.useSelect)(t=>y(t("core/block-editor").getBlocks()).filter(t=>t.clientId!==e).map(e=>`${e.clientId}:${w(e.attributes?.includeTermIds)}:${w(e.attributes?.excludeTermIds)}`).join("|"),[e]),r=(0,i.useRef)(!1);(0,i.useEffect)(()=>{const l=(e=>y((0,s.select)("core/block-editor").getBlocks()).filter(t=>t.clientId!==e))(e);if(!r.current){r.current=!0;const n=l.find(e=>(e.attributes?.includeTermIds||[]).length>0||(e.attributes?.excludeTermIds||[]).length>0),s=0===(t||[]).length&&0===(a||[]).length;return void(n&&s&&o(e,{includeTermIds:n.attributes.includeTermIds||[],excludeTermIds:n.attributes.excludeTermIds||[]}))}const n=t||[],i=a||[];l.forEach(e=>{w(e.attributes?.includeTermIds)===w(n)&&w(e.attributes?.excludeTermIds)===w(i)||o(e.clientId,{includeTermIds:n,excludeTermIds:i})})},[e,t,a,l,o])})(a,p,d);const{updateBlockAttributes:O}=(0,s.useDispatch)("core/block-editor"),T=(0,r.useBlockProps)({className:"forwp-faq-list-editor"}),B=(0,i.useMemo)(()=>x.map(e=>e.name),[x]),A=(0,s.useSelect)(e=>{const t=e("core/block-editor").getBlock(a);return t?.innerBlocks?.[0]||null},[a]);(0,i.useEffect)(()=>{if(!A||"forwp/faq-card"!==A.name)return;const e=A.attributes?.displayMode||"accordion",a=!!A.attributes?.showSources,o="string"==typeof A.attributes?.sourcesLabel?A.attributes.sourcesLabel:"Used in",l=!!A.attributes?.showPostType,r=A.attributes?.questionStyle&&"object"==typeof A.attributes.questionStyle?A.attributes.questionStyle:{},n=A.attributes?.answerStyle&&"object"==typeof A.attributes.answerStyle?A.attributes.answerStyle:{};e===m&&a===_&&o===h&&l===b&&E(r,g)&&E(n,S)||t({cardDisplayMode:e,cardShowSources:a,cardSourcesLabel:o,cardShowPostType:l,cardQuestionStyle:r,cardAnswerStyle:n})},[A?.attributes?.displayMode,A?.attributes?.showSources,A?.attributes?.sourcesLabel,A?.attributes?.showPostType,A?.attributes?.questionStyle,A?.attributes?.answerStyle,m,_,h,b,g,S,t,A]);const D=e=>{if(!A?.clientId)return;O(A.clientId,e);const a={};Object.prototype.hasOwnProperty.call(e,"answerStyle")&&(a.cardAnswerStyle=e.answerStyle),Object.prototype.hasOwnProperty.call(e,"questionStyle")&&(a.cardQuestionStyle=e.questionStyle),Object.prototype.hasOwnProperty.call(e,"displayMode")&&(a.cardDisplayMode=e.displayMode),Object.prototype.hasOwnProperty.call(e,"showSources")&&(a.cardShowSources=e.showSources),Object.prototype.hasOwnProperty.call(e,"sourcesLabel")&&(a.cardSourcesLabel=e.sourcesLabel),Object.prototype.hasOwnProperty.call(e,"showPostType")&&(a.cardShowPostType=e.showPostType),Object.keys(a).length&&t(a)};return(0,o.createElement)("div",{...T},(0,o.createElement)(r.InspectorControls,null,(0,o.createElement)(n.PanelBody,{title:(0,c.__)("List","4wp-faq"),initialOpen:!0},(0,o.createElement)(n.RadioControl,{label:(0,c.__)("Layout","4wp-faq"),selected:l,options:[{label:(0,c.__)("Grouped by category","4wp-faq"),value:"grouped"},{label:(0,c.__)("Single list","4wp-faq"),value:"flat"}],onChange:e=>t({layout:e||"grouped"})})),(0,o.createElement)(n.PanelBody,{title:(0,c.__)("Categories","4wp-faq"),initialOpen:!0},k?C?(0,o.createElement)(n.Spinner,null):(0,o.createElement)(o.Fragment,null,(0,o.createElement)(n.FormTokenField,{label:(0,c.__)("Include categories","4wp-faq"),value:F(p,x),suggestions:B,onChange:e=>t({includeTermIds:I(e,x)}),__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),(0,o.createElement)("p",{className:"forwp-faq-list-editor__help"},(0,c.__)("Shared with 4WP FAQ Categories on this page. Leave empty to include all categories.","4wp-faq")),(0,o.createElement)(n.FormTokenField,{label:(0,c.__)("Exclude categories","4wp-faq"),value:F(d,x),suggestions:B,onChange:e=>t({excludeTermIds:I(e,x)}),__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0})):(0,o.createElement)(n.Notice,{status:"warning",isDismissible:!1},(0,c.__)("Complete FAQ registry setup to filter by category.","4wp-faq")))),(0,o.createElement)(r.InspectorControls,{group:"styles"},(0,o.createElement)(v,{panelId:"forwp-faq-list-question-style",title:(0,c.__)("Question","4wp-faq"),help:(0,c.__)("Empty values inherit from the theme or parent Group/Column.","4wp-faq"),value:A?.attributes?.questionStyle||g||{},onChange:e=>D({questionStyle:e})}),(0,o.createElement)(v,{panelId:"forwp-faq-list-answer-style",title:(0,c.__)("Answer","4wp-faq"),help:(0,c.__)("Empty values inherit from the theme or parent Group/Column.","4wp-faq"),value:A?.attributes?.answerStyle||S||{},onChange:e=>D({answerStyle:e})})),(0,o.createElement)("div",{className:"forwp-faq-list-editor__template"},(0,o.createElement)("p",{className:"forwp-faq-list-editor__hint"},(0,c.__)("FAQ Card controls display mode, source links, and question/answer styles.","4wp-faq")),(0,o.createElement)(r.InnerBlocks,{allowedBlocks:["forwp/faq-card"],template:q,templateLock:"all"})),(0,o.createElement)(n.Disabled,null,(0,o.createElement)(f(),{block:"forwp/faq-list",attributes:e})))},save:()=>(0,o.createElement)(r.InnerBlocks.Content,null)})}},a={};function o(e){var l=a[e];if(void 0!==l)return l.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,o),r.exports}o.m=t,e=[],o.O=(t,a,l,r)=>{if(!a){var n=1/0;for(p=0;p<e.length;p++){for(var[a,l,r]=e[p],s=!0,i=0;i<a.length;i++)(!1&r||n>=r)&&Object.keys(o.O).every(e=>o.O[e](a[i]))?a.splice(i--,1):(s=!1,r<n&&(n=r));if(s){e.splice(p--,1);var c=l();void 0!==c&&(t=c)}}return t}r=r||0;for(var p=e.length;p>0&&e[p-1][2]>r;p--)e[p]=e[p-1];e[p]=[a,l,r]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={610:0,135:0};o.O.j=t=>0===e[t];var t=(t,a)=>{var l,r,[n,s,i]=a,c=0;if(n.some(t=>0!==e[t])){for(l in s)o.o(s,l)&&(o.m[l]=s[l]);if(i)var p=i(o)}for(t&&t(a);c<n.length;c++)r=n[c],o.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return o.O(p)},a=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];a.forEach(t.bind(null,0)),a.push=t.bind(null,a.push.bind(a))})();var l=o.O(void 0,[135],()=>o(970));l=o.O(l)})();
     1(()=>{"use strict";var e,t={658(e,t,r){const o=window.React,a=window.wp.blocks,n=window.wp.blockEditor,l=window.wp.components,s=window.wp.data,i=window.wp.element,c=window.wp.i18n,u=window.wp.apiFetch;var p=r.n(u);const d=window.wp.serverSideRender;var f=r.n(d);const m=["forwp/faq-list","forwp/faq-categories"],y=(e,t=[])=>((e||[]).forEach(e=>{m.includes(e.name)&&t.push(e),e.innerBlocks&&e.innerBlocks.length&&y(e.innerBlocks,t)}),t),w=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0).sort((e,t)=>e-t).join(","),h=e=>[...e||[]].map(e=>Number(e)).filter(e=>e>0),g=(e,t,r,o)=>{const a=w(e),n=(0,i.useMemo)(()=>((e,t)=>(e||[]).map(e=>{const r=Number(e);return t.find(e=>Number(e.id)===r)?.name}).filter(Boolean))(e,t),[a,t]),l=(0,i.useCallback)(e=>{const n=((e,t)=>(e||[]).map(e=>t.find(t=>t.name===e)?.id).map(e=>Number(e)).filter(e=>e>0))(e,t);w(n)!==a&&r({[o]:n})},[o,r,t,a]);return{value:n,onChange:l}},b=window.wp.compose,S={},_={popoverProps:{placement:"left-start",offset:259}},v=e=>{const t=[],r=new Set,o=e=>{if(!e||"object"!=typeof e)return;const o="string"==typeof e.fontFamily?e.fontFamily:"",a="string"==typeof e.slug?e.slug:"",n=o||a;n&&!r.has(n)&&(r.add(n),t.push({name:"string"==typeof e.name&&e.name||a||o,slug:a||n.replace(/[^a-z0-9\-]+/gi,"-").toLowerCase(),fontFamily:o||(a?`var(--wp--preset--font-family--${a})`:"")}))};return Array.isArray(e)?(e.forEach(o),t):(e&&"object"==typeof e&&Object.values(e).forEach(e=>{Array.isArray(e)&&e.forEach(o)}),t)},q=e=>null==e||""===e?"":"number"==typeof e&&Number.isFinite(e)?`${e}px`:String(e),E=e=>{if(null==e||""===e)return"";const t=String(e).trim(),r=t.match(/^var:preset\|color\|([a-z0-9\-]+)$/i);return r?`var(--wp--preset--color--${r[1].toLowerCase()})`:t},I={color:"",fontFamily:"",fontSize:"",fontStyle:"",fontWeight:"",lineHeight:"",letterSpacing:"",textDecoration:"",textTransform:""},x={colors:[],gradients:[],disableCustomColors:!1,disableCustomGradients:!0,hasColorsOrGradients:!1};function C({value:e={},onChange:t,title:r,panelId:a}){const{fontSizes:u,fontFamilies:p}=(0,s.useSelect)(e=>{var t,r;const o=e("core/block-editor")?.getSettings?.()||{},a=o.__experimentalFeatures||{},n=null!==(t=null!==(r=a?.typography?.fontFamilies)&&void 0!==r?r:o.fontFamilies)&&void 0!==t?t:null;return{fontSizes:Array.isArray(o.fontSizes)?o.fontSizes:Array.isArray(a?.typography?.fontSizes)?a.typography.fontSizes:void 0,fontFamilies:v(n)}},[]),d=(()=>{const e=(0,b.useViewportMatch)("medium","<");return(0,i.useMemo)(()=>e?S:_,[e])})(),f=("function"==typeof n.__experimentalUseMultipleOriginColorsAndGradients?(0,n.__experimentalUseMultipleOriginColorsAndGradients)():null)||x,m=e&&"object"==typeof e?e:{},y=e=>t({...m,...e}),w=e=>()=>!!m[e],h=(...e)=>()=>y(Object.fromEntries(e.map(e=>[e,""])));return(0,o.createElement)(l.__experimentalToolsPanel,{label:r,resetAll:()=>t({...I}),panelId:a,__experimentalFirstVisibleItemClass:"first",dropdownMenuProps:d},(0,o.createElement)(n.__experimentalColorGradientSettingsDropdown,{__experimentalIsRenderedInSidebar:!0,settings:[{colorValue:m.color||void 0,label:(0,c.__)("Color","4wp-faq"),onColorChange:e=>y({color:E(e)}),isShownByDefault:!0,resetAllFilter:()=>y({color:""}),hasValue:w("color"),onDeselect:h("color")}],panelId:a,...f}),p.length>0?(0,o.createElement)(l.__experimentalToolsPanelItem,{label:(0,c.__)("Font","4wp-faq"),hasValue:w("fontFamily"),onDeselect:h("fontFamily"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.__experimentalFontFamilyControl,{fontFamilies:p,value:m.fontFamily||"",onChange:e=>y({fontFamily:e||""})})):null,(0,o.createElement)(l.__experimentalToolsPanelItem,{label:(0,c.__)("Size","4wp-faq"),hasValue:w("fontSize"),onDeselect:h("fontSize"),isShownByDefault:!0,panelId:a},(0,o.createElement)(l.FontSizePicker,{fontSizes:u,value:m.fontSize||void 0,onChange:e=>y({fontSize:q(e)}),withReset:!1,withSlider:!0})),(0,o.createElement)(l.__experimentalToolsPanelItem,{label:(0,c.__)("Appearance","4wp-faq"),hasValue:()=>!!m.fontWeight||!!m.fontStyle,onDeselect:h("fontWeight","fontStyle"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.__experimentalFontAppearanceControl,{value:{fontStyle:m.fontStyle||void 0,fontWeight:m.fontWeight||void 0},onChange:e=>y({fontStyle:e?.fontStyle?String(e.fontStyle):"",fontWeight:e?.fontWeight?String(e.fontWeight):""}),hasFontStyles:!0,hasFontWeights:!0})),(0,o.createElement)(l.__experimentalToolsPanelItem,{className:"single-column",label:(0,c.__)("Line height","4wp-faq"),hasValue:w("lineHeight"),onDeselect:h("lineHeight"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.LineHeightControl,{__unstableInputWidth:"auto",value:m.lineHeight||void 0,onChange:e=>y({lineHeight:e?String(e):""})})),(0,o.createElement)(l.__experimentalToolsPanelItem,{className:"single-column",label:(0,c.__)("Letter spacing","4wp-faq"),hasValue:w("letterSpacing"),onDeselect:h("letterSpacing"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.__experimentalLetterSpacingControl,{__unstableInputWidth:"auto",value:m.letterSpacing||void 0,onChange:e=>y({letterSpacing:e||""})})),(0,o.createElement)(l.__experimentalToolsPanelItem,{label:(0,c.__)("Decoration","4wp-faq"),hasValue:w("textDecoration"),onDeselect:h("textDecoration"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.__experimentalTextDecorationControl,{value:m.textDecoration||void 0,onChange:e=>y({textDecoration:e||""})})),(0,o.createElement)(l.__experimentalToolsPanelItem,{label:(0,c.__)("Letter case","4wp-faq"),hasValue:w("textTransform"),onDeselect:h("textTransform"),isShownByDefault:!0,panelId:a},(0,o.createElement)(n.__experimentalTextTransformControl,{value:m.textTransform||void 0,onChange:e=>y({textTransform:e||""})})))}const T=[["forwp/faq-card",{}],["forwp/faq-no-results",{},[["core/paragraph",{content:(0,c.__)("No questions found. Try another search.","4wp-faq")}]]]];(0,a.registerBlockType)("forwp/faq-no-results",{edit:()=>{const e=(0,n.useBlockProps)({className:"forwp-faq-no-results-editor"});return(0,o.createElement)("div",{...e},(0,o.createElement)("p",{className:"forwp-faq-list-editor__hint"},(0,c.__)("Shown when the search finds no questions.","4wp-faq")),(0,o.createElement)(n.InnerBlocks,{templateLock:!1}))},save:()=>(0,o.createElement)(n.InnerBlocks.Content,null)});const k=(e,t)=>JSON.stringify(e&&"object"==typeof e?e:{})===JSON.stringify(t&&"object"==typeof t?t:{});(0,a.registerBlockType)("forwp/faq-list",{edit:({attributes:e,setAttributes:t,clientId:r})=>{const{layout:a="grouped",includeTermIds:u=[],excludeTermIds:d=[],cardDisplayMode:m="accordion",cardShowSources:b=!1,cardSourcesLabel:S="Used in",cardSourcesSeparator:_=", ",cardShowPostType:v=!1,cardQuestionStyle:q={},cardAnswerStyle:E={},groupTitleStyle:I={}}=e,{terms:x,loading:O,registryReady:F}=(()=>{const[e,t]=(0,i.useState)([]),[r,o]=(0,i.useState)(!1),a="undefined"!=typeof window&&window.forwpFaqDisplay?window.forwpFaqDisplay:{},n=!!a.registrySetupComplete,l=a.categoriesPath||"/forwp-faq/v1/editor/categories",c=(0,s.useSelect)(e=>e("core/editor")?.getCurrentPostId?.(),[]),u="number"==typeof c&&c>0?`?post_id=${c}`:"";return(0,i.useEffect)(()=>{if(!n)return void t([]);let e=!1;return o(!0),p()({path:`${l}${u}`}).then(r=>{e||t(Array.isArray(r?.terms)?r.terms:[])}).catch(()=>{e||t([])}).finally(()=>{e||o(!1)}),()=>{e=!0}},[n,l,u]),{terms:e,loading:r,registryReady:n}})();((e,t,r)=>{const{updateBlockAttributes:o}=(0,s.useDispatch)("core/block-editor"),a=w(t),n=w(r),l=`${a}|${n}`,c=(0,i.useRef)(""),u=(0,i.useRef)(!1),p=(0,s.useSelect)(t=>y(t("core/block-editor").getBlocks()).filter(t=>t.clientId!==e).map(e=>`${w(e.attributes?.includeTermIds)}:${w(e.attributes?.excludeTermIds)}`).join("|"),[e]);(0,i.useEffect)(()=>{const i=(e=>y((0,s.select)("core/block-editor").getBlocks()).filter(t=>t.clientId!==e))(e),p=h(t),d=h(r);if(!u.current){u.current=!0;const t=i.find(e=>(e.attributes?.includeTermIds||[]).length>0||(e.attributes?.excludeTermIds||[]).length>0);if(t&&!a&&!n){const r=h(t.attributes.includeTermIds),a=h(t.attributes.excludeTermIds);return c.current=`${w(r)}|${w(a)}`,void o(e,{includeTermIds:r,excludeTermIds:a})}return void(c.current=l)}c.current!==l&&(c.current=l,i.forEach(e=>{w(e.attributes?.includeTermIds)===a&&w(e.attributes?.excludeTermIds)===n||o(e.clientId,{includeTermIds:p,excludeTermIds:d})}))},[e,a,n,l,p,o])})(r,u,d);const P=g(u,x,t,"includeTermIds"),D=g(d,x,t,"excludeTermIds"),{updateBlockAttributes:B}=(0,s.useDispatch)("core/block-editor"),A=(0,n.useBlockProps)({className:"forwp-faq-list-editor"}),j=(0,i.useMemo)(()=>x.map(e=>e.name),[x]),L=(0,s.useSelect)(e=>{const t=e("core/block-editor").getBlock(r);return t?.innerBlocks?.[0]||null},[r]);(0,i.useEffect)(()=>{if(!L||"forwp/faq-card"!==L.name)return;const e=L.attributes?.displayMode||"accordion",r=!!L.attributes?.showSources,o="string"==typeof L.attributes?.sourcesLabel?L.attributes.sourcesLabel:"Used in",a="string"==typeof L.attributes?.sourcesSeparator?L.attributes.sourcesSeparator:", ",n=!!L.attributes?.showPostType,l=L.attributes?.questionStyle&&"object"==typeof L.attributes.questionStyle?L.attributes.questionStyle:{},s=L.attributes?.answerStyle&&"object"==typeof L.attributes.answerStyle?L.attributes.answerStyle:{};e===m&&r===b&&o===S&&a===_&&n===v&&k(l,q)&&k(s,E)||t({cardDisplayMode:e,cardShowSources:r,cardSourcesLabel:o,cardSourcesSeparator:a,cardShowPostType:n,cardQuestionStyle:l,cardAnswerStyle:s})},[L?.attributes?.displayMode,L?.attributes?.showSources,L?.attributes?.sourcesLabel,L?.attributes?.sourcesSeparator,L?.attributes?.showPostType,L?.attributes?.questionStyle,L?.attributes?.answerStyle,m,b,S,_,v,q,E,t,L]);const N=e=>{if(!L?.clientId)return;B(L.clientId,e);const r={};Object.prototype.hasOwnProperty.call(e,"answerStyle")&&(r.cardAnswerStyle=e.answerStyle),Object.prototype.hasOwnProperty.call(e,"questionStyle")&&(r.cardQuestionStyle=e.questionStyle),Object.prototype.hasOwnProperty.call(e,"displayMode")&&(r.cardDisplayMode=e.displayMode),Object.prototype.hasOwnProperty.call(e,"showSources")&&(r.cardShowSources=e.showSources),Object.prototype.hasOwnProperty.call(e,"sourcesLabel")&&(r.cardSourcesLabel=e.sourcesLabel),Object.prototype.hasOwnProperty.call(e,"sourcesSeparator")&&(r.cardSourcesSeparator=e.sourcesSeparator),Object.prototype.hasOwnProperty.call(e,"showPostType")&&(r.cardShowPostType=e.showPostType),Object.keys(r).length&&t(r)};return(0,o.createElement)("div",{...A},(0,o.createElement)(n.InspectorControls,null,(0,o.createElement)(l.PanelBody,{title:(0,c.__)("List","4wp-faq"),initialOpen:!0},(0,o.createElement)(l.RadioControl,{label:(0,c.__)("Layout","4wp-faq"),selected:a,options:[{label:(0,c.__)("Grouped by category","4wp-faq"),value:"grouped"},{label:(0,c.__)("Single list","4wp-faq"),value:"flat"}],onChange:e=>t({layout:e||"grouped"})})),(0,o.createElement)(l.PanelBody,{title:(0,c.__)("Categories","4wp-faq"),initialOpen:!0},F?O?(0,o.createElement)(l.Spinner,null):(0,o.createElement)(o.Fragment,null,(0,o.createElement)(l.FormTokenField,{label:(0,c.__)("Include categories","4wp-faq"),value:P.value,suggestions:j,onChange:P.onChange,__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),(0,o.createElement)("p",{className:"forwp-faq-list-editor__help"},(0,c.__)("Shared with 4WP FAQ Categories on this page. Leave empty to include all categories.","4wp-faq")),(0,o.createElement)(l.FormTokenField,{label:(0,c.__)("Exclude categories","4wp-faq"),value:D.value,suggestions:j,onChange:D.onChange,__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0})):(0,o.createElement)(l.Notice,{status:"warning",isDismissible:!1},(0,c.__)("Complete FAQ registry setup to filter by category.","4wp-faq")))),(0,o.createElement)(n.InspectorControls,{group:"styles"},(0,o.createElement)(C,{panelId:"forwp-faq-list-group-title-style",title:(0,c.__)("Category title","4wp-faq"),value:I,onChange:e=>t({groupTitleStyle:e})}),(0,o.createElement)(C,{panelId:"forwp-faq-list-question-style",title:(0,c.__)("Question","4wp-faq"),value:L?.attributes?.questionStyle||q||{},onChange:e=>N({questionStyle:e})}),(0,o.createElement)(C,{panelId:"forwp-faq-list-answer-style",title:(0,c.__)("Answer","4wp-faq"),value:L?.attributes?.answerStyle||E||{},onChange:e=>N({answerStyle:e})})),(0,o.createElement)("div",{className:"forwp-faq-list-editor__template"},(0,o.createElement)("p",{className:"forwp-faq-list-editor__hint"},(0,c.__)("FAQ Card controls display mode, source links, and question/answer styles.","4wp-faq")),(0,o.createElement)(n.InnerBlocks,{allowedBlocks:["forwp/faq-card","forwp/faq-no-results"],template:T,templateLock:"all"})),(0,o.createElement)(l.Disabled,null,(0,o.createElement)(f(),{block:"forwp/faq-list",attributes:e,httpMethod:"POST"})))},save:()=>(0,o.createElement)(n.InnerBlocks.Content,null)})}},r={};function o(e){var a=r[e];if(void 0!==a)return a.exports;var n=r[e]={exports:{}};return t[e](n,n.exports,o),n.exports}o.m=t,e=[],o.O=(t,r,a,n)=>{if(!r){var l=1/0;for(u=0;u<e.length;u++){for(var[r,a,n]=e[u],s=!0,i=0;i<r.length;i++)(!1&n||l>=n)&&Object.keys(o.O).every(e=>o.O[e](r[i]))?r.splice(i--,1):(s=!1,n<l&&(l=n));if(s){e.splice(u--,1);var c=a();void 0!==c&&(t=c)}}return t}n=n||0;for(var u=e.length;u>0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[r,a,n]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={610:0,135:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var a,n,[l,s,i]=r,c=0;if(l.some(t=>0!==e[t])){for(a in s)o.o(s,a)&&(o.m[a]=s[a]);if(i)var u=i(o)}for(t&&t(r);c<l.length;c++)n=l[c],o.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return o.O(u)},r=globalThis.webpackChunkforwp_faq=globalThis.webpackChunkforwp_faq||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var a=o.O(void 0,[135],()=>o(658));a=o.O(a)})();
  • 4wp-faq/trunk/build/index.asset.php

    r3685374 r3748403  
    1 <?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'e5bc29fc46a5f8f653fe');
     1<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd763aa49ed0dffc25df4');
  • 4wp-faq/trunk/build/index.js

    r3685374 r3748403  
    1 (()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var o in r)e.o(r,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:r[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,r=window.wp.blocks,o=window.wp.blockEditor,n=window.wp.components,a=window.wp.data,c=window.wp.element,l=window.wp.hooks,i=window.wp.compose,s=window.wp.apiFetch;var d=e.n(s);const p=window.wp.i18n;(0,l.addFilter)("blocks.registerBlockType","forwp/faq/search-faq-filter-attribute",(e,t)=>"core/search"!==t?e:{...e,attributes:{...e.attributes,forwpFaqFilter:{type:"boolean",default:!1}}});const m=(0,i.createHigherOrderComponent)(e=>r=>{if("core/search"!==r.name)return(0,t.createElement)(e,{...r});const{attributes:a,setAttributes:l}=r;return(0,t.createElement)(c.Fragment,null,(0,t.createElement)(e,{...r}),(0,t.createElement)(o.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,p.__)("4WP FAQ","4wp-faq"),initialOpen:!1},(0,t.createElement)(n.ToggleControl,{label:(0,p.__)("Filter 4WP FAQ List","4wp-faq"),help:(0,p.__)("When on, this Search filters FAQ cards on the same page via the Interactivity API.","4wp-faq"),checked:!!a.forwpFaqFilter,onChange:e=>l({forwpFaqFilter:!!e})}))))},"withFaqSearchFilter");(0,l.addFilter)("editor.BlockEdit","forwp/faq/search-faq-filter-control",m);const f=e=>{if(!e||!e.length)return"";const t=(0,r.serialize)(e);return((new DOMParser).parseFromString(t,"text/html").body.textContent||"").trim()},u=e=>"string"==typeof e&&e.includes("accordion")&&!e.includes("accordion-item"),g=()=>"undefined"!=typeof window&&window.forwpFaqEditor?window.forwpFaqEditor:{},k=()=>g().globalJsonLdEnabled,h="none",w="existing",B=["core/accordion","core/accordion-group","core/details"],b=()=>(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:(0,p.__)("Question","4wp-faq")}),(0,r.createBlock)("core/accordion-panel",{},[(0,r.createBlock)("core/paragraph",{placeholder:(0,p.__)("Answer…","4wp-faq")})])]),y=()=>(0,r.createBlock)("core/accordion",{},[b()]),q=e=>e&&"number"==typeof e.level,_=["core/paragraph","core/heading","core/list","core/quote"],E=e=>!(!Array.isArray(e)||e.length<2)&&e.every(e=>_.includes(e?.name)),A=e=>(0,r.createBlock)(e.name,{...e.attributes||{}},(e.innerBlocks||[]).map(A)),F=e=>String(e||"").replace(/<[^>]+>/g," ").replace(/&nbsp;/gi," ").replace(/\s+/g," ").trim(),C=e=>e?"core/heading"===e.name||"core/paragraph"===e.name?e.attributes?.content||"":"core/list"===e.name?L(e.innerBlocks)[0]||"":f(e.innerBlocks?.length?e.innerBlocks:[e]):"",v=e=>"core/heading"===e?.name||/\?\s*$/.test(F(C(e))),I=e=>{if((e=>{if(!Array.isArray(e)||e.length<2||e.length%2!=0)return!1;if(2===e.length)return(e=>{if(!Array.isArray(e)||2!==e.length)return!1;const t=e.map(e=>e.name);return"core/heading"===t[0]&&"core/paragraph"===t[1]||"core/paragraph"===t[0]&&"core/heading"===t[1]})(e);for(let t=0;t<e.length;t+=2)if("core/heading"!==e[t]?.name||"core/paragraph"!==e[t+1]?.name)return!1;return!0})(e))return O(e.map(e=>e.attributes),e.map(e=>e.innerBlocks));const t=(e=>{if(e.some(v)){const t=[];let r=null;return e.forEach(e=>{if(!r||v(e))return r&&t.push(r),void(r={question:C(e),answers:[]});r.answers.push(e)}),r&&t.push(r),t}const t=[];for(let r=0;r<e.length;r+=2)t.push({question:C(e[r]),answers:e[r+1]?[e[r+1]]:[]});return t})(e);return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},t.map(e=>((e,t)=>{const o=F(e)?e:(0,p.__)("Question","4wp-faq"),n=t.length>0?t.map(A):[(0,r.createBlock)("core/paragraph",{placeholder:(0,p.__)("Answer…","4wp-faq")})];return(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:o}),(0,r.createBlock)("core/accordion-panel",{},n)])})(e.question,e.answers)))])},S=(e,t)=>{const o=Array.isArray(e),n=o?e:[e],a=o?t:[t||[]];return(0,r.createBlock)("forwp/faq",{},n.map((e,t)=>(0,r.createBlock)("core/details",e||{},a[t]||[])))},M=(e,t)=>{const o=Array.isArray(e),n=o?e:[e],a=o?t:[t||[]];return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},n.map((e,t)=>(0,r.createBlock)("core/accordion-item",e||{},a[t]||[])))])},O=(e,t)=>{if(2===e.length&&!q(e[0]))return((e,t)=>{let o=e[0],n=e[1],a=t[1]||[];q(o)||(o=e[1],n=e[0],a=t[0]||[]);const c=o.content||"",l=(0,r.createBlock)("core/paragraph",n,a);return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},[(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:c}),(0,r.createBlock)("core/accordion-panel",{},[l])])])])})(e,t);const o=[];for(let n=0;n<e.length;n+=2){const a=e[n]?.content||"",c=(0,r.createBlock)("core/paragraph",e[n+1]||{},t[n+1]||[]);o.push((0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:a}),(0,r.createBlock)("core/accordion-panel",{},[c])]))}return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},o)])},x=(0,p.__)("Convert to 4WP FAQ","4wp-faq"),T={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,isMatch:(e,t)=>E(t),__experimentalConvert:e=>I(e)},Q={type:"block",blocks:["*"],isMultiBlock:!0,isMatch:(e,t)=>E(t),__experimentalConvert:e=>I(e)},P={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,transform:(e,t)=>S(e,t)},N={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,transform:(e,t)=>M(e,t)},D={type:"block",blocks:["forwp/faq"],transform:(e,t)=>(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",e,t)])},L=e=>{const t=[];return(e||[]).forEach(e=>{if("core/list-item"!==e.name)return;const r=(e.attributes?.content||"").trim();r&&t.push(r)}),t},J=(e,t)=>{let o=L(t);return!o.length&&e?.values&&(o=(e=>{if(!e||"string"!=typeof e)return[];const t=(new DOMParser).parseFromString(`<ul>${e}</ul>`,"text/html");return Array.from(t.querySelectorAll("li")).map(e=>(e.innerHTML||e.textContent||"").trim()).filter(Boolean)})(e.values)),o.length?(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},o.map(e=>(e=>(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:e}),(0,r.createBlock)("core/accordion-panel",{},[(0,r.createBlock)("core/paragraph",{placeholder:(0,p.__)("Answer…","4wp-faq")})])]))(e)))]):(0,r.createBlock)("forwp/faq",{},[y()])},R={type:"block",blocks:["forwp/faq"],transform:(e,t)=>J(e,t)};(0,r.registerBlockType)("forwp/faq",{edit:e=>{const{attributes:r,setAttributes:l,clientId:i}=e,{getBlock:s,postId:m}=(0,a.useSelect)(e=>({getBlock:e("core/block-editor").getBlock,postId:e("core/editor")?.getCurrentPostId?.()||0}),[e.clientId]),{insertBlock:u}=(0,a.useDispatch)("core/block-editor"),q=s(i),_=(0,c.useMemo)(()=>(e=>{const t=[],r=e=>{e.forEach(e=>{const o=e.name;if((e=>"string"==typeof e&&("core/accordion-item"===e||e.includes("accordion-item")))(o)||(e=>"string"==typeof e&&("core/details"===e||e.endsWith("/details")))(o)){const{question:r,answer:o}=(e=>{const t=e.attributes||{};let r=(t.title||t.summary||t.question||t.heading||"").trim(),o="";const n=e.innerBlocks||[];return!r&&n.length&&(r=f([n[0]]),n.length>1&&(o=f(n.slice(1)))),!o&&n.length&&(o=f(n)),{question:r.trim(),answer:o.trim()}})(e);r&&o&&t.push({question:r,answer:o})}e.innerBlocks&&e.innerBlocks.length&&r(e.innerBlocks)})};return r(e||[]),t})(q?.innerBlocks||[]),[q]),E=(0,c.useMemo)(()=>(q?.innerBlocks||[]).find(e=>"core/accordion"===e.name||"core/accordion-group"===e.name)||null,[q]),A=r.jsonLd||"",F=Array.isArray(r.categoryTermIds)?r.categoryTermIds:[],C=r.categoryTermId||0,v=F.length>0?F:C?[C]:[],I=r.categoryName||"",[S,M]=(0,c.useState)(!(!I||!String(I).trim())),{terms:O,loading:x,registryReady:T}=(e=>{const[t,r]=(0,c.useState)([]),[o,n]=(0,c.useState)(!1),a=!!g().registrySetupComplete,l=g().categoriesPath||"/forwp-faq/v1/editor/categories";return(0,c.useEffect)(()=>{if(!a)return void r([]);let t=!1;n(!0);const o=e?`?post_id=${e}`:"";return d()({path:`${l}${o}`}).then(e=>{t||r(Array.isArray(e?.terms)?e.terms:[])}).catch(()=>{t||r([])}).finally(()=>{t||n(!1)}),()=>{t=!0}},[a,l,e]),{terms:t,loading:o,registryReady:a}})(m),Q=(e=>{const t=e||"";return"enable"===t||"disable"!==t&&!!k()})(A),P=k(),N=(0,c.useMemo)(()=>_.length&&Q?JSON.stringify({"@context":"https://schema.org","@type":"FAQPage",mainEntity:_.map(e=>({"@type":"Question",name:e.question,acceptedAnswer:{"@type":"Answer",text:e.answer}}))},null,2):"",[_,Q]),D=P?(0,p.__)("Site-wide JSON-LD is on. Choose “Off for this block” to exclude this FAQ from structured data.","4wp-faq"):(0,p.__)("Site-wide JSON-LD is off. Choose “On for this block” to output FAQPage schema for this block only.","4wp-faq");return(0,t.createElement)(c.Fragment,null,(0,t.createElement)(o.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,p.__)("SEO","4wp-faq"),initialOpen:!0},(0,t.createElement)(n.SelectControl,{label:(0,p.__)("JSON-LD on front end","4wp-faq"),help:D,value:A,options:[{label:P?(0,p.__)("Default (on — site setting)","4wp-faq"):(0,p.__)("Default (off — site setting)","4wp-faq"),value:""},{label:(0,p.__)("On for this block","4wp-faq"),value:"enable"},{label:(0,p.__)("Off for this block","4wp-faq"),value:"disable"}],onChange:e=>l({jsonLd:e||""})})),(0,t.createElement)(n.PanelBody,{title:(0,p.__)("Registry category","4wp-faq"),initialOpen:!1},T?x?(0,t.createElement)(n.Spinner,null):(0,t.createElement)(c.Fragment,null,(0,t.createElement)(n.FormTokenField,{label:(0,p.__)("FAQ categories","4wp-faq"),help:(0,p.__)("Search by name. The first category is the primary group for this FAQ. Applied on scan.","4wp-faq"),value:(v||[]).map(e=>O.find(t=>t.id===e)?.name).filter(Boolean),suggestions:O.map(e=>e.name),onChange:e=>{const t=(e||[]).map(e=>O.find(t=>t.name===e)?.id).filter(Boolean);l({categoryTermIds:t,categoryTermId:t[0]||0,categoryMode:t.length?w:I?"new":h})},__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),S?(0,t.createElement)(n.TextControl,{label:(0,p.__)("New category name","4wp-faq"),help:(0,p.__)("Created in the FAQ registry taxonomy on scan (language follows this page). Becomes primary if no existing category is selected.","4wp-faq"),value:I,onChange:e=>l({categoryName:e||"",categoryMode:v.length?w:e?"new":h})}):(0,t.createElement)(n.Button,{variant:"secondary",onClick:()=>M(!0)},(0,p.__)("Add new","4wp-faq"))):(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,p.__)("Complete FAQ registry setup to assign categories during scan.","4wp-faq"))),(0,t.createElement)(n.PanelBody,{title:(0,p.__)("FAQ preview","4wp-faq"),initialOpen:!1},0===_.length?(0,t.createElement)(n.Notice,{status:"warning",isDismissible:!1},(0,p.__)("Add accordion items to generate FAQ schema.","4wp-faq")):null,!Q&&_.length>0?(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,p.__)("JSON-LD is off for this block on the front end.","4wp-faq")):null,(0,t.createElement)("p",null,(0,p.__)("Items:","4wp-faq")," ",_.length),(0,t.createElement)(n.TextareaControl,{label:(0,p.__)("Schema JSON-LD (preview)","4wp-faq"),value:N,rows:Math.min(12,Math.max(6,2*_.length)),readOnly:!0}))),(0,t.createElement)("div",{className:e.className},(0,t.createElement)(o.InnerBlocks,{allowedBlocks:B,template:[["core/accordion",{},[["core/accordion-item",{},[["core/accordion-heading",{content:(0,p.__)("Question","4wp-faq")}],["core/accordion-panel",{},[["core/paragraph",{placeholder:(0,p.__)("Answer…","4wp-faq")}]]]]]]]],templateLock:!1}),(0,t.createElement)("div",{className:"forwp-faq-editor-actions",style:{marginTop:"12px"}},(0,t.createElement)(n.Button,{variant:"secondary",onClick:()=>{const e=b();E?u(e,E.clientId,E.innerBlocks?.length||0):u(y(),i,0)}},(0,p.__)("Add FAQ item","4wp-faq")))))},save:()=>(0,t.createElement)(o.InnerBlocks.Content,null),transforms:{from:[{type:"block",blocks:["core/accordion","core/accordion-group"],transform:(e,t)=>(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",e,t)])},{type:"block",blocks:["core/accordion-item"],isMultiBlock:!0,transform:(e,t)=>M(e,t)},{type:"block",blocks:["core/details"],isMultiBlock:!0,transform:(e,t)=>S(e,t)},Q,{type:"block",blocks:["core/list"],transform:(e,t)=>J(e,t)}]}});const H=(0,i.createHigherOrderComponent)(e=>l=>{const i=u(l.name),s="core/accordion-item"===l.name,d="core/details"===l.name,p="core/list"===l.name;if(!(i||s||d||p))return(0,t.createElement)(e,{...l});const{replaceBlock:m,replaceBlocks:f}=(0,a.useDispatch)("core/block-editor"),{getBlock:g,getBlockRootClientId:k,getMultiSelectedBlockClientIds:h}=(0,a.useSelect)(e=>({getBlock:e("core/block-editor").getBlock,getBlockRootClientId:e("core/block-editor").getBlockRootClientId,getMultiSelectedBlockClientIds:e("core/block-editor").getMultiSelectedBlockClientIds}),[l.clientId]),w=h(),B=(w||[]).map(e=>g(e)).filter(Boolean),b=B.length>1&&B.every(e=>e.name===l.name)&&(d||s);return b&&w[0]!==l.clientId?(0,t.createElement)(e,{...l}):(0,t.createElement)(c.Fragment,null,(0,t.createElement)(e,{...l}),(0,t.createElement)(o.BlockControls,null,(0,t.createElement)(n.ToolbarGroup,null,(0,t.createElement)(n.ToolbarButton,{icon:"editor-help",text:x,label:x,onClick:()=>{if(b){const e=B.map(e=>e.attributes),t=B.map(e=>e.innerBlocks),r=d?S(e,t):M(e,t);return void f(w,[r])}if(p)return void m(l.clientId,J(l.attributes,l.innerBlocks));if(d)return void m(l.clientId,S(l.attributes,l.innerBlocks));if(i)return void m(l.clientId,(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)(l.name,l.attributes,l.innerBlocks)]));const e=k(l.clientId),t=e?g(e):null;t&&u(t.name)?m(e,(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)(t.name,t.attributes,t.innerBlocks)])):m(l.clientId,M(l.attributes,l.innerBlocks))}}))))},"withFaqTransform");(0,l.addFilter)("editor.BlockEdit","forwp/faq/with-transform",H);const W=(0,i.createHigherOrderComponent)(e=>r=>{if(!_.includes(r.name))return(0,t.createElement)(e,{...r});const{getMultiSelectedBlockClientIds:l,getBlock:i}=(0,a.useSelect)(e=>({getMultiSelectedBlockClientIds:e("core/block-editor").getMultiSelectedBlockClientIds,getBlock:e("core/block-editor").getBlock}),[]),{replaceBlocks:s}=(0,a.useDispatch)("core/block-editor"),d=l(),p=d.length>=2?d.map(e=>i(e)).filter(Boolean):[],m=E(p),f=m&&d[0]===r.clientId;return(0,t.createElement)(c.Fragment,null,(0,t.createElement)(e,{...r}),f?(0,t.createElement)(o.BlockControls,null,(0,t.createElement)(n.ToolbarGroup,null,(0,t.createElement)(n.ToolbarButton,{icon:"editor-help",text:x,label:x,onClick:()=>{m&&s(d,[I(p)])}}))):null)},"withHeadingParagraphFaqConvert");(0,l.addFilter)("editor.BlockEdit","forwp/faq/with-heading-paragraph-convert",W),(0,l.addFilter)("blocks.registerBlockType","forwp/faq/block-to-faq-transforms",(e,t)=>{if("core/heading"===t||"core/paragraph"===t||"core/quote"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,T]}}}if("core/list"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,R,T]}}}if("core/details"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,P]}}}if("core/accordion-item"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,N]}}}if("core/accordion"===t||"core/accordion-group"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,D]}}}return e})})();
     1(()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var o in r)e.o(r,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:r[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,r=window.wp.blocks,o=window.wp.blockEditor,n=window.wp.components,c=window.wp.data,a=window.wp.element,l=window.wp.hooks,i=window.wp.compose,s=window.wp.apiFetch;var p=e.n(s);const d=window.wp.i18n;(0,l.addFilter)("blocks.registerBlockType","forwp/faq/search-faq-filter-attribute",(e,t)=>"core/search"!==t?e:{...e,attributes:{...e.attributes,forwpFaqFilter:{type:"boolean",default:!1}}});const m=(0,i.createHigherOrderComponent)(e=>r=>{if("core/search"!==r.name)return(0,t.createElement)(e,{...r});const{attributes:c,setAttributes:l}=r;return(0,t.createElement)(a.Fragment,null,(0,t.createElement)(e,{...r}),(0,t.createElement)(o.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,d.__)("4WP FAQ","4wp-faq"),initialOpen:!1},(0,t.createElement)(n.ToggleControl,{label:(0,d.__)("Filter 4WP FAQ List","4wp-faq"),help:(0,d.__)("When on, this Search filters FAQ cards on the same page via the Interactivity API.","4wp-faq"),checked:!!c.forwpFaqFilter,onChange:e=>l({forwpFaqFilter:!!e})}))))},"withFaqSearchFilter");(0,l.addFilter)("editor.BlockEdit","forwp/faq/search-faq-filter-control",m);const f=e=>(0,r.createBlock)("forwp/faq",{},[(0,r.cloneBlock)(e)]),u=e=>{if(!e||!e.length)return"";const t=(0,r.serialize)(e);return((new DOMParser).parseFromString(t,"text/html").body.textContent||"").trim()},g=e=>"string"==typeof e&&e.includes("accordion")&&!e.includes("accordion-item"),k=()=>"undefined"!=typeof window&&window.forwpFaqEditor?window.forwpFaqEditor:{},h=()=>k().globalJsonLdEnabled,w="none",B="existing",b=["core/accordion","core/accordion-group","core/details"],y=()=>(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:(0,d.__)("Question","4wp-faq")}),(0,r.createBlock)("core/accordion-panel",{},[(0,r.createBlock)("core/paragraph",{placeholder:(0,d.__)("Answer…","4wp-faq")})])]),q=()=>(0,r.createBlock)("core/accordion",{},[y()]),_=e=>e&&"number"==typeof e.level,E=["core/paragraph","core/heading","core/list","core/quote"],A=e=>!(!Array.isArray(e)||e.length<2)&&e.every(e=>E.includes(e?.name)),F=e=>(0,r.createBlock)(e.name,{...e.attributes||{}},(e.innerBlocks||[]).map(F)),C=e=>String(e||"").replace(/<[^>]+>/g," ").replace(/&nbsp;/gi," ").replace(/\s+/g," ").trim(),v=e=>e?"core/heading"===e.name||"core/paragraph"===e.name?e.attributes?.content||"":"core/list"===e.name?H(e.innerBlocks)[0]||"":u(e.innerBlocks?.length?e.innerBlocks:[e]):"",I=e=>"core/heading"===e?.name||/\?\s*$/.test(C(v(e))),S=e=>{if((e=>{if(!Array.isArray(e)||e.length<2||e.length%2!=0)return!1;if(2===e.length)return(e=>{if(!Array.isArray(e)||2!==e.length)return!1;const t=e.map(e=>e.name);return"core/heading"===t[0]&&"core/paragraph"===t[1]||"core/paragraph"===t[0]&&"core/heading"===t[1]})(e);for(let t=0;t<e.length;t+=2)if("core/heading"!==e[t]?.name||"core/paragraph"!==e[t+1]?.name)return!1;return!0})(e))return T(e.map(e=>e.attributes),e.map(e=>e.innerBlocks));const t=(e=>{if(e.some(I)){const t=[];let r=null;return e.forEach(e=>{if(!r||I(e))return r&&t.push(r),void(r={question:v(e),answers:[]});r.answers.push(e)}),r&&t.push(r),t}const t=[];for(let r=0;r<e.length;r+=2)t.push({question:v(e[r]),answers:e[r+1]?[e[r+1]]:[]});return t})(e);return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},t.map(e=>((e,t)=>{const o=C(e)?e:(0,d.__)("Question","4wp-faq"),n=t.length>0?t.map(F):[(0,r.createBlock)("core/paragraph",{placeholder:(0,d.__)("Answer…","4wp-faq")})];return(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:o}),(0,r.createBlock)("core/accordion-panel",{},n)])})(e.question,e.answers)))])},M=e=>(e||[]).map(e=>e&&"object"==typeof e&&e.name?(0,r.cloneBlock)(e):e),O=(e,t)=>{const o=Array.isArray(e),n=o?e:[e],c=o?t:[t||[]];return(0,r.createBlock)("forwp/faq",{},n.map((e,t)=>(0,r.createBlock)("core/details",e||{},M(c[t]||[]))))},x=(e,t)=>{const o=Array.isArray(e),n=o?e:[e],c=o?t:[t||[]];return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},n.map((e,t)=>(0,r.createBlock)("core/accordion-item",e||{},M(c[t]||[]))))])},T=(e,t)=>{if(2===e.length&&!_(e[0]))return((e,t)=>{let o=e[0],n=e[1],c=t[1]||[];_(o)||(o=e[1],n=e[0],c=t[0]||[]);const a=o.content||"",l=(0,r.createBlock)("core/paragraph",n,c);return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},[(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:a}),(0,r.createBlock)("core/accordion-panel",{},[l])])])])})(e,t);const o=[];for(let n=0;n<e.length;n+=2){const c=e[n]?.content||"",a=(0,r.createBlock)("core/paragraph",e[n+1]||{},t[n+1]||[]);o.push((0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:c}),(0,r.createBlock)("core/accordion-panel",{},[a])]))}return(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},o)])},Q=(0,d.__)("Convert to 4WP FAQ","4wp-faq"),P=(0,d.__)("Unwrap 4WP FAQ","4wp-faq"),N={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,isMatch:(e,t)=>A(t),__experimentalConvert:e=>S(e)},D={type:"block",blocks:["*"],isMultiBlock:!0,isMatch:(e,t)=>A(t),__experimentalConvert:e=>S(e)},L={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,transform:(e,t)=>O(e,t)},J={type:"block",blocks:["forwp/faq"],isMultiBlock:!0,transform:(e,t)=>x(e,t)},R={type:"block",blocks:["forwp/faq"],transform:(e,t)=>(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",e,t)])},H=e=>{const t=[];return(e||[]).forEach(e=>{if("core/list-item"!==e.name)return;const r=(e.attributes?.content||"").trim();r&&t.push(r)}),t},W=(e,t)=>{let o=H(t);return!o.length&&e?.values&&(o=(e=>{if(!e||"string"!=typeof e)return[];const t=(new DOMParser).parseFromString(`<ul>${e}</ul>`,"text/html");return Array.from(t.querySelectorAll("li")).map(e=>(e.innerHTML||e.textContent||"").trim()).filter(Boolean)})(e.values)),o.length?(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",{},o.map(e=>(e=>(0,r.createBlock)("core/accordion-item",{},[(0,r.createBlock)("core/accordion-heading",{content:e}),(0,r.createBlock)("core/accordion-panel",{},[(0,r.createBlock)("core/paragraph",{placeholder:(0,d.__)("Answer…","4wp-faq")})])]))(e)))]):(0,r.createBlock)("forwp/faq",{},[q()])},j={type:"block",blocks:["forwp/faq"],transform:(e,t)=>W(e,t)};(0,r.registerBlockType)("forwp/faq",{edit:e=>{const{attributes:l,setAttributes:i,clientId:s}=e,{getBlock:m,postId:f}=(0,c.useSelect)(e=>({getBlock:e("core/block-editor").getBlock,postId:e("core/editor")?.getCurrentPostId?.()||0}),[e.clientId]),{insertBlock:g,replaceBlock:_,replaceBlocks:E}=(0,c.useDispatch)("core/block-editor"),A=m(s),F=(A?.innerBlocks||[]).length>0,C=(0,a.useMemo)(()=>(e=>{const t=[],r=e=>{e.forEach(e=>{const o=e.name;if((e=>"string"==typeof e&&("core/accordion-item"===e||e.includes("accordion-item")))(o)||(e=>"string"==typeof e&&("core/details"===e||e.endsWith("/details")))(o)){const{question:r,answer:o}=(e=>{const t=e.attributes||{};let r=(t.title||t.summary||t.question||t.heading||"").trim(),o="";const n=e.innerBlocks||[];return!r&&n.length&&(r=u([n[0]]),n.length>1&&(o=u(n.slice(1)))),!o&&n.length&&(o=u(n)),{question:r.trim(),answer:o.trim()}})(e);r&&o&&t.push({question:r,answer:o})}e.innerBlocks&&e.innerBlocks.length&&r(e.innerBlocks)})};return r(e||[]),t})(A?.innerBlocks||[]),[A]),v=(0,a.useMemo)(()=>(A?.innerBlocks||[]).find(e=>"core/accordion"===e.name||"core/accordion-group"===e.name)||null,[A]),I=l.jsonLd||"",S=Array.isArray(l.categoryTermIds)?l.categoryTermIds:[],M=l.categoryTermId||0,O=S.length>0?S:M?[M]:[],x=l.categoryName||"",[T,Q]=(0,a.useState)(!(!x||!String(x).trim())),{terms:N,loading:D,registryReady:L}=(e=>{const[t,r]=(0,a.useState)([]),[o,n]=(0,a.useState)(!1),c=!!k().registrySetupComplete,l=k().categoriesPath||"/forwp-faq/v1/editor/categories";return(0,a.useEffect)(()=>{if(!c)return void r([]);let t=!1;n(!0);const o=e?`?post_id=${e}`:"";return p()({path:`${l}${o}`}).then(e=>{t||r(Array.isArray(e?.terms)?e.terms:[])}).catch(()=>{t||r([])}).finally(()=>{t||n(!1)}),()=>{t=!0}},[c,l,e]),{terms:t,loading:o,registryReady:c}})(f),J=(e=>{const t=e||"";return"enable"===t||"disable"!==t&&!!h()})(I),R=h(),H=(0,a.useMemo)(()=>C.length&&J?JSON.stringify({"@context":"https://schema.org","@type":"FAQPage",mainEntity:C.map(e=>({"@type":"Question",name:e.question,acceptedAnswer:{"@type":"Answer",text:e.answer}}))},null,2):"",[C,J]),W=R?(0,d.__)("Site-wide JSON-LD is on. Choose “Off for this block” to exclude this FAQ from structured data.","4wp-faq"):(0,d.__)("Site-wide JSON-LD is off. Choose “On for this block” to output FAQPage schema for this block only.","4wp-faq");return(0,t.createElement)(a.Fragment,null,(0,t.createElement)(o.BlockControls,null,(0,t.createElement)(n.ToolbarGroup,null,(0,t.createElement)(n.ToolbarButton,{icon:"undo",text:P,label:P,onClick:()=>{const e=A?.innerBlocks||[];e.length?E([s],e.map(e=>(0,r.cloneBlock)(e))):_(s,q())}}))),(0,t.createElement)(o.InspectorControls,null,(0,t.createElement)(n.PanelBody,{title:(0,d.__)("SEO","4wp-faq"),initialOpen:!0},(0,t.createElement)(n.SelectControl,{label:(0,d.__)("JSON-LD on front end","4wp-faq"),help:W,value:I,options:[{label:R?(0,d.__)("Default (on — site setting)","4wp-faq"):(0,d.__)("Default (off — site setting)","4wp-faq"),value:""},{label:(0,d.__)("On for this block","4wp-faq"),value:"enable"},{label:(0,d.__)("Off for this block","4wp-faq"),value:"disable"}],onChange:e=>i({jsonLd:e||""})})),(0,t.createElement)(n.PanelBody,{title:(0,d.__)("Registry category","4wp-faq"),initialOpen:!1},L?D?(0,t.createElement)(n.Spinner,null):(0,t.createElement)(a.Fragment,null,(0,t.createElement)(n.FormTokenField,{label:(0,d.__)("FAQ categories","4wp-faq"),help:(0,d.__)("Search by name. The first category is the primary group for this FAQ. Applied on scan.","4wp-faq"),value:(O||[]).map(e=>N.find(t=>t.id===e)?.name).filter(Boolean),suggestions:N.map(e=>e.name),onChange:e=>{const t=(e||[]).map(e=>N.find(t=>t.name===e)?.id).filter(Boolean);i({categoryTermIds:t,categoryTermId:t[0]||0,categoryMode:t.length?B:x?"new":w})},__experimentalExpandOnFocus:!0,__nextHasNoMarginBottom:!0}),T?(0,t.createElement)(n.TextControl,{label:(0,d.__)("New category name","4wp-faq"),help:(0,d.__)("Created in the FAQ registry taxonomy on scan (language follows this page). Becomes primary if no existing category is selected.","4wp-faq"),value:x,onChange:e=>i({categoryName:e||"",categoryMode:O.length?B:e?"new":w})}):(0,t.createElement)(n.Button,{variant:"secondary",onClick:()=>Q(!0)},(0,d.__)("Add new","4wp-faq"))):(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,d.__)("Complete FAQ registry setup to assign categories during scan.","4wp-faq"))),(0,t.createElement)(n.PanelBody,{title:(0,d.__)("FAQ preview","4wp-faq"),initialOpen:!1},0===C.length?(0,t.createElement)(n.Notice,{status:"warning",isDismissible:!1},(0,d.__)("Add accordion items to generate FAQ schema.","4wp-faq")):null,!J&&C.length>0?(0,t.createElement)(n.Notice,{status:"info",isDismissible:!1},(0,d.__)("JSON-LD is off for this block on the front end.","4wp-faq")):null,(0,t.createElement)("p",null,(0,d.__)("Items:","4wp-faq")," ",C.length),(0,t.createElement)(n.TextareaControl,{label:(0,d.__)("Schema JSON-LD (preview)","4wp-faq"),value:H,rows:Math.min(12,Math.max(6,2*C.length)),readOnly:!0}))),(0,t.createElement)("div",{className:e.className},(0,t.createElement)(o.InnerBlocks,{allowedBlocks:b,template:F?void 0:[["core/accordion",{},[["core/accordion-item",{},[["core/accordion-heading",{content:(0,d.__)("Question","4wp-faq")}],["core/accordion-panel",{},[["core/paragraph",{placeholder:(0,d.__)("Answer…","4wp-faq")}]]]]]]]],templateLock:!1}),(0,t.createElement)("div",{className:"forwp-faq-editor-actions",style:{marginTop:"12px"}},(0,t.createElement)(n.Button,{variant:"secondary",onClick:()=>{const e=y();v?g(e,v.clientId,v.innerBlocks?.length||0):g(q(),s,0)}},(0,d.__)("Add FAQ item","4wp-faq")))))},save:()=>(0,t.createElement)(o.InnerBlocks.Content,null),transforms:{from:[{type:"block",blocks:["core/accordion","core/accordion-group"],transform:(e,t)=>(0,r.createBlock)("forwp/faq",{},[(0,r.createBlock)("core/accordion",e,t)])},{type:"block",blocks:["core/accordion-item"],isMultiBlock:!0,transform:(e,t)=>x(e,t)},{type:"block",blocks:["core/details"],isMultiBlock:!0,transform:(e,t)=>O(e,t)},D,{type:"block",blocks:["core/list"],transform:(e,t)=>W(e,t)}]}});const $=(0,i.createHigherOrderComponent)(e=>r=>{const l=g(r.name),i="core/accordion-item"===r.name,s="core/details"===r.name,p="core/list"===r.name;if(!(l||i||s||p))return(0,t.createElement)(e,{...r});const{replaceBlock:d,replaceBlocks:m}=(0,c.useDispatch)("core/block-editor"),{getBlock:u,getBlockRootClientId:k,getMultiSelectedBlockClientIds:h}=(0,c.useSelect)(e=>({getBlock:e("core/block-editor").getBlock,getBlockRootClientId:e("core/block-editor").getBlockRootClientId,getMultiSelectedBlockClientIds:e("core/block-editor").getMultiSelectedBlockClientIds}),[r.clientId]),w=h(),B=(w||[]).map(e=>u(e)).filter(Boolean),b=B.length>1&&B.every(e=>e.name===r.name)&&(s||i);return b&&w[0]!==r.clientId?(0,t.createElement)(e,{...r}):(0,t.createElement)(a.Fragment,null,(0,t.createElement)(e,{...r}),(0,t.createElement)(o.BlockControls,null,(0,t.createElement)(n.ToolbarGroup,null,(0,t.createElement)(n.ToolbarButton,{icon:"editor-help",text:Q,label:Q,onClick:()=>{if(b){const e=B.map(e=>e.attributes),t=B.map(e=>e.innerBlocks),r=s?O(e,t):x(e,t);return void m(w,[r])}const e=u(r.clientId);if(!e)return;if(p)return void d(r.clientId,W(e.attributes,e.innerBlocks));if(s)return void d(r.clientId,f(e));if(l)return void d(r.clientId,f(e));const t=k(r.clientId),o=t?u(t):null;o&&g(o.name)?d(t,f(o)):d(r.clientId,x(e.attributes,e.innerBlocks))}}))))},"withFaqTransform");(0,l.addFilter)("editor.BlockEdit","forwp/faq/with-transform",$);const G=(0,i.createHigherOrderComponent)(e=>r=>{if(!E.includes(r.name))return(0,t.createElement)(e,{...r});const{getMultiSelectedBlockClientIds:l,getBlock:i}=(0,c.useSelect)(e=>({getMultiSelectedBlockClientIds:e("core/block-editor").getMultiSelectedBlockClientIds,getBlock:e("core/block-editor").getBlock}),[]),{replaceBlocks:s}=(0,c.useDispatch)("core/block-editor"),p=l(),d=p.length>=2?p.map(e=>i(e)).filter(Boolean):[],m=A(d),f=m&&p[0]===r.clientId;return(0,t.createElement)(a.Fragment,null,(0,t.createElement)(e,{...r}),f?(0,t.createElement)(o.BlockControls,null,(0,t.createElement)(n.ToolbarGroup,null,(0,t.createElement)(n.ToolbarButton,{icon:"editor-help",text:Q,label:Q,onClick:()=>{m&&s(p,[S(d)])}}))):null)},"withHeadingParagraphFaqConvert");(0,l.addFilter)("editor.BlockEdit","forwp/faq/with-heading-paragraph-convert",G),(0,l.addFilter)("blocks.registerBlockType","forwp/faq/block-to-faq-transforms",(e,t)=>{if("core/heading"===t||"core/paragraph"===t||"core/quote"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,N]}}}if("core/list"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,j,N]}}}if("core/details"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,L]}}}if("core/accordion-item"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,J]}}}if("core/accordion"===t||"core/accordion-group"===t){const t=e.transforms?.to||[];return{...e,transforms:{...e.transforms,to:[...t,R]}}}return e})})();
  • 4wp-faq/trunk/build/style-faq-card-rtl.css

    r3685374 r3748403  
    1 .forwp-faq-card,.wp-block-forwp-faq-card{border-bottom:1px solid rgba(15,23,42,.12);margin:0}.forwp-faq-card__details{margin:0}.forwp-faq-card__question{color:var(--forwp-faq-q-color,inherit);cursor:pointer;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-weight:var(--forwp-faq-q-weight,650);line-height:var(--forwp-faq-q-line,inherit);list-style:none;margin:0;padding:.9rem 0}.forwp-faq-card__question::-webkit-details-marker{display:none}.forwp-faq-card__details .forwp-faq-card__question:after{content:"+";float:left;font-weight:500;margin-right:.75rem}.forwp-faq-card__details[open] .forwp-faq-card__question:after{content:"–"}.forwp-faq-card.is-display-heading .forwp-faq-card__question{cursor:default;padding-bottom:.35rem}.forwp-faq-card__body{padding:0 0 1rem}.forwp-faq-card__answer{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-weight:var(--forwp-faq-a-weight,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:0}.forwp-faq-card .forwp-faq-card__answer div,.forwp-faq-card .forwp-faq-card__answer li,.forwp-faq-card .forwp-faq-card__answer p,.forwp-faq-card .forwp-faq-card__answer span,.wp-block-forwp-faq-card .forwp-faq-card__answer div,.wp-block-forwp-faq-card .forwp-faq-card__answer li,.wp-block-forwp-faq-card .forwp-faq-card__answer p,.wp-block-forwp-faq-card .forwp-faq-card__answer span{color:inherit;font-family:inherit;font-size:inherit;font-weight:inherit;line-height:inherit}.forwp-faq-card__answer>:first-child{margin-top:0}.forwp-faq-card__answer>:last-child{margin-bottom:0}.forwp-faq-card__sources{margin-top:.85rem}.forwp-faq-card__sources-label{font-size:.75rem;font-weight:700;letter-spacing:.04em;margin:0 0 .35rem;opacity:.7;text-transform:uppercase}.forwp-faq-card__sources-list{list-style:none;margin:0;padding:0}.forwp-faq-card__sources-item{display:flex;flex-wrap:wrap;font-size:.875rem;gap:.35rem .75rem;margin:.2rem 0}.forwp-faq-card__sources-type{opacity:.65}.forwp-faq-card-editor{padding:.25rem 0}.forwp-faq-card-editor__question{color:var(--forwp-faq-q-color,inherit);display:block;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-weight:var(--forwp-faq-q-weight,650);margin:0}.forwp-faq-card-editor__answer,.forwp-faq-card-editor__sources{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-weight:var(--forwp-faq-a-weight,inherit);margin:.35rem 0 0;opacity:.75}
     1.forwp-faq-card,.wp-block-forwp-faq-card{border-bottom:1px solid rgba(15,23,42,.12);margin:0}.forwp-faq-card__details{margin:0}.forwp-faq-card__question{color:var(--forwp-faq-q-color,inherit);cursor:pointer;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-style:var(--forwp-faq-q-style,inherit);font-weight:var(--forwp-faq-q-weight,650);letter-spacing:var(--forwp-faq-q-spacing,inherit);line-height:var(--forwp-faq-q-line,inherit);list-style:none;margin:0;padding:.9rem 0;-webkit-text-decoration:var(--forwp-faq-q-decoration,inherit);text-decoration:var(--forwp-faq-q-decoration,inherit);text-transform:var(--forwp-faq-q-transform,inherit)}.forwp-faq-card__question::-webkit-details-marker{display:none}.forwp-faq-card__details .forwp-faq-card__question:after{content:"+";float:left;font-weight:500;margin-right:.75rem}.forwp-faq-card__details[open] .forwp-faq-card__question:after{content:"–"}.forwp-faq-card.is-display-heading .forwp-faq-card__question{cursor:default;padding-bottom:.35rem}.forwp-faq-card__body{padding:0 0 1rem}.forwp-faq-card__answer{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-style:var(--forwp-faq-a-style,inherit);font-weight:var(--forwp-faq-a-weight,inherit);letter-spacing:var(--forwp-faq-a-spacing,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:0;-webkit-text-decoration:var(--forwp-faq-a-decoration,inherit);text-decoration:var(--forwp-faq-a-decoration,inherit);text-transform:var(--forwp-faq-a-transform,inherit)}.forwp-faq-card .forwp-faq-card__answer div,.forwp-faq-card .forwp-faq-card__answer li,.forwp-faq-card .forwp-faq-card__answer p,.forwp-faq-card .forwp-faq-card__answer span,.wp-block-forwp-faq-card .forwp-faq-card__answer div,.wp-block-forwp-faq-card .forwp-faq-card__answer li,.wp-block-forwp-faq-card .forwp-faq-card__answer p,.wp-block-forwp-faq-card .forwp-faq-card__answer span{color:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-transform:inherit}.forwp-faq-card__answer>:first-child{margin-top:0}.forwp-faq-card__answer>:last-child{margin-bottom:0}.forwp-faq-card__sources{align-items:baseline;display:flex;flex-wrap:wrap;gap:.25rem .5rem;margin-top:.85rem}.forwp-faq-card__sources-label{font-size:.75rem;font-weight:700;letter-spacing:.04em;margin:0;opacity:.7;text-transform:uppercase}.forwp-faq-card__sources-list{font-size:.875rem;margin:0}.forwp-faq-card__sources-item.is-inactive{cursor:not-allowed;opacity:.5}.forwp-faq-card__sources-type{opacity:.65}.forwp-faq-card-editor{padding:.25rem 0}.forwp-faq-card-editor__question{color:var(--forwp-faq-q-color,inherit);display:block;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-style:var(--forwp-faq-q-style,inherit);font-weight:var(--forwp-faq-q-weight,650);letter-spacing:var(--forwp-faq-q-spacing,inherit);line-height:var(--forwp-faq-q-line,inherit);margin:0;-webkit-text-decoration:var(--forwp-faq-q-decoration,inherit);text-decoration:var(--forwp-faq-q-decoration,inherit);text-transform:var(--forwp-faq-q-transform,inherit)}.forwp-faq-card-editor__answer,.forwp-faq-card-editor__sources{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-style:var(--forwp-faq-a-style,inherit);font-weight:var(--forwp-faq-a-weight,inherit);letter-spacing:var(--forwp-faq-a-spacing,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:.35rem 0 0;opacity:.75;-webkit-text-decoration:var(--forwp-faq-a-decoration,inherit);text-decoration:var(--forwp-faq-a-decoration,inherit);text-transform:var(--forwp-faq-a-transform,inherit)}
  • 4wp-faq/trunk/build/style-faq-card.css

    r3685374 r3748403  
    1 .forwp-faq-card,.wp-block-forwp-faq-card{border-bottom:1px solid rgba(15,23,42,.12);margin:0}.forwp-faq-card__details{margin:0}.forwp-faq-card__question{color:var(--forwp-faq-q-color,inherit);cursor:pointer;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-weight:var(--forwp-faq-q-weight,650);line-height:var(--forwp-faq-q-line,inherit);list-style:none;margin:0;padding:.9rem 0}.forwp-faq-card__question::-webkit-details-marker{display:none}.forwp-faq-card__details .forwp-faq-card__question:after{content:"+";float:right;font-weight:500;margin-left:.75rem}.forwp-faq-card__details[open] .forwp-faq-card__question:after{content:"–"}.forwp-faq-card.is-display-heading .forwp-faq-card__question{cursor:default;padding-bottom:.35rem}.forwp-faq-card__body{padding:0 0 1rem}.forwp-faq-card__answer{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-weight:var(--forwp-faq-a-weight,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:0}.forwp-faq-card .forwp-faq-card__answer div,.forwp-faq-card .forwp-faq-card__answer li,.forwp-faq-card .forwp-faq-card__answer p,.forwp-faq-card .forwp-faq-card__answer span,.wp-block-forwp-faq-card .forwp-faq-card__answer div,.wp-block-forwp-faq-card .forwp-faq-card__answer li,.wp-block-forwp-faq-card .forwp-faq-card__answer p,.wp-block-forwp-faq-card .forwp-faq-card__answer span{color:inherit;font-family:inherit;font-size:inherit;font-weight:inherit;line-height:inherit}.forwp-faq-card__answer>:first-child{margin-top:0}.forwp-faq-card__answer>:last-child{margin-bottom:0}.forwp-faq-card__sources{margin-top:.85rem}.forwp-faq-card__sources-label{font-size:.75rem;font-weight:700;letter-spacing:.04em;margin:0 0 .35rem;opacity:.7;text-transform:uppercase}.forwp-faq-card__sources-list{list-style:none;margin:0;padding:0}.forwp-faq-card__sources-item{display:flex;flex-wrap:wrap;font-size:.875rem;gap:.35rem .75rem;margin:.2rem 0}.forwp-faq-card__sources-type{opacity:.65}.forwp-faq-card-editor{padding:.25rem 0}.forwp-faq-card-editor__question{color:var(--forwp-faq-q-color,inherit);display:block;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-weight:var(--forwp-faq-q-weight,650);margin:0}.forwp-faq-card-editor__answer,.forwp-faq-card-editor__sources{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-weight:var(--forwp-faq-a-weight,inherit);margin:.35rem 0 0;opacity:.75}
     1.forwp-faq-card,.wp-block-forwp-faq-card{border-bottom:1px solid rgba(15,23,42,.12);margin:0}.forwp-faq-card__details{margin:0}.forwp-faq-card__question{color:var(--forwp-faq-q-color,inherit);cursor:pointer;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-style:var(--forwp-faq-q-style,inherit);font-weight:var(--forwp-faq-q-weight,650);letter-spacing:var(--forwp-faq-q-spacing,inherit);line-height:var(--forwp-faq-q-line,inherit);list-style:none;margin:0;padding:.9rem 0;-webkit-text-decoration:var(--forwp-faq-q-decoration,inherit);text-decoration:var(--forwp-faq-q-decoration,inherit);text-transform:var(--forwp-faq-q-transform,inherit)}.forwp-faq-card__question::-webkit-details-marker{display:none}.forwp-faq-card__details .forwp-faq-card__question:after{content:"+";float:right;font-weight:500;margin-left:.75rem}.forwp-faq-card__details[open] .forwp-faq-card__question:after{content:"–"}.forwp-faq-card.is-display-heading .forwp-faq-card__question{cursor:default;padding-bottom:.35rem}.forwp-faq-card__body{padding:0 0 1rem}.forwp-faq-card__answer{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-style:var(--forwp-faq-a-style,inherit);font-weight:var(--forwp-faq-a-weight,inherit);letter-spacing:var(--forwp-faq-a-spacing,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:0;-webkit-text-decoration:var(--forwp-faq-a-decoration,inherit);text-decoration:var(--forwp-faq-a-decoration,inherit);text-transform:var(--forwp-faq-a-transform,inherit)}.forwp-faq-card .forwp-faq-card__answer div,.forwp-faq-card .forwp-faq-card__answer li,.forwp-faq-card .forwp-faq-card__answer p,.forwp-faq-card .forwp-faq-card__answer span,.wp-block-forwp-faq-card .forwp-faq-card__answer div,.wp-block-forwp-faq-card .forwp-faq-card__answer li,.wp-block-forwp-faq-card .forwp-faq-card__answer p,.wp-block-forwp-faq-card .forwp-faq-card__answer span{color:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-transform:inherit}.forwp-faq-card__answer>:first-child{margin-top:0}.forwp-faq-card__answer>:last-child{margin-bottom:0}.forwp-faq-card__sources{align-items:baseline;display:flex;flex-wrap:wrap;gap:.25rem .5rem;margin-top:.85rem}.forwp-faq-card__sources-label{font-size:.75rem;font-weight:700;letter-spacing:.04em;margin:0;opacity:.7;text-transform:uppercase}.forwp-faq-card__sources-list{font-size:.875rem;margin:0}.forwp-faq-card__sources-item.is-inactive{cursor:not-allowed;opacity:.5}.forwp-faq-card__sources-type{opacity:.65}.forwp-faq-card-editor{padding:.25rem 0}.forwp-faq-card-editor__question{color:var(--forwp-faq-q-color,inherit);display:block;font-family:var(--forwp-faq-q-family,inherit);font-size:var(--forwp-faq-q-size,inherit);font-style:var(--forwp-faq-q-style,inherit);font-weight:var(--forwp-faq-q-weight,650);letter-spacing:var(--forwp-faq-q-spacing,inherit);line-height:var(--forwp-faq-q-line,inherit);margin:0;-webkit-text-decoration:var(--forwp-faq-q-decoration,inherit);text-decoration:var(--forwp-faq-q-decoration,inherit);text-transform:var(--forwp-faq-q-transform,inherit)}.forwp-faq-card-editor__answer,.forwp-faq-card-editor__sources{color:var(--forwp-faq-a-color,inherit);font-family:var(--forwp-faq-a-family,inherit);font-size:var(--forwp-faq-a-size,inherit);font-style:var(--forwp-faq-a-style,inherit);font-weight:var(--forwp-faq-a-weight,inherit);letter-spacing:var(--forwp-faq-a-spacing,inherit);line-height:var(--forwp-faq-a-line,inherit);margin:.35rem 0 0;opacity:.75;-webkit-text-decoration:var(--forwp-faq-a-decoration,inherit);text-decoration:var(--forwp-faq-a-decoration,inherit);text-transform:var(--forwp-faq-a-transform,inherit)}
  • 4wp-faq/trunk/build/style-faq-categories-rtl.css

    r3691205 r3748403  
    1 .forwp-faq-categories,.wp-block-forwp-faq-categories{margin:0}.forwp-faq-categories__label{font-size:.7rem;font-weight:700;letter-spacing:.08em;margin:0 0 .75rem;opacity:.7;text-transform:uppercase}.forwp-faq-categories__list{display:flex;flex-direction:column;gap:0;list-style:none;margin:0;padding:0}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__list{flex-direction:row;flex-wrap:wrap;gap:.35rem}.forwp-faq-categories.is-collapsible .forwp-faq-categories__item{align-items:center;display:grid;grid-template-columns:minmax(0,1fr) 1.75rem minmax(2.25em,max-content)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__link{grid-column:1;justify-content:flex-start;min-width:0}.forwp-faq-categories.is-collapsible .forwp-faq-categories__toggle{grid-column:2;grid-row:1;justify-self:center}.forwp-faq-categories.is-collapsible .forwp-faq-categories__count{font-variant-numeric:tabular-nums;grid-column:3;grid-row:1;justify-self:end;min-width:1.5em;text-align:left}.forwp-faq-categories.is-collapsible .forwp-faq-categories__children{grid-column:1/-1}.forwp-faq-categories__toggle{all:unset;align-items:center;background:transparent;border:0;border-radius:.25rem;box-sizing:border-box;color:inherit;cursor:pointer;display:inline-flex;height:1.75rem;justify-content:center;line-height:0;margin:0;padding:0;width:1.75rem}.forwp-faq-categories__toggle:focus-visible,.forwp-faq-categories__toggle:hover{background:color-mix(in srgb,currentColor 12%,transparent);outline:none}.forwp-faq-categories__chevron{border:0;display:block;fill:none;height:.75rem;pointer-events:none;stroke:currentColor;transform:rotate(0deg);transform-origin:50% 50%;transition:transform .15s ease;width:.75rem}.forwp-faq-categories__item.is-expanded>.forwp-faq-categories__toggle .forwp-faq-categories__chevron{transform:rotate(-90deg)}.forwp-faq-categories__children{list-style:none;margin:0;padding:0 .85rem 0 0}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__children{flex-basis:100%;padding-right:0}.forwp-faq-categories__link{align-items:center;color:inherit;display:flex;gap:.5rem;justify-content:space-between;padding:.55rem 0;text-decoration:none}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__link{border:1px solid;padding:.4rem .75rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__toggle{height:1.5rem;width:1.5rem}.forwp-faq-categories__item.is-active .forwp-faq-categories__link,.forwp-faq-categories__link:focus-visible,.forwp-faq-categories__link:hover{font-weight:650;outline:none}.forwp-faq-categories__count{font-size:.75rem;opacity:.65}.forwp-faq-categories__empty{margin:0;opacity:.75}.forwp-faq-categories-editor__help{font-size:.8125rem;margin:.25rem 0 1rem;opacity:.75}
     1.forwp-faq-categories,.wp-block-forwp-faq-categories{margin:0}.forwp-faq-categories__label{font-size:.7rem;font-weight:700;letter-spacing:.08em;margin:0 0 .75rem;opacity:.7;text-transform:uppercase}.forwp-faq-categories__menu{align-items:center;background:transparent;border:1px solid;color:inherit;cursor:pointer;display:none;font:inherit;gap:.5rem;line-height:1.2;margin:0 0 .75rem;padding:.6rem .75rem;text-align:right;width:100%}.forwp-faq-categories__menu-icon{display:block;flex:0 0 auto}.forwp-faq-categories__list{display:flex;flex-direction:column;gap:var(--forwp-faq-item-gap,0);list-style:none;margin:0;padding:0}@media(max-width:781px){.forwp-faq-categories__menu{display:flex}.forwp-faq-categories__list{display:none}.forwp-faq-categories.is-menu-open .forwp-faq-categories__list{display:flex;flex-direction:column}}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__list{flex-direction:row;flex-wrap:wrap;gap:var(--forwp-faq-item-gap,.35rem)}.forwp-faq-categories__item.is-all .forwp-faq-categories__term{font-size:var(--forwp-faq-all-size,inherit)}.forwp-faq-categories__item:not(.is-all) .forwp-faq-categories__term{font-size:var(--forwp-faq-item-size,inherit)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__item{align-items:center;display:grid;grid-template-columns:minmax(0,1fr) 1.75rem minmax(2.25em,max-content)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__link{grid-column:1;justify-content:flex-start;min-width:0}.forwp-faq-categories.is-collapsible .forwp-faq-categories__toggle{grid-column:2;grid-row:1;justify-self:center}.forwp-faq-categories.is-collapsible .forwp-faq-categories__count{font-variant-numeric:tabular-nums;grid-column:3;grid-row:1;justify-self:end;min-width:1.5em;text-align:left}.forwp-faq-categories.is-collapsible .forwp-faq-categories__children{grid-column:1/-1}.forwp-faq-categories__toggle{all:unset;align-items:center;background:transparent;border:0;border-radius:.25rem;box-sizing:border-box;color:inherit;cursor:pointer;display:inline-flex;height:1.75rem;justify-content:center;line-height:0;margin:0;padding:0;width:1.75rem}.forwp-faq-categories__toggle:focus-visible,.forwp-faq-categories__toggle:hover{background:color-mix(in srgb,currentColor 12%,transparent);outline:none}.forwp-faq-categories__chevron{border:0;display:block;fill:none;height:.75rem;pointer-events:none;stroke:currentColor;transform:rotate(0deg);transform-origin:50% 50%;transition:transform .15s ease;width:.75rem}.forwp-faq-categories__item.is-expanded>.forwp-faq-categories__toggle .forwp-faq-categories__chevron{transform:rotate(-90deg)}.forwp-faq-categories__children{list-style:none;margin:0;padding:0 .85rem 0 0}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__children{flex-basis:100%;padding-right:0}.forwp-faq-categories__link{align-items:center;color:inherit;display:flex;gap:.5rem;justify-content:space-between;padding:.55rem 0;text-decoration:none}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__link{border:1px solid;padding:.4rem .75rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__toggle{height:1.5rem;width:1.5rem}.forwp-faq-categories__item.is-active .forwp-faq-categories__link,.forwp-faq-categories__link:focus-visible,.forwp-faq-categories__link:hover{font-weight:650;outline:none}.forwp-faq-categories__count{font-size:.75rem;opacity:.65}.forwp-faq-categories__empty{margin:0;opacity:.75}.forwp-faq-categories-editor__help{font-size:.8125rem;margin:.25rem 0 1rem;opacity:.75}
  • 4wp-faq/trunk/build/style-faq-categories.css

    r3691205 r3748403  
    1 .forwp-faq-categories,.wp-block-forwp-faq-categories{margin:0}.forwp-faq-categories__label{font-size:.7rem;font-weight:700;letter-spacing:.08em;margin:0 0 .75rem;opacity:.7;text-transform:uppercase}.forwp-faq-categories__list{display:flex;flex-direction:column;gap:0;list-style:none;margin:0;padding:0}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__list{flex-direction:row;flex-wrap:wrap;gap:.35rem}.forwp-faq-categories.is-collapsible .forwp-faq-categories__item{align-items:center;display:grid;grid-template-columns:minmax(0,1fr) 1.75rem minmax(2.25em,max-content)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__link{grid-column:1;justify-content:flex-start;min-width:0}.forwp-faq-categories.is-collapsible .forwp-faq-categories__toggle{grid-column:2;grid-row:1;justify-self:center}.forwp-faq-categories.is-collapsible .forwp-faq-categories__count{font-variant-numeric:tabular-nums;grid-column:3;grid-row:1;justify-self:end;min-width:1.5em;text-align:right}.forwp-faq-categories.is-collapsible .forwp-faq-categories__children{grid-column:1/-1}.forwp-faq-categories__toggle{all:unset;align-items:center;background:transparent;border:0;border-radius:.25rem;box-sizing:border-box;color:inherit;cursor:pointer;display:inline-flex;height:1.75rem;justify-content:center;line-height:0;margin:0;padding:0;width:1.75rem}.forwp-faq-categories__toggle:focus-visible,.forwp-faq-categories__toggle:hover{background:color-mix(in srgb,currentColor 12%,transparent);outline:none}.forwp-faq-categories__chevron{border:0;display:block;fill:none;height:.75rem;pointer-events:none;stroke:currentColor;transform:rotate(0deg);transform-origin:50% 50%;transition:transform .15s ease;width:.75rem}.forwp-faq-categories__item.is-expanded>.forwp-faq-categories__toggle .forwp-faq-categories__chevron{transform:rotate(90deg)}.forwp-faq-categories__children{list-style:none;margin:0;padding:0 0 0 .85rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__children{flex-basis:100%;padding-left:0}.forwp-faq-categories__link{align-items:center;color:inherit;display:flex;gap:.5rem;justify-content:space-between;padding:.55rem 0;text-decoration:none}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__link{border:1px solid;padding:.4rem .75rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__toggle{height:1.5rem;width:1.5rem}.forwp-faq-categories__item.is-active .forwp-faq-categories__link,.forwp-faq-categories__link:focus-visible,.forwp-faq-categories__link:hover{font-weight:650;outline:none}.forwp-faq-categories__count{font-size:.75rem;opacity:.65}.forwp-faq-categories__empty{margin:0;opacity:.75}.forwp-faq-categories-editor__help{font-size:.8125rem;margin:.25rem 0 1rem;opacity:.75}
     1.forwp-faq-categories,.wp-block-forwp-faq-categories{margin:0}.forwp-faq-categories__label{font-size:.7rem;font-weight:700;letter-spacing:.08em;margin:0 0 .75rem;opacity:.7;text-transform:uppercase}.forwp-faq-categories__menu{align-items:center;background:transparent;border:1px solid;color:inherit;cursor:pointer;display:none;font:inherit;gap:.5rem;line-height:1.2;margin:0 0 .75rem;padding:.6rem .75rem;text-align:left;width:100%}.forwp-faq-categories__menu-icon{display:block;flex:0 0 auto}.forwp-faq-categories__list{display:flex;flex-direction:column;gap:var(--forwp-faq-item-gap,0);list-style:none;margin:0;padding:0}@media(max-width:781px){.forwp-faq-categories__menu{display:flex}.forwp-faq-categories__list{display:none}.forwp-faq-categories.is-menu-open .forwp-faq-categories__list{display:flex;flex-direction:column}}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__list{flex-direction:row;flex-wrap:wrap;gap:var(--forwp-faq-item-gap,.35rem)}.forwp-faq-categories__item.is-all .forwp-faq-categories__term{font-size:var(--forwp-faq-all-size,inherit)}.forwp-faq-categories__item:not(.is-all) .forwp-faq-categories__term{font-size:var(--forwp-faq-item-size,inherit)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__item{align-items:center;display:grid;grid-template-columns:minmax(0,1fr) 1.75rem minmax(2.25em,max-content)}.forwp-faq-categories.is-collapsible .forwp-faq-categories__link{grid-column:1;justify-content:flex-start;min-width:0}.forwp-faq-categories.is-collapsible .forwp-faq-categories__toggle{grid-column:2;grid-row:1;justify-self:center}.forwp-faq-categories.is-collapsible .forwp-faq-categories__count{font-variant-numeric:tabular-nums;grid-column:3;grid-row:1;justify-self:end;min-width:1.5em;text-align:right}.forwp-faq-categories.is-collapsible .forwp-faq-categories__children{grid-column:1/-1}.forwp-faq-categories__toggle{all:unset;align-items:center;background:transparent;border:0;border-radius:.25rem;box-sizing:border-box;color:inherit;cursor:pointer;display:inline-flex;height:1.75rem;justify-content:center;line-height:0;margin:0;padding:0;width:1.75rem}.forwp-faq-categories__toggle:focus-visible,.forwp-faq-categories__toggle:hover{background:color-mix(in srgb,currentColor 12%,transparent);outline:none}.forwp-faq-categories__chevron{border:0;display:block;fill:none;height:.75rem;pointer-events:none;stroke:currentColor;transform:rotate(0deg);transform-origin:50% 50%;transition:transform .15s ease;width:.75rem}.forwp-faq-categories__item.is-expanded>.forwp-faq-categories__toggle .forwp-faq-categories__chevron{transform:rotate(90deg)}.forwp-faq-categories__children{list-style:none;margin:0;padding:0 0 0 .85rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__children{flex-basis:100%;padding-left:0}.forwp-faq-categories__link{align-items:center;color:inherit;display:flex;gap:.5rem;justify-content:space-between;padding:.55rem 0;text-decoration:none}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__link{border:1px solid;padding:.4rem .75rem}.forwp-faq-categories.is-orientation-horizontal .forwp-faq-categories__toggle{height:1.5rem;width:1.5rem}.forwp-faq-categories__item.is-active .forwp-faq-categories__link,.forwp-faq-categories__link:focus-visible,.forwp-faq-categories__link:hover{font-weight:650;outline:none}.forwp-faq-categories__count{font-size:.75rem;opacity:.65}.forwp-faq-categories__empty{margin:0;opacity:.75}.forwp-faq-categories-editor__help{font-size:.8125rem;margin:.25rem 0 1rem;opacity:.75}
  • 4wp-faq/trunk/build/style-faq-list-rtl.css

    r3685374 r3748403  
    1 .forwp-faq-list,.wp-block-forwp-faq-list{display:flex;flex-direction:column;gap:2rem}.forwp-faq-list__group{display:flex;flex-direction:column;gap:.75rem}.forwp-faq-list__group.is-child .forwp-faq-list__group-title{font-size:1.1rem}.forwp-faq-list__children{display:flex;flex-direction:column;gap:1.25rem;margin-top:.5rem;padding-right:.85rem}.forwp-faq-list__more{margin:.75rem 0 0}.forwp-faq-list__more-link{font-size:.9rem}.forwp-faq-list__items{display:flex;flex-direction:column;gap:0}.forwp-faq-list__empty{margin:0;opacity:.75}.forwp-faq-card[hidden],.forwp-faq-list__group[hidden],.wp-block-forwp-faq-card[hidden]{display:none!important}.forwp-faq-list-editor__template{border:1px dashed;margin-bottom:1.5rem;opacity:.9;padding:.75rem 1rem}.forwp-faq-list-editor__help,.forwp-faq-list-editor__hint{font-size:.8125rem;margin:0 0 .75rem;opacity:.75}.forwp-faq-list-editor__help{margin:.25rem 0 1rem}.forwp-faq-typography-help{color:#757575;font-size:12px;line-height:1.4;margin:0 16px 8px}
     1.forwp-faq-list,.wp-block-forwp-faq-list{display:flex;flex-direction:column;gap:2rem}.forwp-faq-list__group{display:flex;flex-direction:column;gap:.75rem}.forwp-faq-list__group.is-child .forwp-faq-list__group-title{font-size:1.1rem}.forwp-faq-list.has-g-size .forwp-faq-list__group-title{font-size:var(--forwp-faq-g-size)}.forwp-faq-list.has-g-family .forwp-faq-list__group-title{font-family:var(--forwp-faq-g-family)}.forwp-faq-list.has-g-weight .forwp-faq-list__group-title{font-weight:var(--forwp-faq-g-weight)}.forwp-faq-list.has-g-color .forwp-faq-list__group-title{color:var(--forwp-faq-g-color)}.forwp-faq-list.has-g-style .forwp-faq-list__group-title{font-style:var(--forwp-faq-g-style)}.forwp-faq-list.has-g-line .forwp-faq-list__group-title{line-height:var(--forwp-faq-g-line)}.forwp-faq-list.has-g-spacing .forwp-faq-list__group-title{letter-spacing:var(--forwp-faq-g-spacing)}.forwp-faq-list.has-g-decoration .forwp-faq-list__group-title{-webkit-text-decoration:var(--forwp-faq-g-decoration);text-decoration:var(--forwp-faq-g-decoration)}.forwp-faq-list.has-g-transform .forwp-faq-list__group-title{text-transform:var(--forwp-faq-g-transform)}.forwp-faq-list__children{display:flex;flex-direction:column;gap:1.25rem;margin-top:.5rem;padding-right:.85rem}.forwp-faq-list__more{margin:.75rem 0 0}.forwp-faq-list__more-link{font-size:.9rem}.forwp-faq-list__items{display:flex;flex-direction:column;gap:0}.forwp-faq-list__empty{margin:0;opacity:.75}.forwp-faq-card[hidden],.forwp-faq-list__group[hidden],.forwp-faq-list__no-results[hidden],.wp-block-forwp-faq-card[hidden]{display:none!important}.forwp-faq-no-results-editor{border:1px dashed rgba(15,23,42,.25);margin-top:.75rem;padding:.5rem .75rem}.forwp-faq-list-editor__template{border:1px dashed;margin-bottom:1.5rem;opacity:.9;padding:.75rem 1rem}.forwp-faq-list-editor__help,.forwp-faq-list-editor__hint{font-size:.8125rem;margin:0 0 .75rem;opacity:.75}.forwp-faq-list-editor__help{margin:.25rem 0 1rem}
  • 4wp-faq/trunk/build/style-faq-list.css

    r3685374 r3748403  
    1 .forwp-faq-list,.wp-block-forwp-faq-list{display:flex;flex-direction:column;gap:2rem}.forwp-faq-list__group{display:flex;flex-direction:column;gap:.75rem}.forwp-faq-list__group.is-child .forwp-faq-list__group-title{font-size:1.1rem}.forwp-faq-list__children{display:flex;flex-direction:column;gap:1.25rem;margin-top:.5rem;padding-left:.85rem}.forwp-faq-list__more{margin:.75rem 0 0}.forwp-faq-list__more-link{font-size:.9rem}.forwp-faq-list__items{display:flex;flex-direction:column;gap:0}.forwp-faq-list__empty{margin:0;opacity:.75}.forwp-faq-card[hidden],.forwp-faq-list__group[hidden],.wp-block-forwp-faq-card[hidden]{display:none!important}.forwp-faq-list-editor__template{border:1px dashed;margin-bottom:1.5rem;opacity:.9;padding:.75rem 1rem}.forwp-faq-list-editor__help,.forwp-faq-list-editor__hint{font-size:.8125rem;margin:0 0 .75rem;opacity:.75}.forwp-faq-list-editor__help{margin:.25rem 0 1rem}.forwp-faq-typography-help{color:#757575;font-size:12px;line-height:1.4;margin:0 16px 8px}
     1.forwp-faq-list,.wp-block-forwp-faq-list{display:flex;flex-direction:column;gap:2rem}.forwp-faq-list__group{display:flex;flex-direction:column;gap:.75rem}.forwp-faq-list__group.is-child .forwp-faq-list__group-title{font-size:1.1rem}.forwp-faq-list.has-g-size .forwp-faq-list__group-title{font-size:var(--forwp-faq-g-size)}.forwp-faq-list.has-g-family .forwp-faq-list__group-title{font-family:var(--forwp-faq-g-family)}.forwp-faq-list.has-g-weight .forwp-faq-list__group-title{font-weight:var(--forwp-faq-g-weight)}.forwp-faq-list.has-g-color .forwp-faq-list__group-title{color:var(--forwp-faq-g-color)}.forwp-faq-list.has-g-style .forwp-faq-list__group-title{font-style:var(--forwp-faq-g-style)}.forwp-faq-list.has-g-line .forwp-faq-list__group-title{line-height:var(--forwp-faq-g-line)}.forwp-faq-list.has-g-spacing .forwp-faq-list__group-title{letter-spacing:var(--forwp-faq-g-spacing)}.forwp-faq-list.has-g-decoration .forwp-faq-list__group-title{-webkit-text-decoration:var(--forwp-faq-g-decoration);text-decoration:var(--forwp-faq-g-decoration)}.forwp-faq-list.has-g-transform .forwp-faq-list__group-title{text-transform:var(--forwp-faq-g-transform)}.forwp-faq-list__children{display:flex;flex-direction:column;gap:1.25rem;margin-top:.5rem;padding-left:.85rem}.forwp-faq-list__more{margin:.75rem 0 0}.forwp-faq-list__more-link{font-size:.9rem}.forwp-faq-list__items{display:flex;flex-direction:column;gap:0}.forwp-faq-list__empty{margin:0;opacity:.75}.forwp-faq-card[hidden],.forwp-faq-list__group[hidden],.forwp-faq-list__no-results[hidden],.wp-block-forwp-faq-card[hidden]{display:none!important}.forwp-faq-no-results-editor{border:1px dashed rgba(15,23,42,.25);margin-top:.75rem;padding:.5rem .75rem}.forwp-faq-list-editor__template{border:1px dashed;margin-bottom:1.5rem;opacity:.9;padding:.75rem 1rem}.forwp-faq-list-editor__help,.forwp-faq-list-editor__hint{font-size:.8125rem;margin:0 0 .75rem;opacity:.75}.forwp-faq-list-editor__help{margin:.25rem 0 1rem}
  • 4wp-faq/trunk/includes/class-admin-dashboard.php

    r3685374 r3748403  
    268268                $rows = [
    269269                        [
    270                                 'class' => 'questions',
    271270                                'url'   => $list,
    272                                 'html'  => sprintf(
    273                                         /* translators: %s: count */
    274                                         __( 'Questions <strong>%s</strong>', '4wp-faq' ),
    275                                         number_format_i18n( (int) ( $stats['total_questions'] ?? 0 ) )
    276                                 ),
    277                         ],
    278                         [
    279                                 'class' => 'categories',
     271                                'value' => (int) ( $stats['total_questions'] ?? 0 ),
     272                                'label' => __( 'Questions', '4wp-faq' ),
     273                        ],
     274                        [
    280275                                'url'   => $cats,
    281                                 'html'  => sprintf(
    282                                         /* translators: %s: count */
    283                                         __( 'Categories <strong>%s</strong>', '4wp-faq' ),
    284                                         number_format_i18n( (int) ( $stats['faq_categories'] ?? 0 ) )
    285                                 ),
    286                         ],
    287                         [
    288                                 'class' => 'reused',
     276                                'value' => (int) ( $stats['faq_categories'] ?? 0 ),
     277                                'label' => __( 'Categories', '4wp-faq' ),
     278                        ],
     279                        [
    289280                                'url'   => $list,
    290                                 'html'  => sprintf(
    291                                         /* translators: %s: count */
    292                                         __( 'Reused <strong>%s</strong>', '4wp-faq' ),
    293                                         number_format_i18n( (int) ( $stats['reused_questions'] ?? 0 ) )
    294                                 ),
    295                         ],
    296                         [
    297                                 'class' => 'once',
     281                                'value' => (int) ( $stats['reused_questions'] ?? 0 ),
     282                                'label' => __( 'Reused', '4wp-faq' ),
     283                        ],
     284                        [
    298285                                'url'   => $list,
    299                                 'html'  => sprintf(
    300                                         /* translators: %s: count */
    301                                         __( 'Used once <strong>%s</strong>', '4wp-faq' ),
    302                                         number_format_i18n( (int) ( $stats['single_use_questions'] ?? 0 ) )
    303                                 ),
    304                         ],
    305                         [
    306                                 'class' => 'pages',
     286                                'value' => (int) ( $stats['single_use_questions'] ?? 0 ),
     287                                'label' => __( 'Used once', '4wp-faq' ),
     288                        ],
     289                        [
    307290                                'url'   => admin_url( 'edit.php?post_type=page' ),
    308                                 'html'  => sprintf(
    309                                         /* translators: %s: count */
    310                                         __( 'Pages with FAQ <strong>%s</strong>', '4wp-faq' ),
    311                                         number_format_i18n( (int) ( $stats['pages_with_faq'] ?? 0 ) )
    312                                 ),
    313                         ],
    314                         [
    315                                 'class' => 'posts',
     291                                'value' => (int) ( $stats['pages_with_faq'] ?? 0 ),
     292                                'label' => __( 'Pages with FAQ', '4wp-faq' ),
     293                        ],
     294                        [
    316295                                'url'   => admin_url( 'edit.php' ),
    317                                 'html'  => sprintf(
    318                                         /* translators: %s: count */
    319                                         __( 'Posts with FAQ <strong>%s</strong>', '4wp-faq' ),
    320                                         number_format_i18n( (int) ( $stats['posts_with_faq'] ?? 0 ) )
    321                                 ),
    322                         ],
    323                         [
    324                                 'class' => 'uncat',
     296                                'value' => (int) ( $stats['posts_with_faq'] ?? 0 ),
     297                                'label' => __( 'Posts with FAQ', '4wp-faq' ),
     298                        ],
     299                        [
    325300                                'url'   => $list,
    326                                 'html'  => sprintf(
    327                                         /* translators: %s: count */
    328                                         __( 'Uncategorized <strong>%s</strong>', '4wp-faq' ),
    329                                         number_format_i18n( (int) ( $stats['uncategorized'] ?? 0 ) )
    330                                 ),
    331                         ],
    332                         [
    333                                 'class' => 'unused',
     301                                'value' => (int) ( $stats['uncategorized'] ?? 0 ),
     302                                'label' => __( 'Uncategorized', '4wp-faq' ),
     303                        ],
     304                        [
    334305                                'url'   => $list,
    335                                 'html'  => sprintf(
    336                                         /* translators: %s: count */
    337                                         __( 'Unused <strong>%s</strong>', '4wp-faq' ),
    338                                         number_format_i18n( (int) ( $stats['unused_questions'] ?? 0 ) )
    339                                 ),
     306                                'value' => (int) ( $stats['unused_questions'] ?? 0 ),
     307                                'label' => __( 'Unused', '4wp-faq' ),
    340308                        ],
    341309                ];
    342310
    343                 echo '<ul class="forwp-faq-status-list">';
     311                self::render_language_note( $data );
     312
     313                echo '<div class="forwp-faq-stats">';
    344314                foreach ( $rows as $row ) {
    345                         echo '<li class="' . esc_attr( $row['class'] ) . '">';
    346                         echo '<a href="' . esc_url( $row['url'] ) . '">';
    347                         echo wp_kses( $row['html'], [ 'strong' => [] ] );
    348                         echo '</a></li>';
    349                 }
    350                 echo '</ul>';
     315                        echo '<a class="forwp-faq-stat-cell" href="' . esc_url( $row['url'] ) . '">';
     316                        echo '<span class="forwp-faq-stat-cell__value">' . esc_html( number_format_i18n( $row['value'] ) ) . '</span>';
     317                        echo '<span class="forwp-faq-stat-cell__label">' . esc_html( $row['label'] ) . '</span>';
     318                        echo '</a>';
     319                }
     320                echo '</div>';
    351321
    352322                echo '<div class="forwp-faq-dash-meta">';
    … …  
    374344                }
    375345                echo '</div>';
     346        }
     347
     348        /**
     349         * Which language the numbers are for; per-language breakdown when "All languages" is selected.
     350         *
     351         * @param array<string, mixed> $data Dashboard data.
     352         */
     353        public static function render_language_note( $data ) {
     354                $name = isset( $data['language']['name'] ) ? (string) $data['language']['name'] : '';
     355                if ( '' === $name ) {
     356                        return;
     357                }
     358
     359                echo '<p class="forwp-faq-dash-lang">';
     360                echo esc_html(
     361                        sprintf(
     362                                /* translators: %s: language name or "All languages" */
     363                                __( 'Language: %s', '4wp-faq' ),
     364                                $name
     365                        )
     366                );
     367                echo '</p>';
     368
     369                $rows = isset( $data['by_language'] ) && is_array( $data['by_language'] ) ? $data['by_language'] : [];
     370                if ( empty( $rows ) ) {
     371                        return;
     372                }
     373
     374                echo '<table class="forwp-faq-dash-langs widefat striped"><thead><tr>';
     375                echo '<th>' . esc_html__( 'Language', '4wp-faq' ) . '</th>';
     376                echo '<th>' . esc_html__( 'Questions', '4wp-faq' ) . '</th>';
     377                echo '<th>' . esc_html__( 'Categories', '4wp-faq' ) . '</th>';
     378                echo '<th>' . esc_html__( 'Uncategorized', '4wp-faq' ) . '</th>';
     379                echo '<th>' . esc_html__( 'Pages with FAQ', '4wp-faq' ) . '</th>';
     380                echo '</tr></thead><tbody>';
     381                foreach ( $rows as $row ) {
     382                        echo '<tr>';
     383                        echo '<td>' . esc_html( (string) ( $row['name'] ?? '' ) ) . '</td>';
     384                        foreach ( [ 'questions', 'categories', 'uncategorized', 'pages' ] as $key ) {
     385                                echo '<td>' . esc_html( number_format_i18n( (int) ( $row[ $key ] ?? 0 ) ) ) . '</td>';
     386                        }
     387                        echo '</tr>';
     388                }
     389                echo '</tbody></table>';
    376390        }
    377391
  • 4wp-faq/trunk/includes/class-dashboard-setup.php

    r3552602 r3748403  
    1515        public static function init() {
    1616                add_action( 'wp_dashboard_setup', [ __CLASS__, 'register_widget' ] );
     17                add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue' ] );
     18        }
     19
     20        /**
     21         * Status list styles on the main Dashboard.
     22         *
     23         * @param string $hook Current admin page.
     24         */
     25        public static function enqueue( $hook ) {
     26                if ( 'index.php' !== $hook ) {
     27                        return;
     28                }
     29
     30                wp_enqueue_style(
     31                        'forwp-faq-dashboard',
     32                        FORWP_FAQ_PLUGIN_URL . 'assets/admin-dashboard.css',
     33                        [],
     34                        FORWP_FAQ_VERSION
     35                );
    1736        }
    1837
    … …  
    2140         */
    2241        public static function register_widget() {
    23                 if ( ! current_user_can( 'manage_options' ) ) {
     42                if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'manage_options' ) ) {
    2443                        return;
    2544                }
    2645
    27                 if ( Settings::is_setup_complete() ) {
     46                if ( ! Settings::is_setup_complete() ) {
     47                        if ( ! current_user_can( 'manage_options' ) ) {
     48                                return;
     49                        }
     50
     51                        wp_add_dashboard_widget(
     52                                'forwp_faq_dashboard_setup',
     53                                __( '4WP FAQ Setup', '4wp-faq' ),
     54                                [ __CLASS__, 'render_widget' ]
     55                        );
    2856                        return;
    2957                }
    3058
    3159                wp_add_dashboard_widget(
    32                         'forwp_faq_dashboard_setup',
    33                         __( '4WP FAQ Setup', '4wp-faq' ),
    34                         [ __CLASS__, 'render_widget' ]
     60                        'forwp_faq_home',
     61                        __( 'FAQ', '4wp-faq' ),
     62                        [ __CLASS__, 'render_home' ]
    3563                );
     64        }
     65
     66        /**
     67         * Condensed status on the main Dashboard, with a link to the FAQ dashboard.
     68         */
     69        public static function render_home() {
     70                $data  = Plugin::get_dashboard_data();
     71                $stats = isset( $data['stats'] ) && is_array( $data['stats'] ) ? $data['stats'] : [];
     72                $url   = Admin_Settings::get_dashboard_url();
     73                $list  = admin_url( 'edit.php?post_type=' . rawurlencode( Settings::get_post_type() ) );
     74                $cats  = isset( $data['categories_url'] ) ? (string) $data['categories_url'] : $list;
     75
     76                $rows = [
     77                        [
     78                                'class' => 'questions',
     79                                'href'  => $list,
     80                                'html'  => sprintf(
     81                                        /* translators: %s: count */
     82                                        __( 'Questions <strong>%s</strong>', '4wp-faq' ),
     83                                        number_format_i18n( (int) ( $stats['total_questions'] ?? 0 ) )
     84                                ),
     85                        ],
     86                        [
     87                                'class' => 'categories',
     88                                'href'  => $cats,
     89                                'html'  => sprintf(
     90                                        /* translators: %s: count */
     91                                        __( 'Categories <strong>%s</strong>', '4wp-faq' ),
     92                                        number_format_i18n( (int) ( $stats['faq_categories'] ?? 0 ) )
     93                                ),
     94                        ],
     95                        [
     96                                'class' => 'reused',
     97                                'href'  => $list,
     98                                'html'  => sprintf(
     99                                        /* translators: %s: count */
     100                                        __( 'Reused <strong>%s</strong>', '4wp-faq' ),
     101                                        number_format_i18n( (int) ( $stats['reused_questions'] ?? 0 ) )
     102                                ),
     103                        ],
     104                        [
     105                                'class' => 'uncat',
     106                                'href'  => $list,
     107                                'html'  => sprintf(
     108                                        /* translators: %s: count */
     109                                        __( 'Uncategorized <strong>%s</strong>', '4wp-faq' ),
     110                                        number_format_i18n( (int) ( $stats['uncategorized'] ?? 0 ) )
     111                                ),
     112                        ],
     113                ];
     114
     115                Admin_Dashboard::render_language_note( $data );
     116
     117                echo '<ul class="forwp-faq-status-list">';
     118                foreach ( $rows as $row ) {
     119                        echo '<li class="' . esc_attr( $row['class'] ) . '">';
     120                        echo '<a href="' . esc_url( $row['href'] ) . '">';
     121                        echo wp_kses( $row['html'], [ 'strong' => [] ] );
     122                        echo '</a></li>';
     123                }
     124                echo '</ul>';
     125
     126                echo '<div class="forwp-faq-dash-meta">';
     127                echo '<span>';
     128                if ( ! empty( $data['last_scan_label'] ) ) {
     129                        echo esc_html(
     130                                sprintf(
     131                                        /* translators: %s: date/time */
     132                                        __( 'Last scan: %s', '4wp-faq' ),
     133                                        $data['last_scan_label']
     134                                )
     135                        );
     136                } else {
     137                        echo esc_html__( 'Not scanned yet.', '4wp-faq' );
     138                }
     139                echo '</span>';
     140                echo '<a class="button button-primary" href="' . esc_url( $url ) . '">';
     141                echo esc_html__( 'Open dashboard', '4wp-faq' );
     142                echo '</a>';
     143                echo '</div>';
    36144        }
    37145
  • 4wp-faq/trunk/includes/class-display-blocks.php

    r3698640 r3748403  
    77
    88namespace ForWP\FAQ;
     9
     10use ForWP\FAQ\Integrations\Polylang;
    911
    1012if ( ! defined( 'ABSPATH' ) ) {
    … …  
    2022        public const CATEGORIES_BLOCK = 'forwp/faq-categories';
    2123        public const COUNT_BLOCK      = 'forwp/faq-count';
     24        public const NO_RESULTS_BLOCK = 'forwp/faq-no-results';
    2225        public const STORE            = 'forwp/faq';
    2326
    … …  
    3841                add_action( 'init', [ __CLASS__, 'register_blocks' ] );
    3942                add_action( 'enqueue_block_editor_assets', [ __CLASS__, 'localize_editor_scripts' ], 20 );
     43                add_filter( 'rest_pre_dispatch', [ __CLASS__, 'strip_unknown_preview_attributes' ], 10, 3 );
    4044                add_filter( 'render_block_core/search', [ __CLASS__, 'render_related_search' ], 10, 2 );
    4145                /**
    … …  
    7680                                'render' => [ __CLASS__, 'render_count' ],
    7781                        ],
     82                        'faq-no-results' => [
     83                                'script' => self::LIST_SCRIPT,
     84                                'style'  => self::LIST_STYLE,
     85                                'render' => [ __CLASS__, 'render_no_results' ],
     86                        ],
    7887                ];
    7988
    … …  
    184193                ];
    185194
    186                 foreach ( [ self::LIST_SCRIPT, self::CARD_SCRIPT, self::CATEGORIES_SCRIPT, self::COUNT_SCRIPT ] as $handle ) {
    187                         if ( wp_script_is( $handle, 'registered' ) ) {
     195                $registry = \WP_Block_Type_Registry::get_instance();
     196
     197                foreach ( [ self::LIST_BLOCK, self::CARD_BLOCK, self::CATEGORIES_BLOCK, self::COUNT_BLOCK ] as $block_name ) {
     198                        $block = $registry->get_registered( $block_name );
     199
     200                        if ( ! $block || empty( $block->editor_script_handles ) ) {
     201                                continue;
     202                        }
     203
     204                        foreach ( $block->editor_script_handles as $handle ) {
    188205                                wp_localize_script( $handle, 'forwpFaqDisplay', $config );
    189206                        }
    190207                }
     208        }
     209
     210        /**
     211         * Drop attributes the editor added but this block does not register.
     212         *
     213         * Other plugins attach attributes to every block in the editor. The block
     214         * renderer rejects unknown keys with HTTP 400, and the preview then shows
     215         * "Error loading block: [object Object]".
     216         *
     217         * @param mixed            $result  Response to replace, or null to continue.
     218         * @param \WP_REST_Server  $server  Server instance.
     219         * @param \WP_REST_Request $request Request used to generate the response.
     220         * @return mixed
     221         */
     222        public static function strip_unknown_preview_attributes( $result, $server, $request ) {
     223                unset( $server );
     224
     225                if ( null !== $result || ! $request instanceof \WP_REST_Request ) {
     226                        return $result;
     227                }
     228
     229                $route = $request->get_route();
     230                $prefix = '/wp/v2/block-renderer/';
     231
     232                if ( ! is_string( $route ) || ! str_starts_with( $route, $prefix ) ) {
     233                        return $result;
     234                }
     235
     236                $name = rawurldecode( substr( $route, strlen( $prefix ) ) );
     237                $ours = [ self::LIST_BLOCK, self::CARD_BLOCK, self::CATEGORIES_BLOCK, self::COUNT_BLOCK ];
     238
     239                if ( ! in_array( $name, $ours, true ) ) {
     240                        return $result;
     241                }
     242
     243                // Polylang does not filter REST queries: preview in the edited page's language, like the front end.
     244                $post_id = (int) $request->get_param( 'post_id' );
     245                if ( $post_id > 0 ) {
     246                        $lang = Polylang::get_post_language( $post_id );
     247                        if ( '' !== $lang ) {
     248                                Polylang::force_language( $lang );
     249                        }
     250                }
     251
     252                $attributes = $request->get_param( 'attributes' );
     253
     254                if ( ! is_array( $attributes ) ) {
     255                        return $result;
     256                }
     257
     258                $block = \WP_Block_Type_Registry::get_instance()->get_registered( $name );
     259
     260                if ( ! $block ) {
     261                        return $result;
     262                }
     263
     264                $allowed = array_fill_keys( array_keys( $block->get_attributes() ), true );
     265                $request->set_param( 'attributes', array_intersect_key( $attributes, $allowed ) );
     266
     267                return $result;
    191268        }
    192269
    … …  
    252329                self::ensure_runtime();
    253330
     331                $group_title = self::group_title_vars( $attributes['groupTitleStyle'] ?? [] );
     332
    254333                $wrapper_attrs = [
    255                         'class'               => 'forwp-faq-list is-layout-' . $layout,
     334                        'class'               => trim( 'forwp-faq-list is-layout-' . $layout . ' ' . $group_title['class'] ),
    256335                        'data-wp-interactive' => self::STORE,
    257336                ];
    258337
    259                 $typo_style = self::typography_style_attr( $card_attrs );
     338                $typo_style = implode(
     339                        ';',
     340                        array_filter( [ self::typography_style_attr( $card_attrs ), $group_title['style'] ] )
     341                );
    260342                if ( '' !== $typo_style ) {
    261343                        $wrapper_attrs['style'] = $typo_style;
    … …  
    289371                }
    290372
     373                $html .= self::render_list_no_results( $block );
    291374                $html .= '</div>';
    292375
    293376                return $html;
     377        }
     378
     379        /**
     380         * The list's inner No Results block, or a default message for lists saved before it existed.
     381         *
     382         * @param \WP_Block|null $block List block instance.
     383         * @return string
     384         */
     385        private static function render_list_no_results( $block ) {
     386                if ( $block instanceof \WP_Block && ! empty( $block->parsed_block['innerBlocks'] ) ) {
     387                        foreach ( $block->parsed_block['innerBlocks'] as $inner ) {
     388                                if ( self::NO_RESULTS_BLOCK === ( $inner['blockName'] ?? '' ) ) {
     389                                        return render_block( $inner );
     390                                }
     391                        }
     392                }
     393
     394                return '<div ' . self::plain_attributes( self::no_results_attrs() ) . ' hidden><p>'
     395                        . esc_html__( 'No questions found. Try another search.', '4wp-faq' )
     396                        . '</p></div>';
     397        }
     398
     399        /**
     400         * Render 4WP FAQ No Results (hidden until a search matches nothing).
     401         *
     402         * @param array  $attributes Block attributes.
     403         * @param string $content    Inner blocks HTML.
     404         * @return string
     405         */
     406        public static function render_no_results( $attributes, $content = '' ) {
     407                unset( $attributes );
     408
     409                return '<div ' . get_block_wrapper_attributes( self::no_results_attrs() ) . ' hidden>' . $content . '</div>';
     410        }
     411
     412        /**
     413         * @return array<string, string>
     414         */
     415        private static function no_results_attrs() {
     416                return [
     417                        'class'                => 'forwp-faq-list__no-results',
     418                        'data-wp-interactive'  => self::STORE,
     419                        'data-wp-bind--hidden' => '!state.hasNoResults',
     420                ];
     421        }
     422
     423        /**
     424         * @param array<string, string> $attrs Attribute map.
     425         * @return string
     426         */
     427        private static function plain_attributes( $attrs ) {
     428                $out = '';
     429                foreach ( $attrs as $name => $value ) {
     430                        $out .= ' ' . $name . '="' . esc_attr( $value ) . '"';
     431                }
     432
     433                return ltrim( $out );
    294434        }
    295435
    … …  
    315455                        ? $attributes['allLabel']
    316456                        : __( 'All categories', '4wp-faq' );
    317                 $nav_label        = isset( $attributes['label'] ) && is_string( $attributes['label'] ) && '' !== $attributes['label']
    318                         ? $attributes['label']
    319                         : __( 'Categories', '4wp-faq' );
     457                $nav_label = isset( $attributes['label'] ) && is_string( $attributes['label'] )
     458                        ? trim( $attributes['label'] )
     459                        : '';
    320460
    321461                if ( 'horizontal' !== $orientation ) {
    … …  
    330470                }
    331471
    332                 $wrapper = get_block_wrapper_attributes(
    333                         [
    334                                 'class'               => $nav_class,
    335                                 'data-wp-interactive' => self::STORE,
    336                         ]
    337                 );
     472                $wrapper_attrs = [
     473                        'class'                       => $nav_class,
     474                        'data-wp-interactive'         => self::STORE,
     475                        'data-wp-class--is-menu-open' => 'state.isMenuOpen',
     476                ];
     477                $size_style    = self::categories_size_vars( $attributes );
     478                if ( '' !== $size_style ) {
     479                        $wrapper_attrs['style'] = $size_style;
     480                }
     481
     482                $wrapper = get_block_wrapper_attributes( $wrapper_attrs );
    338483
    339484                if ( ! Settings::is_setup_complete() ) {
    … …  
    351496                        : 'forwp-faq-cats-label';
    352497
    353                 $html  = '<nav ' . $wrapper . ' aria-labelledby="' . esc_attr( $label_id ) . '">';
    354                 $html .= '<p class="forwp-faq-categories__label" id="' . esc_attr( $label_id ) . '">' . esc_html( $nav_label ) . '</p>';
    355                 $html .= '<ul class="forwp-faq-categories__list" role="list">';
     498                $list_id = function_exists( 'wp_unique_id' )
     499                        ? wp_unique_id( 'forwp-faq-cats-list-' )
     500                        : 'forwp-faq-cats-list';
     501
     502                $html = '<nav ' . $wrapper;
     503                if ( '' !== $nav_label ) {
     504                        $html .= ' aria-labelledby="' . esc_attr( $label_id ) . '"';
     505                }
     506                $html .= '>';
     507                if ( '' !== $nav_label ) {
     508                        $html .= '<p class="forwp-faq-categories__label" id="' . esc_attr( $label_id ) . '">' . esc_html( $nav_label ) . '</p>';
     509                }
     510                $html .= '<button type="button" class="forwp-faq-categories__menu"';
     511                $html .= ' data-wp-on--click="actions.toggleMenu"';
     512                $html .= ' data-wp-bind--aria-expanded="state.isMenuOpen"';
     513                $html .= ' aria-expanded="false" aria-controls="' . esc_attr( $list_id ) . '"';
     514                if ( '' === $nav_label ) {
     515                        $html .= ' aria-label="' . esc_attr__( 'Categories', '4wp-faq' ) . '"';
     516                }
     517                $html .= '>';
     518                $html .= '<svg class="forwp-faq-categories__menu-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false"><path d="M2 4h12M2 8h12M2 12h12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>';
     519                if ( '' !== $nav_label ) {
     520                        $html .= '<span class="forwp-faq-categories__menu-text">' . esc_html( $nav_label ) . '</span>';
     521                }
     522                $html .= '</button>';
     523                $html .= '<ul class="forwp-faq-categories__list" id="' . esc_attr( $list_id ) . '" role="list">';
    356524
    357525                if ( $show_all ) {
    … …  
    382550                unset( $attributes );
    383551
     552                return self::count_markup( true );
     553        }
     554
     555        /**
     556         * Count span markup.
     557         *
     558         * @param bool $use_block_wrapper False for the shortcode: otherwise the enclosing block's classes (e.g. alignfull) leak in.
     559         * @return string
     560         */
     561        private static function count_markup( $use_block_wrapper ) {
    384562                self::ensure_runtime();
    385563
    386564                $context = self::get_list_query_context();
    387                 $count   = Registry_Content::count_visible_posts(
    388                         $context['includeTermIds'],
    389                         $context['excludeTermIds'],
    390                         $context['activeSlug'],
    391                         $context['previewLimit'],
    392                         $context['layout']
    393                 );
    394 
    395                 $wrapper = get_block_wrapper_attributes(
    396                         [
    397                                 'class'               => 'forwp-faq-count',
    398                                 'data-wp-interactive' => self::STORE,
    399                                 'data-wp-text'        => 'state.visibleCount',
    400                         ]
    401                 );
     565                $totals  = self::count_totals( $context );
     566                $count   = (int) ( $totals[ $context['activeSlug'] ] ?? 0 );
     567
     568                $attrs = [
     569                        'class'               => 'forwp-faq-count',
     570                        'data-wp-interactive' => self::STORE,
     571                        'data-wp-text'        => 'state.visibleCount',
     572                ];
     573
     574                $wrapper = $use_block_wrapper ? get_block_wrapper_attributes( $attrs ) : self::plain_attributes( $attrs );
    402575
    403576                return '<span ' . $wrapper . '>' . esc_html( (string) $count ) . '</span>';
     577        }
     578
     579        /**
     580         * Question totals matching the category nav counts.
     581         *
     582         * Key '' = sum of top-level category counts; each slug = that category's nav count.
     583         *
     584         * @param array $context From get_list_query_context().
     585         * @return array<string, int>
     586         */
     587        private static function count_totals( $context ) {
     588                static $cache = null;
     589                if ( null !== $cache ) {
     590                        return $cache;
     591                }
     592
     593                $totals = [ '' => 0 ];
     594                $walk   = static function ( $nodes, $top ) use ( &$walk, &$totals ) {
     595                        foreach ( (array) $nodes as $node ) {
     596                                $term = $node['term'] ?? null;
     597                                if ( ! $term instanceof \WP_Term ) {
     598                                        continue;
     599                                }
     600                                $count                  = isset( $node['inclusive_count'] ) ? (int) $node['inclusive_count'] : (int) $term->count;
     601                                $totals[ $term->slug ] = $count;
     602                                if ( $top ) {
     603                                        $totals[''] += $count;
     604                                }
     605                                if ( ! empty( $node['children'] ) ) {
     606                                        $walk( $node['children'], false );
     607                                }
     608                        }
     609                };
     610                $walk( Registry_Content::get_nav_tree( $context['includeTermIds'], $context['excludeTermIds'] ), true );
     611
     612                $cache = $totals;
     613
     614                return $totals;
    404615        }
    405616
    … …  
    413624                unset( $atts );
    414625
    415                 return self::render_count( [] );
     626                return self::count_markup( false );
    416627        }
    417628
    … …  
    637848         * @param array          $attributes List attributes.
    638849         * @param \WP_Block|null $block      List block instance.
    639          * @return array{displayMode: string, showSources: bool, sourcesLabel: string, showPostType: bool, questionStyle: array, answerStyle: array}
     850         * @return array{displayMode: string, showSources: bool, sourcesLabel: string, sourcesSeparator: string, showPostType: bool, questionStyle: array, answerStyle: array}
    640851         */
    641852        private static function resolve_card_attributes( $attributes, $block ) {
    … …  
    667878                }
    668879
     880                if ( array_key_exists( 'sourcesSeparator', $inner ) ) {
     881                        $sources_separator = (string) $inner['sourcesSeparator'];
     882                } elseif ( isset( $attributes['cardSourcesSeparator'] ) ) {
     883                        $sources_separator = (string) $attributes['cardSourcesSeparator'];
     884                } else {
     885                        $sources_separator = ', ';
     886                }
     887
    669888                if ( array_key_exists( 'showPostType', $inner ) ) {
    670889                        $show_post_type = ! empty( $inner['showPostType'] );
    … …  
    688907
    689908                return [
    690                         'displayMode'   => $display,
    691                         'showSources'   => $show_sources,
    692                         'sourcesLabel'  => $sources_label,
    693                         'showPostType'  => $show_post_type,
    694                         'questionStyle' => self::sanitize_typography_style( $question_style ),
    695                         'answerStyle'   => self::sanitize_typography_style( $answer_style ),
     909                        'displayMode'      => $display,
     910                        'showSources'      => $show_sources,
     911                        'sourcesLabel'     => $sources_label,
     912                        'sourcesSeparator' => $sources_separator,
     913                        'showPostType'     => $show_post_type,
     914                        'questionStyle'    => self::sanitize_typography_style( $question_style ),
     915                        'answerStyle'      => self::sanitize_typography_style( $answer_style ),
    696916                ];
    697917        }
    … …  
    699919        /**
    700920         * @param mixed $style Raw style object.
    701          * @return array{fontSize?: string, fontFamily?: string, fontWeight?: string, color?: string}
     921         * @return array<string, string> Keys from typography_var_suffixes().
    702922         */
    703923        private static function sanitize_typography_style( $style ) {
    … …  
    736956                }
    737957
     958                $patterns = [
     959                        'fontStyle'      => '/^(normal|italic)$/',
     960                        'lineHeight'     => '/^\d+(\.\d+)?(px|rem|em|%)?$/',
     961                        'letterSpacing'  => '/^-?\d+(\.\d+)?(px|rem|em)$/',
     962                        'textDecoration' => '/^(none|underline|line-through)$/',
     963                        'textTransform'  => '/^(none|uppercase|lowercase|capitalize)$/',
     964                ];
     965                foreach ( $patterns as $key => $pattern ) {
     966                        if ( ! isset( $style[ $key ] ) || '' === $style[ $key ] ) {
     967                                continue;
     968                        }
     969                        $val = trim( sanitize_text_field( (string) $style[ $key ] ) );
     970                        if ( preg_match( $pattern, $val ) ) {
     971                                $out[ $key ] = $val;
     972                        }
     973                }
     974
    738975                return $out;
     976        }
     977
     978        /**
     979         * Style keys → CSS custom property suffix (shared by q / a / g prefixes).
     980         *
     981         * @return array<string, string>
     982         */
     983        private static function typography_var_suffixes() {
     984                return [
     985                        'fontSize'       => 'size',
     986                        'fontFamily'     => 'family',
     987                        'fontWeight'     => 'weight',
     988                        'fontStyle'      => 'style',
     989                        'lineHeight'     => 'line',
     990                        'letterSpacing'  => 'spacing',
     991                        'textDecoration' => 'decoration',
     992                        'textTransform'  => 'transform',
     993                        'color'          => 'color',
     994                ];
    739995        }
    740996
    … …  
    8411097                        : [];
    8421098
    843                 $map = [
    844                         '--forwp-faq-q-size'   => $question['fontSize'] ?? '',
    845                         '--forwp-faq-q-family' => $question['fontFamily'] ?? '',
    846                         '--forwp-faq-q-weight' => $question['fontWeight'] ?? '',
    847                         '--forwp-faq-q-color'  => $question['color'] ?? '',
    848                         '--forwp-faq-a-size'   => $answer['fontSize'] ?? '',
    849                         '--forwp-faq-a-family' => $answer['fontFamily'] ?? '',
    850                         '--forwp-faq-a-weight' => $answer['fontWeight'] ?? '',
    851                         '--forwp-faq-a-color'  => $answer['color'] ?? '',
    852                 ];
     1099                $map = [];
     1100                foreach ( self::typography_var_suffixes() as $key => $suffix ) {
     1101                        $map[ '--forwp-faq-q-' . $suffix ] = $question[ $key ] ?? '';
     1102                        $map[ '--forwp-faq-a-' . $suffix ] = $answer[ $key ] ?? '';
     1103                }
    8531104
    8541105                $parts = [];
    … …  
    8621113
    8631114                return implode( ';', $parts );
     1115        }
     1116
     1117        /**
     1118         * Category title typography: CSS variables plus one class per set property.
     1119         *
     1120         * Classes keep theme heading styles untouched for properties left empty.
     1121         *
     1122         * @param mixed $style Raw groupTitleStyle attribute.
     1123         * @return array{class: string, style: string}
     1124         */
     1125        private static function group_title_vars( $style ) {
     1126                $clean   = self::sanitize_typography_style( $style );
     1127                $vars    = [];
     1128                $classes = [];
     1129
     1130                foreach ( self::typography_var_suffixes() as $key => $suffix ) {
     1131                        if ( empty( $clean[ $key ] ) ) {
     1132                                continue;
     1133                        }
     1134                        $vars[]    = '--forwp-faq-g-' . $suffix . ':' . $clean[ $key ];
     1135                        $classes[] = 'has-g-' . $suffix;
     1136                }
     1137
     1138                return [
     1139                        'class' => implode( ' ', $classes ),
     1140                        'style' => implode( ';', $vars ),
     1141                ];
    8641142        }
    8651143
    … …  
    9011179                        $html .= '<section class="' . esc_attr( $group_class ) . '"' . self::context_attr(
    9021180                                [
    903                                         'slug'      => $slug,
    904                                         'ancestors' => implode( ' ', $ancestors ),
     1181                                        'slug'       => $slug,
     1182                                        'ancestors'  => implode( ' ', $ancestors ),
     1183                                        'searchText' => self::group_search_text( $posts, $children ),
    9051184                                ]
    9061185                        ) . ' data-wp-bind--hidden="!state.isGroupVisible"' . ( $hidden ? ' hidden' : '' ) . '>';
    … …  
    9261205
    9271206                return $html;
     1207        }
     1208
     1209        /**
     1210         * Question and answer text for this group and its children, for search.
     1211         *
     1212         * @param \WP_Post[] $posts    Posts rendered in the group.
     1213         * @param array[]    $children Nested groups.
     1214         * @return string
     1215         */
     1216        private static function group_search_text( $posts, $children ) {
     1217                $parts = [];
     1218
     1219                foreach ( $posts as $post ) {
     1220                        if ( ! $post instanceof \WP_Post ) {
     1221                                continue;
     1222                        }
     1223                        $answer  = Registry_Content::get_answer( (int) $post->ID );
     1224                        $parts[] = strtolower( trim( get_the_title( $post ) . ' ' . ( $answer['text'] ?? '' ) ) );
     1225                }
     1226
     1227                foreach ( $children as $child ) {
     1228                        if ( ! is_array( $child ) ) {
     1229                                continue;
     1230                        }
     1231                        $child_posts = isset( $child['posts'] ) && is_array( $child['posts'] ) ? $child['posts'] : [];
     1232                        $child_nodes = isset( $child['children'] ) && is_array( $child['children'] ) ? $child['children'] : [];
     1233                        $parts[]     = self::group_search_text( $child_posts, $child_nodes );
     1234                }
     1235
     1236                return trim( implode( ' ', array_filter( $parts ) ) );
    9281237        }
    9291238
    … …  
    9821291                        ? sanitize_text_field( (string) $attributes['sourcesLabel'] )
    9831292                        : __( 'Used in', '4wp-faq' );
     1293                $sources_separator = isset( $attributes['sourcesSeparator'] )
     1294                        ? (string) $attributes['sourcesSeparator']
     1295                        : ', ';
    9841296                if ( 'heading' !== $display ) {
    9851297                        $display = 'accordion';
    … …  
    10191331
    10201332                $body  = self::render_answer( $answer );
    1021                 $body .= self::render_sources( $sources, $sources_label, $show_type );
     1333                $body .= self::render_sources( $sources, $sources_label, $show_type, $sources_separator );
    10221334
    10231335                if ( 'heading' === $display ) {
    … …  
    10461358
    10471359        /**
     1360         * Drop color classes copied from dark page sections so the answer uses the card color.
     1361         *
     1362         * @param string $html Answer HTML.
     1363         * @return string
     1364         */
     1365        private static function strip_answer_color( $html ) {
     1366                $html = preg_replace_callback(
     1367                        '/\sclass=("|\')([^"\']*)\1/',
     1368                        static function ( $matches ) {
     1369                                $classes = preg_split( '/\s+/', $matches[2], -1, PREG_SPLIT_NO_EMPTY );
     1370                                $classes = array_values(
     1371                                        array_filter(
     1372                                                $classes,
     1373                                                static function ( $class ) {
     1374                                                        if ( in_array( $class, [ 'has-text-color', 'has-background', 'has-link-color' ], true ) ) {
     1375                                                                return false;
     1376                                                        }
     1377
     1378                                                        return ! preg_match( '/^has-.+-(color|background-color)$/', $class );
     1379                                                }
     1380                                        )
     1381                                );
     1382
     1383                                if ( ! $classes ) {
     1384                                        return '';
     1385                                }
     1386
     1387                                return ' class=' . $matches[1] . implode( ' ', $classes ) . $matches[1];
     1388                        },
     1389                        $html
     1390                );
     1391
     1392                $html = preg_replace_callback(
     1393                        '/\sstyle=("|\')([^"\']*)\1/',
     1394                        static function ( $matches ) {
     1395                                $style = preg_replace( '/(?:^|;)\s*color\s*:[^;]*/i', '', $matches[2] );
     1396                                $style = trim( (string) $style, " \t;" );
     1397
     1398                                if ( '' === $style ) {
     1399                                        return '';
     1400                                }
     1401
     1402                                return ' style=' . $matches[1] . $style . $matches[1];
     1403                        },
     1404                        (string) $html
     1405                );
     1406
     1407                return (string) $html;
     1408        }
     1409
     1410        /**
    10481411         * @param array{text: string, html: string} $answer Answer payload.
    10491412         * @return string
    … …  
    10541417
    10551418                if ( '' !== $html ) {
    1056                         return '<div class="forwp-faq-card__answer">' . wp_kses_post( $html ) . '</div>';
     1419                        return '<div class="forwp-faq-card__answer">' . wp_kses_post( self::strip_answer_color( $html ) ) . '</div>';
    10571420                }
    10581421
    … …  
    10651428
    10661429        /**
    1067          * @param list<array{title: string, url: string, post_type_label: string}> $sources        Sources.
    1068          * @param string                                                           $sources_label  Label placeholder.
    1069          * @param bool                                                             $show_post_type Show CPT type.
    1070          * @return string
    1071          */
    1072         private static function render_sources( $sources, $sources_label = '', $show_post_type = false ) {
     1430         * @param list<array{title: string, url: string, post_type_label: string, is_public?: bool}> $sources        Sources.
     1431         * @param string                                                                            $sources_label  Label placeholder.
     1432         * @param bool                                                                              $show_post_type Show CPT type.
     1433         * @param string                                                                            $separator      Between items.
     1434         * @return string
     1435         */
     1436        private static function render_sources( $sources, $sources_label = '', $show_post_type = false, $separator = ', ' ) {
    10731437                if ( empty( $sources ) ) {
    10741438                        return '';
    … …  
    10791443                        $html .= '<p class="forwp-faq-card__sources-label">' . esc_html( $sources_label ) . '</p>';
    10801444                }
    1081                 $html .= '<ul class="forwp-faq-card__sources-list">';
    1082 
     1445                $html .= '<p class="forwp-faq-card__sources-list">';
     1446
     1447                $items = [];
    10831448                foreach ( $sources as $source ) {
    1084                         $html .= '<li class="forwp-faq-card__sources-item">';
    1085                         $html .= '<a href="' . esc_url( $source['url'] ) . '">' . esc_html( $source['title'] ) . '</a>';
     1449                        $is_public = ! isset( $source['is_public'] ) || $source['is_public'];
     1450                        $item      = $is_public
     1451                                ? '<a class="forwp-faq-card__sources-item" href="' . esc_url( $source['url'] ) . '">' . esc_html( $source['title'] ) . '</a>'
     1452                                : '<span class="forwp-faq-card__sources-item is-inactive" title="' . esc_attr__( 'Not public: visible to editors only', '4wp-faq' ) . '">' . esc_html( $source['title'] ) . '</span>';
    10861453                        if ( $show_post_type && ! empty( $source['post_type_label'] ) ) {
    1087                                 $html .= ' <span class="forwp-faq-card__sources-type">' . esc_html( $source['post_type_label'] ) . '</span>';
    1088                         }
    1089                         $html .= '</li>';
    1090                 }
    1091 
    1092                 $html .= '</ul></div>';
     1454                                $item .= ' <span class="forwp-faq-card__sources-type">' . esc_html( $source['post_type_label'] ) . '</span>';
     1455                        }
     1456                        $items[] = $item;
     1457                }
     1458
     1459                $html .= implode(
     1460                        '<span class="forwp-faq-card__sources-separator">' . esc_html( $separator ) . '</span>',
     1461                        $items
     1462                );
     1463                $html .= '</p></div>';
    10931464
    10941465                return $html;
    … …  
    12091580
    12101581                return '<p class="forwp-faq-list__more"><a class="forwp-faq-list__more-link" href="' . esc_url( $url ) . '">' . esc_html( $label ) . '</a></p>';
     1582        }
     1583
     1584        /**
     1585         * CSS variables for the All link, category names, and the gap between them.
     1586         *
     1587         * @param array $attributes Block attributes.
     1588         * @return string
     1589         */
     1590        private static function categories_size_vars( $attributes ) {
     1591                $map   = [
     1592                        'allItemFontSize' => '--forwp-faq-all-size',
     1593                        'itemFontSize'    => '--forwp-faq-item-size',
     1594                        'itemGap'         => '--forwp-faq-item-gap',
     1595                ];
     1596                $parts = [];
     1597
     1598                foreach ( $map as $key => $var ) {
     1599                        $size = self::sanitize_css_size( $attributes[ $key ] ?? '' );
     1600                        if ( '' !== $size ) {
     1601                                $parts[] = $var . ':' . $size;
     1602                        }
     1603                }
     1604
     1605                return implode( ';', $parts );
    12111606        }
    12121607
    … …  
    12531648
    12541649                $classes = 'forwp-faq-categories__item';
     1650                if ( '' === $slug ) {
     1651                        $classes .= ' is-all';
     1652                }
    12551653                if ( $is_active ) {
    12561654                        $classes .= ' is-active';
    … …  
    13231721
    13241722                $context = self::get_list_query_context();
    1325                 $count   = Registry_Content::count_visible_posts(
    1326                         $context['includeTermIds'],
    1327                         $context['excludeTermIds'],
    1328                         $context['activeSlug'],
    1329                         $context['previewLimit'],
    1330                         $context['layout']
    1331                 );
     1723                $totals  = self::count_totals( $context );
    13321724
    13331725                $done = true;
    … …  
    13371729                                'category'       => $context['activeSlug'],
    13381730                                'search'         => '',
    1339                                 'visibleCount'   => $count,
     1731                                'visibleCount'   => (int) ( $totals[ $context['activeSlug'] ] ?? 0 ),
     1732                                'totals'         => (object) $totals,
    13401733                                'openBranches'   => (object) [],
    13411734                                'isNavActive'    => static function () {
  • 4wp-faq/trunk/includes/class-plugin.php

    r3704354 r3748403  
    567567         */
    568568        public static function get_registry_stats() {
     569                return Polylang::with_language(
     570                        Polylang::get_admin_language(),
     571                        [ __CLASS__, 'build_registry_stats' ]
     572                );
     573        }
     574
     575        /**
     576         * Registry stats for whatever language the current queries resolve to.
     577         *
     578         * @return array<string, int>
     579         */
     580        public static function build_registry_stats() {
    569581                $stats = [
    570582                        'total_questions'        => 0,
    … …  
    604616
    605617                foreach ( $faq_ids as $faq_id ) {
    606                         $usage = (int) get_post_meta( $faq_id, 'count_usage', true );
    607                         if ( $usage > 1 ) {
     618                        if ( Registry_Content::count_public_usage( $faq_id ) > 1 ) {
    608619                                ++$reused;
    609620                        }
    … …  
    633644         */
    634645        public static function get_dashboard_data() {
    635                 $stats     = self::get_registry_stats();
     646                $lang = Polylang::get_admin_language();
     647                $data = Polylang::with_language( $lang, [ __CLASS__, 'build_dashboard_data' ] );
     648
     649                $data['language'] = [
     650                        'slug' => (string) $lang,
     651                        'name' => null === $lang ? '' : ( '' === $lang ? __( 'All languages', '4wp-faq' ) : Polylang::get_language_name( $lang ) ),
     652                ];
     653                $data['by_language'] = [];
     654
     655                if ( '' === $lang ) {
     656                        foreach ( Polylang::get_language_slugs() as $slug ) {
     657                                $slice = Polylang::with_language( $slug, [ __CLASS__, 'build_dashboard_data' ] );
     658                                $stats = isset( $slice['stats'] ) && is_array( $slice['stats'] ) ? $slice['stats'] : [];
     659
     660                                $data['by_language'][] = [
     661                                        'slug'          => $slug,
     662                                        'name'          => Polylang::get_language_name( $slug ),
     663                                        'questions'     => (int) ( $stats['total_questions'] ?? 0 ),
     664                                        'categories'    => (int) ( $stats['faq_categories'] ?? 0 ),
     665                                        'uncategorized' => (int) ( $stats['uncategorized'] ?? 0 ),
     666                                        'pages'         => (int) ( $stats['pages_with_faq'] ?? 0 ),
     667                                ];
     668                        }
     669                }
     670
     671                return $data;
     672        }
     673
     674        /**
     675         * Dashboard data for whatever language the current queries resolve to.
     676         *
     677         * @return array<string, mixed>
     678         */
     679        public static function build_dashboard_data() {
     680                $stats     = self::build_registry_stats();
    636681                $last_scan = (int) get_option( 'forwp_faq_last_scan_at', 0 );
    637682                $data      = [
    … …  
    687732                foreach ( $faq_ids as $faq_id ) {
    688733                        $faq_id = (int) $faq_id;
    689                         $usage  = (int) get_post_meta( $faq_id, 'count_usage', true );
     734                        $usage  = Registry_Content::count_public_usage( $faq_id );
    690735                        if ( $usage < 1 ) {
    691736                                ++$unused;
  • 4wp-faq/trunk/includes/class-registry-content.php

    r3685374 r3748403  
    6464
    6565        /**
     66         * Published public pages/posts using this FAQ (internal post types excluded).
     67         *
     68         * @param int $post_id Registry post ID.
     69         * @return int
     70         */
     71        public static function count_public_usage( $post_id ) {
     72                $used_in = get_post_meta( (int) $post_id, 'used_in_posts', true );
     73                if ( ! is_array( $used_in ) ) {
     74                        return 0;
     75                }
     76
     77                $count = 0;
     78                foreach ( array_unique( array_map( 'intval', $used_in ) ) as $source_id ) {
     79                        $source = $source_id > 0 ? get_post( $source_id ) : null;
     80                        if ( ! $source instanceof \WP_Post || 'publish' !== $source->post_status ) {
     81                                continue;
     82                        }
     83                        $type = get_post_type_object( $source->post_type );
     84                        if ( $type && ! empty( $type->public ) ) {
     85                                ++$count;
     86                        }
     87                }
     88
     89                return $count;
     90        }
     91
     92        /**
     93         * Block editor server-side preview (REST), not the front end.
     94         *
     95         * @return bool
     96         */
     97        private static function is_editor_preview() {
     98                return function_exists( 'wp_is_serving_rest_request' )
     99                        ? wp_is_serving_rest_request()
     100                        : ( defined( 'REST_REQUEST' ) && REST_REQUEST );
     101        }
     102
     103        /**
    66104         * Public pages/posts where this FAQ registry entry appears.
    67105         *
    68106         * @param int $post_id Registry post ID.
    69          * @return list<array{id: int, title: string, url: string, post_type: string, post_type_label: string}>
     107         * @return list<array{id: int, title: string, url: string, post_type: string, post_type_label: string, is_public: bool}>
    70108         */
    71109        public static function get_sources( $post_id ) {
    … …  
    112150                                : $source_post->post_type;
    113151
     152                        // Internal (non-public) types have no working front URL: editor preview only, no link.
     153                        $is_public = $type_object && ! empty( $type_object->public );
     154                        if ( ! $is_public && ! ( self::is_editor_preview() && current_user_can( 'edit_post', $source_id ) ) ) {
     155                                continue;
     156                        }
     157
    114158                        $sources[] = [
    115159                                'id'              => $source_id,
    116160                                'title'           => $title,
    117                                 'url'             => $url,
     161                                'url'             => $is_public ? $url : '',
    118162                                'post_type'       => $source_post->post_type,
    119163                                'post_type_label' => $type_label,
     164                                'is_public'       => $is_public,
    120165                        ];
    121166                        $seen_url[ $url ] = true;
    … …  
    143188                                        'post_type'       => (string) ( $row['post_type'] ?? '' ),
    144189                                        'post_type_label' => (string) ( $row['post_type_label'] ?? '' ),
     190                                        'is_public'       => true,
    145191                                ];
    146192                        }
  • 4wp-faq/trunk/includes/integrations/class-polylang.php

    r3654057 r3748403  
    7272
    7373                return $taxonomies;
     74        }
     75
     76        /**
     77         * Language picked in the admin bar filter: slug, '' for all languages, null without Polylang.
     78         *
     79         * Read from user meta so admin pages and REST (Settings app) agree.
     80         */
     81        public static function get_admin_language(): ?string {
     82                if ( ! self::is_active() || ! function_exists( 'pll_languages_list' ) ) {
     83                        return null;
     84                }
     85
     86                $lang = (string) get_user_meta( get_current_user_id(), 'pll_filter_content', true );
     87
     88                return in_array( $lang, self::get_language_slugs(), true ) ? $lang : '';
     89        }
     90
     91        /**
     92         * @return string[]
     93         */
     94        public static function get_language_slugs(): array {
     95                if ( ! self::is_active() || ! function_exists( 'pll_languages_list' ) ) {
     96                        return [];
     97                }
     98
     99                $slugs = pll_languages_list( [ 'fields' => 'slug' ] );
     100
     101                return is_array( $slugs ) ? array_values( array_filter( array_map( 'strval', $slugs ) ) ) : [];
     102        }
     103
     104        /**
     105         * @param string $slug Language slug.
     106         */
     107        public static function get_language_name( $slug ): string {
     108                if ( ! self::is_active() || ! function_exists( 'pll_languages_list' ) ) {
     109                        return (string) $slug;
     110                }
     111
     112                $slugs = pll_languages_list( [ 'fields' => 'slug' ] );
     113                $names = pll_languages_list( [ 'fields' => 'name' ] );
     114                $index = is_array( $slugs ) ? array_search( $slug, $slugs, true ) : false;
     115
     116                return false !== $index && isset( $names[ $index ] ) ? (string) $names[ $index ] : (string) $slug;
     117        }
     118
     119        /**
     120         * Run a callback with every post/term query forced to one language ('' = all languages).
     121         *
     122         * @param string|null $lang Language slug, '' for all, null = leave queries untouched.
     123         * @param callable    $fn   Callback.
     124         * @return mixed
     125         */
     126        public static function with_language( $lang, callable $fn ) {
     127                if ( null === $lang || ! self::is_active() ) {
     128                        return $fn();
     129                }
     130
     131                $hooks = self::force_language( $lang );
     132
     133                try {
     134                        return $fn();
     135                } finally {
     136                        remove_action( 'parse_query', $hooks[0], 0 );
     137                        remove_filter( 'get_terms_args', $hooks[1], 0 );
     138                }
     139        }
     140
     141        /**
     142         * Force every following post/term query to one language ('' = all languages).
     143         *
     144         * @param string $lang Language slug.
     145         * @return callable[] The two hooked callbacks (parse_query, get_terms_args).
     146         */
     147        public static function force_language( $lang ): array {
     148                $posts = static function ( $query ) use ( $lang ) {
     149                        $query->query_vars['lang'] = $lang;
     150                };
     151                $terms = static function ( $args ) use ( $lang ) {
     152                        $args['lang'] = $lang;
     153                        return $args;
     154                };
     155
     156                // Before Polylang's own parse_query / get_terms_args handlers read `lang`.
     157                add_action( 'parse_query', $posts, 0 );
     158                add_filter( 'get_terms_args', $terms, 0 );
     159
     160                return [ $posts, $terms ];
    74161        }
    75162
  • 4wp-faq/trunk/readme.txt

    r3704354 r3748403  
    11=== 4WP FAQ ===
    22Contributors: 4wpdev, anatolikkk
    3 Tags: faq, accordion, json-ld, gutenberg, seo
     3Tags: faq, faq schema, accordion, json-ld, structured data
    44Requires at least: 6.6
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 2.6.1
     7Stable tag: 2.6.5
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1010
    11 FAQPage schema for core Accordion, optional registry you can edit or add from, hub pages, and AI via Connectors.
     11FAQ schema for the core Accordion. Scan every question on your site into one registry, edit once, and build a searchable FAQ hub.
    1212
    1313== Description ==
    1414
    15 4WP FAQ wraps WordPress core **Accordion** blocks so you can keep your design and still get:
    16 
    17 * **FAQPage JSON-LD** for Google rich results (off by default; turn on when you are ready)
    18 * An optional **FAQ registry** (scan of unique questions). Edit one record to push Q/A onto every **Used In** page. **Add FAQ** places a new item on category pages or one page. Site content stays the source of truth.
    19 * **Hub pages** with List + Categories blocks, pretty category URLs, category SEO titles, collapsible subcategory nav, and drag-and-drop category order (admin + front end)
    20 * **Drag-and-drop FAQ category order** on **FAQ → Categories** — same order in admin lists and on the front end (List / Categories hub)
    21 * Optional **AI category copy** through the standard **WordPress AI Client** (Settings → Connectors) — description, display title, SEO title, and SEO description. No custom vendor SDK.
     15**Not another FAQ block.** 4WP FAQ wraps the core **Accordion** you already use, adds **FAQPage JSON-LD**, and turns every question on your site into one registry you can reuse, update everywhere, and show as a searchable hub. Your design stays the same.
     16
     17https://www.youtube.com/watch?v=SI3slJFYVbg
     18
     19👉 **Live demo, docs and comparison:** [4wp.dev/plugin/4wp-faq](https://4wp.dev/plugin/4wp-faq/)
     20💬 **Real hub with 296 questions in 9 categories:** [4wp.dev/faqs](https://4wp.dev/faqs/)
     21
     22= Why 4WP FAQ =
     23
     24* **Built on core.** A thin wrapper over the core Accordion. No new design, no lock-in: unwrap any time and the Accordion stays.
     25* **The only FAQ plugin that scans.** Questions live on your pages. A scan collects them into one registry. You never type a question twice.
     26* **Edit once, update everywhere.** Change a question in the registry and 4WP FAQ writes it onto every page listed in **Used in**.
     27* **SEO hub for free.** List, Categories, Search and Count blocks, pretty category URLs, category SEO titles, canonical and Open Graph. No Pro tier.
     28* **AI without a vendor.** Category copy through the standard **WordPress AI Client** (Connectors). No custom SDK, no API keys in the plugin.
     29
     30= What you get =
     31
     32* **FAQPage JSON-LD** — structured data for search engines and AI answers. Opt-in, site-wide or per block. Skips its own output when Yoast already prints FAQ schema.
     33* **Convert to FAQ** — one click on an Accordion, or **Transform to → 4WP FAQ** from Details, heading + paragraph pairs or a List.
     34* **FAQ registry** — every unique question with **Used in** sources, categories and a Dashboard. **Add FAQ** places a new question on every page of a category, or on one page.
     35* **FSE hub** — **4WP FAQ List**, **Categories**, **Count** and core **Search** with in-place filtering (Interactivity API). Nested categories, drag-and-drop order.
     36* **Polylang** — categories follow the page language; the Dashboard shows figures per language.
     37* **4WP Drive** — an H2 FAQ section with H3 questions in a Google Doc becomes a 4WP FAQ block on import.
    2238
    2339A plugin by [4wp.dev](https://4wp.dev/). **4WP** is our project brand; this plugin is not affiliated with, endorsed, or sponsored by WordPress.
    2440
    25 Source: [github.com/4wpdev/4wp-faq](https://github.com/4wpdev/4wp-faq)
     41Source: [github.com/4wpdev/4wp-faq](https://github.com/4wpdev/4wp-faq) · More plugins: [4wp.dev/plugins](https://4wp.dev/plugins/)
    2642
    2743= How to work with it (short path) =
    … …  
    210226== Screenshots ==
    211227
    212 1. 4WP FAQ block wrapping core Accordion in the editor
    213 2. Settings — rescan, JSON-LD, preview count, pretty category URLs, and how category titles are built
    214 3. FAQ hub — List + Categories (and Count) in the Site Editor
     2281. A live FAQ hub on 4wp.dev: 296 questions, category navigation, search and count — built from the 4WP FAQ registry.
     2292. Convert to FAQ: one click wraps a core Accordion. Your design stays the same.
     2303. One Accordion Item = one question (heading) and one answer (panel).
     2314. FAQ → Settings: turn on FAQPage JSON-LD site-wide or per block.
     2325. FAQ Dashboard: registry status, Rescan, questions by category, reused and uncategorized.
     2336. Build the hub in the Site Editor: Categories, List, Search and Count blocks.
     2347. Add FAQ: place a new question on every page of a category, or on one page.
     2358. Edit once in the registry — the update is written to every page in Used in.
     2369. Generate category description and SEO titles with the WordPress AI Client.
    215237
    216238== External services ==
    … …  
    223245
    224246== Changelog ==
     247
     248= 2.6.5 =
     249* **Directory assets:** animated banner and icon GIFs for WordPress.org; nine screenshots aligned with the current hub and editor UI.
     250* **Docs:** README and readme.txt refreshed for the directory listing (demo, comparison, video).
     251
     252= 2.6.4 =
     253* **Hub filter:** the host page slug (e.g. `/4wp-faq/`) no longer activates a FAQ category with the same slug. Pretty category URLs still match the full nav path (`/4wp-faq/hooks/`). Accordion FAQ on the page is unchanged; List / Categories keep their own settings.
     254* **Editor:** Include/Exclude category tokens no longer freeze the editor (Maximum update depth) when List and Categories sync filters.
     255* **Convert to FAQ:** wrapping an Accordion no longer drops its items (toolbar used empty innerBlocks). **Unwrap 4WP FAQ** restores the Accordion / Details.
     256
     257= 2.6.3 =
     258* **Typography:** List, Card, and Categories panels match core (size, appearance, line height, letter spacing, decoration, letter case).
     259* **Used in:** sources stay on one line with a separator. Non-public sources are hidden on the front; the editor preview shows them greyed.
     260* **Count:** the badge is the sum of the categories on All, or that category’s count on a category page. The number and the label stay on one line.
     261* **No results:** an empty search shows a message you can edit, the same way as Query Loop no-results.
     262* **Dashboard:** figures follow the Polylang admin language and name it. All languages adds a per-language breakdown. Reused counts public pages only.
     263* **Editor preview:** List and Categories follow the page language, and Exclude hides that category.
     264
     265= 2.6.2 =
     266* **Editor:** List, Categories, and Count previews load with POST, so the editor no longer shows “Error loading block: [object Object]”.
     267* **Answers:** color classes copied from dark sections (such as `has-white-50-color`) are stripped on output, so answer text uses the card color.
     268* **Settings:** Overview is four blocks — Registry, SEO, AI, Category titles. A click opens that section. Card headers are shorter, and the Connectors notice sits apart from the toggle.
     269* **Dashboard:** FAQ Status uses large figures. In two columns the third column stacks on the right instead of covering the first. The main WordPress Dashboard has a short FAQ widget with a link to this dashboard.
    225270
    226271= 2.6.1 =
    … …  
    291336== Upgrade Notice ==
    292337
     338= 2.6.5 =
     339WordPress.org banner/icon GIFs and screenshots; directory docs refresh. No functional change from 2.6.4.
     340
     341= 2.6.4 =
     342Hub List no longer disappears when the page slug matches a FAQ category. Convert to FAQ keeps Accordion items; Unwrap restores them. Include/Exclude no longer freezes the editor.
     343
     344= 2.6.3 =
     345Typography matches core, Used in stays on one line, the count matches the categories on the page, empty search has an editable message, and the dashboard follows the admin language.
     346
     347= 2.6.2 =
     348Editor previews load again, FAQ answers no longer keep a forced light color, Settings opens from Overview blocks, and the FAQ Dashboard shows large figures plus a widget on the main WordPress Dashboard.
     349
    293350= 2.6.1 =
    294351Registers the FAQ block with 4WP Drive so imported documents can map an FAQ heading to forwp/faq. https://wordpress.org/plugins/4wp-drive/
Note: See TracChangeset for help on using the changeset viewer.