Overview
The Blocks API provides a comprehensive interface for working with blocks in Yoopta Editor. It handles all block-level operations including creation, deletion, movement, transformation, and navigation.
The Blocks API is the primary way to manipulate the structure of your editor content. It works at a higher level than the Elements API, operating on entire blocks rather than individual elements within blocks.
Accessing Blocks API
Blocks API methods are available through the Blocks namespace:
import { Blocks } from '@yoopta/editor';
// Use methods through Blocks namespace
Blocks.insertBlock(editor, 'Paragraph', { at: 0 });
Blocks.deleteBlock(editor, { at: 3 });
Blocks.moveBlock(editor, 'block-id', 5);
Unlike Elements API, Blocks API methods are not available directly on the editor instance. You must use the Blocks namespace.
Why Blocks API?
- Block-Level Operations: Work with entire blocks, not just elements
- Structure Management: Handle block ordering, depth, and relationships
- Type Safety: Full TypeScript support with proper type inference
- Lifecycle Hooks: Integrates with plugin lifecycle methods
- Focus Management: Built-in focus handling for better UX
Core Methods
The Blocks API consists of several categories:
CRUD Operations
Navigation & Movement
Depth Management
Utilities
Quick Example
import { Blocks } from '@yoopta/editor';
import { useYooptaEditor } from '@yoopta/editor';
function MyComponent() {
const editor = useYooptaEditor();
const handleAddParagraph = () => {
// Insert new paragraph block
const blockId = Blocks.insertBlock(editor, 'Paragraph', {
at: editor.path.current,
focus: true,
});
};
const handleDeleteBlock = () => {
// Delete current block
Blocks.deleteBlock(editor, {
at: editor.path.current,
focusTarget: 'previous',
});
};
const handleToggleToHeading = () => {
// Transform current paragraph to heading
Blocks.toggleBlock(editor, 'Heading', {
preserveContent: true,
focus: true,
});
};
return (
// Your component JSX
);
}
Common Use Cases
Inserting Blocks
// Insert paragraph at current position
Blocks.insertBlock(editor, 'Paragraph', {
at: editor.path.current,
focus: true,
});
// Insert heading with custom content
Blocks.insertBlock(editor, 'Heading', {
at: 0,
elements: editor.y('heading-one', {
children: [editor.y.text('New Heading')]
}),
});
Moving and Reordering
// Move block to new position
Blocks.moveBlock(editor, 'block-id-123', 5);
// Increase block depth (indent)
Blocks.increaseBlockDepth(editor, { blockId: 'block-id-123' });
// Decrease block depth (outdent)
Blocks.decreaseBlockDepth(editor, { at: 3 });
// Toggle paragraph to heading
Blocks.toggleBlock(editor, 'Heading', {
preserveContent: true,
});
// Split block at current selection
const newBlockId = Blocks.splitBlock(editor, {
focusTarget: 'new',
});
// Merge current block into previous
Blocks.mergeBlock(editor);
Type Definitions
Common Types
// Block path/index specification
type YooptaPathIndex = number;
// Block data structure
type YooptaBlockData = {
id: string;
type: string;
value: SlateElement[];
meta: {
order: number;
depth: number;
align?: 'left' | 'center' | 'right';
};
};
Best Practices
Always specify at or blockId when working with specific blocks. Using editor.path.current is convenient but can be unreliable if the path changes.
1. Use Block IDs When Possible
// ✅ Good - using block ID
Blocks.deleteBlock(editor, { blockId: 'block-123' });
// ⚠️ Acceptable - using path
Blocks.deleteBlock(editor, { at: 3 });
2. Handle Focus Appropriately
// Focus after insertion for better UX
Blocks.insertBlock(editor, 'Paragraph', {
at: editor.path.current,
focus: true, // User can immediately start typing
});
// Don't focus when doing batch operations
for (let i = 0; i < 10; i++) {
Blocks.insertBlock(editor, 'Paragraph', {
at: i,
focus: false, // Don't focus each block
});
}
3. Preserve Content When Transforming
// ✅ Good - preserve user's content
Blocks.toggleBlock(editor, 'Heading', {
preserveContent: true,
});
// ❌ Avoid - loses user content
Blocks.toggleBlock(editor, 'Heading', {
preserveContent: false,
});
4. Check Block Existence
const block = Blocks.getBlock(editor, { at: 3 });
if (block) {
Blocks.updateBlock(editor, block.id, {
meta: { align: 'center' },
});
}
Next Steps