UNPKG

@ndbx/runtime

Version:

The `@ndbx/runtime` package provides a runtime environment to embed NodeBox visualizations directly into React applications. NodeBox is a powerful tool for creating interactive and generative visualizations, and this runtime allows you to integrate those

162 lines (149 loc) 4.99 kB
/** * Change data based on a condition. * * @category Data */ export default function (node) { const dataIn = node.tableIn({ name: "dataIn", label: "Data" }); const changeIn = node.tableIn({ name: "change data" }); node.pushSection({ name: "General" }); const changeAttrIn = node.stringIn({ name: "changeAttr", label: "Change attribute name" }); const changeValueIn = node.stringIn({ name: "changeValue", label: "Change value" }); node.popSection(); node.pushSection({ name: "Condition" }); const leftIn = node.stringIn({ name: "leftValue", label: "Left value" }); const operatorIn = node.stringIn({ name: "operator", label: "Operator", value: "equal", choices: [ "equal", "not equal", "greater than", "smaller than", "greater than or equal", "smaller than or equal", "between", "between or equal", "in", "contains any", "contains all", "begins with", "ends with", "like (regex)", ], }); const rightIn = node.stringIn({ name: "rightValue", label: "Right value" }); const notIn = node.booleanIn({ name: "not", label: "Negate", value: false }); node.popSection(); const dataOut = node.tableOut({ name: "dataOut", label: "Data" }); const [EQUAL, NOTEQUAL, GREATER, SMALLER, GREATEREQUAL, SMALLEREQUAL] = [ "equal", "not equal", "greater than", "smaller than", "greater than or equal", "smaller than or equal", ]; const [BETWEEN, BETWEENEQUAL, IN, CONTAINS, CONTAINSANY, CONTAINSALL] = [ "between", "between or equal", "in", "contains", "contains any", "contains all", ]; const [BEGINS, ENDS, LIKE] = ["begins with", "ends with", "like (regex)"]; function param2numb(val) { const result = Number(val) || val; return result; } function param2array(val) { let result; if (typeof val === "string" && val.includes(",")) { const regex = new RegExp('^".*"$'); result = val.split(",").map((d) => (!isNaN(Number(d)) ? Number(d) : d.match(regex) ? JSON.parse(d) : d)); // Convert comma-separated value to array } else { result = [val]; } return result; } // Function to change data function changeData(data, changeData, fleft, fright, fattr, fval) { let newData = new Array(); let cond, arr, regex; data.forEach((d, i) => { switch (operatorIn.value) { case EQUAL: cond = param2numb(fleft(d)) === param2numb(fright(d)); break; case NOTEQUAL: cond = param2numb(fleft(d)) !== param2numb(fright(d)); break; case GREATER: cond = param2numb(fleft(d)) > param2numb(fright(d)); break; case SMALLER: cond = param2numb(fleft(d)) < param2numb(fright(d)); break; case GREATEREQUAL: cond = param2numb(fleft(d)) >= param2numb(fright(d)); break; case SMALLEREQUAL: cond = param2numb(fleft(d)) <= param2numb(fright(d)); break; case BETWEEN: arr = param2array(param2numb(fright(d))); cond = arr[0] < fleft(d) < arr[1]; break; case BETWEENEQUAL: arr = param2array(fright(d)); cond = arr[0] <= fleft(d) <= arr[1]; break; case IN: cond = param2array(fright(d)).includes(fleft(d)); break; case CONTAINS: cond = param2array(fleft(d)).includes(fright(d)); break; case CONTAINSANY: cond = param2array(fleft(d)).some((v) => param2array(fright(d)).includes(v)); break; case CONTAINSALL: cond = param2array(fleft(d)).every((v) => param2array(fright(d)).includes(v)); break; case BEGINS: regex = new RegExp("^" + fright(d)); cond = fleft(d).match(regex); break; case ENDS: regex = new RegExp(fright(d) + "$"); cond = fleft(d).match(regex); break; case LIKE: regex = new RegExp(fright(d)); cond = fleft(d).match(regex); break; } if (notIn.value) cond = !cond; // If the condition is met, update or create the attribute if (cond) { const attrName = fattr(d); const j = i < changeData.length ? i : 0; if (!(attrName in d)) { d[attrName] = undefined; // Initialize the new attribute if it doesn't exist } d[attrName] = fval(changeData[j]); } newData.push(d); }); return newData; } node.onRender = () => { let data = structuredClone(dataIn.value ? dataIn.value : []); const changeDataInput = structuredClone(changeIn.value ? changeIn.value : dataIn.value); const [fleft, fright, fattr, fval] = [leftIn.fn, rightIn.fn, changeAttrIn.fn, changeValueIn.fn]; const newData = changeData(data, changeDataInput, fleft, fright, fattr, fval); dataOut.set(newData); }; }