@wordpress/block-library
Version:
Block library for the WordPress editor.
217 lines (207 loc) • 5.78 kB
JavaScript
/**
* WordPress dependencies
*/
import {
useBlockProps,
useInnerBlocksProps,
InspectorControls,
BlockControls,
useBlockEditingMode,
store as blockEditorStore,
HeadingLevelDropdown,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import {
ToggleControl,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
ToolbarButton,
ToolbarGroup,
} from '@wordpress/components';
import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
import { createBlock } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
const ACCORDION_BLOCK_NAME = 'core/accordion-item';
const ACCORDION_HEADING_BLOCK_NAME = 'core/accordion-heading';
const ACCORDION_BLOCK = {
name: ACCORDION_BLOCK_NAME,
};
export default function Edit( {
attributes: {
autoclose,
iconPosition,
showIcon,
headingLevel,
levelOptions,
},
clientId,
setAttributes,
isSelected: isSingleSelected,
} ) {
const registry = useRegistry();
const { getBlockOrder } = useSelect( blockEditorStore );
const blockProps = useBlockProps( {
role: 'group',
} );
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
const { updateBlockAttributes, insertBlock } =
useDispatch( blockEditorStore );
const blockEditingMode = useBlockEditingMode();
const isContentOnlyMode = blockEditingMode === 'contentOnly';
const innerBlocksProps = useInnerBlocksProps( blockProps, {
template: [ [ ACCORDION_BLOCK_NAME ] ],
defaultBlock: ACCORDION_BLOCK,
directInsert: true,
templateInsertUpdatesSelection: true,
} );
const addAccordionItemBlock = () => {
// When adding, set the header's level to current headingLevel
const newAccordionItem = createBlock( ACCORDION_BLOCK_NAME, {}, [
createBlock( ACCORDION_HEADING_BLOCK_NAME, {
level: headingLevel,
} ),
createBlock( 'core/accordion-panel', {} ),
] );
insertBlock( newAccordionItem, undefined, clientId );
};
/**
* Update all child Accordion Header blocks with a new heading level
* based on the accordion group setting.
* @param {number} newHeadingLevel The new heading level to set
*/
const updateHeadingLevel = ( newHeadingLevel ) => {
const innerBlockClientIds = getBlockOrder( clientId );
// Get all accordion-header blocks from all accordion-content blocks.
const accordionHeaderClientIds = [];
innerBlockClientIds.forEach( ( contentClientId ) => {
const headerClientIds = getBlockOrder( contentClientId );
accordionHeaderClientIds.push( ...headerClientIds );
} );
// Update own and child block heading levels.
registry.batch( () => {
setAttributes( { headingLevel: newHeadingLevel } );
updateBlockAttributes( accordionHeaderClientIds, {
level: newHeadingLevel,
} );
} );
};
return (
<>
{ isSingleSelected && ! isContentOnlyMode && (
<>
<BlockControls>
<ToolbarGroup>
<HeadingLevelDropdown
value={ headingLevel }
options={ levelOptions }
onChange={ updateHeadingLevel }
/>
</ToolbarGroup>
</BlockControls>
<BlockControls group="other">
<ToolbarButton onClick={ addAccordionItemBlock }>
{ __( 'Add item' ) }
</ToolbarButton>
</BlockControls>
</>
) }
<InspectorControls key="setting">
<ToolsPanel
label={ __( 'Settings' ) }
resetAll={ () => {
setAttributes( {
autoclose: false,
showIcon: true,
iconPosition: 'right',
} );
} }
dropdownMenuProps={ dropdownMenuProps }
>
<ToolsPanelItem
label={ __( 'Auto-close' ) }
isShownByDefault
hasValue={ () => !! autoclose }
onDeselect={ () =>
setAttributes( { autoclose: false } )
}
>
<ToggleControl
isBlock
__nextHasNoMarginBottom
label={ __( 'Auto-close' ) }
onChange={ ( value ) => {
setAttributes( {
autoclose: value,
} );
} }
checked={ autoclose }
help={ __(
'Automatically close accordions when a new one is opened.'
) }
/>
</ToolsPanelItem>
<ToolsPanelItem
label={ __( 'Show icon' ) }
isShownByDefault
hasValue={ () => ! showIcon }
onDeselect={ () => setAttributes( { showIcon: true } ) }
>
<ToggleControl
isBlock
__nextHasNoMarginBottom
label={ __( 'Show icon' ) }
onChange={ ( value ) => {
setAttributes( {
showIcon: value,
iconPosition: value
? iconPosition
: 'right',
} );
} }
checked={ showIcon }
help={ __(
'Display a plus icon next to the accordion header.'
) }
/>
</ToolsPanelItem>
{ showIcon && (
<ToolsPanelItem
label={ __( 'Icon Position' ) }
isShownByDefault
hasValue={ () => iconPosition !== 'right' }
onDeselect={ () =>
setAttributes( { iconPosition: 'right' } )
}
>
<ToggleGroupControl
__nextHasNoMarginBottom
__next40pxDefaultSize
isBlock
label={ __( 'Icon Position' ) }
value={ iconPosition }
onChange={ ( value ) => {
setAttributes( { iconPosition: value } );
} }
>
<ToggleGroupControlOption
label={ __( 'Left' ) }
value="left"
/>
<ToggleGroupControlOption
label={ __( 'Right' ) }
value="right"
/>
</ToggleGroupControl>
</ToolsPanelItem>
) }
</ToolsPanel>
</InspectorControls>
<div { ...innerBlocksProps } />
</>
);
}