Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
23 lines
1.4 KiB
JavaScript
23 lines
1.4 KiB
JavaScript
// A search box over every installed node. -> the chosen node class, or null.
|
|
import { composer as c } from "../../composer/composer.js";
|
|
|
|
export function pickNode(api, title) {
|
|
return new Promise((resolve) => {
|
|
const list = c.region.stack({ gap: "xs" }), note = c.hint.default({ text: "" });
|
|
let timer = 0, ticket = 0, done = false;
|
|
const finish = (v) => { if (!done) { done = true; resolve(v); } };
|
|
const win = c.modal.generic({ title, size: "md", onClose: () => finish(null),
|
|
body: c.region.stack({ gap: "sm", children: [c.input.md({ label: "Search", placeholder: "Search installed nodes by name or category…", onInput: (q) => { clearTimeout(timer); timer = setTimeout(() => run(q), 200); } }), note, list] }) });
|
|
async function run(q) {
|
|
const mine = ++ticket;
|
|
let found;
|
|
try { found = await api.searchNodes(q, 40); } catch (err) { return note.setText(`Could not search: ${err.message}`); }
|
|
if (mine !== ticket) return;
|
|
const nodes = found.nodes || [];
|
|
list.set(nodes.map((n) => c.button.sm({ label: `${n.title || n.node} ${n.category || ""}${n.outputs && n.outputs.length ? ` → ${n.outputs.join(", ")}` : ""}`, tone: "ghost", onClick: () => { finish(n.node); win.close("done"); } })));
|
|
note.setText(found.total > nodes.length ? `${nodes.length} of ${found.total} shown: type more to narrow it.` : nodes.length ? "" : "Nothing matches.");
|
|
}
|
|
run("");
|
|
});
|
|
}
|