| 1 |
( function () { |
| 2 |
const el = window.wp.element.createElement; |
| 3 |
const { registerBlockType } = window.wp.blocks; |
| 4 |
const { InspectorControls, PanelColorSettings } = window.wp.blockEditor; |
| 5 |
const { PanelBody, TextControl, ToggleControl, Button, RangeControl } = window.wp.components; |
| 6 |
const { __ } = window.wp.i18n; |
| 7 |
|
| 8 |
function getTypographyControl() { return (window.bkbgTypographyControl || function () { return null; }); } |
| 9 |
function getTypoCssVars() { return (window.bkbgTypoCssVars || function () { return {}; }); } |
| 10 |
function _tv(typo, prefix) { var fn = getTypoCssVars(); return fn(typo || {}, prefix); } |
| 11 |
|
| 12 |
function CellValue({ val, checkColor, crossColor }) { |
| 13 |
if ( val === 'true' ) return el('span',{className:'bkct-check',style:{color:checkColor}},'✓'); |
| 14 |
if ( val === 'false' ) return el('span',{className:'bkct-cross',style:{color:crossColor}},'✕'); |
| 15 |
return el('span',{className:'bkct-text'}, val); |
| 16 |
} |
| 17 |
|
| 18 |
registerBlockType('blockenberg/comparison-table', { |
| 19 |
edit: function(props) { |
| 20 |
const {attributes:attr,setAttributes}=props; |
| 21 |
|
| 22 |
function updatePlan(i,key,val){ const p=attr.plans.slice();p[i]=Object.assign({},p[i],{[key]:val});setAttributes({plans:p}); } |
| 23 |
function addPlan(){ setAttributes({plans:[...attr.plans,{name:'New Plan',subtitle:'',highlighted:false}],features:attr.features.map(f=>({...f,values:[...f.values,'']}))}); } |
| 24 |
function removePlan(i){ setAttributes({plans:attr.plans.filter((_,x)=>x!==i),features:attr.features.map(f=>({...f,values:f.values.filter((_,x)=>x!==i)}))}); } |
| 25 |
|
| 26 |
function updateFeature(i,key,val){ const f=attr.features.slice();f[i]=Object.assign({},f[i],{[key]:val});setAttributes({features:f}); } |
| 27 |
function updateCell(fi,pi,val){ const f=attr.features.slice();const v=f[fi].values.slice();v[pi]=val;f[fi]={...f[fi],values:v};setAttributes({features:f}); } |
| 28 |
function addFeature(){ setAttributes({features:[...attr.features,{label:'New Feature',values:attr.plans.map(()=>'')}]}); } |
| 29 |
function removeFeature(i){ setAttributes({features:attr.features.filter((_,x)=>x!==i)}); } |
| 30 |
|
| 31 |
const tableStyle=Object.assign({ |
| 32 |
'--bkct-header-bg':attr.headerBg,'--bkct-header-text':attr.headerText, |
| 33 |
'--bkct-hl-bg':attr.highlightBg,'--bkct-hl-border':attr.highlightBorder, |
| 34 |
'--bkct-check':attr.checkColor,'--bkct-cross':attr.crossColor, |
| 35 |
'--bkct-radius':attr.borderRadius+'px', |
| 36 |
borderRadius:attr.borderRadius+'px',overflow:'hidden', |
| 37 |
}, _tv(attr.typoHeader, '--bkct-th-'), _tv(attr.typoCell, '--bkct-td-')); |
| 38 |
|
| 39 |
return el('div',{className:'bkct-wrap',style:tableStyle}, |
| 40 |
|
| 41 |
el(InspectorControls,null, |
| 42 |
el(PanelBody,{title:__('Plans (Columns)'),initialOpen:true}, |
| 43 |
attr.plans.map((plan,i)=>el('div',{key:i,style:{border:'1px solid #ddd',borderRadius:'8px',padding:'10px',marginBottom:'8px',background:'#fafafa'}}, |
| 44 |
el(TextControl,{label:__('Plan Name'),value:plan.name,onChange:v=>updatePlan(i,'name',v)}), |
| 45 |
el(TextControl,{label:__('Subtitle / Price'),value:plan.subtitle,onChange:v=>updatePlan(i,'subtitle',v)}), |
| 46 |
el(ToggleControl,{label:__('Highlighted (Popular)'),checked:plan.highlighted,onChange:v=>updatePlan(i,'highlighted',v),__nextHasNoMarginBottom:true}), |
| 47 |
el(Button,{isDestructive:true,isSmall:true,onClick:()=>removePlan(i)},__('Remove Plan')) |
| 48 |
)), |
| 49 |
el(Button,{variant:'secondary',onClick:addPlan,style:{width:'100%',justifyContent:'center',marginTop:'8px'}},__('+ Add Plan')) |
| 50 |
), |
| 51 |
el(PanelBody,{title:__('Features (Rows)'),initialOpen:false}, |
| 52 |
el('p',{style:{fontSize:'12px',color:'#888',marginTop:0}},__('Use "true" / "false" for ✓ / ✕, or type any text value.')), |
| 53 |
attr.features.map((feat,fi)=>el('div',{key:fi,style:{border:'1px solid #ddd',borderRadius:'8px',padding:'10px',marginBottom:'8px',background:'#fafafa'}}, |
| 54 |
el(TextControl,{label:__('Feature Label'),value:feat.label,onChange:v=>updateFeature(fi,'label',v)}), |
| 55 |
attr.plans.map((plan,pi)=>el(TextControl,{key:pi,label:plan.name+' value',value:feat.values[pi]||'',onChange:v=>updateCell(fi,pi,v)})), |
| 56 |
el(Button,{isDestructive:true,isSmall:true,onClick:()=>removeFeature(fi)},__('Remove Feature')) |
| 57 |
)), |
| 58 |
el(Button,{variant:'secondary',onClick:addFeature,style:{width:'100%',justifyContent:'center',marginTop:'8px'}},__('+ Add Feature')) |
| 59 |
), |
| 60 |
el(PanelBody,{title:__('Style'),initialOpen:false}, |
| 61 |
el(RangeControl,{label:__('Border Radius'),value:attr.borderRadius,min:0,max:32,onChange:v=>setAttributes({borderRadius:v})}), |
| 62 |
el(ToggleControl,{label:__('Zebra Stripes'),checked:attr.zebraStripe,onChange:v=>setAttributes({zebraStripe:v}),__nextHasNoMarginBottom:true}), |
| 63 |
el(ToggleControl,{label:__('Sticky Header'),checked:attr.stickyHeader,onChange:v=>setAttributes({stickyHeader:v}),__nextHasNoMarginBottom:true}) |
| 64 |
), |
| 65 |
el(PanelBody,{title:__('Typography'),initialOpen:false}, |
| 66 |
el(getTypographyControl(), { label: __('Header Typography'), value: attr.typoHeader, onChange: v => setAttributes({ typoHeader: v }) }), |
| 67 |
el(getTypographyControl(), { label: __('Cell Typography'), value: attr.typoCell, onChange: v => setAttributes({ typoCell: v }) }) |
| 68 |
), |
| 69 |
el(PanelColorSettings,{title:__('Colors'),initialOpen:false,colorSettings:[ |
| 70 |
{label:__('Header Background'),value:attr.headerBg,onChange:v=>setAttributes({headerBg:v||'#6c3fb5'})}, |
| 71 |
{label:__('Header Text'),value:attr.headerText,onChange:v=>setAttributes({headerText:v||'#ffffff'})}, |
| 72 |
{label:__('Highlight Background'),value:attr.highlightBg,onChange:v=>setAttributes({highlightBg:v||'#f3eeff'})}, |
| 73 |
{label:__('Highlight Border'),value:attr.highlightBorder,onChange:v=>setAttributes({highlightBorder:v||'#6c3fb5'})}, |
| 74 |
{label:__('Check Color'),value:attr.checkColor,onChange:v=>setAttributes({checkColor:v||'#22c55e'})}, |
| 75 |
{label:__('Cross Color'),value:attr.crossColor,onChange:v=>setAttributes({crossColor:v||'#ef4444'})}, |
| 76 |
]}) |
| 77 |
), |
| 78 |
|
| 79 |
el('div',{className:'bkct-scroll'}, |
| 80 |
el('table',{className:'bkct-table'+(attr.zebraStripe?' bkct-zebra':'')}, |
| 81 |
el('thead',null, |
| 82 |
el('tr',null, |
| 83 |
el('th',{className:'bkct-feature-col'},__('Features')), |
| 84 |
attr.plans.map((plan,i)=> |
| 85 |
el('th',{key:i,className:'bkct-plan-col'+(plan.highlighted?' bkct-highlight':'')}, |
| 86 |
el('div',{className:'bkct-plan-name'},plan.name), |
| 87 |
plan.subtitle&&el('div',{className:'bkct-plan-sub'},plan.subtitle) |
| 88 |
) |
| 89 |
) |
| 90 |
) |
| 91 |
), |
| 92 |
el('tbody',null, |
| 93 |
attr.features.map((feat,fi)=> |
| 94 |
el('tr',{key:fi,className:'bkct-row'}, |
| 95 |
el('td',{className:'bkct-label'},feat.label), |
| 96 |
attr.plans.map((plan,pi)=> |
| 97 |
el('td',{key:pi,className:'bkct-cell'+(plan.highlighted?' bkct-highlight':'')}, |
| 98 |
el(CellValue,{val:feat.values[pi]||'',checkColor:attr.checkColor,crossColor:attr.crossColor}) |
| 99 |
) |
| 100 |
) |
| 101 |
) |
| 102 |
) |
| 103 |
) |
| 104 |
) |
| 105 |
) |
| 106 |
); |
| 107 |
}, |
| 108 |
|
| 109 |
save: function({attributes:attr}) { |
| 110 |
const wrapStyle=Object.assign({ |
| 111 |
'--bkct-header-bg':attr.headerBg,'--bkct-header-text':attr.headerText, |
| 112 |
'--bkct-hl-bg':attr.highlightBg,'--bkct-hl-border':attr.highlightBorder, |
| 113 |
'--bkct-check':attr.checkColor,'--bkct-cross':attr.crossColor, |
| 114 |
'--bkct-radius':attr.borderRadius+'px', |
| 115 |
}, _tv(attr.typoHeader, '--bkct-th-'), _tv(attr.typoCell, '--bkct-td-')); |
| 116 |
function CVal({val}) { |
| 117 |
if (val==='true') return el('span',{className:'bkct-check'},'✓'); |
| 118 |
if (val==='false') return el('span',{className:'bkct-cross'},'✕'); |
| 119 |
return el('span',{className:'bkct-text'},val); |
| 120 |
} |
| 121 |
return el('div',{className:'bkct-wrap',style:wrapStyle}, |
| 122 |
el('div',{className:'bkct-scroll'}, |
| 123 |
el('table',{className:'bkct-table'+(attr.zebraStripe?' bkct-zebra':'')}, |
| 124 |
el('thead',{className:attr.stickyHeader?'bkct-sticky':''}, |
| 125 |
el('tr',null, |
| 126 |
el('th',{className:'bkct-feature-col'}), |
| 127 |
attr.plans.map((plan,i)=> |
| 128 |
el('th',{key:i,className:'bkct-plan-col'+(plan.highlighted?' bkct-highlight':'')}, |
| 129 |
el('div',{className:'bkct-plan-name'},plan.name), |
| 130 |
plan.subtitle&&el('div',{className:'bkct-plan-sub'},plan.subtitle) |
| 131 |
) |
| 132 |
) |
| 133 |
) |
| 134 |
), |
| 135 |
el('tbody',null, |
| 136 |
attr.features.map((feat,fi)=> |
| 137 |
el('tr',{key:fi,className:'bkct-row'}, |
| 138 |
el('td',{className:'bkct-label'},feat.label), |
| 139 |
attr.plans.map((plan,pi)=> |
| 140 |
el('td',{key:pi,className:'bkct-cell'+(plan.highlighted?' bkct-highlight':'')}, |
| 141 |
el(CVal,{val:feat.values[pi]||''}) |
| 142 |
) |
| 143 |
) |
| 144 |
) |
| 145 |
) |
| 146 |
) |
| 147 |
) |
| 148 |
) |
| 149 |
); |
| 150 |
} |
| 151 |
}); |
| 152 |
}() ); |
| 153 |
|