Spaces:
Running
Running
Update components/PropertiesPanel.tsx
Browse files
components/PropertiesPanel.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
import { Node } from 'reactflow';
|
| 3 |
import { NodeData, LayerDefinition } from '../types';
|
|
@@ -6,7 +7,7 @@ import { X, Trash2 } from 'lucide-react';
|
|
| 6 |
|
| 7 |
interface PropertiesPanelProps {
|
| 8 |
selectedNode: Node<NodeData> | null;
|
| 9 |
-
onChange: (id: string,
|
| 10 |
onDelete: (id: string) => void;
|
| 11 |
onClose: () => void;
|
| 12 |
}
|
|
@@ -30,12 +31,19 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChang
|
|
| 30 |
if (type === 'number') parsedValue = Number(value);
|
| 31 |
if (type === 'boolean') parsedValue = value === 'true';
|
| 32 |
|
|
|
|
| 33 |
onChange(selectedNode.id, {
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
| 36 |
});
|
| 37 |
};
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
return (
|
| 40 |
<div className="w-80 bg-slate-900 border-l border-slate-800 flex flex-col h-full">
|
| 41 |
<div className="p-4 border-b border-slate-800 flex justify-between items-center">
|
|
@@ -53,6 +61,21 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChang
|
|
| 53 |
{definition.description}
|
| 54 |
</div>
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
<div className="space-y-4">
|
| 57 |
{definition.parameters.map((param) => (
|
| 58 |
<div key={param.name} className="space-y-1.5">
|
|
@@ -79,12 +102,21 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChang
|
|
| 79 |
<option value="true">True</option>
|
| 80 |
<option value="false">False</option>
|
| 81 |
</select>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
) : (
|
| 83 |
<input
|
| 84 |
type={param.type === 'number' ? 'number' : 'text'}
|
| 85 |
className="w-full bg-slate-950 border border-slate-700 rounded px-3 py-2 text-sm text-slate-200 focus:ring-1 focus:ring-blue-500 outline-none placeholder-slate-700"
|
| 86 |
value={selectedNode.data.params[param.name] ?? param.default}
|
| 87 |
onChange={(e) => handleParamChange(param.name, e.target.value, param.type)}
|
|
|
|
| 88 |
/>
|
| 89 |
)}
|
| 90 |
</div>
|
|
@@ -109,4 +141,4 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChang
|
|
| 109 |
);
|
| 110 |
};
|
| 111 |
|
| 112 |
-
export default PropertiesPanel;
|
|
|
|
| 1 |
+
|
| 2 |
import React from 'react';
|
| 3 |
import { Node } from 'reactflow';
|
| 4 |
import { NodeData, LayerDefinition } from '../types';
|
|
|
|
| 7 |
|
| 8 |
interface PropertiesPanelProps {
|
| 9 |
selectedNode: Node<NodeData> | null;
|
| 10 |
+
onChange: (id: string, newData: Partial<NodeData>) => void;
|
| 11 |
onDelete: (id: string) => void;
|
| 12 |
onClose: () => void;
|
| 13 |
}
|
|
|
|
| 31 |
if (type === 'number') parsedValue = Number(value);
|
| 32 |
if (type === 'boolean') parsedValue = value === 'true';
|
| 33 |
|
| 34 |
+
// Update only the params object within data
|
| 35 |
onChange(selectedNode.id, {
|
| 36 |
+
params: {
|
| 37 |
+
...selectedNode.data.params,
|
| 38 |
+
[name]: parsedValue
|
| 39 |
+
}
|
| 40 |
});
|
| 41 |
};
|
| 42 |
|
| 43 |
+
const handleLabelChange = (newLabel: string) => {
|
| 44 |
+
onChange(selectedNode.id, { label: newLabel });
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
return (
|
| 48 |
<div className="w-80 bg-slate-900 border-l border-slate-800 flex flex-col h-full">
|
| 49 |
<div className="p-4 border-b border-slate-800 flex justify-between items-center">
|
|
|
|
| 61 |
{definition.description}
|
| 62 |
</div>
|
| 63 |
|
| 64 |
+
{/* Node Label Renaming */}
|
| 65 |
+
<div className="space-y-1.5">
|
| 66 |
+
<label className="block text-xs font-semibold text-slate-300 uppercase tracking-wide">
|
| 67 |
+
Node Label (Name)
|
| 68 |
+
</label>
|
| 69 |
+
<input
|
| 70 |
+
type="text"
|
| 71 |
+
className="w-full bg-slate-950 border border-slate-700 rounded px-3 py-2 text-sm text-slate-200 focus:ring-1 focus:ring-blue-500 outline-none placeholder-slate-700 font-medium"
|
| 72 |
+
value={selectedNode.data.label}
|
| 73 |
+
onChange={(e) => handleLabelChange(e.target.value)}
|
| 74 |
+
/>
|
| 75 |
+
</div>
|
| 76 |
+
|
| 77 |
+
<div className="h-px bg-slate-800 my-4" />
|
| 78 |
+
|
| 79 |
<div className="space-y-4">
|
| 80 |
{definition.parameters.map((param) => (
|
| 81 |
<div key={param.name} className="space-y-1.5">
|
|
|
|
| 102 |
<option value="true">True</option>
|
| 103 |
<option value="false">False</option>
|
| 104 |
</select>
|
| 105 |
+
) : param.type === 'text' ? (
|
| 106 |
+
<textarea
|
| 107 |
+
className="w-full h-32 bg-slate-950 border border-slate-700 rounded px-3 py-2 text-xs font-mono text-slate-300 focus:ring-1 focus:ring-blue-500 outline-none placeholder-slate-700 resize-y"
|
| 108 |
+
value={selectedNode.data.params[param.name] ?? param.default}
|
| 109 |
+
onChange={(e) => handleParamChange(param.name, e.target.value, param.type)}
|
| 110 |
+
placeholder={param.description}
|
| 111 |
+
spellCheck={false}
|
| 112 |
+
/>
|
| 113 |
) : (
|
| 114 |
<input
|
| 115 |
type={param.type === 'number' ? 'number' : 'text'}
|
| 116 |
className="w-full bg-slate-950 border border-slate-700 rounded px-3 py-2 text-sm text-slate-200 focus:ring-1 focus:ring-blue-500 outline-none placeholder-slate-700"
|
| 117 |
value={selectedNode.data.params[param.name] ?? param.default}
|
| 118 |
onChange={(e) => handleParamChange(param.name, e.target.value, param.type)}
|
| 119 |
+
placeholder={param.description}
|
| 120 |
/>
|
| 121 |
)}
|
| 122 |
</div>
|
|
|
|
| 141 |
);
|
| 142 |
};
|
| 143 |
|
| 144 |
+
export default PropertiesPanel;
|