优化叠加模式子节点显示

从互斥模式切回叠加模式时恢复全部直接子节点可见

补充模式切换回归测试并同步实施合同
This commit is contained in:
2026-08-20 11:42:27 +08:00
parent bfecfffd2b
commit 901534519f
3 changed files with 21 additions and 1 deletions
@@ -741,11 +741,24 @@ export function useUiEditorSession(
function setNodeChildrenDisplayMode(mode: ChildrenDisplayMode) {
if (!activeImageId || !selectedNodeId) return;
const selectedNode = treeForActiveImage
? findUiNodeLocation(treeForActiveImage.root, selectedNodeId)?.node
: null;
const result = editor.setNodeChildrenDisplayMode(
activeImageId,
selectedNodeId,
mode,
);
if (result.ok && mode === 'Stack' && selectedNode) {
setHiddenNodeIds((current) => {
if (!selectedNode.children.some((child) => current.has(child.id))) {
return current;
}
const next = new Set(current);
for (const child of selectedNode.children) next.delete(child.id);
return next;
});
}
if (!result.ok) setStatus('子节点显示模式更新失败。');
return result;
}
@@ -436,6 +436,13 @@ describe('UiEditorPage', () => {
act(() => result.current.canvas.selectExclusiveChild(childAId!));
expect(result.current.canvas.isNodePreviewVisible(childAId!)).toBe(true);
expect(result.current.canvas.isNodePreviewVisible(childBId!)).toBe(false);
act(() => result.current.inspector.setNodeChildrenDisplayMode('Stack'));
expect(result.current.canvas.isNodePreviewVisible(childAId!)).toBe(true);
expect(result.current.canvas.isNodePreviewVisible(childBId!)).toBe(true);
expect(
result.current.canvas.isNodePreviewVisible(childBDescendantId!),
).toBe(true);
});
it('shows a page-level save failure and allows a retry', async () => {
@@ -4,7 +4,7 @@
## 2026-08-20 UI Editor 最终预览互斥子节点
最终预览中,选中一个 `Exclusive` 父节点时,它的子节点切换条必须在该父节点自身的预览坐标空间内、紧贴节点上方悬浮;不得固定在预览容器左上角,也不得另行按屏幕坐标换算。点击 tab 必须显式选中对应子节点,不能按通用“切换可见性”语义把当前分支隐藏。切换条始终按内容宽度展开并允许溢出节点边界,不设最大宽度或内部滚动区域。切换条仅改变现有子节点可见性状态,不能触发参考图重读、视口重新适配或预览树的异步重建。
最终预览中,选中一个 `Exclusive` 父节点时,它的子节点切换条必须在该父节点自身的预览坐标空间内、紧贴节点上方悬浮;不得固定在预览容器左上角,也不得另行按屏幕坐标换算。点击 tab 必须显式选中对应子节点,不能按通用“切换可见性”语义把当前分支隐藏。切换条始终按内容宽度展开并允许溢出节点边界,不设最大宽度或内部滚动区域。`Exclusive` 切回 `Stack` 时必须清除全部直接子节点因互斥选择产生的隐藏状态并立即显示所有子节点,后代节点自身的独立隐藏状态保持不变。切换条仅改变现有子节点可见性状态,不能触发参考图重读、视口重新适配或预览树的异步重建。
`BestFit` 文本测量的 effect 只依赖字号模式的标量值、文本测量键和实际容器,不能依赖整个 `FontSizing` 对象引用。UI State 对任意节点(包括切换 `children_display_mode`)的不可变更新会 clone 整棵树;等值 clone 不得重新创建 `ResizeObserver` 或同步重复二分测量,以避免最终预览已显示时出现明显的“重新加载”。