feat(workspace): bar above the phone keyboard to indent, outdent and move bullets
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m33s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-31 11:09:39 +01:00
1 parent 32b79b5d62
commit c6a2cfb85c
9 files changed
+183 -7

No files matched your search

+27
View File
@@ -63,3 +63,30 @@ export function numberedLabels(blocks: DocumentBlock[]): Map<string, string> {
}
return labels;
}
// Swaps a bullet (with its children) with the previous (-1) or next (+1) bullet on the same level
// under the same parent. Returns the same array when there is no such sibling.
export function moveSibling<T extends Pick<DocumentBlock, 'id' | 'level'>>(blocks: T[], blockId: string, direction: -1 | 1): T[] {
const lvl = (b: T) => Math.max(0, b.level || 0);
const subtreeEnd = (start: number) => {
let end = start + 1;
while (end < blocks.length && lvl(blocks[end]) > lvl(blocks[start])) end++;
return end;
};
const idx = blocks.findIndex((b) => b.id === blockId);
if (idx === -1) return blocks;
const level = lvl(blocks[idx]);
const end = subtreeEnd(idx);
if (direction === -1) {
for (let i = idx - 1; i >= 0; i--) {
if (lvl(blocks[i]) < level) return blocks; // reached the parent: already the first child
if (lvl(blocks[i]) === level) {
return [...blocks.slice(0, i), ...blocks.slice(idx, end), ...blocks.slice(i, idx), ...blocks.slice(end)];
}
}
return blocks;
}
if (end >= blocks.length || lvl(blocks[end]) !== level) return blocks; // already the last child
const nextEnd = subtreeEnd(end);
return [...blocks.slice(0, idx), ...blocks.slice(end, nextEnd), ...blocks.slice(idx, end), ...blocks.slice(nextEnd)];
}