Spaces:
Running
Running
File size: 3,131 Bytes
c993983 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | import type { Stream, StreamType } from '../../types/stream';
import './StreamEditor.css';
interface Props {
id?: string;
stream: Stream;
onChange: (updated: Stream) => void;
onDelete: () => void;
}
const ALL_VARS = [
'Tin',
'Tout',
'ṁ',
'cp',
'CP',
'Water Content In',
'Water Content Out',
'Density',
'Pressure',
];
const DEFAULT_VARS: Record<StreamType, string[]> = {
product: ['Tin', 'Tout', 'ṁ', 'cp'],
steam: ['Tin', 'ṁ'],
water: ['Tin', 'ṁ', 'Water Content In', 'Water Content Out'],
air: ['Tin', 'ṁ'],
};
const STREAM_TYPES: StreamType[] = ['product', 'steam', 'air', 'water'];
export default function StreamEditor({ id, stream, onChange, onDelete }: Props) {
const displayVars = stream.display_vars?.length
? stream.display_vars
: DEFAULT_VARS[stream.type] || DEFAULT_VARS.product;
const update = (partial: Partial<Stream>) => {
onChange({ ...stream, ...partial });
};
const handleTypeChange = (type: StreamType) => {
update({
type,
display_vars: DEFAULT_VARS[type],
});
};
const toggleVar = (varName: string) => {
const current = [...displayVars];
const idx = current.indexOf(varName);
if (idx >= 0) {
current.splice(idx, 1);
} else {
current.push(varName);
}
update({ display_vars: current });
};
const updateValue = (key: string, value: string) => {
const sv = { ...(stream.stream_values || {}) };
sv[key] = value;
update({ stream_values: sv });
};
return (
<div className="se-card" id={id}>
{/* Header row */}
<div className="se-header">
<input
type="text"
className="se-name"
value={stream.name}
onChange={(e) => update({ name: e.target.value })}
placeholder="Stream name"
/>
<select
className="se-type"
value={stream.type}
onChange={(e) => handleTypeChange(e.target.value as StreamType)}
>
{STREAM_TYPES.map((t) => (
<option key={t} value={t}>
{t}
</option>
))}
</select>
<button className="btn btn-sm" onClick={onDelete} title="Delete stream">
✕
</button>
</div>
{/* Variable selector */}
<div className="se-var-selector">
{ALL_VARS.map((v) => {
const isSelected = displayVars.includes(v);
return (
<button
key={v}
className={`se-var-pill ${isSelected ? 'active' : ''}`}
onClick={() => toggleVar(v)}
>
{v}
</button>
);
})}
</div>
{/* Value inputs */}
<div className="se-values">
{displayVars.map((v) => (
<div key={v} className="se-value-field">
<label>{v}</label>
<input
type="text"
value={stream.stream_values?.[v] || ''}
onChange={(e) => updateValue(v, e.target.value)}
placeholder="—"
/>
</div>
))}
</div>
</div>
);
}
|