(function(){
const PREACT_URL='https://unpkg.com/preact@10.19.3/dist/preact.umd.js';
const HOOKS_URL='https://unpkg.com/preact@10.19.3/hooks/dist/hooks.umd.js';
function load(src){return new Promise(res=>{const s=document.createElement('script');s.src=src;s.onload=res;document.head.appendChild(s);});}
(async()=>{
if(!window.preact)await load(PREACT_URL);
if(!window.preactHooks)await load(HOOKS_URL);
const {h,render}=window.preact;
const {useState}=window.preactHooks;
const container=document.getElementById('data-calc');
if(!container)return;
const raw=container.getAttribute('data-calc');
if(!raw)return;
let schema;try{schema=JSON.parse(raw);}catch(e){return;}
function App(){
const [state,setState]=useState(initState());
return h('div',{class:'cbs-calc-runtime'},(schema.layout||[]).map((b,i)=>renderBlock(b,i)));
function renderBlock(block,i){
const cols=(block?.cols||[]).filter(col=>(col?.span??1)>0);
if(!cols.length)return null;
return h('div',{class:'grid',key:i},cols.map((col,c)=>renderCol(col,c)));
}
function renderCol(col,c){
const span=Math.max(1,Math.min(3,col?.span||1));
const style={gridColumn:'span '+span};
return h('div',{class:'col',style,key:c},(col?.items||[]).map(idx=>renderElement(schema.elements?.[idx])));
}
function renderElement(item){
if(!item)return null;
if(item.type==='Header')return h('div',{class:'header'},item.text||'');
if(item.type==='Image'){
if(!item.src)return null;
const aspect=item.aspect==='wide'?'image-wide':'image-square';
return h('div',{class:'image-wrap '+aspect},h('img',{class:'image',src:item.src}));
}
if(item.type==='Input')return h('div',{class:'field'},item.name?h('div',{class:'field-label'},item.name):null,
h('input',{value:state[item.key]??'',onInput:e=>update(item.key,parseFloat(e.target.value)||0)}));
if(item.type==='Select')return h('div',{class:'field'},item.name?h('div',{class:'field-label'},item.name):null,
h('select',{value:state[item.key],onChange:e=>update(item.key,parseFloat(e.target.value)||0)},
(item.variants||[]).map(v=>h('option',{value:v.value},v.name))));
if(item.type==='Radio')return h('div',{},item.name?h('div',{class:'field-label'},item.name):null,
h('div',{class:'radio-group',style:{gridTemplateColumns:'repeat('+(item.cols||4)+',1fr)'}},(item.variants||[]).map(v=>{
const ratioClass=v.imageRatio==='wide'?'radio-ratio-wide':'radio-ratio-square';
return h('div',{class:'radio-card'+(state[item.key]===v.value?' active':''),onClick:()=>update(item.key,v.value)},
v.image?h('img',{class:'radio-img '+ratioClass,src:v.image}):null,
h('div',{class:'radio-card-label'},v.name));
})));
if(item.type==='Result')return renderResult(item);
return null;
}
function renderResult(block){
const rows=[];
(block.data||[]).forEach(row=>{
const cols=(row||[]).map(cell=>{
const val=state[cell];
if(isFinite(val))return h('td',{},val);
return h('td',{},cell);
});
rows.push(h('tr',{},cols));
});
return h('div',{class:'results-card'},
block.title?h('div',{class:'header'},block.title):null,
h('table',{},rows));
}
function update(key,val){
const next={...state};
next[key]=val;
solve(next);
setState(next);
}
function solve(s){
let changed=true,guard=0;
while(changed&&guard<1000){
changed=false;guard++;
(schema.elements||[]).forEach(item=>{
if(item.type!=='Calc')return;
const newVal=calc(item.formula,s);
if(s[item.key]!==newVal){s[item.key]=newVal;changed=true;}
});
}
}
function calc(formula,s){
if(!formula)return 0;
try{const fn=new Function('state','with(state){ return '+formula+' }');return fn(s);}
catch(e){return 0;}
}
function initState(){
const s={};
(schema.elements||[]).forEach(item=>{
if(item.type==='Input'||item.type==='Select'||item.type==='Radio'){
if(item.key&&s[item.key]===undefined){
s[item.key]=item.default??(item.variants?.[0]?.value??0);
}
}
});
solve(s);
return s;
}
}
render(h(App),container);
})();
})();
Lorem ipsum
test
Показать калькулятор