rename grains to particle, add colormap adjust, table math

This commit is contained in:
2026-03-24 23:48:03 -07:00
parent edfdead4c1
commit 44de72d31b
12 changed files with 512 additions and 109 deletions

View File

@@ -26,7 +26,7 @@ const CAT_COLORS = {
modify: '#0f766e',
level: '#1b5e20',
analysis: '#4a148c',
grains: '#bf360c',
particles:'#bf360c',
display: '#212121',
};
@@ -171,6 +171,69 @@ function CollapsibleSection({ title, defaultOpen, children }) {
);
}
function getTableColumns(rows) {
const columns = [];
for (const row of rows) {
if (!row || typeof row !== 'object') continue;
for (const key of Object.keys(row)) {
if (!columns.includes(key)) columns.push(key);
}
}
return columns;
}
function formatTableCell(value) {
if (value == null) return '';
if (typeof value === 'number') {
if (!Number.isFinite(value)) return String(value);
const abs = Math.abs(value);
if (Number.isInteger(value) && abs < 1e6) return String(value);
if ((abs > 0 && abs < 1e-3) || abs >= 1e4) return value.toExponential(3);
return value.toFixed(4).replace(/\.?0+$/, '');
}
if (Array.isArray(value)) return value.join(', ');
return String(value);
}
function NodeTable({ rows }) {
const columns = getTableColumns(rows);
if (columns.length === 0) return null;
return (
<div className="node-table-wrap">
<div className="node-table-scroll">
<table className="node-table-grid">
<thead>
<tr>
{columns.map((column) => (
<th key={column} scope="col">{column}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, rowIndex) => (
<tr key={row.id ?? row.quantity ?? rowIndex}>
{columns.map((column) => {
const value = row?.[column];
return (
<td
key={`${rowIndex}-${column}`}
className={typeof value === 'number' ? 'node-table-num' : ''}
title={formatTableCell(value)}
>
{formatTableCell(value)}
</td>
);
})}
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
// ── CustomNode component ──────────────────────────────────────────────
function CustomNode({ id, data }) {
@@ -411,21 +474,7 @@ function CustomNode({ id, data }) {
{/* Collapsible table data */}
{data.tableRows && data.tableRows.length > 0 && (
<CollapsibleSection title="Table" defaultOpen={true}>
<div className="node-table">
{data.tableRows.map((row, i) => {
let line;
if (row.quantity !== undefined) {
const val = typeof row.value === 'number' ? row.value.toExponential(3) : row.value;
line = `${row.quantity}: ${val} ${row.unit || ''}`;
} else {
line = Object.entries(row)
.slice(0, 3)
.map(([k, v]) => `${k}: ${typeof v === 'number' ? v.toExponential(2) : v}`)
.join(' ');
}
return <div key={i} className="table-line">{line}</div>;
})}
</div>
<NodeTable rows={data.tableRows} />
</CollapsibleSection>
)}
</div>
@@ -480,6 +529,26 @@ function WidgetControl({ widget, nodeId, value, widgetValues, onChange, openFile
);
}
if (type === 'BUTTON') {
const updates = opts?.set_widgets && typeof opts.set_widgets === 'object'
? Object.entries(opts.set_widgets)
: [];
return (
<button
className="nodrag widget-button"
type="button"
onClick={() => {
for (const [targetName, targetValue] of updates) {
onChange(nodeId, targetName, targetValue);
}
}}
>
{opts?.label || name}
</button>
);
}
if (type === 'FLOAT') {
if (opts?.slider) {
const rawMin = opts?.min_widget ? widgetValues?.[opts.min_widget] : opts?.min;