PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / scientific-calculator / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/scientific-calculator/index.js

238 lines 16.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var ToggleControl = wp.components.ToggleControl;
15
16 var _tc, _tv;
17 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
18 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
19
20 var BTN_LAYOUT = [
21 ['MC','MR','MS','M+','M−'],
22 ['2nd','π','e','C',''],
23 ['','','√x','ʸ√x','1/x'],
24 ['sin','cos','tan','log','ln'],
25 ['sin⁻¹','cos⁻¹','tan⁻¹','10ˣ',''],
26 ['(',')', '%', '÷', ''],
27 ['7', '8', '9', '×', ''],
28 ['4', '5', '6', '', ''],
29 ['1', '2', '3', '+', ''],
30 ['±', '0', '.', '=', '']
31 ];
32
33 function ScientificCalcPreview(props) {
34 var a = props.attributes;
35 var accent = a.accentColor || '#6c3fb5';
36
37 var _disp = useState('0');
38 var display = _disp[0]; var setDisplay = _disp[1];
39
40 var _expr = useState('');
41 var expr = _expr[0]; var setExpr = _expr[1];
42
43 var _hist = useState([]);
44 var history = _hist[0]; var setHistory = _hist[1];
45
46 var _mem = useState(0);
47 var memory = _mem[0]; var setMemory = _mem[1];
48
49 var _ang = useState(a.angleMode || 'deg');
50 var angleMode = _ang[0]; var setAngleMode = _ang[1];
51
52 var _shift = useState(false);
53 var shift = _shift[0]; var setShift = _shift[1];
54
55 function toRad(x) { return angleMode === 'deg' ? x * Math.PI / 180 : x; }
56
57 function evaluate(e) {
58 try {
59 var safe = e
60 .replace(/×/g,'*').replace(/÷/g,'/')
61 .replace(//g,'-').replace(/π/g,'Math.PI')
62 .replace(/\be\b/g,'Math.E');
63 var r = Function('"use strict"; return (' + safe + ')')();
64 return isFinite(r) ? parseFloat(r.toPrecision(a.precision||10)).toString() : 'Error';
65 } catch(err) { return 'Error'; }
66 }
67
68 function handleBtn(lbl) {
69 if (lbl === '') return;
70 if (lbl === 'C') { setDisplay('0'); setExpr(''); return; }
71 if (lbl === '') { setDisplay(function(d){ var s = d.slice(0,-1); return s===''||s==='-'?'0':s; }); return; }
72 if (lbl === '±') { setDisplay(function(d){ return d.startsWith('-')?d.slice(1):'-'+d; }); return; }
73 if (lbl === '=') {
74 var full = expr + display;
75 var res = evaluate(full);
76 if (a.showHistory) setHistory(function(h){ return [{expr:full+'='+res}].concat(h).slice(0,a.historyMax||10); });
77 setExpr(''); setDisplay(res); return;
78 }
79 if (lbl === 'MC') { setMemory(0); return; }
80 if (lbl === 'MR') { setDisplay(memory.toString()); return; }
81 if (lbl === 'MS') { setMemory(parseFloat(display)||0); return; }
82 if (lbl === 'M+') { setMemory(function(m){ return m + (parseFloat(display)||0); }); return; }
83 if (lbl === 'M−') { setMemory(function(m){ return m - (parseFloat(display)||0); }); return; }
84 if (lbl === '2nd') { setShift(!shift); return; }
85 var num = parseFloat(display);
86 var unary = {
87 '': function(v){ return (v*v).toString(); },
88 '√x': function(v){ return Math.sqrt(v).toString(); },
89 '1/x': function(v){ return (1/v).toString(); },
90 'sin': function(v){ return Math.sin(toRad(v)).toPrecision(a.precision||10)*1+''; },
91 'cos': function(v){ return Math.cos(toRad(v)).toPrecision(a.precision||10)*1+''; },
92 'tan': function(v){ return Math.tan(toRad(v)).toPrecision(a.precision||10)*1+''; },
93 'sin⁻¹': function(v){ return (angleMode==='deg'?Math.asin(v)*180/Math.PI:Math.asin(v)).toPrecision(a.precision||10)*1+''; },
94 'cos⁻¹': function(v){ return (angleMode==='deg'?Math.acos(v)*180/Math.PI:Math.acos(v)).toPrecision(a.precision||10)*1+''; },
95 'tan⁻¹': function(v){ return (angleMode==='deg'?Math.atan(v)*180/Math.PI:Math.atan(v)).toPrecision(a.precision||10)*1+''; },
96 'log': function(v){ return Math.log10(v).toPrecision(a.precision||10)*1+''; },
97 'ln': function(v){ return Math.log(v).toPrecision(a.precision||10)*1+''; },
98 '10ˣ': function(v){ return Math.pow(10,v).toString(); },
99 '': function(v){ return Math.exp(v).toPrecision(a.precision||10)*1+''; },
100 '%': function(v){ return (v/100).toString(); }
101 };
102 if (unary[lbl]) { setDisplay(unary[lbl](num)); return; }
103 var ops = ['+','','×','÷','','ʸ√x'];
104 if (ops.includes(lbl)) {
105 setExpr(expr + display + lbl);
106 setDisplay('0');
107 return;
108 }
109 if (lbl === 'π') { setDisplay(Math.PI.toPrecision(a.precision||10)*1+''); return; }
110 if (lbl === 'e') { setDisplay(Math.E.toPrecision(a.precision||10)*1+''); return; }
111 if (lbl === '(' || lbl === ')') { setExpr(expr+lbl); return; }
112 setDisplay(function(d){ return d==='0'||d==='Error'?lbl:(d+lbl); });
113 }
114
115 function getBtnStyle(lbl) {
116 var base = {padding:'0',border:'none',cursor:'pointer',fontWeight:600,fontSize:(a.btnSize||15)+'px',fontFamily:'inherit',borderRadius:(a.btnRadius||10)+'px',transition:'filter .15s, transform .1s',minHeight:'44px'};
117 if (lbl === '=') return Object.assign({},base,{background:a.btnEqBg||accent,color:a.btnEqColor||'#fff'});
118 if (['C',''].includes(lbl)) return Object.assign({},base,{background:a.btnClearBg||'#7f1d1d',color:a.btnClearColor||'#fecaca'});
119 if (['MC','MR','MS','M+','M−'].includes(lbl))return Object.assign({},base,{background:a.btnFnBg||'#1e2a4a',color:a.memColor||'#86efac'});
120 if (['+','','×','÷','=','%','','ʸ√x','(',')',].includes(lbl)) return Object.assign({},base,{background:a.btnOpBg||'#3d2d6a',color:a.btnOpColor||'#c4b5fd'});
121 if (['0','1','2','3','4','5','6','7','8','9','.','±'].includes(lbl)) return Object.assign({},base,{background:a.btnNumBg||'#2d2d4a',color:a.btnNumColor||'#fff'});
122 return Object.assign({},base,{background:a.btnFnBg||'#1e2a4a',color:a.btnFnColor||'#93c5fd'});
123 }
124
125 var wrapStyle = {paddingTop:(a.paddingTop||60)+'px',paddingBottom:(a.paddingBottom||60)+'px',background:a.sectionBg||undefined};
126 var cardStyle = {background:a.cardBg||'#1a1a2e',borderRadius:(a.cardRadius||20)+'px',padding:'24px',maxWidth:(a.maxWidth||420)+'px',margin:'0 auto',boxShadow:'0 8px 40px rgba(0,0,0,.45)'};
127
128 return el('div',{style:wrapStyle},
129 (a.showTitle||a.showSubtitle) && el('div',{style:{textAlign:'center',marginBottom:'20px'}},
130 a.showTitle && el('div',{className:'bkbg-sc-title',style:{color:a.titleColor,marginBottom:'6px'}},a.title),
131 a.showSubtitle && el('div',{className:'bkbg-sc-subtitle',style:{color:a.subtitleColor}},a.subtitle)
132 ),
133 el('div',{style:cardStyle},
134 // Angle mode + memory indicator
135 el('div',{style:{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:'8px'}},
136 el('div',{style:{display:'flex',gap:'4px'}},
137 ['deg','rad'].map(function(m){
138 return el('button',{key:m,onClick:function(){setAngleMode(m);},style:{padding:'3px 10px',border:'none',borderRadius:'6px',cursor:'pointer',fontWeight:700,fontSize:'12px',fontFamily:'inherit',background:angleMode===m?(a.accentColor||accent):'rgba(255,255,255,.1)',color:angleMode===m?'#fff':'rgba(255,255,255,.5)'}},m.toUpperCase());
139 })
140 ),
141 a.showMemory && el('div',{style:{fontSize:'12px',color:a.memColor||'#86efac',fontWeight:700}}, memory !== 0 ? 'M: '+memory : '')
142 ),
143 // Expression bar
144 el('div',{style:{textAlign:'right',fontSize:'13px',color:'rgba(255,255,255,.4)',minHeight:'18px',marginBottom:'2px',fontFamily:'ui-monospace,monospace',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}},expr||'\u00a0'),
145 // Display
146 el('div',{style:{background:a.displayBg||'#0d0d1a',borderRadius:'10px',padding:'12px 16px',textAlign:'right',fontSize:(a.displaySize||36)+'px',fontWeight:700,color:a.displayColor||'#fff',fontFamily:'ui-monospace,monospace',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',marginBottom:'14px',minHeight:'64px',display:'flex',alignItems:'center',justifyContent:'flex-end'}},display),
147 // Button grid
148 el('div',{style:{display:'grid',gridTemplateColumns:'repeat(5,1fr)',gap:'6px'}},
149 BTN_LAYOUT.flat().map(function(lbl,i){
150 if (lbl==='') return el('div',{key:i});
151 return el('button',{key:i,onClick:function(){handleBtn(lbl);},style:getBtnStyle(lbl)},lbl);
152 })
153 ),
154 // History
155 a.showHistory && history.length > 0 && el('div',{style:{marginTop:'16px',background:a.historyBg||'#111128',borderRadius:'8px',padding:'10px 12px',maxHeight:'140px',overflowY:'auto'}},
156 el('div',{style:{fontSize:'11px',fontWeight:700,color:'rgba(255,255,255,.3)',textTransform:'uppercase',letterSpacing:'.05em',marginBottom:'6px'}},'History'),
157 history.map(function(h,i){
158 return el('div',{key:i,style:{fontSize:'13px',color:a.historyColor||'#9ca3af',fontFamily:'ui-monospace,monospace',padding:'2px 0',borderBottom:'1px solid rgba(255,255,255,.05)'}},h.expr);
159 })
160 )
161 )
162 );
163 }
164
165 registerBlockType('blockenberg/scientific-calculator', {
166 edit: function(props) {
167 var a = props.attributes; var set = props.setAttributes;
168 var blockProps = useBlockProps((function(){
169 var _tv = getTypoCssVars();
170 var s = {};
171 if(_tv) Object.assign(s, _tv(a.titleTypo||{}, '--bksc-tt-'));
172 if(_tv) Object.assign(s, _tv(a.subtitleTypo||{}, '--bksc-st-'));
173 return { style: s };
174 })());
175 var colorSettings = [
176 {value:a.accentColor, onChange:function(v){set({accentColor:v});}, label:'Accent / Equals Button'},
177 {value:a.cardBg, onChange:function(v){set({cardBg:v});}, label:'Calculator Body'},
178 {value:a.displayBg, onChange:function(v){set({displayBg:v});}, label:'Display Background'},
179 {value:a.displayColor, onChange:function(v){set({displayColor:v});}, label:'Display Text'},
180 {value:a.btnNumBg, onChange:function(v){set({btnNumBg:v});}, label:'Number Button Background'},
181 {value:a.btnNumColor, onChange:function(v){set({btnNumColor:v});}, label:'Number Button Text'},
182 {value:a.btnOpBg, onChange:function(v){set({btnOpBg:v});}, label:'Operator Button Background'},
183 {value:a.btnOpColor, onChange:function(v){set({btnOpColor:v});}, label:'Operator Button Text'},
184 {value:a.btnFnBg, onChange:function(v){set({btnFnBg:v});}, label:'Function Button Background'},
185 {value:a.btnFnColor, onChange:function(v){set({btnFnColor:v});}, label:'Function Button Text'},
186 {value:a.btnEqBg, onChange:function(v){set({btnEqBg:v});}, label:'Equals Button Background'},
187 {value:a.btnEqColor, onChange:function(v){set({btnEqColor:v});}, label:'Equals Button Text'},
188 {value:a.btnClearBg, onChange:function(v){set({btnClearBg:v});}, label:'Clear Button Background'},
189 {value:a.btnClearColor,onChange:function(v){set({btnClearColor:v});}, label:'Clear Button Text'},
190 {value:a.historyBg, onChange:function(v){set({historyBg:v});}, label:'History Background'},
191 {value:a.historyColor, onChange:function(v){set({historyColor:v});}, label:'History Text'},
192 {value:a.memColor, onChange:function(v){set({memColor:v});}, label:'Memory Indicator'},
193 {value:a.titleColor, onChange:function(v){set({titleColor:v});}, label:'Title Color'},
194 {value:a.subtitleColor,onChange:function(v){set({subtitleColor:v});}, label:'Subtitle Color'},
195 {value:a.sectionBg, onChange:function(v){set({sectionBg:v});}, label:'Section Background'}
196 ];
197 return el(Fragment,null,
198 el(InspectorControls,null,
199 el(PanelBody,{title:'Header',initialOpen:false},
200 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Title', checked:a.showTitle, onChange:function(v){set({showTitle:v});}}),
201 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Subtitle',checked:a.showSubtitle,onChange:function(v){set({showSubtitle:v});}}),
202 el(TextControl,{label:'Title', value:a.title, onChange:function(v){set({title:v});}}),
203 el(TextControl,{label:'Subtitle',value:a.subtitle,onChange:function(v){set({subtitle:v});}})
204 ),
205 el(PanelBody,{title:'Calculator Settings',initialOpen:true},
206 el(SelectControl,{label:'Default Angle Mode',value:a.angleMode,options:[{label:'Degrees',value:'deg'},{label:'Radians',value:'rad'}],onChange:function(v){set({angleMode:v});}}),
207 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Memory Buttons',checked:a.showMemory, onChange:function(v){set({showMemory:v});}}),
208 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show History', checked:a.showHistory, onChange:function(v){set({showHistory:v});}}),
209 el(RangeControl,{label:'History Max Entries',value:a.historyMax,min:3,max:20,step:1,onChange:function(v){set({historyMax:v});}}),
210 el(RangeControl,{label:'Calculation Precision',value:a.precision,min:4,max:14,step:1,onChange:function(v){set({precision:v});}})
211 ),
212
213 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
214 getTypoControl() && el(getTypoControl(), { label: __('Title Typography','blockenberg'), value: a.titleTypo||{}, onChange: function(v){ set({titleTypo:v}); } }),
215 getTypoControl() && el(getTypoControl(), { label: __('Subtitle Typography','blockenberg'), value: a.subtitleTypo||{}, onChange: function(v){ set({subtitleTypo:v}); } }),
216 el(RangeControl,{label:'Display Font Size',value:a.displaySize, min:18,max:64,step:2, onChange:function(v){set({displaySize:v});}}),
217 el(RangeControl,{label:'Button Font Size', value:a.btnSize, min:11,max:22,step:1, onChange:function(v){set({btnSize:v});}})
218 ),
219 el(PanelColorSettings,{title:'Colors',initialOpen:false,colorSettings:colorSettings}),
220 el(PanelBody,{title:'Sizing & Layout',initialOpen:false},
221 el(RangeControl,{label:'Card Border Radius',value:a.cardRadius, min:0, max:40,step:1, onChange:function(v){set({cardRadius:v});}}),
222 el(RangeControl,{label:'Button Radius', value:a.btnRadius, min:0, max:20,step:1, onChange:function(v){set({btnRadius:v});}}),
223 el(RangeControl,{label:'Max Width (px)', value:a.maxWidth, min:320,max:640,step:10,onChange:function(v){set({maxWidth:v});}}),
224 el(RangeControl,{label:'Padding Top', value:a.paddingTop, min:0, max:160,step:4, onChange:function(v){set({paddingTop:v});}}),
225 el(RangeControl,{label:'Padding Bottom', value:a.paddingBottom,min:0,max:160,step:4, onChange:function(v){set({paddingBottom:v});}})
226 )
227 ),
228 el('div',blockProps, el(ScientificCalcPreview,{attributes:a}))
229 );
230 },
231 save: function(props){
232 var a = props.attributes;
233 return el('div',wp.blockEditor.useBlockProps.save(),
234 el('div',{className:'bkbg-sc-app','data-opts':JSON.stringify(a)}));
235 }
236 });
237 }() );
238