| 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 MORSE_MAP = { |
| 21 |
'A':'.-','B':'-...','C':'-.-.','D':'-..','E':'.','F':'..-.','G':'--.','H':'....','I':'..','J':'.---', |
| 22 |
'K':'-.-','L':'.-..','M':'--','N':'-.','O':'---','P':'.--.','Q':'--.-','R':'.-.','S':'...','T':'-', |
| 23 |
'U':'..-','V':'...-','W':'.--','X':'-..-','Y':'-.--','Z':'--..', |
| 24 |
'0':'-----','1':'.----','2':'..---','3':'...--','4':'....-','5':'.....','6':'-....','7':'--...','8':'---..','9':'----.', |
| 25 |
' ':'/' |
| 26 |
}; |
| 27 |
var REVERSE_MAP = {}; |
| 28 |
Object.keys(MORSE_MAP).forEach(function(k){ REVERSE_MAP[MORSE_MAP[k]] = k; }); |
| 29 |
|
| 30 |
function toMorse(text) { |
| 31 |
return text.toUpperCase().split('').map(function(c){ |
| 32 |
return MORSE_MAP[c] || ''; |
| 33 |
}).join(' ').replace(/ +/g,' '); |
| 34 |
} |
| 35 |
|
| 36 |
function fromMorse(morse) { |
| 37 |
return morse.trim().split(' / ').map(function(word){ |
| 38 |
return word.trim().split(' ').map(function(code){ |
| 39 |
return REVERSE_MAP[code.trim()] || ''; |
| 40 |
}).join(''); |
| 41 |
}).join(' '); |
| 42 |
} |
| 43 |
|
| 44 |
function MCPreview(props) { |
| 45 |
var a = props.attributes; |
| 46 |
var accent = a.accentColor || '#6c3fb5'; |
| 47 |
var _mode = useState(a.defaultMode || 'encode'); var mode = _mode[0]; var setMode = _mode[1]; |
| 48 |
var _input = useState(a.defaultText || 'Hello World'); var input = _input[0]; var setInput = _input[1]; |
| 49 |
|
| 50 |
var output = mode === 'encode' ? toMorse(input) : fromMorse(input); |
| 51 |
|
| 52 |
var tabStyle = function(active) { return { |
| 53 |
padding: '8px 22px', border: 'none', cursor: 'pointer', |
| 54 |
fontWeight: 700, fontSize: '14px', fontFamily: 'inherit', |
| 55 |
transition: 'all .15s', |
| 56 |
background: active ? (a.tabActiveBg || accent) : (a.tabInactiveBg || '#f3f4f6'), |
| 57 |
color: active ? (a.tabActiveColor || '#fff') : (a.tabInactiveColor || '#374151') |
| 58 |
}; }; |
| 59 |
|
| 60 |
var CHARS = Object.keys(MORSE_MAP).filter(function(k){ return k !== ' '; }); |
| 61 |
|
| 62 |
return el('div', {style:{paddingTop:(a.paddingTop||60)+'px',paddingBottom:(a.paddingBottom||60)+'px',background:a.sectionBg||undefined}}, |
| 63 |
el('div', {style:{background:a.cardBg,borderRadius:(a.cardRadius||16)+'px',padding:'32px',maxWidth:(a.maxWidth||620)+'px',margin:'0 auto',boxShadow:'0 4px 24px rgba(0,0,0,.09)'}}, |
| 64 |
|
| 65 |
(a.showTitle||a.showSubtitle) && el('div',{className:'bkbg-mcc-header'}, |
| 66 |
a.showTitle && el('div',{className:'bkbg-mcc-title',style:{color:a.titleColor}},a.title), |
| 67 |
a.showSubtitle && el('div',{className:'bkbg-mcc-subtitle',style:{color:a.subtitleColor}},a.subtitle) |
| 68 |
), |
| 69 |
|
| 70 |
// Mode tabs |
| 71 |
el('div',{style:{display:'flex',borderRadius:'10px',overflow:'hidden',border:'1.5px solid '+(a.inputBorder||'#e5e7eb'),marginBottom:'16px',width:'fit-content'}}, |
| 72 |
el('button',{style:tabStyle(mode==='encode'),onClick:function(){setMode('encode');setInput(a.defaultText||'Hello World');}}, 'Text → Morse'), |
| 73 |
el('button',{style:tabStyle(mode==='decode'),onClick:function(){setMode('decode');setInput(toMorse(a.defaultText||'Hello World'));}}, 'Morse → Text') |
| 74 |
), |
| 75 |
|
| 76 |
// Input |
| 77 |
el('div',{style:{marginBottom:'12px'}}, |
| 78 |
el('label',{style:{display:'block',fontSize:'12px',fontWeight:600,color:a.labelColor||'#374151',textTransform:'uppercase',letterSpacing:'.05em',marginBottom:'5px'}}, |
| 79 |
mode==='encode' ? 'Enter Text' : 'Enter Morse Code (use / between words)'), |
| 80 |
el('textarea',{ |
| 81 |
value:input, rows:3, |
| 82 |
onChange:function(e){setInput(e.target.value);}, |
| 83 |
style:{width:'100%',padding:'10px 12px',border:'1.5px solid '+(a.inputBorder||'#e5e7eb'),borderRadius:(a.inputRadius||8)+'px',fontSize:'15px',fontFamily:'inherit',resize:'vertical',outline:'none',boxSizing:'border-box'} |
| 84 |
}) |
| 85 |
), |
| 86 |
|
| 87 |
// Output |
| 88 |
el('div',{style:{background:a.outputBg||'#f5f3ff',border:'1.5px solid '+(a.outputBorder||'#ede9fe'),borderRadius:(a.inputRadius||8)+'px',padding:'14px 16px',marginBottom:'14px',minHeight:'60px'}}, |
| 89 |
el('div',{style:{fontSize:'11px',fontWeight:700,color:a.labelColor||'#374151',textTransform:'uppercase',letterSpacing:'.05em',marginBottom:'6px'}},mode==='encode'?'Morse Code':'Decoded Text'), |
| 90 |
el('div',{className:'bkbg-mcc-output-text',style:{color:a.outputColor||'#3b0764'}}, |
| 91 |
output || el('span',{style:{opacity:.4,fontStyle:'italic',fontFamily:'inherit'}},'Output will appear here…')) |
| 92 |
), |
| 93 |
|
| 94 |
// Action buttons row |
| 95 |
(a.showCopyButton || a.showPlayButton) && el('div',{style:{display:'flex',gap:'8px',marginBottom:'20px'}}, |
| 96 |
a.showCopyButton && el('button',{onClick:function(){},style:{padding:'8px 18px',background:accent,color:'#fff',border:'none',borderRadius:'8px',fontWeight:700,cursor:'pointer',fontSize:'13px',fontFamily:'inherit'}}, '📋 Copy'), |
| 97 |
a.showPlayButton && el('button',{onClick:function(){},style:{padding:'8px 18px',background:'#f3f4f6',color:'#374151',border:'1.5px solid #e5e7eb',borderRadius:'8px',fontWeight:700,cursor:'pointer',fontSize:'13px',fontFamily:'inherit'}}, '🔊 Play Audio') |
| 98 |
), |
| 99 |
|
| 100 |
// Reference table |
| 101 |
a.showReference && el('details',{style:{border:'1px solid '+(a.refBorder||'#e5e7eb'),borderRadius:'10px',overflow:'hidden'}}, |
| 102 |
el('summary',{style:{padding:'10px 16px',fontWeight:700,fontSize:'13px',color:a.labelColor||'#374151',cursor:'pointer',background:a.refBg||'#f9fafb',userSelect:'none'}}, 'Morse Code Reference (A–Z, 0–9)'), |
| 103 |
el('div',{style:{padding:'12px 16px',display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(80px,1fr))',gap:'5px',background:a.refBg||'#f9fafb'}}, |
| 104 |
CHARS.map(function(c){ |
| 105 |
return el('div',{key:c,style:{textAlign:'center',padding:'5px 2px',borderRadius:'6px',background:'#fff',border:'1px solid '+(a.refBorder||'#e5e7eb')}}, |
| 106 |
el('div',{style:{fontWeight:800,fontSize:'14px',color:accent}},c), |
| 107 |
el('div',{style:{fontFamily:'monospace',fontSize:'11px',color:'#6b7280',marginTop:'2px'}},MORSE_MAP[c]) |
| 108 |
); |
| 109 |
}) |
| 110 |
) |
| 111 |
) |
| 112 |
) |
| 113 |
); |
| 114 |
} |
| 115 |
|
| 116 |
registerBlockType('blockenberg/morse-code-converter', { |
| 117 |
edit: function(props) { |
| 118 |
var a = props.attributes; var set = props.setAttributes; |
| 119 |
var blockProps = useBlockProps((function () { |
| 120 |
var _tvf = getTypoCssVars(); |
| 121 |
var s = {}; |
| 122 |
Object.assign(s, _tvf(a.titleTypo, '--bkbg-mcc-tt-')); |
| 123 |
Object.assign(s, _tvf(a.subtitleTypo, '--bkbg-mcc-st-')); |
| 124 |
Object.assign(s, _tvf(a.outputTypo, '--bkbg-mcc-ot-')); |
| 125 |
return { style: s }; |
| 126 |
})()); |
| 127 |
var colorSettings = [ |
| 128 |
{value:a.accentColor, onChange:function(v){set({accentColor:v});}, label:'Accent Color'}, |
| 129 |
{value:a.cardBg, onChange:function(v){set({cardBg:v});}, label:'Card Background'}, |
| 130 |
{value:a.outputBg, onChange:function(v){set({outputBg:v});}, label:'Output Background'}, |
| 131 |
{value:a.outputBorder, onChange:function(v){set({outputBorder:v});}, label:'Output Border'}, |
| 132 |
{value:a.outputColor, onChange:function(v){set({outputColor:v});}, label:'Output Text Color'}, |
| 133 |
{value:a.tabActiveBg, onChange:function(v){set({tabActiveBg:v});}, label:'Active Tab Background'}, |
| 134 |
{value:a.tabActiveColor, onChange:function(v){set({tabActiveColor:v});}, label:'Active Tab Text'}, |
| 135 |
{value:a.tabInactiveBg, onChange:function(v){set({tabInactiveBg:v});}, label:'Inactive Tab Background'}, |
| 136 |
{value:a.tabInactiveColor, onChange:function(v){set({tabInactiveColor:v});}, label:'Inactive Tab Text'}, |
| 137 |
{value:a.refBg, onChange:function(v){set({refBg:v});}, label:'Reference Background'}, |
| 138 |
{value:a.refBorder, onChange:function(v){set({refBorder:v});}, label:'Reference Border'}, |
| 139 |
{value:a.inputBorder, onChange:function(v){set({inputBorder:v});}, label:'Input Border'}, |
| 140 |
{value:a.labelColor, onChange:function(v){set({labelColor:v});}, label:'Label Color'}, |
| 141 |
{value:a.titleColor, onChange:function(v){set({titleColor:v});}, label:'Title Color'}, |
| 142 |
{value:a.subtitleColor, onChange:function(v){set({subtitleColor:v});}, label:'Subtitle Color'}, |
| 143 |
{value:a.sectionBg, onChange:function(v){set({sectionBg:v});}, label:'Section Background'} |
| 144 |
]; |
| 145 |
return el(Fragment, null, |
| 146 |
el(InspectorControls, null, |
| 147 |
el(PanelBody,{title:'Header',initialOpen:false}, |
| 148 |
el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Title', checked:a.showTitle, onChange:function(v){set({showTitle:v});}}), |
| 149 |
el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Subtitle',checked:a.showSubtitle,onChange:function(v){set({showSubtitle:v});}}), |
| 150 |
el(TextControl,{label:'Title', value:a.title, onChange:function(v){set({title:v});}}), |
| 151 |
el(TextControl,{label:'Subtitle',value:a.subtitle,onChange:function(v){set({subtitle:v});}}) |
| 152 |
), |
| 153 |
el(PanelBody,{title:'Converter Settings',initialOpen:true}, |
| 154 |
el(SelectControl,{label:'Default Mode',value:a.defaultMode,options:[{label:'Text → Morse (Encode)',value:'encode'},{label:'Morse → Text (Decode)',value:'decode'}],onChange:function(v){set({defaultMode:v});}}), |
| 155 |
el(TextControl,{label:'Default Input Text',value:a.defaultText,onChange:function(v){set({defaultText:v});}}), |
| 156 |
el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Copy Button', checked:a.showCopyButton, onChange:function(v){set({showCopyButton:v});}}), |
| 157 |
el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Play Audio Button',checked:a.showPlayButton,onChange:function(v){set({showPlayButton:v});}}), |
| 158 |
el(ToggleControl,{__nextHasNoMarginBottom:true,label:'Show Reference Table', checked:a.showReference, onChange:function(v){set({showReference:v});}}) |
| 159 |
), |
| 160 |
|
| 161 |
el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false }, |
| 162 |
el(getTypoControl(), { label: __('Title', 'blockenberg'), value: a.titleTypo, onChange: function (v) { set({ titleTypo: v }); } }), |
| 163 |
el(getTypoControl(), { label: __('Subtitle', 'blockenberg'), value: a.subtitleTypo, onChange: function (v) { set({ subtitleTypo: v }); } }), |
| 164 |
el(getTypoControl(), { label: __('Output', 'blockenberg'), value: a.outputTypo, onChange: function (v) { set({ outputTypo: v }); } }) |
| 165 |
), |
| 166 |
el(PanelColorSettings,{title:'Colors',initialOpen:false,colorSettings:colorSettings}), |
| 167 |
el(PanelBody,{title:'Sizing & Layout',initialOpen:false}, |
| 168 |
el(RangeControl,{label:'Card Border Radius',value:a.cardRadius, min:0, max:40,step:1, onChange:function(v){set({cardRadius:v});}}), |
| 169 |
el(RangeControl,{label:'Input Border Radius',value:a.inputRadius, min:0, max:20,step:1, onChange:function(v){set({inputRadius:v});}}), |
| 170 |
el(RangeControl,{label:'Max Width (px)', value:a.maxWidth, min:360,max:1000,step:10,onChange:function(v){set({maxWidth:v});}}), |
| 171 |
el(RangeControl,{label:'Padding Top', value:a.paddingTop, min:0, max:160,step:4, onChange:function(v){set({paddingTop:v});}}), |
| 172 |
el(RangeControl,{label:'Padding Bottom', value:a.paddingBottom, min:0, max:160,step:4, onChange:function(v){set({paddingBottom:v});}}) |
| 173 |
) |
| 174 |
), |
| 175 |
el('div', blockProps, el(MCPreview, {attributes:a})) |
| 176 |
); |
| 177 |
}, |
| 178 |
deprecated: [{ |
| 179 |
save: function(props) { |
| 180 |
var a = props.attributes; |
| 181 |
return el('div', wp.blockEditor.useBlockProps.save(), |
| 182 |
el('div',{className:'bkbg-mcc-app','data-opts':JSON.stringify(a)})); |
| 183 |
} |
| 184 |
}], |
| 185 |
|
| 186 |
save: function(props) { |
| 187 |
var a = props.attributes; |
| 188 |
var blockProps = wp.blockEditor.useBlockProps.save((function () { |
| 189 |
var _tvf = getTypoCssVars(); |
| 190 |
var s = {}; |
| 191 |
Object.assign(s, _tvf(a.titleTypo, '--bkbg-mcc-tt-')); |
| 192 |
Object.assign(s, _tvf(a.subtitleTypo, '--bkbg-mcc-st-')); |
| 193 |
Object.assign(s, _tvf(a.outputTypo, '--bkbg-mcc-ot-')); |
| 194 |
return { style: s }; |
| 195 |
})()); |
| 196 |
return el('div', blockProps, |
| 197 |
el('div',{className:'bkbg-mcc-app','data-opts':JSON.stringify(a)})); |
| 198 |
} |
| 199 |
}); |
| 200 |
}() ); |
| 201 |
|