mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 23:50:08 +00:00
refactor: centralized node mode management
This commit is contained in:
@@ -4,44 +4,41 @@ import { useI18n } from 'vue-i18n'
|
||||
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import { LGraphEventMode } from '@/lib/litegraph/src/litegraph'
|
||||
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
|
||||
import FormSelectButton from '@/renderer/extensions/vueNodes/widgets/components/form/FormSelectButton.vue'
|
||||
|
||||
import LayoutField from './LayoutField.vue'
|
||||
|
||||
/**
|
||||
* Good design limits dependencies and simplifies the interface of the abstraction layer.
|
||||
* Here, we only care about the mode method,
|
||||
* and do not concern ourselves with other methods.
|
||||
*/
|
||||
type PickedNode = Pick<LGraphNode, 'mode'>
|
||||
|
||||
const { nodes } = defineProps<{ nodes: PickedNode[] }>()
|
||||
const { nodes } = defineProps<{ nodes: LGraphNode[] }>()
|
||||
const emit = defineEmits<{ (e: 'changed'): void }>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const nodeState = computed({
|
||||
get() {
|
||||
let mode: LGraphNode['mode'] | null = null
|
||||
|
||||
if (nodes.length === 0) return null
|
||||
|
||||
// For multiple nodes, if all nodes have the same mode, return that mode, otherwise return null
|
||||
if (nodes.length > 1) {
|
||||
mode = nodes[0].mode
|
||||
if (!nodes.every((node) => node.mode === mode)) {
|
||||
mode = null
|
||||
}
|
||||
} else {
|
||||
mode = nodes[0].mode
|
||||
}
|
||||
const nodeIds = nodes.map((node) => node.id.toString())
|
||||
const modes = nodeIds
|
||||
.map((nodeId) => {
|
||||
const nodeRef = layoutStore.getNodeLayoutRef(nodeId)
|
||||
return nodeRef.value?.mode
|
||||
})
|
||||
.filter((mode): mode is number => mode !== undefined && mode !== null)
|
||||
|
||||
return mode
|
||||
if (modes.length === 0) return null
|
||||
|
||||
// For multiple nodes, if all nodes have the same mode, return that mode, otherwise return null
|
||||
const firstMode = modes[0]
|
||||
const allSame = modes.every((mode) => mode === firstMode)
|
||||
|
||||
return allSame ? firstMode : null
|
||||
},
|
||||
set(value: LGraphNode['mode']) {
|
||||
nodes.forEach((node) => {
|
||||
node.mode = value
|
||||
})
|
||||
if (value === null || value === undefined) return
|
||||
|
||||
const nodeIds = nodes.map((node) => node.id.toString())
|
||||
layoutStore.setNodesMode(nodeIds, value)
|
||||
emit('changed')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useSelectedLiteGraphItems } from '@/composables/canvas/useSelectedLiteGraphItems'
|
||||
import type { LGraphNode, Positionable } from '@/lib/litegraph/src/litegraph'
|
||||
import { LGraphEventMode, Reroute } from '@/lib/litegraph/src/litegraph'
|
||||
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { app } from '@/scripts/app'
|
||||
|
||||
@@ -224,8 +225,19 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
|
||||
it('toggleSelectedNodesMode should toggle node modes correctly', () => {
|
||||
const { toggleSelectedNodesMode } = useSelectedLiteGraphItems()
|
||||
const node1 = { id: 1, mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const node2 = { id: 2, mode: LGraphEventMode.NEVER } as LGraphNode
|
||||
const node1 = { id: '1', mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const node2 = { id: '2', mode: LGraphEventMode.NEVER } as LGraphNode
|
||||
|
||||
// Initialize nodes in layoutStore
|
||||
layoutStore.initializeFromLiteGraph([
|
||||
{
|
||||
id: '1',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.ALWAYS
|
||||
},
|
||||
{ id: '2', pos: [0, 0], size: [100, 100], mode: LGraphEventMode.NEVER }
|
||||
])
|
||||
|
||||
app.canvas.selected_nodes = { '0': node1, '1': node2 }
|
||||
|
||||
@@ -234,13 +246,22 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
|
||||
// node1 should change from ALWAYS to NEVER
|
||||
// node2 should stay NEVER (since a selected node exists which is not NEVER)
|
||||
expect(node1.mode).toBe(LGraphEventMode.NEVER)
|
||||
expect(node2.mode).toBe(LGraphEventMode.NEVER)
|
||||
expect(layoutStore.getNodeLayoutRef('1').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
)
|
||||
expect(layoutStore.getNodeLayoutRef('2').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
)
|
||||
})
|
||||
|
||||
it('toggleSelectedNodesMode should set mode to ALWAYS when already in target mode', () => {
|
||||
const { toggleSelectedNodesMode } = useSelectedLiteGraphItems()
|
||||
const node = { id: 1, mode: LGraphEventMode.BYPASS } as LGraphNode
|
||||
const node = { id: '1', mode: LGraphEventMode.BYPASS } as LGraphNode
|
||||
|
||||
// Initialize node in layoutStore
|
||||
layoutStore.initializeFromLiteGraph([
|
||||
{ id: '1', pos: [0, 0], size: [100, 100], mode: LGraphEventMode.BYPASS }
|
||||
])
|
||||
|
||||
app.canvas.selected_nodes = { '0': node }
|
||||
|
||||
@@ -248,7 +269,9 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
toggleSelectedNodesMode(LGraphEventMode.BYPASS)
|
||||
|
||||
// Should change to ALWAYS
|
||||
expect(node.mode).toBe(LGraphEventMode.ALWAYS)
|
||||
expect(layoutStore.getNodeLayoutRef('1').value?.mode).toBe(
|
||||
LGraphEventMode.ALWAYS
|
||||
)
|
||||
})
|
||||
|
||||
it('getSelectedNodes should include nodes from subgraphs', () => {
|
||||
@@ -277,17 +300,43 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
|
||||
it('toggleSelectedNodesMode should apply unified state to subgraph children', () => {
|
||||
const { toggleSelectedNodesMode } = useSelectedLiteGraphItems()
|
||||
const subNode1 = { id: 11, mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const subNode2 = { id: 12, mode: LGraphEventMode.NEVER } as LGraphNode
|
||||
const subNode1 = { id: '11', mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const subNode2 = { id: '12', mode: LGraphEventMode.NEVER } as LGraphNode
|
||||
const subgraphNode = {
|
||||
id: 1,
|
||||
id: '1',
|
||||
mode: LGraphEventMode.ALWAYS,
|
||||
isSubgraphNode: () => true,
|
||||
subgraph: {
|
||||
nodes: [subNode1, subNode2]
|
||||
}
|
||||
} as unknown as LGraphNode
|
||||
const regularNode = { id: 2, mode: LGraphEventMode.BYPASS } as LGraphNode
|
||||
const regularNode = {
|
||||
id: '2',
|
||||
mode: LGraphEventMode.BYPASS
|
||||
} as LGraphNode
|
||||
|
||||
// Initialize all nodes in layoutStore
|
||||
layoutStore.initializeFromLiteGraph([
|
||||
{
|
||||
id: '1',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.ALWAYS
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.BYPASS
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.ALWAYS
|
||||
},
|
||||
{ id: '12', pos: [0, 0], size: [100, 100], mode: LGraphEventMode.NEVER }
|
||||
])
|
||||
|
||||
app.canvas.selected_nodes = { '0': subgraphNode, '1': regularNode }
|
||||
|
||||
@@ -296,22 +345,30 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
|
||||
// Selected nodes follow standard toggle logic:
|
||||
// subgraphNode: ALWAYS -> NEVER (since ALWAYS != NEVER)
|
||||
expect(subgraphNode.mode).toBe(LGraphEventMode.NEVER)
|
||||
expect(layoutStore.getNodeLayoutRef('1').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
)
|
||||
// regularNode: BYPASS -> NEVER (since BYPASS != NEVER)
|
||||
expect(regularNode.mode).toBe(LGraphEventMode.NEVER)
|
||||
expect(layoutStore.getNodeLayoutRef('2').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
)
|
||||
|
||||
// Subgraph children get unified state (same as their parent):
|
||||
// Both children should now be NEVER, regardless of their previous states
|
||||
expect(subNode1.mode).toBe(LGraphEventMode.NEVER) // was ALWAYS, now NEVER
|
||||
expect(subNode2.mode).toBe(LGraphEventMode.NEVER) // was NEVER, stays NEVER
|
||||
expect(layoutStore.getNodeLayoutRef('11').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
) // was ALWAYS, now NEVER
|
||||
expect(layoutStore.getNodeLayoutRef('12').value?.mode).toBe(
|
||||
LGraphEventMode.NEVER
|
||||
) // was NEVER, stays NEVER
|
||||
})
|
||||
|
||||
it('toggleSelectedNodesMode should toggle to ALWAYS when subgraph is already in target mode', () => {
|
||||
const { toggleSelectedNodesMode } = useSelectedLiteGraphItems()
|
||||
const subNode1 = { id: 11, mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const subNode2 = { id: 12, mode: LGraphEventMode.BYPASS } as LGraphNode
|
||||
const subNode1 = { id: '11', mode: LGraphEventMode.ALWAYS } as LGraphNode
|
||||
const subNode2 = { id: '12', mode: LGraphEventMode.BYPASS } as LGraphNode
|
||||
const subgraphNode = {
|
||||
id: 1,
|
||||
id: '1',
|
||||
mode: LGraphEventMode.NEVER, // Already in NEVER mode
|
||||
isSubgraphNode: () => true,
|
||||
subgraph: {
|
||||
@@ -319,17 +376,40 @@ describe('useSelectedLiteGraphItems', () => {
|
||||
}
|
||||
} as unknown as LGraphNode
|
||||
|
||||
// Initialize all nodes in layoutStore
|
||||
layoutStore.initializeFromLiteGraph([
|
||||
{ id: '1', pos: [0, 0], size: [100, 100], mode: LGraphEventMode.NEVER },
|
||||
{
|
||||
id: '11',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.ALWAYS
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
pos: [0, 0],
|
||||
size: [100, 100],
|
||||
mode: LGraphEventMode.BYPASS
|
||||
}
|
||||
])
|
||||
|
||||
app.canvas.selected_nodes = { '0': subgraphNode }
|
||||
|
||||
// Toggle to NEVER mode (but subgraphNode is already NEVER)
|
||||
toggleSelectedNodesMode(LGraphEventMode.NEVER)
|
||||
|
||||
// Selected subgraph should toggle to ALWAYS (since it was already NEVER)
|
||||
expect(subgraphNode.mode).toBe(LGraphEventMode.ALWAYS)
|
||||
expect(layoutStore.getNodeLayoutRef('1').value?.mode).toBe(
|
||||
LGraphEventMode.ALWAYS
|
||||
)
|
||||
|
||||
// All children should also get ALWAYS (unified with parent's new state)
|
||||
expect(subNode1.mode).toBe(LGraphEventMode.ALWAYS)
|
||||
expect(subNode2.mode).toBe(LGraphEventMode.ALWAYS)
|
||||
expect(layoutStore.getNodeLayoutRef('11').value?.mode).toBe(
|
||||
LGraphEventMode.ALWAYS
|
||||
)
|
||||
expect(layoutStore.getNodeLayoutRef('12').value?.mode).toBe(
|
||||
LGraphEventMode.ALWAYS
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { LGraphNode, Positionable } from '@/lib/litegraph/src/litegraph'
|
||||
import { LGraphEventMode, Reroute } from '@/lib/litegraph/src/litegraph'
|
||||
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { app } from '@/scripts/app'
|
||||
import {
|
||||
@@ -119,16 +120,21 @@ export function useSelectedLiteGraphItems() {
|
||||
for (const i in selectedNodes) {
|
||||
selectedNodeArray.push(selectedNodes[i])
|
||||
}
|
||||
const allNodesMatch = !selectedNodeArray.some(
|
||||
(selectedNode) => selectedNode.mode !== mode
|
||||
)
|
||||
|
||||
// Check if all selected nodes are already in the target mode
|
||||
const allNodesMatch = !selectedNodeArray.some((selectedNode) => {
|
||||
const nodeRef = layoutStore.getNodeLayoutRef(selectedNode.id.toString())
|
||||
return nodeRef.value?.mode !== mode
|
||||
})
|
||||
const newModeForSelectedNode = allNodesMatch ? LGraphEventMode.ALWAYS : mode
|
||||
|
||||
// Process each selected node independently to determine its target state and apply to children
|
||||
selectedNodeArray.forEach((selectedNode) => {
|
||||
// Apply standard toggle logic to the selected node itself
|
||||
|
||||
selectedNode.mode = newModeForSelectedNode
|
||||
layoutStore.setNodeMode(
|
||||
selectedNode.id.toString(),
|
||||
newModeForSelectedNode
|
||||
)
|
||||
|
||||
// If this selected node is a subgraph, apply the same mode uniformly to all its children
|
||||
// This ensures predictable behavior: all children get the same state as their parent
|
||||
@@ -139,7 +145,7 @@ export function useSelectedLiteGraphItems() {
|
||||
if (node === selectedNode) return undefined
|
||||
|
||||
// Apply the parent's new mode to all children uniformly
|
||||
node.mode = newModeForSelectedNode
|
||||
layoutStore.setNodeMode(node.id.toString(), newModeForSelectedNode)
|
||||
return undefined
|
||||
}
|
||||
})
|
||||
|
||||
@@ -150,6 +150,7 @@ export function useLayoutMutations(): LayoutMutations {
|
||||
size: layout.size ?? { width: 200, height: 100 },
|
||||
zIndex: layout.zIndex ?? 0,
|
||||
visible: layout.visible ?? true,
|
||||
mode: layout.mode ?? 0, // Default to ALWAYS
|
||||
bounds: {
|
||||
x: layout.position?.x ?? 0,
|
||||
y: layout.position?.y ?? 0,
|
||||
|
||||
@@ -17,6 +17,7 @@ describe('layoutStore CRDT operations', () => {
|
||||
size: { width: 200, height: 100 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x: 100, y: 100, width: 200, height: 100 }
|
||||
})
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import type {
|
||||
RerouteId,
|
||||
RerouteLayout,
|
||||
ResizeNodeOperation,
|
||||
SetNodeModeOperation,
|
||||
SetNodeZIndexOperation,
|
||||
SlotLayout
|
||||
} from '@/renderer/core/layout/types'
|
||||
@@ -295,6 +296,18 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
if (existingLayout.mode !== newLayout.mode) {
|
||||
this.applyOperation({
|
||||
type: 'setNodeMode',
|
||||
entity: 'node',
|
||||
nodeId,
|
||||
mode: newLayout.mode,
|
||||
previousMode: existingLayout.mode,
|
||||
timestamp: Date.now(),
|
||||
source: this.currentSource,
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
trigger()
|
||||
@@ -870,6 +883,9 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
case 'setNodeZIndex':
|
||||
this.handleSetNodeZIndex(operation as SetNodeZIndexOperation, change)
|
||||
break
|
||||
case 'setNodeMode':
|
||||
this.handleSetNodeMode(operation as SetNodeModeOperation, change)
|
||||
break
|
||||
case 'createNode':
|
||||
this.handleCreateNode(operation as CreateNodeOperation, change)
|
||||
break
|
||||
@@ -969,7 +985,12 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
* Initialize store with existing nodes
|
||||
*/
|
||||
initializeFromLiteGraph(
|
||||
nodes: Array<{ id: string; pos: [number, number]; size: [number, number] }>
|
||||
nodes: Array<{
|
||||
id: string
|
||||
pos: [number, number]
|
||||
size: [number, number]
|
||||
mode?: number
|
||||
}>
|
||||
): void {
|
||||
this.ydoc.transact(() => {
|
||||
this.ynodes.clear()
|
||||
@@ -993,6 +1014,7 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
size: { width: node.size[0], height: node.size[1] },
|
||||
zIndex: index,
|
||||
visible: true,
|
||||
mode: node.mode ?? 0, // Default to ALWAYS if not provided
|
||||
bounds: {
|
||||
x: node.pos[0],
|
||||
y: node.pos[1],
|
||||
@@ -1078,6 +1100,17 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
change.nodeIds.push(operation.nodeId)
|
||||
}
|
||||
|
||||
private handleSetNodeMode(
|
||||
operation: SetNodeModeOperation,
|
||||
change: LayoutChange
|
||||
): void {
|
||||
const ynode = this.ynodes.get(operation.nodeId)
|
||||
if (!ynode) return
|
||||
|
||||
ynode.set('mode', operation.mode)
|
||||
change.nodeIds.push(operation.nodeId)
|
||||
}
|
||||
|
||||
private handleCreateNode(
|
||||
operation: CreateNodeOperation,
|
||||
change: LayoutChange
|
||||
@@ -1428,6 +1461,43 @@ class LayoutStoreImpl implements LayoutStore {
|
||||
return Y.encodeStateAsUpdate(this.ydoc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the execution mode for a single node.
|
||||
* Applies the node's changeMode method if available and notifies the graph.
|
||||
*/
|
||||
setNodeMode(nodeId: NodeId, mode: number): void {
|
||||
const ynode = this.ynodes.get(nodeId)
|
||||
if (!ynode) return
|
||||
|
||||
const currentLayout = yNodeToLayout(ynode)
|
||||
if (currentLayout.mode === mode) return // No change needed
|
||||
|
||||
this.applyOperation({
|
||||
type: 'setNodeMode',
|
||||
entity: 'node',
|
||||
nodeId,
|
||||
mode,
|
||||
previousMode: currentLayout.mode,
|
||||
timestamp: Date.now(),
|
||||
source: this.currentSource,
|
||||
actor: this.currentActor
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the execution mode for multiple nodes.
|
||||
* Applies the mode to all nodes atomically.
|
||||
*/
|
||||
setNodesMode(nodeIds: NodeId[], mode: number): void {
|
||||
if (nodeIds.length === 0) return
|
||||
|
||||
// Apply mode to each node
|
||||
// Note: We could create a batch operation type if needed for better performance
|
||||
nodeIds.forEach((nodeId) => {
|
||||
this.setNodeMode(nodeId, mode)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch update node bounds using Yjs transaction for atomicity.
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,7 @@ export interface NodeLayout {
|
||||
size: Size
|
||||
zIndex: number
|
||||
visible: boolean
|
||||
mode: number // LGraphEventMode: 0=ALWAYS, 2=NEVER, 4=BYPASS, etc.
|
||||
// Computed bounds for hit testing
|
||||
bounds: Bounds
|
||||
}
|
||||
@@ -120,6 +121,7 @@ type OperationType =
|
||||
| 'moveNode'
|
||||
| 'resizeNode'
|
||||
| 'setNodeZIndex'
|
||||
| 'setNodeMode'
|
||||
| 'createNode'
|
||||
| 'deleteNode'
|
||||
| 'setNodeVisibility'
|
||||
@@ -157,6 +159,15 @@ export interface SetNodeZIndexOperation extends NodeOpBase {
|
||||
previousZIndex: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Set node mode operation
|
||||
*/
|
||||
export interface SetNodeModeOperation extends NodeOpBase {
|
||||
type: 'setNodeMode'
|
||||
mode: number
|
||||
previousMode: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Create node operation
|
||||
*/
|
||||
@@ -243,6 +254,7 @@ export type LayoutOperation =
|
||||
| MoveNodeOperation
|
||||
| ResizeNodeOperation
|
||||
| SetNodeZIndexOperation
|
||||
| SetNodeModeOperation
|
||||
| CreateNodeOperation
|
||||
| DeleteNodeOperation
|
||||
| SetNodeVisibilityOperation
|
||||
|
||||
@@ -62,6 +62,7 @@ describe('layoutMath utils', () => {
|
||||
size: { width, height },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x, y, width, height }
|
||||
})
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export const NODE_LAYOUT_DEFAULTS: NodeLayout = {
|
||||
size: { width: 100, height: 50 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0, // LGraphEventMode.ALWAYS
|
||||
bounds: { x: 0, y: 0, width: 100, height: 50 }
|
||||
}
|
||||
|
||||
@@ -20,6 +21,7 @@ export function layoutToYNode(layout: NodeLayout): NodeLayoutMap {
|
||||
ynode.set('size', layout.size)
|
||||
ynode.set('zIndex', layout.zIndex)
|
||||
ynode.set('visible', layout.visible)
|
||||
ynode.set('mode', layout.mode)
|
||||
ynode.set('bounds', layout.bounds)
|
||||
return ynode
|
||||
}
|
||||
@@ -40,6 +42,7 @@ export function yNodeToLayout(ynode: NodeLayoutMap): NodeLayout {
|
||||
size: getOr(ynode, 'size', NODE_LAYOUT_DEFAULTS.size),
|
||||
zIndex: getOr(ynode, 'zIndex', NODE_LAYOUT_DEFAULTS.zIndex),
|
||||
visible: getOr(ynode, 'visible', NODE_LAYOUT_DEFAULTS.visible),
|
||||
mode: getOr(ynode, 'mode', NODE_LAYOUT_DEFAULTS.mode),
|
||||
bounds: getOr(ynode, 'bounds', NODE_LAYOUT_DEFAULTS.bounds)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('MinimapDataSource', () => {
|
||||
size: { width: 100, height: 50 },
|
||||
zIndex: 0,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: { x: 0, y: 0, width: 100, height: 50 }
|
||||
}
|
||||
]
|
||||
|
||||
@@ -80,6 +80,7 @@ const mockData = vi.hoisted(() => {
|
||||
size: { width: 100, height: 100 },
|
||||
zIndex: 1,
|
||||
visible: true,
|
||||
mode: 0,
|
||||
bounds: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
||||
Reference in New Issue
Block a user