PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.13
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.13
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 / url-encoder / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.13, at blocks/url-encoder/index.js

215 lines 15.1 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 TextareaControl = wp.components.TextareaControl;
15 var ToggleControl = wp.components.ToggleControl;
16
17 // Resolve the shared components lazily without defining globals for each block.
18 function _tc(label, key, attrs, setA) {
19 var Control = window.bkbgTypographyControl;
20 return Control ? el(Control, {
21 label: label,
22 value: attrs[key] || {},
23 onChange: function (value) { var update = {}; update[key] = value; setA(update); }
24 }) : null;
25 }
26 function _tvf(vars, key, attrs, prefix) {
27 var cssVars = window.bkbgTypoCssVars;
28 if (cssVars) Object.assign(vars, cssVars(attrs[key] || {}, prefix));
29 return vars;
30 }
31 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
32 function getTypoCssVars(attrs) {
33 var v = {};
34 _tvf(v, 'titleTypo', attrs, '--bkue-tt-');
35 _tvf(v, 'subtitleTypo', attrs, '--bkue-st-');
36 return v;
37 }
38
39 var TABS = [
40 {id:'encode', label:'URL Encode'},
41 {id:'decode', label:'URL Decode'},
42 {id:'b64', label:'Base64'}
43 ];
44
45 function urlEncode(text) { return encodeURIComponent(text); }
46 function urlDecode(text) { try { return decodeURIComponent(text); } catch(e){ return null; } }
47 function b64Encode(text) { try { return btoa(unescape(encodeURIComponent(text))); } catch(e){ return null; } }
48 function b64Decode(text) { try { return decodeURIComponent(escape(atob(text))); } catch(e){ return null; } }
49
50 function process(mode, text) {
51 if (!text) return {result:'', error:''};
52 if (mode === 'encode') return {result: urlEncode(text), error:''};
53 if (mode === 'decode') {
54 var r = urlDecode(text);
55 return r === null ? {result:'', error:'Invalid URI sequence — cannot decode.'} : {result:r, error:''};
56 }
57 if (mode === 'b64') {
58 var enc = b64Encode(text);
59 return enc === null ? {result:'', error:'Encoding failed.'} : {result:enc, error:''};
60 }
61 if (mode === 'b64dec') {
62 var dec = b64Decode(text);
63 return dec === null ? {result:'', error:'Invalid Base64 string — cannot decode.'} : {result:dec, error:''};
64 }
65 return {result:'', error:''};
66 }
67
68 function UEPreview(props) {
69 var a = props.attributes;
70 var accent = a.accentColor || '#6c3fb5';
71
72 var _tab = useState(a.defaultMode || 'encode');
73 var tab = _tab[0]; var setTab = _tab[1];
74
75 var _sub = useState('enc'); // enc | dec (for b64 sub-mode)
76 var b64Sub = _sub[0]; var setB64Sub = _sub[1];
77
78 var _txt = useState(a.defaultText || '');
79 var text = _txt[0]; var setText = _txt[1];
80
81 var activeMode = tab === 'b64' ? (b64Sub === 'enc' ? 'b64' : 'b64dec') : tab;
82 var proc = process(activeMode, text);
83
84 var tabs = a.showBase64Tab ? TABS : TABS.slice(0,2);
85
86 var tabBarStyle = {display:'flex',gap:'4px',marginBottom:'18px',background:a.tabInactiveBg||'#f3f4f6',borderRadius:(a.tabRadius||8)+'px',padding:'4px'};
87 var inpStyle = {width:'100%',padding:'10px 12px',borderRadius:(a.inputRadius||10)+'px',border:'1.5px solid '+(a.inputBorder||'#e5e7eb'),background:a.inputBg||'#f9fafb',color:a.inputColor||'#1f2937',fontSize:'14px',fontFamily:'ui-monospace,monospace',resize:'vertical',minHeight:((a.textareaRows||5)*1.6+2.5)+'em',boxSizing:'border-box',outline:'none',lineHeight:1.6};
88 var outStyle = Object.assign({},inpStyle,{background:a.outputBg||'#f3f4f6',border:'1.5px solid '+(a.outputBorder||'#e5e7eb'),color:a.outputColor||'#1f2937',cursor:'text',userSelect:'all'});
89 var lblStyle = {display:'block',fontSize:'12px',fontWeight:600,color:a.labelColor||'#374151',marginBottom:'5px'};
90 var btnStyle = {padding:'8px 18px',background:accent,color:a.btnColor||'#fff',border:'none',borderRadius:(a.inputRadius||10)+'px',fontWeight:700,cursor:'pointer',fontSize:'13px',fontFamily:'inherit'};
91
92 return el('div',{style:{paddingTop:(a.paddingTop||60)+'px',paddingBottom:(a.paddingBottom||60)+'px',background:a.sectionBg||undefined}},
93 el('div',{style:{background:a.cardBg||'#fff',borderRadius:(a.cardRadius||16)+'px',padding:'32px',maxWidth:(a.maxWidth||680)+'px',margin:'0 auto',boxShadow:'0 4px 24px rgba(0,0,0,.09)'}},
94
95 (a.showTitle || a.showSubtitle) && el('div',{style:{marginBottom:'22px'}},
96 a.showTitle && el('div',{className:'bkbg-ue-title',style:{color:a.titleColor||'#1e1b4b'}},a.title),
97 a.showSubtitle && el('div',{className:'bkbg-ue-subtitle',style:{color:a.subtitleColor||'#6b7280'}},a.subtitle)
98 ),
99
100 // Tab bar
101 el('div',{style:tabBarStyle},
102 tabs.map(function(t){
103 var active = tab===t.id;
104 return el('button',{key:t.id,onClick:function(){setTab(t.id);setText('');},style:{flex:1,padding:'8px',borderRadius:(a.tabRadius||8)+'px',border:'none',cursor:'pointer',fontWeight:active?700:500,fontSize:'14px',fontFamily:'inherit',background:active?(a.tabActiveBg||accent):(a.tabInactiveBg||'transparent'),color:active?(a.tabActiveColor||'#fff'):(a.tabInactiveColor||'#6b7280'),transition:'all .2s'}},t.label);
105 })
106 ),
107
108 // Base64 sub-mode
109 tab==='b64' && el('div',{style:{display:'flex',gap:'6px',marginBottom:'14px'}},
110 el('button',{onClick:function(){setB64Sub('enc');setText('');},style:{padding:'5px 14px',borderRadius:'6px',border:'1.5px solid '+(b64Sub==='enc'?accent:'#d1d5db'),background:b64Sub==='enc'?accent+'18':'#fff',color:b64Sub==='enc'?accent:'#6b7280',fontWeight:b64Sub==='enc'?700:400,cursor:'pointer',fontSize:'13px',fontFamily:'inherit'}},'Encode'),
111 el('button',{onClick:function(){setB64Sub('dec');setText('');},style:{padding:'5px 14px',borderRadius:'6px',border:'1.5px solid '+(b64Sub==='dec'?accent:'#d1d5db'),background:b64Sub==='dec'?accent+'18':'#fff',color:b64Sub==='dec'?accent:'#6b7280',fontWeight:b64Sub==='dec'?700:400,cursor:'pointer',fontSize:'13px',fontFamily:'inherit'}},'Decode')
112 ),
113
114 // Input
115 el('div',{style:{marginBottom:'16px'}},
116 el('label',{style:lblStyle},tab==='b64'?'Input Text':(tab==='encode'?'Text to Encode':'Encoded URL')),
117 el('textarea',{value:text,onChange:function(e){setText(e.target.value);},placeholder:a.defaultText,rows:a.textareaRows||5,style:inpStyle})
118 ),
119
120 // Char count
121 a.showCharCount && el('div',{style:{textAlign:'right',fontSize:'12px',color:'#9ca3af',marginTop:'-12px',marginBottom:'12px'}},
122 (text||'').length,' characters'
123 ),
124
125 // Error
126 proc.error && el('div',{style:{background:a.errorBg||'#fef2f2',border:'1px solid '+(a.errorColor||'#ef4444'),color:a.errorColor||'#ef4444',padding:'10px 14px',borderRadius:'8px',fontSize:'14px',marginBottom:'12px'}},proc.error),
127
128 // Output
129 el('div',{style:{marginBottom:'14px'}},
130 el('label',{style:lblStyle},'Result'),
131 el('textarea',{readOnly:true,value:proc.result,rows:a.textareaRows||5,style:outStyle})
132 ),
133
134 a.showCharCount && el('div',{style:{textAlign:'right',fontSize:'12px',color:'#9ca3af',marginTop:'-10px',marginBottom:'12px'}},
135 (proc.result||'').length,' characters'
136 ),
137
138 // Buttons row
139 el('div',{style:{display:'flex',gap:'8px',flexWrap:'wrap'}},
140 a.showCopyButton && el('button',{style:btnStyle},'Copy Result'),
141 a.showClearButton && el('button',{onClick:function(){setText('');},style:{...btnStyle,background:'#f3f4f6',color:'#374151'}},'Clear')
142 )
143 )
144 );
145 }
146
147 registerBlockType('blockenberg/url-encoder', {
148 edit: function(props) {
149 var a = props.attributes; var set = props.setAttributes;
150 var blockProps = useBlockProps((function () { var _tv = getTypoCssVars(a); return { style: _tv }; })());
151 var colorSettings = [
152 {value:a.accentColor, onChange:function(v){set({accentColor:v});}, label:'Accent Color'},
153 {value:a.cardBg, onChange:function(v){set({cardBg:v});}, label:'Card Background'},
154 {value:a.tabActiveBg, onChange:function(v){set({tabActiveBg:v});}, label:'Active Tab Background'},
155 {value:a.tabActiveColor, onChange:function(v){set({tabActiveColor:v});}, label:'Active Tab Text'},
156 {value:a.tabInactiveBg, onChange:function(v){set({tabInactiveBg:v});}, label:'Inactive Tab Background'},
157 {value:a.tabInactiveColor, onChange:function(v){set({tabInactiveColor:v});}, label:'Inactive Tab Text'},
158 {value:a.inputBg, onChange:function(v){set({inputBg:v});}, label:'Input Background'},
159 {value:a.inputBorder, onChange:function(v){set({inputBorder:v});}, label:'Input Border'},
160 {value:a.inputColor, onChange:function(v){set({inputColor:v});}, label:'Input Text Color'},
161 {value:a.outputBg, onChange:function(v){set({outputBg:v});}, label:'Output Background'},
162 {value:a.outputBorder, onChange:function(v){set({outputBorder:v});}, label:'Output Border'},
163 {value:a.outputColor, onChange:function(v){set({outputColor:v});}, label:'Output Text Color'},
164 {value:a.errorColor, onChange:function(v){set({errorColor:v});}, label:'Error Text Color'},
165 {value:a.errorBg, onChange:function(v){set({errorBg:v});}, label:'Error Background'},
166 {value:a.btnBg, onChange:function(v){set({btnBg:v});}, label:'Button Background'},
167 {value:a.btnColor, onChange:function(v){set({btnColor:v});}, label:'Button Text'},
168 {value:a.labelColor, onChange:function(v){set({labelColor:v});}, label:'Label Color'},
169 {value:a.titleColor, onChange:function(v){set({titleColor:v});}, label:'Title Color'},
170 {value:a.subtitleColor, onChange:function(v){set({subtitleColor:v});}, label:'Subtitle Color'},
171 {value:a.sectionBg, onChange:function(v){set({sectionBg:v});}, label:'Section Background'}
172 ];
173 return el(Fragment, null,
174 el(InspectorControls, null,
175 el(PanelBody,{title:'Header',initialOpen:false},
176 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Title', checked:a.showTitle, onChange:function(v){set({showTitle:v});}}),
177 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Subtitle',checked:a.showSubtitle,onChange:function(v){set({showSubtitle:v});}}),
178 el(TextControl,{label:'Title', value:a.title, onChange:function(v){set({title:v});}}),
179 el(TextControl,{label:'Subtitle',value:a.subtitle,onChange:function(v){set({subtitle:v});}})
180 ),
181 el(PanelBody,{title:'Encoder Settings',initialOpen:true},
182 el(SelectControl,{label:'Default Tab',value:a.defaultMode,options:[{label:'URL Encode',value:'encode'},{label:'URL Decode',value:'decode'},{label:'Base64',value:'b64'}],onChange:function(v){set({defaultMode:v});}}),
183 el(TextareaControl,{label:'Default Input Text',value:a.defaultText,onChange:function(v){set({defaultText:v});},rows:3}),
184 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Base64 Tab', checked:a.showBase64Tab, onChange:function(v){set({showBase64Tab:v});}}),
185 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Copy Button', checked:a.showCopyButton, onChange:function(v){set({showCopyButton:v});}}),
186 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Clear Button', checked:a.showClearButton,onChange:function(v){set({showClearButton:v});}}),
187 el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Char Count', checked:a.showCharCount, onChange:function(v){set({showCharCount:v});}})
188 ),
189
190 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
191 getTypoControl(__('Title', 'blockenberg'), 'titleTypo', a, set),
192 getTypoControl(__('Subtitle', 'blockenberg'), 'subtitleTypo', a, set)
193 ),
194 el(PanelColorSettings,{title:'Colors',initialOpen:false,colorSettings:colorSettings}),
195 el(PanelBody,{title:'Sizing & Layout',initialOpen:false},
196 el(RangeControl,{label:'Textarea Rows', value:a.textareaRows, min:3, max:16,step:1, onChange:function(v){set({textareaRows:v});}}),
197 el(RangeControl,{label:'Card Border Radius',value:a.cardRadius, min:0, max:40,step:1, onChange:function(v){set({cardRadius:v});}}),
198 el(RangeControl,{label:'Input Border Radius',value:a.inputRadius, min:0, max:20,step:1, onChange:function(v){set({inputRadius:v});}}),
199 el(RangeControl,{label:'Tab Border Radius', value:a.tabRadius, min:0, max:20,step:1, onChange:function(v){set({tabRadius:v});}}),
200 el(RangeControl,{label:'Max Width (px)', value:a.maxWidth, min:360,max:1100,step:10,onChange:function(v){set({maxWidth:v});}}),
201 el(RangeControl,{label:'Padding Top', value:a.paddingTop, min:0, max:160,step:4, onChange:function(v){set({paddingTop:v});}}),
202 el(RangeControl,{label:'Padding Bottom', value:a.paddingBottom,min:0, max:160,step:4, onChange:function(v){set({paddingBottom:v});}})
203 )
204 ),
205 el('div', blockProps, el(UEPreview, {attributes:a}))
206 );
207 },
208 save: function(props) {
209 var a = props.attributes;
210 return el('div', wp.blockEditor.useBlockProps.save((function () { var _tv = getTypoCssVars(a); return { style: _tv }; })()),
211 el('div',{className:'bkbg-ue-app','data-opts':JSON.stringify(a)}));
212 }
213 });
214 }() );
215