Compare commits
12 Commits
7f082ad8f6
..
v0.0.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
82c2f08a56
|
|||
|
a00db400bb
|
|||
|
2d9eb0c087
|
|||
|
1e28ded99b
|
|||
|
5fae518392
|
|||
| 954f5726c3 | |||
|
63d5b8079d
|
|||
|
3e32ca419a
|
|||
|
f0cb12a088
|
|||
|
1d60090ffe
|
|||
|
5b55056fc1
|
|||
|
e2c2b1a4d7
|
@@ -8,9 +8,6 @@ test('test', async ({ page }) => {
|
|||||||
|
|
||||||
await page.goto('http://localhost:4173', { waitUntil: 'load' });
|
await page.goto('http://localhost:4173', { waitUntil: 'load' });
|
||||||
|
|
||||||
// await expect(page).toHaveScreenshot();
|
|
||||||
await expect(page.locator('.graph-wrapper')).toHaveScreenshot();
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'projects' }).click();
|
await page.getByRole('button', { name: 'projects' }).click();
|
||||||
await page.getByRole('button', { name: 'New', exact: true }).click();
|
await page.getByRole('button', { name: 'New', exact: true }).click();
|
||||||
await page.getByRole('combobox').selectOption('2');
|
await page.getByRole('combobox').selectOption('2');
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB |
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@nodarium/app",
|
"name": "@nodarium/app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
|||||||
@@ -41,9 +41,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<span class="i-[tabler--arrow-right]"></span>
|
<span class="i-[tabler--arrow-right]"></span>
|
||||||
<button
|
<button class="bg-layer-2 opacity-100 cursor-pointer rounded-sm p-1 px-2">
|
||||||
class="bg-layer-2 opacity-100 cursor-pointer rounded-sm p-1 px-2"
|
|
||||||
>
|
|
||||||
{getGroupName(graph.currentGroupId!)}
|
{getGroupName(graph.currentGroupId!)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ export class GraphManager extends EventEmitter<{
|
|||||||
status = $state<'loading' | 'idle' | 'error'>();
|
status = $state<'loading' | 'idle' | 'error'>();
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
|
||||||
graph: Graph = $state({ id: 0, nodes: [], edges: [], groups: [] });
|
|
||||||
|
|
||||||
// Snapshots of parent levels we navigated away from. Empty at root.
|
// Snapshots of parent levels we navigated away from. Empty at root.
|
||||||
// Entry i has the saved state of depth i (0 = root graph, 1 = first group, …).
|
// Entry i has the saved state of depth i (0 = root graph, 1 = first group, …).
|
||||||
parentStack: {
|
parentStack: {
|
||||||
@@ -59,6 +57,7 @@ export class GraphManager extends EventEmitter<{
|
|||||||
|
|
||||||
// Graph Data
|
// Graph Data
|
||||||
id = $state(0);
|
id = $state(0);
|
||||||
|
meta = $state<Graph['meta']>({});
|
||||||
nodes = new SvelteMap<number, NodeInstance>();
|
nodes = new SvelteMap<number, NodeInstance>();
|
||||||
edges = $state<Edge[]>([]);
|
edges = $state<Edge[]>([]);
|
||||||
groups: GroupDefinition[] = $state([]);
|
groups: GroupDefinition[] = $state([]);
|
||||||
@@ -121,7 +120,7 @@ export class GraphManager extends EventEmitter<{
|
|||||||
const serialized = $state.snapshot({
|
const serialized = $state.snapshot({
|
||||||
id: this.id,
|
id: this.id,
|
||||||
settings: this.settings,
|
settings: this.settings,
|
||||||
meta: this.graph.meta,
|
meta: this.meta,
|
||||||
groups,
|
groups,
|
||||||
nodes,
|
nodes,
|
||||||
edges
|
edges
|
||||||
@@ -331,8 +330,8 @@ export class GraphManager extends EventEmitter<{
|
|||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
graph.groups ??= [];
|
graph.groups ??= [];
|
||||||
|
this.meta = graph.meta;
|
||||||
this.groups = graph.groups;
|
this.groups = graph.groups;
|
||||||
this.graph = graph;
|
|
||||||
this.status = 'loading';
|
this.status = 'loading';
|
||||||
this.id = graph.id;
|
this.id = graph.id;
|
||||||
|
|
||||||
@@ -475,8 +474,37 @@ export class GraphManager extends EventEmitter<{
|
|||||||
|
|
||||||
// Construct the group inputs on the fly
|
// Construct the group inputs on the fly
|
||||||
if (node.type === '__internal/group/instance') {
|
if (node.type === '__internal/group/instance') {
|
||||||
const groupDefinition = this.getGroup(node.props?.groupId as number);
|
const groupId = node.props?.groupId as number;
|
||||||
|
if (!groupId) {
|
||||||
|
return {
|
||||||
|
...node.state.type,
|
||||||
|
meta: {
|
||||||
|
title: 'Group',
|
||||||
|
...node?.state?.type?.meta || {}
|
||||||
|
},
|
||||||
|
inputs: {
|
||||||
|
'groupId': {
|
||||||
|
type: 'select',
|
||||||
|
label: '',
|
||||||
|
value: this.groups?.[0]?.id,
|
||||||
|
internal: true,
|
||||||
|
options: this.groups.map((g) => ({
|
||||||
|
value: g.id,
|
||||||
|
label: g.name || `Group#${g.id}`
|
||||||
|
})).filter((g) => {
|
||||||
|
const activeIds = new SvelteSet([
|
||||||
|
...this.parentStack.filter(e => e.id !== this.id).map(e => e.id),
|
||||||
|
...(this.currentGroupId !== null ? [this.currentGroupId] : [])
|
||||||
|
]);
|
||||||
|
return !activeIds.has(g.value);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
outputs: []
|
||||||
|
} as NodeDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupDefinition = this.getGroup(node.props?.groupId as number);
|
||||||
if (!groupDefinition) {
|
if (!groupDefinition) {
|
||||||
log.error(`Group not found: ${node.props?.groupId}`);
|
log.error(`Group not found: ${node.props?.groupId}`);
|
||||||
return;
|
return;
|
||||||
@@ -835,8 +863,9 @@ export class GraphManager extends EventEmitter<{
|
|||||||
|
|
||||||
const inputs: Record<string, NodeInput> = {};
|
const inputs: Record<string, NodeInput> = {};
|
||||||
[...groupInputs.values()].forEach((edge, i) => {
|
[...groupInputs.values()].forEach((edge, i) => {
|
||||||
|
const internalInputDef = edge[2].state.type?.inputs?.[edge[3]];
|
||||||
const input = {
|
const input = {
|
||||||
label: `Input ${i}`,
|
label: internalInputDef?.label ?? edge[3],
|
||||||
type: edge[0].state.type?.outputs?.[edge[1]] || '*'
|
type: edge[0].state.type?.outputs?.[edge[1]] || '*'
|
||||||
};
|
};
|
||||||
inputs[`input_${i}`] = input as NodeInput;
|
inputs[`input_${i}`] = input as NodeInput;
|
||||||
@@ -845,8 +874,11 @@ export class GraphManager extends EventEmitter<{
|
|||||||
const outputs = [];
|
const outputs = [];
|
||||||
if (groupOutputs.size) {
|
if (groupOutputs.size) {
|
||||||
const edge = groupOutputs.values().next().value!;
|
const edge = groupOutputs.values().next().value!;
|
||||||
|
const outputType = edge[0].state.type?.outputs?.[edge[1]] || '*';
|
||||||
outputs.push({
|
outputs.push({
|
||||||
label: `Output`,
|
label: outputType === '*'
|
||||||
|
? 'Output'
|
||||||
|
: outputType.charAt(0).toUpperCase() + outputType.slice(1),
|
||||||
type: edge[2].state.type?.inputs?.[edge[3]].type || '*'
|
type: edge[2].state.type?.inputs?.[edge[3]].type || '*'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -956,6 +988,124 @@ export class GraphManager extends EventEmitter<{
|
|||||||
return groupNode;
|
return groupNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ungroupNode(nodeId: number) {
|
||||||
|
const groupNode = this.getNode(nodeId);
|
||||||
|
if (!groupNode || groupNode.type !== '__internal/group/instance') return false;
|
||||||
|
|
||||||
|
const groupId = groupNode.props?.groupId as number;
|
||||||
|
const group = this.getGroup(groupId);
|
||||||
|
if (!group) return false;
|
||||||
|
|
||||||
|
log.log('ungrouping node', { groupId, group });
|
||||||
|
|
||||||
|
this.startUndoGroup();
|
||||||
|
|
||||||
|
const edgesToGroup = this.edges.filter(e => e[2].id === nodeId);
|
||||||
|
const edgesFromGroup = this.edges.filter(e => e[0].id === nodeId);
|
||||||
|
|
||||||
|
const groupInputNode = group.nodes.find(n => n.type === '__internal/group/input');
|
||||||
|
const groupOutputNode = group.nodes.find(n => n.type === '__internal/group/output');
|
||||||
|
const internalNodes = group.nodes.filter(
|
||||||
|
n => n.type !== '__internal/group/input' && n.type !== '__internal/group/output'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Offset internal nodes so their average position matches the group node's position
|
||||||
|
let centerX = 0, centerY = 0;
|
||||||
|
for (const n of internalNodes) {
|
||||||
|
centerX += n.position[0];
|
||||||
|
centerY += n.position[1];
|
||||||
|
}
|
||||||
|
const offsetX = internalNodes.length
|
||||||
|
? groupNode.position[0] - centerX / internalNodes.length
|
||||||
|
: 0;
|
||||||
|
const offsetY = internalNodes.length
|
||||||
|
? groupNode.position[1] - centerY / internalNodes.length
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
// Allocate new IDs that don't collide with anything in the current graph
|
||||||
|
const usedIds = new SvelteSet<number>([
|
||||||
|
...this.nodes.keys(),
|
||||||
|
...this.groups.map(g => g.id),
|
||||||
|
...this.groups.flatMap(g => g.nodes.map(n => n.id))
|
||||||
|
]);
|
||||||
|
const nextId = () => {
|
||||||
|
let id = 0;
|
||||||
|
while (usedIds.has(id)) id++;
|
||||||
|
usedIds.add(id);
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map old internal IDs (including boundary nodes) to fresh IDs
|
||||||
|
const idMap = new SvelteMap<number, number>();
|
||||||
|
for (const n of group.nodes) {
|
||||||
|
idMap.set(n.id, nextId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate internal nodes and add them to the graph
|
||||||
|
const newNodes: NodeInstance[] = internalNodes.map(n => {
|
||||||
|
const nodeType = this.registry.getNode(n.type);
|
||||||
|
const node: NodeInstance = $state({
|
||||||
|
id: idMap.get(n.id)!,
|
||||||
|
type: n.type,
|
||||||
|
position: [n.position[0] + offsetX, n.position[1] + offsetY] as [number, number],
|
||||||
|
state: { type: nodeType },
|
||||||
|
props: n.props || {}
|
||||||
|
});
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const node of newNodes) {
|
||||||
|
this.nodes.set(node.id, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// input_X socket on the group node → the external source that was feeding it
|
||||||
|
const inputIdxToExternal = new SvelteMap<number, { node: NodeInstance; socket: number }>();
|
||||||
|
for (const edge of edgesToGroup) {
|
||||||
|
const match = (edge[3] as string).match(/^input_(\d+)$/);
|
||||||
|
if (match) inputIdxToExternal.set(parseInt(match[1]), { node: edge[0], socket: edge[1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// All external nodes that received output from the group node
|
||||||
|
const externalOutputTargets = edgesFromGroup.map(e => ({ toNode: e[2], toSocket: e[3] }));
|
||||||
|
|
||||||
|
// Recreate internal edges, substituting boundary nodes with the real external peers
|
||||||
|
for (const [fromId, fromSocketIdx, toId, toSocketKey] of group.edges) {
|
||||||
|
let fromNode: NodeInstance | undefined;
|
||||||
|
let resolvedFromSocket = fromSocketIdx;
|
||||||
|
|
||||||
|
if (groupInputNode && fromId === groupInputNode.id) {
|
||||||
|
const ext = inputIdxToExternal.get(fromSocketIdx);
|
||||||
|
if (!ext) continue;
|
||||||
|
fromNode = ext.node;
|
||||||
|
resolvedFromSocket = ext.socket;
|
||||||
|
} else {
|
||||||
|
const newId = idMap.get(fromId);
|
||||||
|
if (newId !== undefined) fromNode = this.nodes.get(newId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fromNode) continue;
|
||||||
|
|
||||||
|
if (groupOutputNode && toId === groupOutputNode.id) {
|
||||||
|
for (const { toNode, toSocket } of externalOutputTargets) {
|
||||||
|
this.createEdge(fromNode, resolvedFromSocket, toNode, toSocket, { applyUpdate: false });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newToId = idMap.get(toId);
|
||||||
|
if (newToId === undefined) continue;
|
||||||
|
const toNode = this.nodes.get(newToId);
|
||||||
|
if (!toNode) continue;
|
||||||
|
this.createEdge(fromNode, resolvedFromSocket, toNode, toSocketKey, { applyUpdate: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the group instance node (also cleans up its edges)
|
||||||
|
this.removeNode(groupNode);
|
||||||
|
|
||||||
|
this.saveUndoGroup();
|
||||||
|
|
||||||
|
return newNodes;
|
||||||
|
}
|
||||||
|
|
||||||
createNode({
|
createNode({
|
||||||
type,
|
type,
|
||||||
position,
|
position,
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ describe('groupSelectedNodes', () => {
|
|||||||
const groupNode = state.groupSelectedNodes();
|
const groupNode = state.groupSelectedNodes();
|
||||||
assert.isDefined(groupNode);
|
assert.isDefined(groupNode);
|
||||||
|
|
||||||
expect(manager.graph.groups.length).toBe(1);
|
expect(manager.groups.length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,26 +139,6 @@ describe('exitGroupNode', () => {
|
|||||||
expect(state.cameraPosition).toEqual(before);
|
expect(state.cameraPosition).toEqual(before);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('restores the camera position from before entry', () => {
|
|
||||||
const { manager, state } = createFixture();
|
|
||||||
|
|
||||||
const nodeA = manager.createNode({ type: 'test/node/output', position: [0, 0], props: {} });
|
|
||||||
assert.isDefined(nodeA);
|
|
||||||
const groupNode = manager.groupNodes([nodeA!.id]);
|
|
||||||
assert.isDefined(groupNode);
|
|
||||||
|
|
||||||
state.activeNodeId = groupNode!.id;
|
|
||||||
state.cameraPosition = [77, 88, 4];
|
|
||||||
|
|
||||||
state.enterGroupNode();
|
|
||||||
// Simulate camera moving inside the group
|
|
||||||
state.cameraPosition = [0, 0, 1];
|
|
||||||
|
|
||||||
state.exitGroupNode();
|
|
||||||
|
|
||||||
expect(state.cameraPosition).toEqual([77, 88, 4]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('clears activeNodeId and selection after exit', () => {
|
it('clears activeNodeId and selection after exit', () => {
|
||||||
const { manager, state } = createFixture();
|
const { manager, state } = createFixture();
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,10 @@ export class GraphState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unGroupSelectedNodes() {
|
||||||
|
return this.graph.ungroupNode(this.activeNodeId);
|
||||||
|
}
|
||||||
|
|
||||||
groupSelectedNodes() {
|
groupSelectedNodes() {
|
||||||
return this.graph.groupNodes([...this.selectedNodes.keys(), this.activeNodeId]);
|
return this.graph.groupNodes([...this.selectedNodes.keys(), this.activeNodeId]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,16 +109,6 @@
|
|||||||
|
|
||||||
return nodeType?.outputs?.[index] || 'unknown';
|
return nodeType?.outputs?.[index] || 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupSize = 0;
|
|
||||||
$effect(() => {
|
|
||||||
if (graph.graph.groups.length > groupSize) {
|
|
||||||
groupSize = graph.graph.groups.length;
|
|
||||||
}
|
|
||||||
if (graph.graph.groups.length < groupSize) {
|
|
||||||
console.error('We have lost a group!');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
|
|||||||
@@ -66,6 +66,14 @@ export function setupKeymaps(keymap: Keymap, graph: GraphManager, graphState: Gr
|
|||||||
callback: () => graphState.groupSelectedNodes()
|
callback: () => graphState.groupSelectedNodes()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
keymap.addShortcut({
|
||||||
|
key: 'g',
|
||||||
|
alt: true,
|
||||||
|
preventDefault: true,
|
||||||
|
description: 'Ungroup selected nodes',
|
||||||
|
callback: () => graphState.unGroupSelectedNodes()
|
||||||
|
});
|
||||||
|
|
||||||
keymap.addShortcut({
|
keymap.addShortcut({
|
||||||
key: 'Tab',
|
key: 'Tab',
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ export const groupNode = {
|
|||||||
id: '__internal/group/instance',
|
id: '__internal/group/instance',
|
||||||
meta: { title: 'Group' },
|
meta: { title: 'Group' },
|
||||||
inputs: {
|
inputs: {
|
||||||
input: {
|
groupId: {
|
||||||
|
label: '',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
values: []
|
values: []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import { debounceAsyncFunction } from '$lib/helpers';
|
import { debounceAsyncFunction } from '$lib/helpers';
|
||||||
import { createKeyMap } from '$lib/helpers/createKeyMap';
|
import { createKeyMap } from '$lib/helpers/createKeyMap';
|
||||||
import { debugNode } from '$lib/node-registry/debugNode';
|
import { debugNode } from '$lib/node-registry/debugNode';
|
||||||
|
import { groupNode } from '$lib/node-registry/groupNode.js';
|
||||||
import { IndexDBCache, RemoteNodeRegistry } from '$lib/node-registry/index';
|
import { IndexDBCache, RemoteNodeRegistry } from '$lib/node-registry/index';
|
||||||
import NodeStore from '$lib/node-store/NodeStore.svelte';
|
import NodeStore from '$lib/node-store/NodeStore.svelte';
|
||||||
import PerformanceViewer from '$lib/performance/PerformanceViewer.svelte';
|
import PerformanceViewer from '$lib/performance/PerformanceViewer.svelte';
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
|
|
||||||
const registryCache = new IndexDBCache('node-registry');
|
const registryCache = new IndexDBCache('node-registry');
|
||||||
|
|
||||||
const nodeRegistry = new RemoteNodeRegistry('', registryCache, [debugNode]);
|
const nodeRegistry = new RemoteNodeRegistry('', registryCache, [debugNode, groupNode]);
|
||||||
const workerRuntime = new WorkerRuntimeExecutor();
|
const workerRuntime = new WorkerRuntimeExecutor();
|
||||||
const runtimeCache = new MemoryRuntimeCache();
|
const runtimeCache = new MemoryRuntimeCache();
|
||||||
const memoryRuntime = new MemoryRuntimeExecutor(nodeRegistry, runtimeCache);
|
const memoryRuntime = new MemoryRuntimeExecutor(nodeRegistry, runtimeCache);
|
||||||
@@ -171,6 +172,7 @@
|
|||||||
config={tutorialConfig}
|
config={tutorialConfig}
|
||||||
actions={{
|
actions={{
|
||||||
'setup-default': () => {
|
'setup-default': () => {
|
||||||
|
console.log('setup-default');
|
||||||
const ts = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
|
const ts = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
|
||||||
pm.handleCreateProject(
|
pm.handleCreateProject(
|
||||||
structuredClone(templates.defaultPlant) as unknown as Graph,
|
structuredClone(templates.defaultPlant) as unknown as Graph,
|
||||||
@@ -178,15 +180,16 @@
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
'load-tutorial-template': () => {
|
'load-tutorial-template': () => {
|
||||||
|
console.log('load-tutorial-template');
|
||||||
if (!pm.graph) return;
|
if (!pm.graph) return;
|
||||||
const g = structuredClone(templates.tutorial) as unknown as Graph;
|
const g = structuredClone(templates.tutorial) as unknown as Graph;
|
||||||
g.id = pm.graph.id;
|
g.id = pm.graph.id;
|
||||||
g.meta = { ...pm.graph.meta };
|
g.meta = { ...pm.graph.meta };
|
||||||
pm.graph = g;
|
manager.load(g);
|
||||||
pm.saveGraph(g);
|
|
||||||
graphInterface.state.centerNode(graphInterface.manager.getAllNodes()[0]);
|
graphInterface.state.centerNode(graphInterface.manager.getAllNodes()[0]);
|
||||||
},
|
},
|
||||||
'open-github-nodes': () => {
|
'open-github-nodes': () => {
|
||||||
|
console.log('open-github-nodes');
|
||||||
window.open(
|
window.open(
|
||||||
'https://github.com/jim-fx/nodarium/tree/main/nodes/max/plantarium',
|
'https://github.com/jim-fx/nodarium/tree/main/nodes/max/plantarium',
|
||||||
'__blank'
|
'__blank'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nodarium/planty",
|
"name": "@nodarium/planty",
|
||||||
"version": "0.0.1",
|
"version": "0.0.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"module": "NodeNext",
|
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nodarium/types",
|
"name": "@nodarium/types",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nodarium/ui",
|
"name": "@nodarium/ui",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||||
"@testing-library/svelte": "^5.3.1",
|
"@testing-library/svelte": "^5.3.1",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
|
"@types/node": "^25.6.0",
|
||||||
"@types/three": "^0.184.0",
|
"@types/three": "^0.184.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
||||||
"@typescript-eslint/parser": "^8.59.1",
|
"@typescript-eslint/parser": "^8.59.1",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import type { NodeInput } from '@nodarium/types';
|
||||||
import '$lib/app.css';
|
import '$lib/app.css';
|
||||||
import {
|
import {
|
||||||
Details,
|
Details,
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
settings: { seed: 42, enabled: true }
|
settings: { seed: 42, enabled: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
let socketTypes = $state({
|
let socketTypes: Record<string, NodeInput> = $state({
|
||||||
input_0: {
|
input_0: {
|
||||||
'label': 'Input 0',
|
'label': 'Input 0',
|
||||||
'type': 'path'
|
'type': 'path'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nodarium/utils",
|
"name": "@nodarium/utils",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./src/index.ts",
|
"main": "./src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
Generated
+3
@@ -290,6 +290,9 @@ importers:
|
|||||||
'@types/eslint':
|
'@types/eslint':
|
||||||
specifier: ^9.6.1
|
specifier: ^9.6.1
|
||||||
version: 9.6.1
|
version: 9.6.1
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^25.6.0
|
||||||
|
version: 25.6.0
|
||||||
'@types/three':
|
'@types/three':
|
||||||
specifier: ^0.184.0
|
specifier: ^0.184.0
|
||||||
version: 0.184.0
|
version: 0.184.0
|
||||||
|
|||||||
Reference in New Issue
Block a user