import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; import { registerBlockType, type BlockEditProps } from '@wordpress/blocks'; import { PanelBody, RangeControl, TextControl } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useMemo } from 'react'; import { headingsKey, readHeadings, type EditorBlock } from './headings'; const NAME = 'recomaze/toc'; type Attributes = { title: string; maxLevel: number; }; /** * The list as the reader will see it, built from the editor's own blocks * so it follows unsaved headings; the page itself is rendered server side. */ const Edit = ({ attributes, setAttributes, }: BlockEditProps): JSX.Element => { const key = useSelect( // eslint-disable-next-line @typescript-eslint/no-explicit-any (select: any): string => headingsKey(select('core/block-editor').getBlocks() as EditorBlock[]), [] ); const headings = useMemo( () => readHeadings(key, attributes.maxLevel), [key, attributes.maxLevel] ); return ( <> setAttributes({ title })} help="Empty for no title above the list." __nextHasNoMarginBottom __next40pxDefaultSize /> setAttributes({ maxLevel: Number(value) || 3 })} help="H2 headings always appear; raise it to list H3, H4 and deeper too." __nextHasNoMarginBottom __next40pxDefaultSize /> ); }; registerBlockType( { name: NAME, title: 'Table of contents', category: 'text', attributes: { title: { type: 'string', default: 'Table of contents' }, maxLevel: { type: 'number', default: 3 }, }, }, { edit: Edit, save: () => null } );