fix(builder): correct move and sortable behavior
This commit is contained in:
1 parent
0bd2a6860d
commit
edccf06658
5 files changed
+70
-5
No files matched your search
@@ -17,6 +17,7 @@ export type BlockCommand =
|
||||
| { type: "insert"; location: BlockLocation; nodes: BlockNode[] }
|
||||
| { type: "remove"; nodeIds: string[] }
|
||||
| { type: "move"; intent: MoveIntent }
|
||||
| { type: "duplicate"; nodeIds: string[]; ids: string[] }
|
||||
| { type: "updateProps"; nodeId: string; patch: JsonObject }
|
||||
| { type: "updateStyles"; nodeId: string; patch: BlockStyles }
|
||||
| { type: "replace"; nodeId: string; node: BlockNode }
|
||||
@@ -152,9 +153,15 @@ export function applyCommand(
|
||||
},
|
||||
],
|
||||
};
|
||||
const removedBeforeDestination = command.intent.from.filter(
|
||||
(location) =>
|
||||
location.parentId === command.intent.to.parentId &&
|
||||
location.slot === command.intent.to.slot &&
|
||||
location.index < command.intent.to.index,
|
||||
).length;
|
||||
root = insert(
|
||||
remove(root, new Set(command.intent.nodeIds)),
|
||||
command.intent.to,
|
||||
{ ...command.intent.to, index: Math.max(0, command.intent.to.index - removedBeforeDestination) },
|
||||
moving as BlockNode[],
|
||||
);
|
||||
affected = command.intent.nodeIds;
|
||||
@@ -169,6 +176,29 @@ export function applyCommand(
|
||||
},
|
||||
})),
|
||||
};
|
||||
} else if (command.type === "duplicate") {
|
||||
const originals = command.nodeIds.map((id) => findBlock(root, id));
|
||||
const locations = command.nodeIds.map((id) => locationOf(root, id));
|
||||
if (originals.some((node) => !node) || locations.some((location) => !location))
|
||||
return { ok: false, errors: [{ code: "command.missing", message: "A duplicated block does not exist.", severity: "error" }] };
|
||||
const countNodes = (node: BlockNode): number =>
|
||||
1 + Object.values(node.slots).flat().reduce((total, child) => total + countNodes(child), 0);
|
||||
const requiredIds = (originals as BlockNode[]).reduce(
|
||||
(total, node) => total + countNodes(node),
|
||||
0,
|
||||
);
|
||||
if (command.ids.length !== requiredIds || new Set(command.ids).size !== command.ids.length)
|
||||
return { ok: false, errors: [{ code: "command.ids", message: "Duplicate requires one unique id for every copied node.", severity: "error" }] };
|
||||
const copies = duplicateNodes(originals as BlockNode[], (() => {
|
||||
let index = 0;
|
||||
return () => command.ids[index++]!;
|
||||
})());
|
||||
const commands = copies.map((node, index) => ({
|
||||
type: "insert" as const,
|
||||
location: { ...locations[index]!, index: locations[index]!.index + 1 },
|
||||
nodes: [node],
|
||||
}));
|
||||
return applyCommand(document, { type: "batch", commands }, kind, registry);
|
||||
} else if (command.type === "updateProps") {
|
||||
const previous = findBlock(root, command.nodeId);
|
||||
if (!previous)
|
||||
|
||||
Reference in new issue
Block a user