import React, { useEffect, useMemo } from "react";
import { useSelector } from "react-redux";
import { booleanString, emptyObject } from "../../_core";
const safeEval = require('safe-eval-2')
const objectPath = require("object-path");
/**
* Componente wrapper que contiene a aquellos componentes que usan variables.
* @name Reactor.Components.Templates.TagWithVariable
* @param {string} propiedad La propiedad que va a actualizarse con una variable se debe llamar var-nombre_propiedad
* @param {string} context Nombre del contexto que contiene o va a contener la variable, si se omite el contexto sera "global"
* @class
* @example
<input name="nombre_del_campo" var-value="nombre_variable" context="un_contexto" />
*/
export const TagWithVariable = ({tag: Tag = "div", variables = {}, context = "global", ...props}) => {
const variablesState = useSelector(state => state.app.variables[context]) || emptyObject;
const propsVariables = useMemo(() =>
Object.keys(variables).reduce((prev, curr) => {
const variable = variables[curr];
try{
const fnProp = props[`fn-${curr.substring(4)}`];
const propValue = fnProp
? processData(fnProp, objectPath.get(variablesState, variable), variablesState, document)
: objectPath.get(variablesState, variable);
return {
...prev,
[curr.substring(4)]: propValue
}
}catch(e){
console.log(e)
return {
...prev, [curr.substring(4)]: variable
}
}
}, {})
, [context, variables, variablesState]);
const newProps = useMemo(()=>({
...Object.keys(props).reduce((prev, curr)=>{
const propName = curr === "context2" ? "context" : curr;
return {
...prev,
[propName]: !curr.startsWith("fn-") && props[curr]
}
}, {}),
...propsVariables
}), [props, propsVariables]);
useEffect(()=>{
booleanString(newProps?.debug) && console.log("TagWithVariables", {props: newProps});
}, [newProps])
return <Tag {...newProps} context={context}>{newProps.children}</Tag>;
}
const processData = (fn, value, ctx, doc) => {
return safeEval(fn , {value, ctx, doc});
}