Dev #8
No files matched your search
@@ -1029,6 +1029,25 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
[effectiveCanEdit, isLiveEnabled, sendBlockUpdated]
|
||||
);
|
||||
|
||||
const handleUpdateBlocks = useCallback(
|
||||
(updatedBlocks: DocumentBlock[]) => {
|
||||
if (!effectiveCanEdit || updatedBlocks.length === 0) return;
|
||||
const map = new Map<string, DocumentBlock>();
|
||||
for (const b of updatedBlocks) {
|
||||
map.set(b.id, b);
|
||||
}
|
||||
setBlocks((prev) =>
|
||||
prev.map((b) => map.get(b.id) || b)
|
||||
);
|
||||
if (isLiveEnabled) {
|
||||
for (const b of updatedBlocks) {
|
||||
sendBlockUpdated(b);
|
||||
}
|
||||
}
|
||||
},
|
||||
[effectiveCanEdit, isLiveEnabled, sendBlockUpdated]
|
||||
);
|
||||
|
||||
const handleCreateBlock = useCallback(
|
||||
(newBlock: DocumentBlock, afterBlockId?: string) => {
|
||||
if (!effectiveCanEdit) return;
|
||||
@@ -1531,6 +1550,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
remoteCursors={remoteCursors}
|
||||
sendCursorMoved={sendCursorMoved}
|
||||
onUpdateBlock={handleUpdateBlock}
|
||||
onUpdateBlocks={handleUpdateBlocks}
|
||||
onCreateBlock={handleCreateBlock}
|
||||
onDeleteBlock={handleDeleteBlock}
|
||||
onMoveBlock={handleMoveBlock}
|
||||
@@ -1599,6 +1619,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
remoteCursors={remoteCursors}
|
||||
sendCursorMoved={sendCursorMoved}
|
||||
onUpdateBlock={handleUpdateBlock}
|
||||
onUpdateBlocks={handleUpdateBlocks}
|
||||
onCreateBlock={handleCreateBlock}
|
||||
onDeleteBlock={handleDeleteBlock}
|
||||
onMoveBlock={handleMoveBlock}
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface OutlinerTreeProps {
|
||||
remoteCursors?: Record<string, RemoteCursor>;
|
||||
sendCursorMoved?: (blockId: string | null, selectionStart?: number, selectionEnd?: number) => void;
|
||||
onUpdateBlock: (updated: DocumentBlock, immediate?: boolean) => void;
|
||||
onUpdateBlocks?: (updated: DocumentBlock[]) => void;
|
||||
onCreateBlock: (newBlock: DocumentBlock, afterBlockId?: string) => void;
|
||||
onDeleteBlock: (blockId: string) => void;
|
||||
onMoveBlock: (blockId: string, newIndex: number, level?: number) => void;
|
||||
@@ -34,6 +35,7 @@ export const OutlinerTree: React.FC<OutlinerTreeProps> = ({
|
||||
remoteCursors,
|
||||
sendCursorMoved,
|
||||
onUpdateBlock,
|
||||
onUpdateBlocks,
|
||||
onCreateBlock,
|
||||
onDeleteBlock,
|
||||
onMoveBlock,
|
||||
@@ -172,7 +174,7 @@ export const OutlinerTree: React.FC<OutlinerTreeProps> = ({
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [blocks]);
|
||||
}, [blocks, levelOffset]);
|
||||
|
||||
const handleCreateBlockBelow = useCallback(
|
||||
(afterBlockId: string, _currentContent: string) => {
|
||||
@@ -241,9 +243,9 @@ export const OutlinerTree: React.FC<OutlinerTreeProps> = ({
|
||||
const current = blocks[idx];
|
||||
const currentLevel = Math.max(0, current.level || 0);
|
||||
const prevLevel = idx > 0 ? Math.max(0, blocks[idx - 1].level || 0) : 0;
|
||||
const maxLevel = idx === 0 ? 0 : prevLevel + 1;
|
||||
|
||||
const minLevel = levelOffset || 0;
|
||||
const maxLevel = idx === 0 ? minLevel : prevLevel + 1;
|
||||
|
||||
const nextLevel =
|
||||
delta === 1
|
||||
? Math.min(maxLevel, currentLevel + 1)
|
||||
@@ -251,15 +253,38 @@ export const OutlinerTree: React.FC<OutlinerTreeProps> = ({
|
||||
|
||||
if (nextLevel === currentLevel) return;
|
||||
|
||||
onUpdateBlock(
|
||||
{
|
||||
...current,
|
||||
level: nextLevel,
|
||||
},
|
||||
true
|
||||
);
|
||||
const actualDelta = nextLevel - currentLevel;
|
||||
|
||||
// Find all contiguous children / descendants:
|
||||
// contiguous blocks with level > currentLevel
|
||||
let count = 1;
|
||||
for (let i = idx + 1; i < blocks.length; i++) {
|
||||
if (Math.max(0, blocks[i].level || 0) > currentLevel) {
|
||||
count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const updatedBlocks: DocumentBlock[] = [];
|
||||
for (let i = idx; i < idx + count; i++) {
|
||||
const b = blocks[i];
|
||||
const newLvl = Math.max(minLevel, (b.level || 0) + actualDelta);
|
||||
updatedBlocks.push({
|
||||
...b,
|
||||
level: newLvl,
|
||||
});
|
||||
}
|
||||
|
||||
if (onUpdateBlocks) {
|
||||
onUpdateBlocks(updatedBlocks);
|
||||
} else {
|
||||
for (const b of updatedBlocks) {
|
||||
onUpdateBlock(b, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
[blocks, canEdit, onUpdateBlock]
|
||||
[blocks, canEdit, levelOffset, onUpdateBlock, onUpdateBlocks]
|
||||
);
|
||||
|
||||
const handleNavigateFocus = useCallback(
|
||||
|
||||
Reference in new issue
Block a user