/
githubmirror
/
gutenberg
Обзор
Документация
Войти
/
githubmirror
/
gutenberg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
trunk
packages/block-library/src/list/edit.js
183 строки
5 KB
Marco Ciampini
ESLint: Replace strict config with bulk suppressions (#81248)
07 авг 2026, 14:34
Не верифицирован
07 авг 2026, 14:34
7f43eaf
Код
Авторство
О чём код?
import { BlockControls, useBlockProps, useInnerBlocksProps, store as blockEditorStore, } from '@wordpress/block-editor'; import { ToolbarButton } from '@wordpress/components'; import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { isRTL, __ } from '@wordpress/i18n'; import { formatListBullets, formatListBulletsRTL, formatListNumbered, formatListNumberedRTL, formatOutdent, formatOutdentRTL, } from '@wordpress/icons'; import { createBlock } from '@wordpress/blocks'; import { useCallback, useEffect } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; import OrderedListSettings from './ordered-list-settings'; import { migrateToListV2 } from './utils'; import TagName from './tag-name'; const DEFAULT_BLOCK = { name: 'core/list-item', }; /** * At the moment, deprecations don't handle create blocks from attributes * (like when using CPT templates). For this reason, this hook is necessary * to avoid breaking templates using the old list block format. * * @param {Object} attributes Block attributes. * @param {string} clientId Block client ID. */ function useMigrateOnLoad( attributes, clientId ) { const registry = useRegistry(); const { updateBlockAttributes, replaceInnerBlocks, selectBlock } = useDispatch( blockEditorStore ); useEffect( () => { // As soon as the block is loaded, migrate it to the new version. if ( ! attributes.values ) { return; } const [ newAttributes, newInnerBlocks ] = migrateToListV2( attributes ); deprecated( 'Value attribute on the list block', { since: '6.0', version: '6.5', alternative: 'inner blocks', } ); // The selection can be inside an inner block created from the block // type template at insertion, which the migration replaces; restore // the selection to the migrated block in that case. const shouldReselectBlock = registry .select( blockEditorStore ) .hasSelectedInnerBlock( clientId, true ); registry.batch( () => { updateBlockAttributes( clientId, newAttributes ); replaceInnerBlocks( clientId, newInnerBlocks ); if ( shouldReselectBlock ) { selectBlock( clientId ); } } ); }, [ attributes.values ] ); } function useOutdentList( clientId ) { const { replaceBlocks, selectionChange } = useDispatch( blockEditorStore ); const { getBlockRootClientId, getBlockAttributes, getBlock } = useSelect( blockEditorStore ); return useCallback( () => { const parentBlockId = getBlockRootClientId( clientId ); const parentBlockAttributes = getBlockAttributes( parentBlockId ); // Create a new parent block without the inner blocks. const newParentBlock = createBlock( 'core/list-item', parentBlockAttributes ); const { innerBlocks } = getBlock( clientId ); // Replace the parent block with a new parent block without inner blocks, // and make the inner blocks siblings of the parent. replaceBlocks( [ parentBlockId ], [ newParentBlock, ...innerBlocks ] ); // Select the last child of the list being outdent. selectionChange( innerBlocks[ innerBlocks.length - 1 ].clientId ); }, [ clientId ] ); } function IndentUI( { clientId } ) { const outdentList = useOutdentList( clientId ); const canOutdent = useSelect( ( select ) => { const { getBlockRootClientId, getBlockName } = select( blockEditorStore ); return ( getBlockName( getBlockRootClientId( clientId ) ) === 'core/list-item' ); }, [ clientId ] ); return ( <> <ToolbarButton icon={ isRTL() ? formatOutdentRTL : formatOutdent } title={ __( 'Outdent' ) } description={ __( 'Outdent list item' ) } disabled={ ! canOutdent } onClick={ outdentList } /> </> ); } export default function Edit( { attributes, setAttributes, clientId } ) { const { ordered, type, reversed, start } = attributes; const blockProps = useBlockProps( { style: { listStyleType: ordered && type !== 'decimal' ? type : undefined, }, } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { defaultBlock: DEFAULT_BLOCK, directInsert: true, templateLock: false, __experimentalCaptureToolbars: true, } ); useMigrateOnLoad( attributes, clientId ); const controls = ( <BlockControls group="block"> <ToolbarButton icon={ isRTL() ? formatListBulletsRTL : formatListBullets } title={ __( 'Unordered' ) } description={ __( 'Convert to unordered list' ) } isActive={ ordered === false } onClick={ () => { setAttributes( { ordered: false } ); } } /> <ToolbarButton icon={ isRTL() ? formatListNumberedRTL : formatListNumbered } title={ __( 'Ordered' ) } description={ __( 'Convert to ordered list' ) } isActive={ ordered === true } onClick={ () => { setAttributes( { ordered: true } ); } } /> <IndentUI clientId={ clientId } /> </BlockControls> ); return ( <> <TagName ordered={ ordered } reversed={ reversed } start={ start } { ...innerBlocksProps } /> { controls } { ordered && ( <OrderedListSettings { ...{ setAttributes, reversed, start, type, } } /> ) } </> ); }