/**
* Copyright 2019-2025 Nicolas Jonas
* License: GPL 3.0
*/
import { __ } from '@wordpress/i18n';
import {
BaseControl,
PanelBody,
SelectControl,
TextControl,
ToggleControl,
__experimentalToggleGroupControl as ToggleGroupControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControlOption as ToggleGroupControlOption, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
// createElement import removed as we're using JSX syntax
import ImageUpload from './components/ImageUpload';
import UrlOrEmbedCode from './components/UrlOrEmbedCode';
import { hasSameKeys } from './utils';
const { settingPageUrl, options, settings, gutenbergActive } = window.ArveBlockJsBefore;
const { gutenberg_help: gutenbergHelp } = options;
function createHelp( html?: string ): undefined | string | JSX.Element {
if ( ! gutenbergHelp || ! html ) {
return undefined;
}
// Quick check: if no tags, return the html as a single string
if ( ! html.match( / {
if ( node.nodeType === Node.TEXT_NODE ) {
const text = node.textContent;
if ( text !== null && text !== undefined ) {
result.push( text ); // Preserve all whitespace, no trim
}
} else if ( node.nodeType === Node.ELEMENT_NODE ) {
const el = node as HTMLElement;
if ( el.tagName === 'A' ) {
const a = el as HTMLAnchorElement;
const linkText = a.textContent || '';
result.push(
{ linkText }
);
key++;
return; // Don't process children since we handled the text
}
// Process child nodes for other elements (though assuming only text and )
Array.from( el.childNodes ).forEach( walk );
}
};
walk( doc.body );
return <>{ result }>;
}
// Convert options to SelectControl format
function prepareSelectOptions( opts: Record< string, string > ): GutenbergSelectOption[] {
return Object.entries( opts ).map( ( [ value, label ] ) => ( {
label,
value,
} ) );
}
function shouldHide( settingKey: string, attributes: Record< string, unknown > ): boolean {
if ( 'align' === settingKey ) {
return true;
}
const setting = settings[ settingKey ];
// If no dependencies, don't hide
if ( ! setting?.depends?.length ) {
return false;
}
// Check if NONE of the dependency conditions are met
const hide = ! setting.depends.some( ( condition ) => {
// Each condition is an object with a single key-value pair
const [ key, value ] = Object.entries( condition )[ 0 ] || [];
if ( ! attributes[ key ] ) {
return true; // If the is unset (default) show all settings, as advertisement
}
// If the attribute has the key and its value matches the condition, return true
return key !== undefined && attributes[ key ] === value;
} );
return hide;
}
// Main export: build controls for the block inspector
export function buildControls( { attributes, setAttributes }: BuildControlsProps ): JSX.Element[] {
const controls: JSX.Element[] = [];
const sectionControls: Record< string, JSX.Element[] > = {};
// Initialize section controls
Object.values( settings ).forEach( ( setting ) => {
sectionControls[ setting.category ] = [];
} );
// Add controls to sections
Object.entries( settings ).forEach( ( [ sKey, setting ] ) => {
const val = attributes[ sKey ];
const url = ( attributes[ `${ sKey }_url` ] as string ) || '';
const tab = setting.category || 'no-category';
if ( shouldHide( sKey, attributes ) ) {
return;
}
const settingOptions = setting.options || {};
const boolWithDefaultKeys = [ '', 'true', 'false' ] as const; // Use 'as const' for literal type inference
if ( hasSameKeys( settingOptions, boolWithDefaultKeys ) ) {
sectionControls[ tab ].push(
setAttributes( { [ sKey ]: value } ) }
help={ createHelp( setting.description ) }
>
);
} else if ( 'url' === sKey ) {
sectionControls[ tab ].push(
setAttributes( { [ sKey ]: value } ) }
onAspectRatioChange={ ( ratio: string ) =>
setAttributes( { aspect_ratio: ratio } )
}
placeholder={ setting.placeholder }
help={ createHelp( setting.description ) }
/>
);
} else if ( setting.ui === 'image_upload' ) {
sectionControls[ tab ].push(
);
} else if ( setting.ui_element === 'select' ) {
const selectOptions = prepareSelectOptions(
setting.options as Record< string, string >
);
sectionControls[ tab ].push(
setAttributes( { [ sKey ]: value } ) }
help={ createHelp( setting.description ) }
/>
);
} else if ( setting.ui_element_type === 'checkbox' ) {
sectionControls[ tab ].push(
setAttributes( { [ sKey ]: value } ) }
help={ createHelp( setting.description ) }
/>
);
} else {
sectionControls[ tab ].push(
setAttributes( { [ sKey ]: value } ) }
help={ createHelp( setting.description ) }
/>
);
}
} );
if ( gutenbergHelp || gutenbergActive ) {
// Add info panel to main section
sectionControls.main.push(
{ gutenbergHelp && (
<>
{ __(
'Remember changing the defaults is possible on the',
'advanced-responsive-video-embedder'
) }{ ' ' }
{ __( 'Settings page', 'advanced-responsive-video-embedder' ) }
{ '. ' }
{ __(
'You can also disable the extensive help texts there to clean up this UI.',
'advanced-responsive-video-embedder'
) }
>
) }
{ gutenbergActive && (
<>
{ ' ' }
{ __(
'Error 153 in YouTube embeds, is a known issue with the Gutenberg plugin active and effects only the editor and normal mode. Your Videos will work fine on the front-end. Lazyload is not effected.',
'advanced-responsive-video-embedder'
) }
>
) }
>
}
>
{ __( 'Info', 'advanced-responsive-video-embedder' ) }
);
}
const categories = {
main: __( 'Main', 'advanced-responsive-video-embedder' ),
lazyloadAndLightbox: __( 'Lazyload & Lightbox', 'advanced-responsive-video-embedder' ),
lightbox: __( 'Lightbox', 'advanced-responsive-video-embedder' ),
data: __( 'Data', 'advanced-responsive-video-embedder' ),
stickyVideos: __( 'Sticky Videos', 'advanced-responsive-video-embedder' ),
functional: __( 'Functional', 'advanced-responsive-video-embedder' ),
privacy: __( 'Privacy', 'advanced-responsive-video-embedder' ),
misc: __( 'Misc', 'advanced-responsive-video-embedder' ),
};
// Convert section controls to panels
Object.entries( sectionControls ).forEach( ( [ tab, tabControls ] ) => {
if ( tabControls.length > 0 ) {
controls.push(
{ tabControls }
);
}
} );
return controls;
}