feat(logic): array action nodes + accumulate/export unification + migration

Add five action.array.push|set|remove|pop|clear node kinds; replace the
legacy {t,v} in-memory arrays store with array locals as single source of
truth; alias action.accumulate→push and action.clear→array.clear for
backward compat; rewrite action.export as index-aligned CSV with custom
header labels; add ensureArrayDecls() auto-declare migration wired via
Canvas.tsx so undeclared arrays referenced by logic nodes are initialised.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino Ferrari
2026-06-24 11:07:24 +02:00
parent 062bb44dba
commit 8f50bc2498
3 changed files with 159 additions and 68 deletions
+5 -3
View File
@@ -1,7 +1,7 @@
import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import { initLocalState } from './lib/localstate';
import { logicEngine } from './lib/logic';
import { logicEngine, ensureArrayDecls } from './lib/logic';
import { getWidgetCmdStore, type WidgetCmd } from './lib/widgetCommands';
import type { Interface, Widget, SignalRef } from './lib/types';
import TextView from './widgets/TextView';
@@ -119,9 +119,11 @@ export default function Canvas({ iface, onNavigate, timeRange }: Props) {
}
// Instantiate this panel's local state variables from their initial values.
// ensureArrayDecls auto-declares any array referenced by logic nodes that
// are not yet declared as state vars (backward-compat migration).
useEffect(() => {
initLocalState(iface?.statevars);
}, [iface?.id, iface?.statevars]);
initLocalState(ensureArrayDecls(iface?.logic, iface?.statevars ?? []));
}, [iface?.id, iface?.statevars, iface?.logic]);
// Activate panel logic for the live view; tear it down on unmount/panel switch.
useEffect(() => {