fix(editor): array local-variable support in signal-tree pane
The signal-tree pane (edit mode) has its own inline "add local variable" form, separate from the Logic-tab LocalVars form that gained array support in the array-locals feature. This second entry point was missed, so the type dropdown there only offered number/bool/string. Mirror the LogicEditor form: add the array type option plus elem/sizing/capacity selects and a JSON-validated initial value. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+73
-6
@@ -117,17 +117,48 @@ export default function SignalTree({ onDragStart, width, panelId, statevars, onS
|
|||||||
const [showAddLocal, setShowAddLocal] = useState(false);
|
const [showAddLocal, setShowAddLocal] = useState(false);
|
||||||
const [localOpen, setLocalOpen] = useState(true);
|
const [localOpen, setLocalOpen] = useState(true);
|
||||||
const [lvName, setLvName] = useState('');
|
const [lvName, setLvName] = useState('');
|
||||||
const [lvType, setLvType] = useState<'number' | 'bool' | 'string'>('number');
|
const [lvType, setLvType] = useState<'number' | 'bool' | 'string' | 'array'>('number');
|
||||||
const [lvInitial, setLvInitial] = useState('0');
|
const [lvInitial, setLvInitial] = useState('0');
|
||||||
|
// array-specific fields (mirror LogicEditor LocalVars)
|
||||||
|
const [lvElem, setLvElem] = useState<'number' | 'bool' | 'array'>('number');
|
||||||
|
const [lvSizing, setLvSizing] = useState<'dynamic' | 'capped' | 'fixed'>('dynamic');
|
||||||
|
const [lvCapacity, setLvCapacity] = useState('100');
|
||||||
|
const [lvJsonErr, setLvJsonErr] = useState('');
|
||||||
|
|
||||||
|
function handleLvTypeChange(t: 'number' | 'bool' | 'string' | 'array') {
|
||||||
|
setLvType(t);
|
||||||
|
setLvInitial(t === 'array' ? '[]' : t === 'bool' ? 'false' : t === 'string' ? '' : '0');
|
||||||
|
setLvJsonErr('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLvInitialChange(v: string) {
|
||||||
|
setLvInitial(v);
|
||||||
|
if (lvType === 'array') {
|
||||||
|
try { JSON.parse(v); setLvJsonErr(''); }
|
||||||
|
catch (e: any) { setLvJsonErr(e.message); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addLocal() {
|
function addLocal() {
|
||||||
const name = lvName.trim();
|
const name = lvName.trim();
|
||||||
if (!name || !onStateVarsChange) return;
|
if (!name || !onStateVarsChange) return;
|
||||||
|
if (lvType === 'array' && lvJsonErr) return;
|
||||||
|
const base: StateVar = { name, type: lvType, initial: lvInitial };
|
||||||
|
if (lvType === 'array') {
|
||||||
|
base.elem = lvElem;
|
||||||
|
base.sizing = lvSizing;
|
||||||
|
if (lvSizing !== 'dynamic') base.capacity = parseInt(lvCapacity, 10) || 100;
|
||||||
|
}
|
||||||
const next = (statevars ?? []).filter(v => v.name !== name);
|
const next = (statevars ?? []).filter(v => v.name !== name);
|
||||||
next.push({ name, type: lvType, initial: lvInitial });
|
next.push(base);
|
||||||
onStateVarsChange(next);
|
onStateVarsChange(next);
|
||||||
setLvName('');
|
setLvName('');
|
||||||
setLvInitial('0');
|
setLvInitial('0');
|
||||||
|
setLvType('number');
|
||||||
|
setLvElem('number');
|
||||||
|
setLvSizing('dynamic');
|
||||||
|
setLvCapacity('100');
|
||||||
|
setLvJsonErr('');
|
||||||
setShowAddLocal(false);
|
setShowAddLocal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,20 +355,56 @@ export default function SignalTree({ onDragStart, width, panelId, statevars, onS
|
|||||||
class="prop-select"
|
class="prop-select"
|
||||||
style="font-size: 0.7rem; height: 1.6rem; padding: 0 4px;"
|
style="font-size: 0.7rem; height: 1.6rem; padding: 0 4px;"
|
||||||
value={lvType}
|
value={lvType}
|
||||||
onChange={(e) => setLvType((e.target as HTMLSelectElement).value as any)}
|
onChange={(e) => handleLvTypeChange((e.target as HTMLSelectElement).value as any)}
|
||||||
>
|
>
|
||||||
<option value="number">number</option>
|
<option value="number">number</option>
|
||||||
<option value="bool">bool</option>
|
<option value="bool">bool</option>
|
||||||
<option value="string">string</option>
|
<option value="string">string</option>
|
||||||
|
<option value="array">array</option>
|
||||||
</select>
|
</select>
|
||||||
|
{lvType === 'array' && (
|
||||||
|
<Fragment>
|
||||||
|
<select
|
||||||
|
class="prop-select"
|
||||||
|
style="font-size: 0.7rem; height: 1.6rem; padding: 0 4px;"
|
||||||
|
value={lvElem}
|
||||||
|
onChange={(e) => setLvElem((e.target as HTMLSelectElement).value as any)}
|
||||||
|
>
|
||||||
|
<option value="number">elem: number</option>
|
||||||
|
<option value="bool">elem: bool</option>
|
||||||
|
<option value="array">elem: array</option>
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
class="prop-select"
|
||||||
|
style="font-size: 0.7rem; height: 1.6rem; padding: 0 4px;"
|
||||||
|
value={lvSizing}
|
||||||
|
onChange={(e) => setLvSizing((e.target as HTMLSelectElement).value as any)}
|
||||||
|
>
|
||||||
|
<option value="dynamic">sizing: dynamic</option>
|
||||||
|
<option value="capped">sizing: capped</option>
|
||||||
|
<option value="fixed">sizing: fixed</option>
|
||||||
|
</select>
|
||||||
|
{lvSizing !== 'dynamic' && (
|
||||||
|
<input
|
||||||
|
class="signal-add-input"
|
||||||
|
type="number"
|
||||||
|
style="width: 5rem;"
|
||||||
|
placeholder="capacity"
|
||||||
|
value={lvCapacity}
|
||||||
|
onInput={(e) => setLvCapacity((e.target as HTMLInputElement).value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
<input
|
<input
|
||||||
class="signal-add-input"
|
class={`signal-add-input${lvJsonErr ? ' prop-input-error' : ''}`}
|
||||||
style="flex: 1;"
|
style="flex: 1;"
|
||||||
placeholder="initial"
|
placeholder={lvType === 'array' ? 'initial (JSON)' : 'initial'}
|
||||||
value={lvInitial}
|
value={lvInitial}
|
||||||
onInput={(e) => setLvInitial((e.target as HTMLInputElement).value)}
|
onInput={(e) => handleLvInitialChange((e.target as HTMLInputElement).value)}
|
||||||
onKeyDown={(e: KeyboardEvent) => { if (e.key === 'Enter') addLocal(); }}
|
onKeyDown={(e: KeyboardEvent) => { if (e.key === 'Enter') addLocal(); }}
|
||||||
/>
|
/>
|
||||||
|
{lvJsonErr && <p class="wizard-error" style="flex-basis: 100%; margin: 0;">{lvJsonErr}</p>}
|
||||||
<button class="icon-btn" title="Add" onClick={addLocal}>✓</button>
|
<button class="icon-btn" title="Add" onClick={addLocal}>✓</button>
|
||||||
<button class="icon-btn" title="Cancel" onClick={() => setShowAddLocal(false)}>✕</button>
|
<button class="icon-btn" title="Cancel" onClick={() => setShowAddLocal(false)}>✕</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user