| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var __ = wp.i18n.__; |
| 4 |
var registerBlockType = wp.blocks.registerBlockType; |
| 5 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 6 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 7 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 8 |
var MediaUpload = wp.blockEditor.MediaUpload; |
| 9 |
var MediaUploadCheck = wp.blockEditor.MediaUploadCheck; |
| 10 |
var PanelBody = wp.components.PanelBody; |
| 11 |
var RangeControl = wp.components.RangeControl; |
| 12 |
var ToggleControl = wp.components.ToggleControl; |
| 13 |
var SelectControl = wp.components.SelectControl; |
| 14 |
var TextControl = wp.components.TextControl; |
| 15 |
var Button = wp.components.Button; |
| 16 |
var ColorPicker = wp.components.ColorPicker; |
| 17 |
var Popover = wp.components.Popover; |
| 18 |
var useState = wp.element.useState; |
| 19 |
var Fragment = wp.element.Fragment; |
| 20 |
|
| 21 |
var _tc, _tv; |
| 22 |
function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); } |
| 23 |
function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); } |
| 24 |
|
| 25 |
function TilePreview(tile, a, flipped) { |
| 26 |
var face = flipped ? 'back' : 'front'; |
| 27 |
var bg = flipped ? tile.backBg : tile.frontBg; |
| 28 |
var url = flipped ? tile.backUrl : tile.frontUrl; |
| 29 |
|
| 30 |
return el('div', { |
| 31 |
style: { |
| 32 |
width: a.tileWidth + 'px', |
| 33 |
height: a.tileHeight + 'px', |
| 34 |
borderRadius: a.tileRadius + 'px', |
| 35 |
background: url ? 'url(' + url + ') center/cover no-repeat, ' + bg : bg, |
| 36 |
position: 'relative', |
| 37 |
overflow: 'hidden', |
| 38 |
flexShrink: 0 |
| 39 |
} |
| 40 |
}, |
| 41 |
a.showLabel && tile.label && el('div', { |
| 42 |
className: 'bkbg-rit-label', |
| 43 |
style: { |
| 44 |
position: 'absolute', bottom: 0, left: 0, right: 0, |
| 45 |
padding: '8px 12px', |
| 46 |
background: a.labelBg || 'rgba(0,0,0,0.5)', |
| 47 |
color: a.labelColor || '#ffffff', |
| 48 |
textAlign: 'center' |
| 49 |
} |
| 50 |
}, tile.label) |
| 51 |
); |
| 52 |
} |
| 53 |
|
| 54 |
var BkbgColorSwatch = function (props) { |
| 55 |
var _st = useState(false); var isOpen = _st[0]; var setOpen = _st[1]; |
| 56 |
return el(Fragment, {}, |
| 57 |
el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } }, |
| 58 |
el('span', { style: { fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', color: '#1e1e1e' } }, props.label), |
| 59 |
el('button', { |
| 60 |
type: 'button', |
| 61 |
onClick: function () { setOpen(!isOpen); }, |
| 62 |
style: { width: '28px', height: '28px', borderRadius: '4px', border: '1px solid #ccc', background: props.value || '#ffffff', cursor: 'pointer', padding: 0 } |
| 63 |
}) |
| 64 |
), |
| 65 |
isOpen && el(Popover, { onClose: function () { setOpen(false); } }, |
| 66 |
el('div', { style: { padding: '8px' } }, |
| 67 |
el(ColorPicker, { color: props.value, onChangeComplete: function (c) { props.onChange(c.hex); }, enableAlpha: true }) |
| 68 |
) |
| 69 |
) |
| 70 |
); |
| 71 |
}; |
| 72 |
|
| 73 |
registerBlockType('blockenberg/rotating-image-tiles', { |
| 74 |
title: __('Rotating Image Tiles'), |
| 75 |
icon: 'images-alt2', |
| 76 |
category: 'bkbg-effects', |
| 77 |
|
| 78 |
edit: function (props) { |
| 79 |
var attr = props.attributes; |
| 80 |
var setAttr = props.setAttributes; |
| 81 |
var bp = useBlockProps((function () { |
| 82 |
var _tv = getTypoCssVars(); |
| 83 |
var s = {}; |
| 84 |
if (_tv) { |
| 85 |
Object.assign(s, _tv(attr.labelTypo, '--bkrit-lt-')); |
| 86 |
} |
| 87 |
return { className: 'bkbg-rit-wrap', style: s }; |
| 88 |
})()); |
| 89 |
|
| 90 |
function updateTile(idx, field, val) { |
| 91 |
var tiles = attr.tiles.map(function (t, i) { |
| 92 |
return i === idx ? Object.assign({}, t, { [field]: val }) : t; |
| 93 |
}); |
| 94 |
setAttr({ tiles: tiles }); |
| 95 |
} |
| 96 |
function addTile() { |
| 97 |
setAttr({ tiles: attr.tiles.concat([{ |
| 98 |
frontUrl: '', frontAlt: 'Front', backUrl: '', backAlt: 'Back', |
| 99 |
frontBg: '#6366f1', backBg: '#a5b4fc', label: '' |
| 100 |
}]) }); |
| 101 |
} |
| 102 |
function removeTile(idx) { |
| 103 |
if (attr.tiles.length <= 2) return; |
| 104 |
setAttr({ tiles: attr.tiles.filter(function (_, i) { return i !== idx; }) }); |
| 105 |
} |
| 106 |
|
| 107 |
var inspector = el(InspectorControls, {}, |
| 108 |
/* Tiles */ |
| 109 |
el(PanelBody, { title: __('Tiles'), initialOpen: true }, |
| 110 |
attr.tiles.map(function (tile, idx) { |
| 111 |
return el(PanelBody, { key: idx, title: 'Tile ' + (idx + 1), initialOpen: false }, |
| 112 |
/* Front image */ |
| 113 |
el('p', { style: { margin: '0 0 6px', fontWeight: 600 } }, __('Front Face')), |
| 114 |
el(MediaUploadCheck, {}, |
| 115 |
el(MediaUpload, { |
| 116 |
onSelect: function (m) { updateTile(idx, 'frontUrl', m.url); }, |
| 117 |
allowedTypes: ['image'], value: tile.frontUrl, |
| 118 |
render: function (ref) { |
| 119 |
return el(Button, { variant: tile.frontUrl ? 'secondary' : 'primary', onClick: ref.open }, |
| 120 |
tile.frontUrl ? __('Change Front Image') : __('Choose Front Image')); |
| 121 |
} |
| 122 |
}) |
| 123 |
), |
| 124 |
el(BkbgColorSwatch, { label: __('Front BG Color (fallback)'), value: tile.frontBg || '', |
| 125 |
onChange: function (v) { updateTile(idx, 'frontBg', v); } }), |
| 126 |
/* Back image */ |
| 127 |
el('p', { style: { margin: '8px 0 6px', fontWeight: 600 } }, __('Back Face')), |
| 128 |
el(MediaUploadCheck, {}, |
| 129 |
el(MediaUpload, { |
| 130 |
onSelect: function (m) { updateTile(idx, 'backUrl', m.url); }, |
| 131 |
allowedTypes: ['image'], value: tile.backUrl, |
| 132 |
render: function (ref) { |
| 133 |
return el(Button, { variant: tile.backUrl ? 'secondary' : 'primary', onClick: ref.open }, |
| 134 |
tile.backUrl ? __('Change Back Image') : __('Choose Back Image')); |
| 135 |
} |
| 136 |
}) |
| 137 |
), |
| 138 |
el(BkbgColorSwatch, { label: __('Back BG Color (fallback)'), value: tile.backBg || '', |
| 139 |
onChange: function (v) { updateTile(idx, 'backBg', v); } }), |
| 140 |
el(TextControl, { label: __('Label'), value: tile.label || '', |
| 141 |
onChange: function (v) { updateTile(idx, 'label', v); }, |
| 142 |
__nextHasNoMarginBottom: true }), |
| 143 |
attr.tiles.length > 2 && el(Button, { |
| 144 |
isDestructive: true, variant: 'secondary', |
| 145 |
onClick: function () { removeTile(idx); }, |
| 146 |
style: { marginTop: '8px' } |
| 147 |
}, __('Remove Tile')) |
| 148 |
); |
| 149 |
}), |
| 150 |
el(Button, { variant: 'primary', onClick: addTile, |
| 151 |
style: { marginTop: '8px', width: '100%' } |
| 152 |
}, __('+ Add Tile')) |
| 153 |
), |
| 154 |
|
| 155 |
/* Layout */ |
| 156 |
el(PanelBody, { title: __('Layout'), initialOpen: false }, |
| 157 |
el(SelectControl, { |
| 158 |
label: __('Columns'), |
| 159 |
value: String(attr.columns), |
| 160 |
options: ['2','3','4'].map(function (v) { return { label: v, value: v }; }), |
| 161 |
onChange: function (v) { setAttr({ columns: Number(v) }); }, |
| 162 |
__nextHasNoMarginBottom: true |
| 163 |
}), |
| 164 |
el(RangeControl, { label: __('Tile Width (px)'), value: attr.tileWidth, |
| 165 |
min: 120, max: 600, |
| 166 |
onChange: function (v) { setAttr({ tileWidth: v }); }, |
| 167 |
__nextHasNoMarginBottom: true }), |
| 168 |
el(RangeControl, { label: __('Tile Height (px)'), value: attr.tileHeight, |
| 169 |
min: 80, max: 500, |
| 170 |
onChange: function (v) { setAttr({ tileHeight: v }); }, |
| 171 |
__nextHasNoMarginBottom: true }), |
| 172 |
el(RangeControl, { label: __('Tile Radius (px)'), value: attr.tileRadius, |
| 173 |
min: 0, max: 40, |
| 174 |
onChange: function (v) { setAttr({ tileRadius: v }); }, |
| 175 |
__nextHasNoMarginBottom: true }), |
| 176 |
el(RangeControl, { label: __('Gap (px)'), value: attr.gap, |
| 177 |
min: 0, max: 40, |
| 178 |
onChange: function (v) { setAttr({ gap: v }); }, |
| 179 |
__nextHasNoMarginBottom: true }) |
| 180 |
), |
| 181 |
|
| 182 |
/* Animation */ |
| 183 |
el(PanelBody, { title: __('Animation'), initialOpen: false }, |
| 184 |
el(SelectControl, { |
| 185 |
label: __('Flip Axis'), |
| 186 |
value: attr.flipAxis, |
| 187 |
options: [ |
| 188 |
{ label: __('Horizontal (Y)'), value: 'Y' }, |
| 189 |
{ label: __('Vertical (X)'), value: 'X' } |
| 190 |
], |
| 191 |
onChange: function (v) { setAttr({ flipAxis: v }); }, |
| 192 |
__nextHasNoMarginBottom: true |
| 193 |
}), |
| 194 |
el(ToggleControl, { label: __('Auto Flip'), checked: attr.autoFlip, |
| 195 |
onChange: function (v) { setAttr({ autoFlip: v }); }, |
| 196 |
__nextHasNoMarginBottom: true }), |
| 197 |
el(ToggleControl, { label: __('Flip on Hover'), checked: attr.flipOnHover, |
| 198 |
onChange: function (v) { setAttr({ flipOnHover: v }); }, |
| 199 |
__nextHasNoMarginBottom: true }), |
| 200 |
el(RangeControl, { label: __('Flip Duration (ms)'), value: attr.flipDuration, |
| 201 |
min: 200, max: 2000, step: 100, |
| 202 |
onChange: function (v) { setAttr({ flipDuration: v }); }, |
| 203 |
__nextHasNoMarginBottom: true }), |
| 204 |
el(RangeControl, { label: __('Stagger Delay (ms)'), value: attr.staggerDelay, |
| 205 |
min: 0, max: 1000, step: 50, |
| 206 |
onChange: function (v) { setAttr({ staggerDelay: v }); }, |
| 207 |
__nextHasNoMarginBottom: true }), |
| 208 |
attr.autoFlip && el(RangeControl, { label: __('Auto Interval (ms)'), value: attr.autoInterval, |
| 209 |
min: 1000, max: 10000, step: 500, |
| 210 |
onChange: function (v) { setAttr({ autoInterval: v }); }, |
| 211 |
__nextHasNoMarginBottom: true }), |
| 212 |
el(ToggleControl, { label: __('Show Label'), checked: attr.showLabel, |
| 213 |
onChange: function (v) { setAttr({ showLabel: v }); }, |
| 214 |
__nextHasNoMarginBottom: true }), |
| 215 |
), |
| 216 |
|
| 217 |
/* Colors */ |
| 218 |
|
| 219 |
el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false }, |
| 220 |
getTypoControl() && el(getTypoControl(), { |
| 221 |
label: __('Label Typography', 'blockenberg'), |
| 222 |
value: attr.labelTypo || {}, |
| 223 |
onChange: function (v) { setAttr({ labelTypo: v }); } |
| 224 |
}) |
| 225 |
), |
| 226 |
el(PanelColorSettings, { |
| 227 |
title: __('Colors'), initialOpen: false, |
| 228 |
colorSettings: [ |
| 229 |
{ label: __('Label Text'), value: attr.labelColor, |
| 230 |
onChange: function (v) { setAttr({ labelColor: v || '#ffffff' }); } }, |
| 231 |
{ label: __('Label BG'), value: attr.labelBg, |
| 232 |
onChange: function (v) { setAttr({ labelBg: v || 'rgba(0,0,0,0.5)' }); } } |
| 233 |
] |
| 234 |
}) |
| 235 |
); |
| 236 |
|
| 237 |
return el(wp.element.Fragment, {}, inspector, |
| 238 |
el('div', bp, |
| 239 |
el('div', { |
| 240 |
style: { |
| 241 |
display: 'grid', |
| 242 |
gridTemplateColumns: 'repeat(' + attr.columns + ', 1fr)', |
| 243 |
gap: attr.gap + 'px' |
| 244 |
} |
| 245 |
}, |
| 246 |
attr.tiles.map(function (tile, i) { |
| 247 |
return el('div', { key: i }, TilePreview(tile, attr, false)); |
| 248 |
}) |
| 249 |
) |
| 250 |
) |
| 251 |
); |
| 252 |
}, |
| 253 |
|
| 254 |
save: function (props) { |
| 255 |
var attr = props.attributes; |
| 256 |
var bp = useBlockProps.save(); |
| 257 |
return el('div', bp, |
| 258 |
el('div', { className: 'bkbg-rit-app', 'data-opts': JSON.stringify(attr) }) |
| 259 |
); |
| 260 |
} |
| 261 |
}); |
| 262 |
}() ); |
| 263 |
|