| 1 |
/* ==================================================== |
| 2 |
Info Cards Block — editor (index.js) |
| 3 |
Block: blockenberg/info-cards |
| 4 |
==================================================== */ |
| 5 |
( function () { |
| 6 |
var el = wp.element.createElement; |
| 7 |
var Fragment = wp.element.Fragment; |
| 8 |
var useState = wp.element.useState; |
| 9 |
var registerBlockType = wp.blocks.registerBlockType; |
| 10 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 11 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 12 |
var PanelBody = wp.components.PanelBody; |
| 13 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 14 |
var RangeControl = wp.components.RangeControl; |
| 15 |
var SelectControl = wp.components.SelectControl; |
| 16 |
var ToggleControl = wp.components.ToggleControl; |
| 17 |
var TextControl = wp.components.TextControl; |
| 18 |
var Button = wp.components.Button; |
| 19 |
var ColorPicker = wp.components.ColorPicker; |
| 20 |
var Popover = wp.components.Popover; |
| 21 |
var __ = wp.i18n.__; |
| 22 |
|
| 23 |
var _TypographyControl, _typoCssVars; |
| 24 |
function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); } |
| 25 |
function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); } |
| 26 |
|
| 27 |
var IP = function () { return window.bkbgIconPicker; }; |
| 28 |
|
| 29 |
function uid() { return 'i' + Math.random().toString(36).slice(2,7); } |
| 30 |
function move(arr, from, to) { var a=arr.slice(); a.splice(to,0,a.splice(from,1)[0]); return a; } |
| 31 |
|
| 32 |
function wrapStyle(a) { |
| 33 |
var _tv = getTypoCssVars(); |
| 34 |
var s = { |
| 35 |
'--bkbg-infc-cols': a.columns, |
| 36 |
'--bkbg-infc-gap': a.gap + 'px', |
| 37 |
'--bkbg-infc-r': a.cardRadius + 'px', |
| 38 |
'--bkbg-infc-pad': a.cardPadding + 'px', |
| 39 |
'--bkbg-infc-icon-sz': a.iconSize + 'px', |
| 40 |
'--bkbg-infc-icon-bg-sz': a.iconBgSize + 'px', |
| 41 |
'--bkbg-infc-title-sz':a.titleSize + 'px', |
| 42 |
'--bkbg-infc-desc-sz': a.descSize + 'px', |
| 43 |
'--bkbg-infc-pt': a.paddingTop + 'px', |
| 44 |
'--bkbg-infc-pb': a.paddingBottom + 'px', |
| 45 |
'--bkbg-infc-card-bg': a.cardBg, |
| 46 |
'--bkbg-infc-brd': a.cardBorderColor, |
| 47 |
'--bkbg-infc-title-c': a.titleColor, |
| 48 |
'--bkbg-infc-desc-c': a.descColor, |
| 49 |
background: a.sectionBg || undefined, |
| 50 |
}; |
| 51 |
Object.assign(s, _tv(a.titleTypo, '--bkbg-infc-tt-')); |
| 52 |
Object.assign(s, _tv(a.descTypo, '--bkbg-infc-ds-')); |
| 53 |
return s; |
| 54 |
} |
| 55 |
|
| 56 |
function renderIconContent(item, size) { |
| 57 |
if ((item.iconType || 'custom-char') !== 'custom-char') return IP().buildEditorIcon(item.iconType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor); |
| 58 |
return item.icon; |
| 59 |
} |
| 60 |
|
| 61 |
function renderCard(item, a) { |
| 62 |
var iconEl; |
| 63 |
if (a.iconStyle === 'circle-bg') { |
| 64 |
iconEl = el('div', { className:'bkbg-infc-icon-wrap', style:{ background: item.accentColor+'22', width: a.iconBgSize+'px', height: a.iconBgSize+'px' } }, |
| 65 |
el('span', { className:'bkbg-infc-icon', style:{ fontSize: a.iconSize+'px', color: item.accentColor } }, renderIconContent(item, a.iconSize)) |
| 66 |
); |
| 67 |
} else if (a.iconStyle === 'square-bg') { |
| 68 |
iconEl = el('div', { className:'bkbg-infc-icon-wrap bkbg-infc-icon-wrap--square', style:{ background: item.accentColor+'22', width: a.iconBgSize+'px', height: a.iconBgSize+'px' } }, |
| 69 |
el('span', { className:'bkbg-infc-icon', style:{ fontSize: a.iconSize+'px', color: item.accentColor } }, renderIconContent(item, a.iconSize)) |
| 70 |
); |
| 71 |
} else { |
| 72 |
iconEl = el('span', { className:'bkbg-infc-icon bkbg-infc-icon--plain', style:{ fontSize: a.iconSize+'px' } }, renderIconContent(item, a.iconSize)); |
| 73 |
} |
| 74 |
|
| 75 |
var accentBar = a.cardStyle === 'accent-left' |
| 76 |
? el('div', { className:'bkbg-infc-accent-bar', style:{ background: item.accentColor } }) |
| 77 |
: null; |
| 78 |
|
| 79 |
return el('div', { className:'bkbg-infc-card bkbg-infc-card--' + a.cardStyle, style:{ textAlign: a.textAlign }, 'data-id': item.id }, |
| 80 |
accentBar, |
| 81 |
iconEl, |
| 82 |
el('h3', { className:'bkbg-infc-title' }, item.title), |
| 83 |
el('p', { className:'bkbg-infc-desc' }, item.description), |
| 84 |
a.showCta && item.ctaLabel ? el('a', { href:item.ctaUrl||'#', className:'bkbg-infc-cta', style:{ color:item.accentColor }, onClick:function(e){ e.preventDefault(); } }, item.ctaLabel, ' →') : null |
| 85 |
); |
| 86 |
} |
| 87 |
|
| 88 |
var BkbgColorSwatch = function (props) { |
| 89 |
var _st = useState(false); var isOpen = _st[0]; var setOpen = _st[1]; |
| 90 |
return el(Fragment, {}, |
| 91 |
el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } }, |
| 92 |
el('span', { style: { fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', color: '#1e1e1e' } }, props.label), |
| 93 |
el('button', { |
| 94 |
type: 'button', |
| 95 |
onClick: function () { setOpen(!isOpen); }, |
| 96 |
style: { width: '28px', height: '28px', borderRadius: '4px', border: '1px solid #ccc', background: props.value || '#ffffff', cursor: 'pointer', padding: 0 } |
| 97 |
}) |
| 98 |
), |
| 99 |
isOpen && el(Popover, { onClose: function () { setOpen(false); } }, |
| 100 |
el('div', { style: { padding: '8px' } }, |
| 101 |
el(ColorPicker, { color: props.value, onChangeComplete: function (c) { props.onChange(c.hex); }, enableAlpha: true }) |
| 102 |
) |
| 103 |
) |
| 104 |
); |
| 105 |
}; |
| 106 |
|
| 107 |
registerBlockType('blockenberg/info-cards', { |
| 108 |
edit: function (props) { |
| 109 |
var a = props.attributes; |
| 110 |
var setAttr = props.setAttributes; |
| 111 |
var items = a.items; |
| 112 |
|
| 113 |
var _act = useState(null); |
| 114 |
var activeId = _act[0]; var setActiveId = _act[1]; |
| 115 |
|
| 116 |
function update(id, patch) { |
| 117 |
setAttr({ items: items.map(function(it){ return it.id===id ? Object.assign({},it,patch) : it; }) }); |
| 118 |
} |
| 119 |
|
| 120 |
var blockProps = useBlockProps({ className:'bkbg-infc-wrap', style:wrapStyle(a) }); |
| 121 |
|
| 122 |
function itemRow(item, idx) { |
| 123 |
var isActive = activeId === item.id; |
| 124 |
return el('div', { key:item.id }, |
| 125 |
el('div', { |
| 126 |
style:{ display:'flex', alignItems:'center', gap:'6px', background:isActive?'#f3f0ff':'#f8f9fa', border:isActive?'1px solid #6c3fb5':'1px solid #e2e8f0', borderRadius:'6px', padding:'6px 8px', marginBottom:'4px', cursor:'pointer' }, |
| 127 |
onClick:function(){ setActiveId(isActive?null:item.id); } |
| 128 |
}, |
| 129 |
el('span', { style:{fontSize:'18px',marginRight:'4px'} }, item.icon), |
| 130 |
el('span', { style:{flex:1,fontSize:'13px',fontWeight:500,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'} }, item.title||'(untitled)'), |
| 131 |
el(Button, { icon:'arrow-up', isSmall:true, disabled:idx===0, onClick:function(e){ e.stopPropagation(); setAttr({items:move(items,idx,idx-1)}); } }), |
| 132 |
el(Button, { icon:'arrow-down', isSmall:true, disabled:idx===items.length-1, onClick:function(e){ e.stopPropagation(); setAttr({items:move(items,idx,idx+1)}); } }), |
| 133 |
el(Button, { icon:'no-alt', isSmall:true, isDestructive:true, onClick:function(e){ e.stopPropagation(); setAttr({items:items.filter(function(_,i){ return i!==idx; })}); if(activeId===item.id) setActiveId(null); } }) |
| 134 |
), |
| 135 |
isActive ? el('div', { style:{padding:'10px',background:'#faf8ff',border:'1px solid #6c3fb5',borderTop:'none',borderRadius:'0 0 6px 6px',marginBottom:'4px'} }, |
| 136 |
el(IP().IconPickerControl, { iconType: item.iconType || 'custom-char', customChar: item.icon, dashicon: item.iconDashicon || '', imageUrl: item.iconImageUrl || '', |
| 137 |
onChangeType: function(v){ update(item.id,{iconType:v}); }, onChangeChar: function(v){ update(item.id,{icon:v}); }, |
| 138 |
onChangeDashicon: function(v){ update(item.id,{iconDashicon:v}); }, onChangeImageUrl: function(v){ update(item.id,{iconImageUrl:v}); } }), |
| 139 |
el(TextControl, { label:__('Title','blockenberg'), value:item.title, onChange:function(v){ update(item.id,{title:v}); } }), |
| 140 |
el(TextControl, { label:__('Description','blockenberg'), value:item.description, onChange:function(v){ update(item.id,{description:v}); } }), |
| 141 |
el(BkbgColorSwatch, { label:__('Accent color','blockenberg'), value:item.accentColor, onChange:function(v){ update(item.id,{accentColor:v}); } }), |
| 142 |
a.showCta ? el(Fragment, null, |
| 143 |
el(TextControl, { label:__('CTA label','blockenberg'), value:item.ctaLabel, onChange:function(v){ update(item.id,{ctaLabel:v}); } }), |
| 144 |
el(TextControl, { label:__('CTA URL','blockenberg'), value:item.ctaUrl, onChange:function(v){ update(item.id,{ctaUrl:v}); } }) |
| 145 |
) : null |
| 146 |
) : null |
| 147 |
); |
| 148 |
} |
| 149 |
|
| 150 |
var inspector = el(InspectorControls, null, |
| 151 |
el(PanelBody, { title:__('Cards','blockenberg'), initialOpen:true }, |
| 152 |
items.map(function(it,i){ return itemRow(it,i); }), |
| 153 |
el(Button, { variant:'primary', style:{marginTop:'8px',width:'100%'}, |
| 154 |
onClick:function(){ |
| 155 |
var n={id:uid(),icon:'✨',iconType:'custom-char',iconDashicon:'',iconImageUrl:'',title:'New Feature',description:'Describe this feature succinctly.',ctaLabel:'',ctaUrl:'#',accentColor:'#6c3fb5'}; |
| 156 |
setAttr({items:items.concat([n])}); |
| 157 |
setActiveId(n.id); |
| 158 |
} |
| 159 |
}, __('+ Add Card','blockenberg')) |
| 160 |
), |
| 161 |
el(PanelBody, { title:__('Style & Layout','blockenberg'), initialOpen:false }, |
| 162 |
el(SelectControl, { label:__('Card style','blockenberg'), value:a.cardStyle, options:[ |
| 163 |
{label:'Icon top (flat)',value:'icon-top'}, |
| 164 |
{label:'Icon top (card)',value:'icon-top-card'}, |
| 165 |
{label:'Icon left (inline)',value:'icon-left'}, |
| 166 |
{label:'Accent left border',value:'accent-left'}, |
| 167 |
{label:'Dark card',value:'dark'}, |
| 168 |
], onChange:function(v){ setAttr({cardStyle:v}); } }), |
| 169 |
el(SelectControl, { label:__('Icon style','blockenberg'), value:a.iconStyle, options:[ |
| 170 |
{label:'Circle bg',value:'circle-bg'}, |
| 171 |
{label:'Square bg',value:'square-bg'}, |
| 172 |
{label:'Plain emoji',value:'plain'}, |
| 173 |
], onChange:function(v){ setAttr({iconStyle:v}); } }), |
| 174 |
el(SelectControl, { label:__('Text align','blockenberg'), value:a.textAlign, options:[ |
| 175 |
{label:'Left',value:'left'},{label:'Center',value:'center'} |
| 176 |
], onChange:function(v){ setAttr({textAlign:v}); } }), |
| 177 |
el(RangeControl, { label:__('Columns','blockenberg'), value:a.columns, min:1, max:6, onChange:function(v){ setAttr({columns:v}); } }), |
| 178 |
el(RangeControl, { label:__('Gap (px)','blockenberg'), value:a.gap, min:8, max:72, onChange:function(v){ setAttr({gap:v}); } }), |
| 179 |
el(RangeControl, { label:__('Card radius (px)','blockenberg'), value:a.cardRadius, min:0, max:32, onChange:function(v){ setAttr({cardRadius:v}); } }), |
| 180 |
el(RangeControl, { label:__('Card padding (px)','blockenberg'), value:a.cardPadding, min:12, max:60, onChange:function(v){ setAttr({cardPadding:v}); } }), |
| 181 |
el(RangeControl, { label:__('Icon size (px)','blockenberg'), value:a.iconSize, min:16, max:64, onChange:function(v){ setAttr({iconSize:v}); } }), |
| 182 |
el(RangeControl, { label:__('Icon bg size (px)','blockenberg'), value:a.iconBgSize, min:32, max:100, onChange:function(v){ setAttr({iconBgSize:v}); } }), |
| 183 |
el(ToggleControl, { label:__('Show CTA link','blockenberg'), checked:a.showCta, onChange:function(v){ setAttr({showCta:v}); } }) |
| 184 |
), |
| 185 |
el(PanelBody, { title:__('Typography','blockenberg'), initialOpen:false }, |
| 186 |
el(getTypographyControl(), { label: 'Title', value: a.titleTypo, onChange: function(v){ setAttr({ titleTypo: v }); } }), |
| 187 |
el(getTypographyControl(), { label: 'Description', value: a.descTypo, onChange: function(v){ setAttr({ descTypo: v }); } }) |
| 188 |
), |
| 189 |
el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false }, |
| 190 |
el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:160, onChange:function(v){ setAttr({paddingTop:v}); } }), |
| 191 |
el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:160, onChange:function(v){ setAttr({paddingBottom:v}); } }) |
| 192 |
), |
| 193 |
el(PanelColorSettings, { title:__('Colors','blockenberg'), initialOpen:false, colorSettings:[ |
| 194 |
{label:__('Section bg','blockenberg'), value:a.sectionBg, onChange:function(v){ setAttr({sectionBg:v||''}); }}, |
| 195 |
{label:__('Card bg','blockenberg'), value:a.cardBg, onChange:function(v){ setAttr({cardBg:v||''}); }}, |
| 196 |
{label:__('Card border','blockenberg'), value:a.cardBorderColor, onChange:function(v){ setAttr({cardBorderColor:v||''}); }}, |
| 197 |
{label:__('Title','blockenberg'), value:a.titleColor, onChange:function(v){ setAttr({titleColor:v||''}); }}, |
| 198 |
{label:__('Description','blockenberg'), value:a.descColor, onChange:function(v){ setAttr({descColor:v||''}); }}, |
| 199 |
] }) |
| 200 |
); |
| 201 |
|
| 202 |
return el(Fragment, null, |
| 203 |
inspector, |
| 204 |
el('div', blockProps, |
| 205 |
el('div', { className:'bkbg-infc-grid' }, |
| 206 |
items.map(function(item){ return renderCard(item, a); }) |
| 207 |
) |
| 208 |
) |
| 209 |
); |
| 210 |
}, |
| 211 |
|
| 212 |
save: function (props) { |
| 213 |
var a = props.attributes; |
| 214 |
var _tv = getTypoCssVars(); |
| 215 |
var saveStyle = { |
| 216 |
'--bkbg-infc-cols':a.columns,'--bkbg-infc-gap':a.gap+'px','--bkbg-infc-r':a.cardRadius+'px','--bkbg-infc-pad':a.cardPadding+'px','--bkbg-infc-icon-sz':a.iconSize+'px','--bkbg-infc-icon-bg-sz':a.iconBgSize+'px','--bkbg-infc-title-sz':a.titleSize+'px','--bkbg-infc-desc-sz':a.descSize+'px','--bkbg-infc-pt':a.paddingTop+'px','--bkbg-infc-pb':a.paddingBottom+'px','--bkbg-infc-card-bg':a.cardBg,'--bkbg-infc-brd':a.cardBorderColor,'--bkbg-infc-title-c':a.titleColor,'--bkbg-infc-desc-c':a.descColor,background:a.sectionBg||undefined, |
| 217 |
}; |
| 218 |
Object.assign(saveStyle, _tv(a.titleTypo, '--bkbg-infc-tt-')); |
| 219 |
Object.assign(saveStyle, _tv(a.descTypo, '--bkbg-infc-ds-')); |
| 220 |
var blockProps = wp.blockEditor.useBlockProps.save({ className:'bkbg-infc-wrap', style: saveStyle }); |
| 221 |
|
| 222 |
function saveIcon(item) { |
| 223 |
function saveIconContent(item) { |
| 224 |
if ((item.iconType || 'custom-char') !== 'custom-char') return IP().buildSaveIcon(item.iconType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor); |
| 225 |
return item.icon; |
| 226 |
} |
| 227 |
if (a.iconStyle === 'plain') return el('span', { className:'bkbg-infc-icon bkbg-infc-icon--plain', style:{ fontSize:a.iconSize+'px' } }, saveIconContent(item)); |
| 228 |
var cls = a.iconStyle==='square-bg' ? 'bkbg-infc-icon-wrap bkbg-infc-icon-wrap--square' : 'bkbg-infc-icon-wrap'; |
| 229 |
return el('div', { className:cls, style:{ background:item.accentColor+'22', width:a.iconBgSize+'px', height:a.iconBgSize+'px' } }, |
| 230 |
el('span', { className:'bkbg-infc-icon', style:{ fontSize:a.iconSize+'px', color:item.accentColor } }, saveIconContent(item)) |
| 231 |
); |
| 232 |
} |
| 233 |
|
| 234 |
return el('div', blockProps, |
| 235 |
el('div', { className:'bkbg-infc-grid' }, |
| 236 |
a.items.map(function(item) { |
| 237 |
return el('div', { key:item.id, className:'bkbg-infc-card bkbg-infc-card--'+a.cardStyle, style:{ textAlign:a.textAlign } }, |
| 238 |
a.cardStyle==='accent-left' ? el('div', { className:'bkbg-infc-accent-bar', style:{ background:item.accentColor } }) : null, |
| 239 |
saveIcon(item), |
| 240 |
el('h3', { className:'bkbg-infc-title' }, item.title), |
| 241 |
el('p', { className:'bkbg-infc-desc' }, item.description), |
| 242 |
a.showCta && item.ctaLabel ? el('a', { href:item.ctaUrl||'#', className:'bkbg-infc-cta', style:{ color:item.accentColor } }, item.ctaLabel, ' →') : null |
| 243 |
); |
| 244 |
}) |
| 245 |
) |
| 246 |
); |
| 247 |
} |
| 248 |
}); |
| 249 |
}() ); |
| 250 |
|