| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var __ = wp.i18n.__; |
| 4 |
var registerBlockType = wp.blocks.registerBlockType; |
| 5 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 6 |
var RichText = wp.blockEditor.RichText; |
| 7 |
var PanelBody = wp.components.PanelBody; |
| 8 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 9 |
var SelectControl = wp.components.SelectControl; |
| 10 |
var ToggleControl = wp.components.ToggleControl; |
| 11 |
var RangeControl = wp.components.RangeControl; |
| 12 |
var TextareaControl = wp.components.TextareaControl; |
| 13 |
|
| 14 |
// ── Typography helpers ───────────────────────────────────────────────── |
| 15 |
function getTypographyControl() { |
| 16 |
return (window.bkbgTypographyControl || function () { return null; }); |
| 17 |
} |
| 18 |
|
| 19 |
function _tv(typo, prefix) { |
| 20 |
if (!typo) return {}; |
| 21 |
var s = {}; |
| 22 |
if (typo.family) s[prefix + 'font-family'] = "'" + typo.family + "', sans-serif"; |
| 23 |
if (typo.weight) s[prefix + 'font-weight'] = typo.weight; |
| 24 |
if (typo.transform) s[prefix + 'text-transform'] = typo.transform; |
| 25 |
if (typo.style) s[prefix + 'font-style'] = typo.style; |
| 26 |
if (typo.decoration) s[prefix + 'text-decoration'] = typo.decoration; |
| 27 |
var su = typo.sizeUnit || 'px'; |
| 28 |
if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) s[prefix + 'font-size-d'] = typo.sizeDesktop + su; |
| 29 |
if (typo.sizeTablet !== '' && typo.sizeTablet != null) s[prefix + 'font-size-t'] = typo.sizeTablet + su; |
| 30 |
if (typo.sizeMobile !== '' && typo.sizeMobile != null) s[prefix + 'font-size-m'] = typo.sizeMobile + su; |
| 31 |
var lhu = typo.lineHeightUnit || ''; |
| 32 |
if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) s[prefix + 'line-height-d'] = typo.lineHeightDesktop + lhu; |
| 33 |
if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) s[prefix + 'line-height-t'] = typo.lineHeightTablet + lhu; |
| 34 |
if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) s[prefix + 'line-height-m'] = typo.lineHeightMobile + lhu; |
| 35 |
var lsu = typo.letterSpacingUnit || 'px'; |
| 36 |
if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) s[prefix + 'letter-spacing-d'] = typo.letterSpacingDesktop + lsu; |
| 37 |
if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) s[prefix + 'letter-spacing-t'] = typo.letterSpacingTablet + lsu; |
| 38 |
if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) s[prefix + 'letter-spacing-m'] = typo.letterSpacingMobile + lsu; |
| 39 |
var wsu = typo.wordSpacingUnit || 'px'; |
| 40 |
if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) s[prefix + 'word-spacing-d'] = typo.wordSpacingDesktop + wsu; |
| 41 |
if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) s[prefix + 'word-spacing-t'] = typo.wordSpacingTablet + wsu; |
| 42 |
if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) s[prefix + 'word-spacing-m'] = typo.wordSpacingMobile + wsu; |
| 43 |
return s; |
| 44 |
} |
| 45 |
|
| 46 |
var PRESET_TYPES = { |
| 47 |
info: { bg: '#e8f4fd', border: '#2196f3', text: '#1565c0', icon: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 1 0 0 20A10 10 0 0 0 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>' }, |
| 48 |
success: { bg: '#e8f5e9', border: '#4caf50', text: '#2e7d32', icon: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 1 0 0 20A10 10 0 0 0 12 2zm-2 14.4-4-4 1.4-1.4 2.6 2.6 5.6-5.6 1.4 1.4-7 7z"/></svg>' }, |
| 49 |
warning: { bg: '#fff8e1', border: '#ff9800', text: '#e65100', icon: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M1 21L12 2l11 19H1zm11-3h2v-2h-2v2zm0-4h2v-4h-2v4z"/></svg>' }, |
| 50 |
danger: { bg: '#ffebee', border: '#f44336', text: '#b71c1c', icon: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 1 0 0 20A10 10 0 0 0 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>' }, |
| 51 |
custom: { bg: '#f5f0ff', border: '#9c27b0', text: '#4a148c', icon: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 1 0 0 20A10 10 0 0 0 12 2zm1 14h-2v-5h2v5zm0-7h-2V7h2v2z"/></svg>' } |
| 52 |
}; |
| 53 |
|
| 54 |
registerBlockType( 'blockenberg/callout', { |
| 55 |
edit: function ( props ) { |
| 56 |
var attrs = props.attributes; |
| 57 |
var setAttr = props.setAttributes; |
| 58 |
var preset = PRESET_TYPES[ attrs.calloutType ] || PRESET_TYPES.info; |
| 59 |
var bg = attrs.bgColor || preset.bg; |
| 60 |
var brd = attrs.borderColor || preset.border; |
| 61 |
var txt = attrs.textColor || preset.text; |
| 62 |
|
| 63 |
var wrapStyle = Object.assign({ |
| 64 |
'--bkco-bg': bg, |
| 65 |
'--bkco-border': brd, |
| 66 |
'--bkco-text': txt, |
| 67 |
'--bkco-pv': attrs.paddingV + 'px', |
| 68 |
'--bkco-ph': attrs.paddingH + 'px', |
| 69 |
'--bkco-radius': attrs.borderRadius + 'px' |
| 70 |
}, _tv(attrs.typoTitle, '--bkco-tt-'), _tv(attrs.typoBody, '--bkco-tb-')); |
| 71 |
|
| 72 |
return el( 'div', null, |
| 73 |
el( InspectorControls, null, |
| 74 |
el( PanelBody, { title: __( 'Type & Style', 'blockenberg' ), initialOpen: true }, |
| 75 |
el( SelectControl, { |
| 76 |
label: __( 'Callout Type', 'blockenberg' ), |
| 77 |
value: attrs.calloutType, |
| 78 |
options: [ |
| 79 |
{ label: 'Info', value: 'info' }, |
| 80 |
{ label: 'Success', value: 'success' }, |
| 81 |
{ label: 'Warning', value: 'warning' }, |
| 82 |
{ label: 'Danger', value: 'danger' }, |
| 83 |
{ label: 'Custom', value: 'custom' } |
| 84 |
], |
| 85 |
onChange: function ( v ) { setAttr( { calloutType: v, bgColor: '', borderColor: '', textColor: '' } ); } |
| 86 |
} ), |
| 87 |
el( SelectControl, { |
| 88 |
label: __( 'Border Style', 'blockenberg' ), |
| 89 |
value: attrs.borderStyle, |
| 90 |
options: [ |
| 91 |
{ label: 'Left accent', value: 'left' }, |
| 92 |
{ label: 'Top ribbon', value: 'top' }, |
| 93 |
{ label: 'All sides', value: 'all' }, |
| 94 |
{ label: 'No border', value: 'none' } |
| 95 |
], |
| 96 |
onChange: function ( v ) { setAttr( { borderStyle: v } ); } |
| 97 |
} ), |
| 98 |
el( ToggleControl, { |
| 99 |
label: __( 'Show Icon', 'blockenberg' ), |
| 100 |
checked: attrs.showIcon, |
| 101 |
onChange: function ( v ) { setAttr( { showIcon: v } ); }, |
| 102 |
__nextHasNoMarginBottom: true |
| 103 |
} ), |
| 104 |
el( ToggleControl, { |
| 105 |
label: __( 'Dismissible', 'blockenberg' ), |
| 106 |
checked: attrs.dismissible, |
| 107 |
onChange: function ( v ) { setAttr( { dismissible: v } ); }, |
| 108 |
__nextHasNoMarginBottom: true |
| 109 |
} ), |
| 110 |
el( RangeControl, { |
| 111 |
label: __( 'Vertical Padding', 'blockenberg' ), |
| 112 |
value: attrs.paddingV, min: 8, max: 48, |
| 113 |
onChange: function ( v ) { setAttr( { paddingV: v } ); } |
| 114 |
} ), |
| 115 |
el( RangeControl, { |
| 116 |
label: __( 'Horizontal Padding', 'blockenberg' ), |
| 117 |
value: attrs.paddingH, min: 8, max: 64, |
| 118 |
onChange: function ( v ) { setAttr( { paddingH: v } ); } |
| 119 |
} ), |
| 120 |
el( RangeControl, { |
| 121 |
label: __( 'Border Radius', 'blockenberg' ), |
| 122 |
value: attrs.borderRadius, min: 0, max: 24, |
| 123 |
onChange: function ( v ) { setAttr( { borderRadius: v } ); } |
| 124 |
} ) |
| 125 |
), |
| 126 |
el( PanelBody, { title: __( 'Custom Colors', 'blockenberg' ), initialOpen: false }, |
| 127 |
el( PanelColorSettings, { |
| 128 |
title: __( 'Colors', 'blockenberg' ), |
| 129 |
colorSettings: [ |
| 130 |
{ value: attrs.bgColor, onChange: function(v){setAttr({bgColor:v||''});}, label: __('Background') }, |
| 131 |
{ value: attrs.borderColor, onChange: function(v){setAttr({borderColor:v||''});}, label: __('Border / Accent') }, |
| 132 |
{ value: attrs.textColor, onChange: function(v){setAttr({textColor:v||''});}, label: __('Text') } |
| 133 |
] |
| 134 |
} ) |
| 135 |
), |
| 136 |
el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false }, |
| 137 |
el( 'p', { style: { margin: '0 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __( 'Title', 'blockenberg' ) ), |
| 138 |
el( getTypographyControl(), { |
| 139 |
label: __( 'Title Typography', 'blockenberg' ), |
| 140 |
value: attrs.typoTitle, |
| 141 |
onChange: function ( v ) { setAttr( { typoTitle: v } ); } |
| 142 |
} ), |
| 143 |
el( 'hr', {} ), |
| 144 |
el( 'p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __( 'Body', 'blockenberg' ) ), |
| 145 |
el( getTypographyControl(), { |
| 146 |
label: __( 'Body Typography', 'blockenberg' ), |
| 147 |
value: attrs.typoBody, |
| 148 |
onChange: function ( v ) { setAttr( { typoBody: v } ); } |
| 149 |
} ) |
| 150 |
) |
| 151 |
), |
| 152 |
el( 'div', { className: 'bkco-wrap bkco-border-' + attrs.borderStyle + ' bkco-type-' + attrs.calloutType, style: wrapStyle }, |
| 153 |
attrs.showIcon && el( 'span', { |
| 154 |
className: 'bkco-icon', |
| 155 |
dangerouslySetInnerHTML: { __html: preset.icon } |
| 156 |
} ), |
| 157 |
el( 'div', { className: 'bkco-content' }, |
| 158 |
el( RichText, { |
| 159 |
tagName: 'strong', |
| 160 |
className: 'bkco-title', |
| 161 |
value: attrs.title, |
| 162 |
onChange: function ( v ) { setAttr( { title: v } ); }, |
| 163 |
placeholder: __( 'Callout title…', 'blockenberg' ) |
| 164 |
} ), |
| 165 |
el( RichText, { |
| 166 |
tagName: 'p', |
| 167 |
className: 'bkco-body', |
| 168 |
value: attrs.body, |
| 169 |
onChange: function ( v ) { setAttr( { body: v } ); }, |
| 170 |
placeholder: __( 'Callout body text…', 'blockenberg' ) |
| 171 |
} ) |
| 172 |
), |
| 173 |
attrs.dismissible && el( 'button', { className: 'bkco-close', 'aria-label': 'Close' }, '×' ) |
| 174 |
) |
| 175 |
); |
| 176 |
}, |
| 177 |
save: function ( props ) { |
| 178 |
var attrs = props.attributes; |
| 179 |
var preset = PRESET_TYPES[ attrs.calloutType ] || PRESET_TYPES.info; |
| 180 |
var bg = attrs.bgColor || preset.bg; |
| 181 |
var brd = attrs.borderColor || preset.border; |
| 182 |
var txt = attrs.textColor || preset.text; |
| 183 |
return el( 'div', { |
| 184 |
className: 'bkco-wrap bkco-border-' + attrs.borderStyle + ' bkco-type-' + attrs.calloutType, |
| 185 |
style: Object.assign({ |
| 186 |
'--bkco-bg': bg, |
| 187 |
'--bkco-border': brd, |
| 188 |
'--bkco-text': txt, |
| 189 |
'--bkco-pv': attrs.paddingV + 'px', |
| 190 |
'--bkco-ph': attrs.paddingH + 'px', |
| 191 |
'--bkco-radius': attrs.borderRadius + 'px' |
| 192 |
}, _tv(attrs.typoTitle, '--bkco-tt-'), _tv(attrs.typoBody, '--bkco-tb-')), |
| 193 |
'data-dismissible': attrs.dismissible ? '1' : '0' |
| 194 |
}, |
| 195 |
attrs.showIcon && el( 'span', { |
| 196 |
className: 'bkco-icon', |
| 197 |
dangerouslySetInnerHTML: { __html: preset.icon } |
| 198 |
} ), |
| 199 |
el( 'div', { className: 'bkco-content' }, |
| 200 |
el( RichText.Content, { tagName: 'strong', className: 'bkco-title', value: attrs.title } ), |
| 201 |
el( RichText.Content, { tagName: 'p', className: 'bkco-body', value: attrs.body } ) |
| 202 |
), |
| 203 |
attrs.dismissible && el( 'button', { className: 'bkco-close', 'aria-label': 'Close' }, '×' ) |
| 204 |
); |
| 205 |
} |
| 206 |
} ); |
| 207 |
|
| 208 |
/* Expose presets for save() */ |
| 209 |
window.BKCO_PRESETS = PRESET_TYPES; |
| 210 |
} )(); |
| 211 |
|