feature focus on 3d viewer, add copy/paste

This commit is contained in:
2026-03-26 21:25:35 -07:00
parent de0b49acc5
commit 30671a5362
24 changed files with 1680 additions and 320 deletions

View File

@@ -1,25 +1,7 @@
function mergeDefinition(nodeData, defs) {
const savedData = nodeData || {};
const savedDefinition = savedData.definition && typeof savedData.definition === 'object'
? savedData.definition
: null;
const registryDefinition = savedData.className ? defs[savedData.className] : null;
const definition = registryDefinition || savedDefinition;
if (!definition) return null;
const output = Array.isArray(savedData.output)
? savedData.output
: (Array.isArray(savedDefinition?.output) ? savedDefinition.output : null);
const outputName = Array.isArray(savedData.output_name)
? savedData.output_name
: (Array.isArray(savedDefinition?.output_name) ? savedDefinition.output_name : null);
return {
...definition,
...(output ? { output } : {}),
...(outputName ? { output_name: outputName } : {}),
};
return registryDefinition || null;
}
function getSocketType(inputDef) {
@@ -28,12 +10,6 @@ function getSocketType(inputDef) {
return Array.isArray(type) ? type[0] : type;
}
function getInputType(definition, inputName) {
const required = definition?.input?.required || {};
const optional = definition?.input?.optional || {};
return getSocketType(required[inputName] ?? optional[inputName]);
}
function getInputEntries(definition) {
return [
...Object.entries(definition?.input?.required || {}),
@@ -54,31 +30,6 @@ function sanitizeWidgetValues(widgetValues, definition) {
return nextValues;
}
function remapLegacyHandle(handleId, kind, nodeData) {
if (typeof handleId !== 'string') return handleId;
const parts = handleId.split('::');
if (parts.length !== 3 || parts[2] !== 'TABLE') return handleId;
if (kind === 'source' && parts[0] === 'output') {
const outputSlot = Number.parseInt(parts[1], 10);
const outputType = nodeData?.definition?.output?.[outputSlot];
if (typeof outputType === 'string' && outputType !== 'TABLE') {
return `output::${outputSlot}::${outputType}`;
}
return handleId;
}
if (kind === 'target' && parts[0] === 'input') {
const inputType = getInputType(nodeData?.definition, parts[1]);
if (typeof inputType === 'string' && inputType !== 'TABLE') {
return `input::${parts[1]}::${inputType}`;
}
}
return handleId;
}
export function hydrateWorkflowState(data, defs = {}) {
const loadedNodes = Array.isArray(data?.nodes) ? data.nodes : [];
const loadedEdges = Array.isArray(data?.edges) ? data.edges : [];
@@ -94,6 +45,7 @@ export function hydrateWorkflowState(data, defs = {}) {
...node.data,
label: node.data?.label || node.data?.className || 'Node',
widgetValues: sanitizeWidgetValues(node.data?.widgetValues, definition),
runtimeValues: {},
definition,
previewImage: null,
tableRows: null,
@@ -104,13 +56,7 @@ export function hydrateWorkflowState(data, defs = {}) {
};
});
const nodeById = new Map(nodes.map((node) => [String(node.id), node.data]));
const edges = loadedEdges.map((edge) => ({
...edge,
sourceHandle: remapLegacyHandle(edge.sourceHandle, 'source', nodeById.get(String(edge.source))),
targetHandle: remapLegacyHandle(edge.targetHandle, 'target', nodeById.get(String(edge.target))),
}));
const edges = loadedEdges.map((edge) => ({ ...edge }));
const nextNodeId = Math.max(0, ...loadedNodes.map((node) => parseInt(node.id, 10) || 0)) + 1;