feat(workspace): split bulletpoint paragraph at cursor position on Enter
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s
This commit is contained in:
1 parent
5cf6b59377
commit
fdbf691a8d
2 files changed
+26
-7
No files matched your search
@@ -55,7 +55,7 @@ export interface OutlinerBlockProps {
|
|||||||
levelOffset?: number;
|
levelOffset?: number;
|
||||||
onZoomBlock?: (blockId: string) => void;
|
onZoomBlock?: (blockId: string) => void;
|
||||||
onUpdateBlock: (updated: DocumentBlock, immediate?: boolean) => void;
|
onUpdateBlock: (updated: DocumentBlock, immediate?: boolean) => void;
|
||||||
onCreateBlockBelow: (afterBlockId: string, currentContent: string) => void;
|
onCreateBlockBelow: (afterBlockId: string, newContent?: string) => void;
|
||||||
onDeleteBlock: (blockId: string, deleteSubtree?: boolean) => void;
|
onDeleteBlock: (blockId: string, deleteSubtree?: boolean) => void;
|
||||||
onIndentBlock: (blockId: string, delta: 1 | -1) => void;
|
onIndentBlock: (blockId: string, delta: 1 | -1) => void;
|
||||||
onNavigateFocus: (blockId: string, direction: 'up' | 'down') => void;
|
onNavigateFocus: (blockId: string, direction: 'up' | 'down') => void;
|
||||||
@@ -366,7 +366,7 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
|
|||||||
// 2. Enter (without Shift) -> If block is completely empty:
|
// 2. Enter (without Shift) -> If block is completely empty:
|
||||||
// - If level > minLevel, outdent (Shift+Tab behaviour)
|
// - If level > minLevel, outdent (Shift+Tab behaviour)
|
||||||
// - If already at minLevel and is the last block, do NOT create another empty block below
|
// - If already at minLevel and is the last block, do NOT create another empty block below
|
||||||
// - Otherwise create new block below
|
// - Otherwise split paragraph at cursor and create new block below
|
||||||
if (e.key === 'Enter' && !e.shiftKey && block.type !== 'code') {
|
if (e.key === 'Enter' && !e.shiftKey && block.type !== 'code') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -385,8 +385,27 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flushDebounce(localContent);
|
const start = e.currentTarget.selectionStart ?? localContent.length;
|
||||||
onCreateBlockBelowRef.current(block.id, localContent);
|
const end = e.currentTarget.selectionEnd ?? start;
|
||||||
|
let beforeText = localContent.slice(0, start);
|
||||||
|
let afterText = localContent.slice(end);
|
||||||
|
|
||||||
|
// Clean linebreaks at the split boundary if present
|
||||||
|
if (beforeText.endsWith('\r\n')) {
|
||||||
|
beforeText = beforeText.slice(0, -2);
|
||||||
|
} else if (beforeText.endsWith('\n')) {
|
||||||
|
beforeText = beforeText.slice(0, -1);
|
||||||
|
}
|
||||||
|
if (afterText.startsWith('\r\n')) {
|
||||||
|
afterText = afterText.slice(2);
|
||||||
|
} else if (afterText.startsWith('\n')) {
|
||||||
|
afterText = afterText.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocalContent(beforeText);
|
||||||
|
localContentRef.current = beforeText;
|
||||||
|
flushDebounce(beforeText);
|
||||||
|
onCreateBlockBelowRef.current(block.id, afterText);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export const OutlinerTree = forwardRef<OutlinerTreeHandle, OutlinerTreeProps>(({
|
|||||||
}, [blocks, levelOffset]);
|
}, [blocks, levelOffset]);
|
||||||
|
|
||||||
const handleCreateBlockBelow = useCallback(
|
const handleCreateBlockBelow = useCallback(
|
||||||
(afterBlockId: string, _currentContent: string) => {
|
(afterBlockId: string, newContent: string = '') => {
|
||||||
if (!canEdit) return;
|
if (!canEdit) return;
|
||||||
const idx = blocks.findIndex((b) => b.id === afterBlockId);
|
const idx = blocks.findIndex((b) => b.id === afterBlockId);
|
||||||
const currentBlock = idx >= 0 ? blocks[idx] : null;
|
const currentBlock = idx >= 0 ? blocks[idx] : null;
|
||||||
@@ -207,7 +207,7 @@ export const OutlinerTree = forwardRef<OutlinerTreeHandle, OutlinerTreeProps>(({
|
|||||||
id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`,
|
id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`,
|
||||||
documentId: docId,
|
documentId: docId,
|
||||||
type: inheritedType,
|
type: inheritedType,
|
||||||
content: '',
|
content: newContent,
|
||||||
level,
|
level,
|
||||||
checked: false,
|
checked: false,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
@@ -464,7 +464,7 @@ export const OutlinerTree = forwardRef<OutlinerTreeHandle, OutlinerTreeProps>(({
|
|||||||
} else {
|
} else {
|
||||||
const lastBlock = blocks[blocks.length - 1];
|
const lastBlock = blocks[blocks.length - 1];
|
||||||
if (lastBlock.content && lastBlock.content.trim() !== '') {
|
if (lastBlock.content && lastBlock.content.trim() !== '') {
|
||||||
handleCreateBlockBelow(lastBlock.id, lastBlock.content);
|
handleCreateBlockBelow(lastBlock.id, '');
|
||||||
} else {
|
} else {
|
||||||
focusBlockInput(lastBlock.id, 'end');
|
focusBlockInput(lastBlock.id, 'end');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user