| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var Fragment = wp.element.Fragment; |
| 4 |
var useState = wp.element.useState; |
| 5 |
var __ = wp.i18n.__; |
| 6 |
var registerBlockType = wp.blocks.registerBlockType; |
| 7 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 8 |
var MediaUpload = wp.blockEditor.MediaUpload; |
| 9 |
var MediaUploadCheck = wp.blockEditor.MediaUploadCheck; |
| 10 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 11 |
var RichText = wp.blockEditor.RichText; |
| 12 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 13 |
var PanelBody = wp.components.PanelBody; |
| 14 |
var ToggleControl = wp.components.ToggleControl; |
| 15 |
var RangeControl = wp.components.RangeControl; |
| 16 |
var SelectControl = wp.components.SelectControl; |
| 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 |
|
| 22 |
function getTypographyControl() { return (window.bkbgTypographyControl || function () { return null; }); } |
| 23 |
function getTypoCssVars() { return (window.bkbgTypoCssVars || function () { return {}; }); } |
| 24 |
function _tv(typo, prefix) { var fn = getTypoCssVars(); return fn(typo || {}, prefix); } |
| 25 |
|
| 26 |
var CARD_LAYOUT_OPTIONS = [ |
| 27 |
{ label: 'Stacked (Image top)', value: 'stacked' }, |
| 28 |
{ label: 'Overlay (Image bg)', value: 'overlay' }, |
| 29 |
{ label: 'Horizontal', value: 'horizontal' }, |
| 30 |
{ label: 'Text only', value: 'text' }, |
| 31 |
]; |
| 32 |
|
| 33 |
var ASPECT_OPTIONS = [ |
| 34 |
{ label: '1:1 Square', value: '1-1' }, |
| 35 |
{ label: '4:3', value: '4-3' }, |
| 36 |
{ label: '3:2', value: '3-2' }, |
| 37 |
{ label: '16:9', value: '16-9' }, |
| 38 |
{ label: '21:9', value: '21-9' }, |
| 39 |
]; |
| 40 |
|
| 41 |
var SHADOW_OPTIONS = [ |
| 42 |
{ label: 'None', value: 'none' }, |
| 43 |
{ label: 'Small', value: 'sm' }, |
| 44 |
{ label: 'Medium', value: 'md' }, |
| 45 |
{ label: 'Large', value: 'lg' }, |
| 46 |
]; |
| 47 |
|
| 48 |
var LINK_STYLE_OPTIONS = [ |
| 49 |
{ label: 'Arrow link →', value: 'arrow' }, |
| 50 |
{ label: 'Button', value: 'button' }, |
| 51 |
{ label: 'Underline', value: 'underline' }, |
| 52 |
]; |
| 53 |
|
| 54 |
var ASPECT_PADDING = { |
| 55 |
'1-1': '100%', '4-3': '75%', '3-2': '66.67%', '16-9': '56.25%', '21-9': '42.86%', |
| 56 |
}; |
| 57 |
|
| 58 |
var SHADOWS = { |
| 59 |
none: 'none', |
| 60 |
sm: '0 1px 6px rgba(0,0,0,0.08)', |
| 61 |
md: '0 4px 16px rgba(0,0,0,0.12)', |
| 62 |
lg: '0 8px 32px rgba(0,0,0,0.16)', |
| 63 |
}; |
| 64 |
|
| 65 |
function updateItem(items, idx, field, val) { |
| 66 |
return items.map(function (it, i) { |
| 67 |
if (i !== idx) return it; |
| 68 |
var p = {}; p[field] = val; |
| 69 |
return Object.assign({}, it, p); |
| 70 |
}); |
| 71 |
} |
| 72 |
|
| 73 |
function renderCardPreview(item, a, idx) { |
| 74 |
var shadow = SHADOWS[a.cardShadow] || SHADOWS.sm; |
| 75 |
var pt = ASPECT_PADDING[a.imageAspect] || '56.25%'; |
| 76 |
|
| 77 |
var cardStyle = { |
| 78 |
background: a.cardLayout === 'overlay' ? 'transparent' : a.cardBg, |
| 79 |
borderRadius: a.cardBorderRadius + 'px', |
| 80 |
boxShadow: a.cardLayout === 'overlay' ? 'none' : shadow, |
| 81 |
overflow: 'hidden', |
| 82 |
display: 'flex', |
| 83 |
flexDirection: a.cardLayout === 'horizontal' ? 'row' : 'column', |
| 84 |
minHeight: a.cardMinHeight > 0 ? a.cardMinHeight + 'px' : 'auto', |
| 85 |
position: 'relative', |
| 86 |
flex: '0 0 calc(' + (100 / a.desktopCols) + '% - ' + (a.gap * (a.desktopCols - 1) / a.desktopCols) + 'px)', |
| 87 |
}; |
| 88 |
|
| 89 |
var hasImage = item.imageUrl; |
| 90 |
var accentColor = item.accentColor || a.eyebrowColor; |
| 91 |
|
| 92 |
var imageSection = (a.cardLayout !== 'text' && hasImage) ? el('div', { |
| 93 |
style: { |
| 94 |
position: 'relative', |
| 95 |
paddingTop: a.cardLayout === 'horizontal' ? '0' : pt, |
| 96 |
height: a.cardLayout === 'horizontal' ? '100%' : '0', |
| 97 |
width: a.cardLayout === 'horizontal' ? '40%' : '100%', |
| 98 |
flexShrink: a.cardLayout === 'horizontal' ? 0 : 1, |
| 99 |
overflow: 'hidden', |
| 100 |
} |
| 101 |
}, |
| 102 |
el('img', { |
| 103 |
src: item.imageUrl, |
| 104 |
alt: item.imageAlt || '', |
| 105 |
style: { |
| 106 |
position: a.cardLayout === 'horizontal' ? 'static' : 'absolute', |
| 107 |
inset: '0', |
| 108 |
width: '100%', |
| 109 |
height: a.cardLayout === 'horizontal' ? '140px' : '100%', |
| 110 |
objectFit: a.imageFit || 'cover', |
| 111 |
display: 'block', |
| 112 |
} |
| 113 |
}) |
| 114 |
) : (a.cardLayout !== 'text' && !hasImage && a.cardLayout !== 'overlay') ? el('div', { |
| 115 |
style: { |
| 116 |
paddingTop: a.cardLayout === 'horizontal' ? '0' : pt, |
| 117 |
height: a.cardLayout === 'horizontal' ? '120px' : '0', |
| 118 |
width: a.cardLayout === 'horizontal' ? '40%' : '100%', |
| 119 |
background: '#f3f4f6', |
| 120 |
display: 'flex', |
| 121 |
alignItems: 'center', |
| 122 |
justifyContent: 'center', |
| 123 |
color: '#9ca3af', |
| 124 |
fontSize: 12, |
| 125 |
flexShrink: 0, |
| 126 |
overflow: 'hidden', |
| 127 |
} |
| 128 |
}, a.cardLayout !== 'horizontal' ? null : '🖼') : null; |
| 129 |
|
| 130 |
var bodyStyle = { |
| 131 |
padding: a.cardPadding + 'px', |
| 132 |
display: 'flex', |
| 133 |
flexDirection: 'column', |
| 134 |
gap: '8px', |
| 135 |
flex: '1', |
| 136 |
}; |
| 137 |
|
| 138 |
if (a.cardLayout === 'overlay' && hasImage) { |
| 139 |
bodyStyle.position = 'absolute'; |
| 140 |
bodyStyle.inset = '0'; |
| 141 |
bodyStyle.background = 'linear-gradient(180deg, transparent 30%, rgba(0,0,0,0.75) 100%)'; |
| 142 |
bodyStyle.justifyContent = 'flex-end'; |
| 143 |
bodyStyle.borderRadius = a.cardBorderRadius + 'px'; |
| 144 |
} |
| 145 |
|
| 146 |
var body = el('div', { className: 'bkbg-cc-body', style: bodyStyle }, |
| 147 |
a.showBadge && item.badge && el('span', { |
| 148 |
style: { |
| 149 |
display: 'inline-block', |
| 150 |
fontSize: 11, |
| 151 |
fontWeight: 700, |
| 152 |
letterSpacing: '0.05em', |
| 153 |
textTransform: 'uppercase', |
| 154 |
padding: '3px 10px', |
| 155 |
borderRadius: 999, |
| 156 |
background: a.badgeBg, |
| 157 |
color: a.badgeColor, |
| 158 |
alignSelf: 'flex-start', |
| 159 |
} |
| 160 |
}, item.badge), |
| 161 |
a.showEyebrow && item.eyebrow && el('div', { |
| 162 |
className: 'bkbg-cc-eyebrow', |
| 163 |
style: { |
| 164 |
color: a.cardLayout === 'overlay' ? 'rgba(255,255,255,0.75)' : accentColor, |
| 165 |
} |
| 166 |
}, item.eyebrow), |
| 167 |
el('h3', { |
| 168 |
className: 'bkbg-cc-heading', |
| 169 |
style: { |
| 170 |
margin: 0, |
| 171 |
color: a.cardLayout === 'overlay' ? '#fff' : a.headingColor, |
| 172 |
} |
| 173 |
}, item.heading || 'Card Title'), |
| 174 |
a.showDescription && item.description && el('p', { |
| 175 |
className: 'bkbg-cc-desc', |
| 176 |
style: { |
| 177 |
margin: 0, |
| 178 |
color: a.cardLayout === 'overlay' ? 'rgba(255,255,255,0.8)' : a.textColor, |
| 179 |
flexGrow: 1, |
| 180 |
} |
| 181 |
}, item.description), |
| 182 |
a.showLink && item.link && el('a', { |
| 183 |
href: '#', |
| 184 |
style: { |
| 185 |
display: 'inline-flex', |
| 186 |
alignItems: 'center', |
| 187 |
gap: 4, |
| 188 |
fontSize: 14, |
| 189 |
fontWeight: 600, |
| 190 |
color: a.cardLayout === 'overlay' ? '#fff' : a.linkColor, |
| 191 |
textDecoration: a.linkStyle === 'underline' ? 'underline' : 'none', |
| 192 |
marginTop: 4, |
| 193 |
} |
| 194 |
}, (item.linkLabel || 'Learn more'), a.linkStyle === 'arrow' ? ' →' : '') |
| 195 |
); |
| 196 |
|
| 197 |
var cardContent = []; |
| 198 |
if (a.cardLayout === 'overlay' && hasImage) { |
| 199 |
cardContent = [ |
| 200 |
el('img', { |
| 201 |
src: item.imageUrl, |
| 202 |
alt: item.imageAlt || '', |
| 203 |
style: { |
| 204 |
position: 'absolute', |
| 205 |
inset: '0', |
| 206 |
width: '100%', |
| 207 |
height: '100%', |
| 208 |
objectFit: 'cover', |
| 209 |
display: 'block', |
| 210 |
} |
| 211 |
}), |
| 212 |
body |
| 213 |
]; |
| 214 |
} else if (a.cardLayout === 'horizontal') { |
| 215 |
cardContent = [imageSection, body].filter(Boolean); |
| 216 |
} else { |
| 217 |
cardContent = [imageSection, body].filter(Boolean); |
| 218 |
} |
| 219 |
|
| 220 |
return el('div', { key: idx, className: 'bkbg-cc-card shadow-' + a.cardShadow + ' layout-' + a.cardLayout, style: cardStyle }, ...cardContent); |
| 221 |
} |
| 222 |
|
| 223 |
var BkbgColorSwatch = function (props) { |
| 224 |
var _st = useState(false); var isOpen = _st[0]; var setOpen = _st[1]; |
| 225 |
return el(Fragment, {}, |
| 226 |
el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } }, |
| 227 |
el('span', { style: { fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', color: '#1e1e1e' } }, props.label), |
| 228 |
el('button', { |
| 229 |
type: 'button', |
| 230 |
onClick: function () { setOpen(!isOpen); }, |
| 231 |
style: { width: '28px', height: '28px', borderRadius: '4px', border: '1px solid #ccc', background: props.value || '#ffffff', cursor: 'pointer', padding: 0 } |
| 232 |
}) |
| 233 |
), |
| 234 |
isOpen && el(Popover, { onClose: function () { setOpen(false); } }, |
| 235 |
el('div', { style: { padding: '8px' } }, |
| 236 |
el(ColorPicker, { color: props.value, onChangeComplete: function (c) { props.onChange(c.hex); }, enableAlpha: true }) |
| 237 |
) |
| 238 |
) |
| 239 |
); |
| 240 |
}; |
| 241 |
|
| 242 |
registerBlockType('blockenberg/card-carousel', { |
| 243 |
title: __('Card Carousel', 'blockenberg'), |
| 244 |
icon: 'slides', |
| 245 |
category: 'bkbg-effects', |
| 246 |
description: __('Horizontal drag-to-scroll card carousel with rich cards, autoplay, arrows, dots, and responsive columns.', 'blockenberg'), |
| 247 |
|
| 248 |
edit: function (props) { |
| 249 |
var a = props.attributes; |
| 250 |
var set = props.setAttributes; |
| 251 |
var activeState = useState(0); |
| 252 |
var activeCard = activeState[0]; |
| 253 |
var setActiveCard = activeState[1]; |
| 254 |
var blockProps = useBlockProps({ style: Object.assign({ background: a.containerBg || '', padding: a.padding + 'px' }, _tv(a.typoHeading, '--bkbg-cc-h-'), _tv(a.typoDesc, '--bkbg-cc-d-'), _tv(a.typoEyebrow, '--bkbg-cc-e-')) }); |
| 255 |
|
| 256 |
function addItem() { |
| 257 |
var newItem = { |
| 258 |
eyebrow: 'Category', |
| 259 |
heading: 'New Card Title', |
| 260 |
description: 'Write a short description for this card.', |
| 261 |
imageUrl: '', imageId: 0, imageAlt: '', |
| 262 |
link: '', linkLabel: 'Learn more', |
| 263 |
badge: '', |
| 264 |
accentColor: '#6366f1', |
| 265 |
}; |
| 266 |
set({ items: a.items.concat([newItem]) }); |
| 267 |
} |
| 268 |
|
| 269 |
function removeItem(i) { |
| 270 |
if (a.items.length <= 1) return; |
| 271 |
set({ items: a.items.filter(function (_, idx) { return idx !== i; }) }); |
| 272 |
setActiveCard(Math.max(0, activeCard - 1)); |
| 273 |
} |
| 274 |
|
| 275 |
function moveItem(i, dir) { |
| 276 |
var items = a.items.slice(); |
| 277 |
var j = i + dir; |
| 278 |
if (j < 0 || j >= items.length) return; |
| 279 |
var tmp = items[i]; items[i] = items[j]; items[j] = tmp; |
| 280 |
set({ items: items }); |
| 281 |
setActiveCard(j); |
| 282 |
} |
| 283 |
|
| 284 |
var activeItem = a.items[activeCard] || a.items[0]; |
| 285 |
|
| 286 |
return el(Fragment, null, |
| 287 |
el(InspectorControls, null, |
| 288 |
// Items Panel |
| 289 |
el(PanelBody, { title: 'Cards (' + a.items.length + ')', initialOpen: true }, |
| 290 |
a.items.map(function (item, i) { |
| 291 |
return el('div', { |
| 292 |
key: i, |
| 293 |
style: { |
| 294 |
border: i === activeCard ? '2px solid #6366f1' : '1px solid #e5e7eb', |
| 295 |
borderRadius: 8, |
| 296 |
padding: '8px', |
| 297 |
marginBottom: 8, |
| 298 |
background: i === activeCard ? '#f5f3ff' : '#fff', |
| 299 |
cursor: 'pointer', |
| 300 |
} |
| 301 |
}, |
| 302 |
el('div', { |
| 303 |
style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: i === activeCard ? 8 : 0 }, |
| 304 |
onClick: function () { setActiveCard(i); } |
| 305 |
}, |
| 306 |
el('span', { style: { fontWeight: 600, fontSize: 13, color: '#374151' } }, (i + 1) + '. ' + (item.heading || 'Card')), |
| 307 |
el('div', { style: { display: 'flex', gap: 3 } }, |
| 308 |
el(Button, { onClick: function (e) { e.stopPropagation(); moveItem(i, -1); }, variant: 'tertiary', size: 'small', disabled: i === 0, __nextHasNoMarginBottom: true }, '↑'), |
| 309 |
el(Button, { onClick: function (e) { e.stopPropagation(); moveItem(i, 1); }, variant: 'tertiary', size: 'small', disabled: i === a.items.length - 1, __nextHasNoMarginBottom: true }, '↓'), |
| 310 |
el(Button, { onClick: function (e) { e.stopPropagation(); removeItem(i); }, isDestructive: true, variant: 'tertiary', size: 'small', __nextHasNoMarginBottom: true }, '✕') |
| 311 |
) |
| 312 |
), |
| 313 |
i === activeCard && el(Fragment, null, |
| 314 |
el(TextControl, { |
| 315 |
label: 'Eyebrow', |
| 316 |
value: item.eyebrow, |
| 317 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'eyebrow', v) }); }, |
| 318 |
__nextHasNoMarginBottom: true, |
| 319 |
}), |
| 320 |
el('div', { style: { height: 8 } }), |
| 321 |
el(TextControl, { |
| 322 |
label: 'Heading', |
| 323 |
value: item.heading, |
| 324 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'heading', v) }); }, |
| 325 |
__nextHasNoMarginBottom: true, |
| 326 |
}), |
| 327 |
el('div', { style: { height: 8 } }), |
| 328 |
el(TextControl, { |
| 329 |
label: 'Description', |
| 330 |
value: item.description, |
| 331 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'description', v) }); }, |
| 332 |
__nextHasNoMarginBottom: true, |
| 333 |
}), |
| 334 |
el('div', { style: { height: 8 } }), |
| 335 |
el(TextControl, { |
| 336 |
label: 'Badge', |
| 337 |
value: item.badge, |
| 338 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'badge', v) }); }, |
| 339 |
__nextHasNoMarginBottom: true, |
| 340 |
}), |
| 341 |
el('div', { style: { height: 8 } }), |
| 342 |
el(TextControl, { |
| 343 |
label: 'Link URL', |
| 344 |
value: item.link, |
| 345 |
placeholder: 'https://', |
| 346 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'link', v) }); }, |
| 347 |
__nextHasNoMarginBottom: true, |
| 348 |
}), |
| 349 |
el('div', { style: { height: 8 } }), |
| 350 |
el(TextControl, { |
| 351 |
label: 'Link Label', |
| 352 |
value: item.linkLabel, |
| 353 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'linkLabel', v) }); }, |
| 354 |
__nextHasNoMarginBottom: true, |
| 355 |
}), |
| 356 |
el('div', { style: { height: 8 } }), |
| 357 |
el(BkbgColorSwatch, { |
| 358 |
label: 'Accent Color (hex)', |
| 359 |
value: item.accentColor, |
| 360 |
onChange: function (v) { set({ items: updateItem(a.items, i, 'accentColor', v) }); }, |
| 361 |
}), |
| 362 |
el('div', { style: { height: 8 } }), |
| 363 |
el('div', { style: { marginBottom: 4, fontSize: 11, fontWeight: 600, textTransform: 'uppercase', color: '#6b7280', letterSpacing: '0.5px' } }, 'Image'), |
| 364 |
el(MediaUploadCheck, null, |
| 365 |
el(MediaUpload, { |
| 366 |
onSelect: function (media) { |
| 367 |
var items2 = updateItem(a.items, i, 'imageUrl', media.url); |
| 368 |
items2 = updateItem(items2, i, 'imageId', media.id); |
| 369 |
items2 = updateItem(items2, i, 'imageAlt', media.alt || ''); |
| 370 |
set({ items: items2 }); |
| 371 |
}, |
| 372 |
allowedTypes: ['image'], |
| 373 |
value: item.imageId, |
| 374 |
render: function (ref) { |
| 375 |
return el(Button, { |
| 376 |
onClick: ref.open, |
| 377 |
variant: item.imageUrl ? 'secondary' : 'primary', |
| 378 |
size: 'small', |
| 379 |
__nextHasNoMarginBottom: true, |
| 380 |
}, item.imageUrl ? 'Change Image' : 'Add Image'); |
| 381 |
} |
| 382 |
}) |
| 383 |
), |
| 384 |
item.imageUrl && el(Button, { |
| 385 |
onClick: function () { |
| 386 |
var items2 = updateItem(a.items, i, 'imageUrl', ''); |
| 387 |
items2 = updateItem(items2, i, 'imageId', 0); |
| 388 |
set({ items: items2 }); |
| 389 |
}, |
| 390 |
isDestructive: true, variant: 'link', size: 'small', |
| 391 |
style: { display: 'block', marginTop: 4 }, |
| 392 |
__nextHasNoMarginBottom: true, |
| 393 |
}, 'Remove Image') |
| 394 |
) |
| 395 |
); |
| 396 |
}), |
| 397 |
el(Button, { |
| 398 |
onClick: addItem, |
| 399 |
variant: 'secondary', |
| 400 |
style: { width: '100%', justifyContent: 'center', marginTop: 4 }, |
| 401 |
__nextHasNoMarginBottom: true, |
| 402 |
}, '+ Add Card') |
| 403 |
), |
| 404 |
|
| 405 |
// Layout Panel |
| 406 |
el(PanelBody, { title: 'Layout & Columns', initialOpen: false }, |
| 407 |
el(SelectControl, { |
| 408 |
label: 'Card Layout', |
| 409 |
value: a.cardLayout, |
| 410 |
options: CARD_LAYOUT_OPTIONS, |
| 411 |
onChange: function (v) { set({ cardLayout: v }); }, |
| 412 |
__nextHasNoMarginBottom: true, |
| 413 |
}), |
| 414 |
a.cardLayout !== 'text' && el(Fragment, null, |
| 415 |
el('div', { style: { height: 12 } }), |
| 416 |
el(SelectControl, { |
| 417 |
label: 'Image Aspect Ratio', |
| 418 |
value: a.imageAspect, |
| 419 |
options: ASPECT_OPTIONS, |
| 420 |
onChange: function (v) { set({ imageAspect: v }); }, |
| 421 |
__nextHasNoMarginBottom: true, |
| 422 |
}) |
| 423 |
), |
| 424 |
el('div', { style: { height: 12 } }), |
| 425 |
el(RangeControl, { |
| 426 |
label: 'Desktop Columns', |
| 427 |
value: a.desktopCols, |
| 428 |
min: 1, max: 6, |
| 429 |
onChange: function (v) { set({ desktopCols: v }); }, |
| 430 |
__nextHasNoMarginBottom: true, |
| 431 |
}), |
| 432 |
el('div', { style: { height: 12 } }), |
| 433 |
el(RangeControl, { |
| 434 |
label: 'Tablet Columns', |
| 435 |
value: a.tabletCols, |
| 436 |
min: 1, max: 4, |
| 437 |
onChange: function (v) { set({ tabletCols: v }); }, |
| 438 |
__nextHasNoMarginBottom: true, |
| 439 |
}), |
| 440 |
el('div', { style: { height: 12 } }), |
| 441 |
el(RangeControl, { |
| 442 |
label: 'Mobile Columns', |
| 443 |
value: a.mobileCols, |
| 444 |
min: 1, max: 2, |
| 445 |
onChange: function (v) { set({ mobileCols: v }); }, |
| 446 |
__nextHasNoMarginBottom: true, |
| 447 |
}), |
| 448 |
el('div', { style: { height: 12 } }), |
| 449 |
el(RangeControl, { |
| 450 |
label: 'Gap (px)', |
| 451 |
value: a.gap, |
| 452 |
min: 0, max: 60, |
| 453 |
onChange: function (v) { set({ gap: v }); }, |
| 454 |
__nextHasNoMarginBottom: true, |
| 455 |
}), |
| 456 |
el('div', { style: { height: 12 } }), |
| 457 |
el(RangeControl, { |
| 458 |
label: 'Min Card Height (0 = auto)', |
| 459 |
value: a.cardMinHeight, |
| 460 |
min: 0, max: 600, |
| 461 |
onChange: function (v) { set({ cardMinHeight: v }); }, |
| 462 |
__nextHasNoMarginBottom: true, |
| 463 |
}), |
| 464 |
el('div', { style: { height: 12 } }), |
| 465 |
el(RangeControl, { |
| 466 |
label: 'Card Border Radius (px)', |
| 467 |
value: a.cardBorderRadius, |
| 468 |
min: 0, max: 32, |
| 469 |
onChange: function (v) { set({ cardBorderRadius: v }); }, |
| 470 |
__nextHasNoMarginBottom: true, |
| 471 |
}), |
| 472 |
el('div', { style: { height: 12 } }), |
| 473 |
el(SelectControl, { |
| 474 |
label: 'Card Shadow', |
| 475 |
value: a.cardShadow, |
| 476 |
options: SHADOW_OPTIONS, |
| 477 |
onChange: function (v) { set({ cardShadow: v }); }, |
| 478 |
__nextHasNoMarginBottom: true, |
| 479 |
}), |
| 480 |
el('div', { style: { height: 12 } }), |
| 481 |
el(RangeControl, { |
| 482 |
label: 'Card Inner Padding (px)', |
| 483 |
value: a.cardPadding, |
| 484 |
min: 8, max: 48, |
| 485 |
onChange: function (v) { set({ cardPadding: v }); }, |
| 486 |
__nextHasNoMarginBottom: true, |
| 487 |
}), |
| 488 |
el('div', { style: { height: 12 } }), |
| 489 |
el(RangeControl, { |
| 490 |
label: 'Outer Padding (px)', |
| 491 |
value: a.padding, |
| 492 |
min: 0, max: 80, |
| 493 |
onChange: function (v) { set({ padding: v }); }, |
| 494 |
__nextHasNoMarginBottom: true, |
| 495 |
}) |
| 496 |
), |
| 497 |
|
| 498 |
// Navigation Panel |
| 499 |
el(PanelBody, { title: 'Navigation & Autoplay', initialOpen: false }, |
| 500 |
el(ToggleControl, { |
| 501 |
label: 'Show Arrows', |
| 502 |
checked: a.showArrows, |
| 503 |
onChange: function (v) { set({ showArrows: v }); }, |
| 504 |
__nextHasNoMarginBottom: true, |
| 505 |
}), |
| 506 |
el('div', { style: { height: 8 } }), |
| 507 |
el(ToggleControl, { |
| 508 |
label: 'Show Dots', |
| 509 |
checked: a.showDots, |
| 510 |
onChange: function (v) { set({ showDots: v }); }, |
| 511 |
__nextHasNoMarginBottom: true, |
| 512 |
}), |
| 513 |
el('div', { style: { height: 8 } }), |
| 514 |
el(ToggleControl, { |
| 515 |
label: 'Loop (infinite)', |
| 516 |
checked: a.loop, |
| 517 |
onChange: function (v) { set({ loop: v }); }, |
| 518 |
__nextHasNoMarginBottom: true, |
| 519 |
}), |
| 520 |
el('div', { style: { height: 8 } }), |
| 521 |
el(ToggleControl, { |
| 522 |
label: 'Autoplay', |
| 523 |
checked: a.autoplay, |
| 524 |
onChange: function (v) { set({ autoplay: v }); }, |
| 525 |
__nextHasNoMarginBottom: true, |
| 526 |
}), |
| 527 |
a.autoplay && el(Fragment, null, |
| 528 |
el('div', { style: { height: 8 } }), |
| 529 |
el(RangeControl, { |
| 530 |
label: 'Autoplay Speed (ms)', |
| 531 |
value: a.autoplaySpeed, |
| 532 |
min: 1000, max: 10000, step: 500, |
| 533 |
onChange: function (v) { set({ autoplaySpeed: v }); }, |
| 534 |
__nextHasNoMarginBottom: true, |
| 535 |
}), |
| 536 |
el('div', { style: { height: 8 } }), |
| 537 |
el(ToggleControl, { |
| 538 |
label: 'Pause on Hover', |
| 539 |
checked: a.pauseOnHover, |
| 540 |
onChange: function (v) { set({ pauseOnHover: v }); }, |
| 541 |
__nextHasNoMarginBottom: true, |
| 542 |
}) |
| 543 |
) |
| 544 |
), |
| 545 |
|
| 546 |
// Content Toggles Panel |
| 547 |
el(PanelBody, { title: 'Card Content', initialOpen: false }, |
| 548 |
el(ToggleControl, { |
| 549 |
label: 'Show Badge', |
| 550 |
checked: a.showBadge, |
| 551 |
onChange: function (v) { set({ showBadge: v }); }, |
| 552 |
__nextHasNoMarginBottom: true, |
| 553 |
}), |
| 554 |
el('div', { style: { height: 8 } }), |
| 555 |
el(ToggleControl, { |
| 556 |
label: 'Show Eyebrow', |
| 557 |
checked: a.showEyebrow, |
| 558 |
onChange: function (v) { set({ showEyebrow: v }); }, |
| 559 |
__nextHasNoMarginBottom: true, |
| 560 |
}), |
| 561 |
el('div', { style: { height: 8 } }), |
| 562 |
el(ToggleControl, { |
| 563 |
label: 'Show Description', |
| 564 |
checked: a.showDescription, |
| 565 |
onChange: function (v) { set({ showDescription: v }); }, |
| 566 |
__nextHasNoMarginBottom: true, |
| 567 |
}), |
| 568 |
el('div', { style: { height: 8 } }), |
| 569 |
el(ToggleControl, { |
| 570 |
label: 'Show Link', |
| 571 |
checked: a.showLink, |
| 572 |
onChange: function (v) { set({ showLink: v }); }, |
| 573 |
__nextHasNoMarginBottom: true, |
| 574 |
}), |
| 575 |
a.showLink && el(Fragment, null, |
| 576 |
el('div', { style: { height: 8 } }), |
| 577 |
el(SelectControl, { |
| 578 |
label: 'Link Style', |
| 579 |
value: a.linkStyle, |
| 580 |
options: LINK_STYLE_OPTIONS, |
| 581 |
onChange: function (v) { set({ linkStyle: v }); }, |
| 582 |
__nextHasNoMarginBottom: true, |
| 583 |
}) |
| 584 |
), |
| 585 |
el('div', { style: { height: 12 } }), |
| 586 |
el('div', { style: { height: 8 } }), |
| 587 |
el('div', { style: { height: 8 } }), |
| 588 |
), |
| 589 |
|
| 590 |
// Colors Panel |
| 591 |
|
| 592 |
el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false }, |
| 593 |
el(getTypographyControl(), { label: __('Heading', 'blockenberg'), value: a.typoHeading, onChange: function (v) { set({ typoHeading: v }); } }), |
| 594 |
el(getTypographyControl(), { label: __('Description', 'blockenberg'), value: a.typoDesc, onChange: function (v) { set({ typoDesc: v }); } }), |
| 595 |
el(getTypographyControl(), { label: __('Eyebrow', 'blockenberg'), value: a.typoEyebrow, onChange: function (v) { set({ typoEyebrow: v }); } }) |
| 596 |
), |
| 597 |
el(PanelColorSettings, { |
| 598 |
title: 'Colors', |
| 599 |
initialOpen: false, |
| 600 |
colorSettings: [ |
| 601 |
{ label: 'Container Background', value: a.containerBg, onChange: function (v) { set({ containerBg: v || '' }); } }, |
| 602 |
{ label: 'Card Background', value: a.cardBg, onChange: function (v) { set({ cardBg: v || '#ffffff' }); } }, |
| 603 |
{ label: 'Eyebrow Color', value: a.eyebrowColor, onChange: function (v) { set({ eyebrowColor: v || '#6366f1' }); } }, |
| 604 |
{ label: 'Heading Color', value: a.headingColor, onChange: function (v) { set({ headingColor: v || '#111827' }); } }, |
| 605 |
{ label: 'Text Color', value: a.textColor, onChange: function (v) { set({ textColor: v || '#6b7280' }); } }, |
| 606 |
{ label: 'Link Color', value: a.linkColor, onChange: function (v) { set({ linkColor: v || '#6366f1' }); } }, |
| 607 |
{ label: 'Badge Background', value: a.badgeBg, onChange: function (v) { set({ badgeBg: v || '#ede9fe' }); } }, |
| 608 |
{ label: 'Badge Text', value: a.badgeColor, onChange: function (v) { set({ badgeColor: v || '#6366f1' }); } }, |
| 609 |
{ label: 'Arrow Background', value: a.arrowBg, onChange: function (v) { set({ arrowBg: v || '#ffffff' }); } }, |
| 610 |
{ label: 'Arrow Color', value: a.arrowColor, onChange: function (v) { set({ arrowColor: v || '#111827' }); } }, |
| 611 |
{ label: 'Active Dot Color', value: a.dotActiveColor, onChange: function (v) { set({ dotActiveColor: v || '#6366f1' }); } }, |
| 612 |
{ label: 'Inactive Dot Color', value: a.dotInactiveColor, onChange: function (v) { set({ dotInactiveColor: v || '#d1d5db' }); } }, |
| 613 |
] |
| 614 |
}) |
| 615 |
), |
| 616 |
|
| 617 |
// Editor Preview |
| 618 |
el('div', blockProps, |
| 619 |
// Cards strip (horizontal scroll preview) |
| 620 |
el('div', { |
| 621 |
style: { |
| 622 |
display: 'flex', |
| 623 |
gap: a.gap + 'px', |
| 624 |
overflowX: 'auto', |
| 625 |
paddingBottom: 8, |
| 626 |
} |
| 627 |
}, |
| 628 |
a.items.map(function (item, i) { |
| 629 |
return renderCardPreview(item, a, i); |
| 630 |
}) |
| 631 |
), |
| 632 |
// Navigation preview |
| 633 |
el('div', { style: { marginTop: 16, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 16 } }, |
| 634 |
a.showArrows && el('button', { |
| 635 |
disabled: true, |
| 636 |
style: { |
| 637 |
width: 36, height: 36, borderRadius: '50%', |
| 638 |
background: a.arrowBg, border: '1px solid #e5e7eb', |
| 639 |
color: a.arrowColor, cursor: 'not-allowed', fontSize: 16, |
| 640 |
} |
| 641 |
}, '←'), |
| 642 |
a.showDots && el('div', { style: { display: 'flex', gap: 6 } }, |
| 643 |
a.items.map(function (_, i) { |
| 644 |
return el('div', { |
| 645 |
key: i, |
| 646 |
style: { |
| 647 |
width: i === 0 ? 20 : 8, |
| 648 |
height: 8, |
| 649 |
borderRadius: 999, |
| 650 |
background: i === 0 ? a.dotActiveColor : a.dotInactiveColor, |
| 651 |
transition: 'all 0.3s', |
| 652 |
} |
| 653 |
}); |
| 654 |
}) |
| 655 |
), |
| 656 |
a.showArrows && el('button', { |
| 657 |
disabled: true, |
| 658 |
style: { |
| 659 |
width: 36, height: 36, borderRadius: '50%', |
| 660 |
background: a.arrowBg, border: '1px solid #e5e7eb', |
| 661 |
color: a.arrowColor, cursor: 'not-allowed', fontSize: 16, |
| 662 |
} |
| 663 |
}, '→') |
| 664 |
), |
| 665 |
// Info strip |
| 666 |
el('div', { style: { marginTop: 8, fontSize: 11, color: '#9ca3af', textAlign: 'center' } }, |
| 667 |
'🎠 ' + a.items.length + ' cards | Desktop: ' + a.desktopCols + ' cols | Autoplay: ' + (a.autoplay ? 'on' : 'off') + ' | Drag enabled on frontend' |
| 668 |
) |
| 669 |
) |
| 670 |
); |
| 671 |
}, |
| 672 |
|
| 673 |
save: function (props) { |
| 674 |
return el('div', useBlockProps.save(), |
| 675 |
el('div', { |
| 676 |
className: 'bkbg-cc-app', |
| 677 |
'data-opts': JSON.stringify(props.attributes), |
| 678 |
}) |
| 679 |
); |
| 680 |
} |
| 681 |
}); |
| 682 |
}() ); |
| 683 |
|