import type { DragEvent } from 'react'; import { useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import type { ContentBlockKey } from '../types/settings'; type Zone = 'before' | 'after'; type BlockMeta = { key: ContentBlockKey; label: string; zone: Zone | null; // null = not participating (e.g. TOC with after-first-paragraph) moduleEnabled: boolean; }; type ContentBlocksOrderProps = { blocks: BlockMeta[]; order: ContentBlockKey[]; onOrderChange: ( next: ContentBlockKey[] ) => void; onZoneChange: ( key: ContentBlockKey, zone: Zone ) => void; }; const ContentBlocksOrder = ( { blocks, order, onOrderChange, onZoneChange, }: ContentBlocksOrderProps ) => { const dragKey = useRef( null ); const dragSourceZone = useRef( null ); // Sort blocks by their position in order array const sortedBlocks = ( zone: Zone ): BlockMeta[] => { const inZone = blocks.filter( ( b ) => b.zone === zone ); inZone.sort( ( a, b ) => { const ai = order.indexOf( a.key ); const bi = order.indexOf( b.key ); return ( ai === -1 ? 999 : ai ) - ( bi === -1 ? 999 : bi ); } ); return inZone; }; const handleDragStart = ( key: ContentBlockKey, zone: Zone, ) => ( event: DragEvent ) => { dragKey.current = key; dragSourceZone.current = zone; event.dataTransfer.effectAllowed = 'move'; }; const handleDragOver = ( event: DragEvent ) => { event.preventDefault(); event.dataTransfer.dropEffect = 'move'; }; const handleDropOnCard = ( targetKey: ContentBlockKey, targetZone: Zone, ) => ( event: DragEvent ) => { event.preventDefault(); const sourceKey = dragKey.current; const sourceZone = dragSourceZone.current; if ( ! sourceKey ) { return; } // If moving to a different zone, update zone first if ( sourceZone !== targetZone ) { onZoneChange( sourceKey, targetZone ); } // Reorder: move sourceKey before targetKey in the order array if ( sourceKey === targetKey ) { return; } const next = order.filter( ( k ) => k !== sourceKey ); const targetIndex = next.indexOf( targetKey ); if ( targetIndex === -1 ) { next.push( sourceKey ); } else { next.splice( targetIndex, 0, sourceKey ); } onOrderChange( next ); dragKey.current = null; dragSourceZone.current = null; }; const handleDropOnZone = ( targetZone: Zone ) => ( event: DragEvent ) => { event.preventDefault(); const sourceKey = dragKey.current; const sourceZone = dragSourceZone.current; if ( ! sourceKey || sourceZone === targetZone ) { return; } onZoneChange( sourceKey, targetZone ); dragKey.current = null; dragSourceZone.current = null; }; const handleDragEnd = () => { dragKey.current = null; dragSourceZone.current = null; }; const renderCard = ( block: BlockMeta, zone: Zone ) => (
{ block.label }
{ block.moduleEnabled ? __( 'Enabled', 'airygen-seo' ) : __( 'Disabled', 'airygen-seo' ) }
); const renderZone = ( zone: Zone, title: string ) => { const zoneBlocks = sortedBlocks( zone ); return (
{ title }
{ zoneBlocks.length === 0 ? (

{ __( 'Drop blocks here', 'airygen-seo' ) }

) : ( zoneBlocks.map( ( block ) => renderCard( block, zone ) ) ) }
); }; return (
{ renderZone( 'before', __( 'Before content', 'airygen-seo' ) ) } { renderZone( 'after', __( 'After content', 'airygen-seo' ) ) }
); }; export default ContentBlocksOrder;