/** * External dependencies */ import type { ReactNode } from 'react'; import clsx from 'clsx'; /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import { createContext, useCallback, useContext, useState } from '@wordpress/element'; import { __experimentalHeading as Heading } from '@wordpress/components'; import { Card, CollapsibleCard, Stack } from '@wordpress/ui'; import { useDispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ import { AdminContext } from '../index'; import EditorPreview from './components/editor-preview'; import Filter, { type EditorMode } from './components/filter'; import Controls from './components/controls'; import * as EditorSettings from './editor-settings'; import * as EditorOptions from './editor-options'; import type { EditorConfigContextType, EditorSettings as EditorSettingsType, EditorOptions as EditorOptionsType, } from '../../types'; /** * Context */ export const EditorConfigContext = createContext< EditorConfigContextType >( {} as EditorConfigContextType ); // Value for the `inert` attribute; the empty string enables it (React 18 form). function inertValue( condition: boolean ): '' | undefined { return condition ? '' : undefined; } // Whether a setting with the given title matches the current search query. export function useSearchVisibility( title: string ): boolean { const { searchQuery } = useContext( EditorConfigContext ); if ( ! searchQuery ) { return true; } return title.toLowerCase().includes( searchQuery.toLowerCase() ); } // Collapsible panel, forced open while a search query is active and otherwise // toggled by the user. function SettingsPanel( { title, children }: { title: string; children: ReactNode } ) { const { searchQuery } = useContext( EditorConfigContext ); const [ isOpen, setIsOpen ] = useState( false ); return ( }> { title } { children } ); } export default function EditorConfig() { const { isWaiting, editorSettings, editorOptions, setIsWaiting, setEditorOptions, setEditorSettings, } = useContext( AdminContext ); const [ isEditorDisabled, setIsEditorDisabled ] = useState( false ); const [ editorMode, setEditorMode ] = useState< EditorMode >( 'basic' ); const [ searchQuery, setSearchQuery ] = useState( '' ); const [ fontWeights, setFontWeights ] = useState( [ 300 ] ); const { createNotice, createSuccessNotice } = useDispatch( noticesStore ); // Update editor config. const onUpdateOptions = () => { setIsWaiting( true ); apiFetch< { success: boolean; message: string } >( { path: '/custom-html-block-extension/v1/update_editor_config', method: 'POST', data: { editorSettings, editorOptions, }, } ).then( ( response ) => { setTimeout( () => { createNotice( response.success ? 'success' : 'error', response.message, { type: 'snackbar', } ); setIsWaiting( false ); }, 600 ); } ); }; // Reset editor config. const onResetOptions = () => { setIsWaiting( true ); return apiFetch< { editorSettings: EditorSettingsType; editorOptions: EditorOptionsType } >( { path: '/custom-html-block-extension/v1/delete_editor_config', method: 'POST', } ).then( ( response ) => { // Sets default editor config. setEditorSettings( response.editorSettings ); setEditorOptions( response.editorOptions ); return new Promise< void >( ( resolve ) => { setTimeout( () => { createSuccessNotice( __( 'Settings have been reset.', 'custom-html-block-extension' ), { type: 'snackbar', } ); setIsWaiting( false ); resolve(); }, 600 ); } ); } ); }; // Refresh editor. // Memoized so consumers can derive stable (debounced) callbacks from it. const onRefreshEditor = useCallback( () => { // Some options are not reflected when the state is changed. // So disable the editor for a moment by Disabled component as a workaround. setIsEditorDisabled( true ); setTimeout( () => { setIsEditorDisabled( false ); }, 300 ); }, [] ); return ( { __( 'Preview', 'custom-html-block-extension' ) } { 'basic' === editorMode && ! searchQuery && ( <> ) } { ( 'advanced' === editorMode || searchQuery ) && ( <>
) }
); }