| 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 useBlockProps = wp.blockEditor.useBlockProps; |
| 9 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 10 |
var PanelBody = wp.components.PanelBody; |
| 11 |
var ToggleControl = wp.components.ToggleControl; |
| 12 |
var RangeControl = wp.components.RangeControl; |
| 13 |
var SelectControl = wp.components.SelectControl; |
| 14 |
var TextControl = wp.components.TextControl; |
| 15 |
var Button = wp.components.Button; |
| 16 |
|
| 17 |
var _tc, _tvf; |
| 18 |
Object.defineProperty(window, '_tc', { get: function () { return _tc || (_tc = window.bkbgTypographyControl); } }); |
| 19 |
Object.defineProperty(window, '_tvf', { get: function () { return _tvf || (_tvf = window.bkbgTypoCssVars); } }); |
| 20 |
function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); } |
| 21 |
function getTypoCssVars(attrs) { |
| 22 |
var v = {}; |
| 23 |
_tvf(v, 'titleTypo', attrs, '--bkwfc-tt-'); |
| 24 |
return v; |
| 25 |
} |
| 26 |
|
| 27 |
/* ── updateItem (ES5 safe) ── */ |
| 28 |
function updateItem(arr, idx, field, val) { |
| 29 |
return arr.map(function (item, i) { |
| 30 |
if (i !== idx) return item; |
| 31 |
var p = {}; p[field] = val; |
| 32 |
return Object.assign({}, item, p); |
| 33 |
}); |
| 34 |
} |
| 35 |
|
| 36 |
/* ── abbreviate large numbers ── */ |
| 37 |
function abbr(n, prefix, suffix, doAbbr) { |
| 38 |
var abs = Math.abs(n); |
| 39 |
var sign = n < 0 ? '-' : ''; |
| 40 |
var str; |
| 41 |
if (!doAbbr || abs < 1000) { |
| 42 |
str = abs.toLocaleString(); |
| 43 |
} else if (abs < 1000000) { |
| 44 |
str = (abs / 1000).toFixed(1).replace(/\.0$/, '') + 'K'; |
| 45 |
} else if (abs < 1000000000) { |
| 46 |
str = (abs / 1000000).toFixed(1).replace(/\.0$/, '') + 'M'; |
| 47 |
} else { |
| 48 |
str = (abs / 1000000000).toFixed(1).replace(/\.0$/, '') + 'B'; |
| 49 |
} |
| 50 |
return sign + prefix + str + suffix; |
| 51 |
} |
| 52 |
|
| 53 |
/* ── type label ── */ |
| 54 |
var TYPE_LABELS = { |
| 55 |
start: __('Starting value', 'blockenberg'), |
| 56 |
increase: __('Increase (+)', 'blockenberg'), |
| 57 |
decrease: __('Decrease (−)', 'blockenberg'), |
| 58 |
total: __('Total / Net', 'blockenberg') |
| 59 |
}; |
| 60 |
var TYPE_OPTIONS = [ |
| 61 |
{ label: __('Starting value', 'blockenberg'), value: 'start' }, |
| 62 |
{ label: __('Increase (+)', 'blockenberg'), value: 'increase' }, |
| 63 |
{ label: __('Decrease (−)', 'blockenberg'), value: 'decrease' }, |
| 64 |
{ label: __('Total / Net', 'blockenberg'), value: 'total' } |
| 65 |
]; |
| 66 |
|
| 67 |
/* ── color for type ── */ |
| 68 |
function typeColor(type, a) { |
| 69 |
if (type === 'start') return a.startColor; |
| 70 |
if (type === 'increase') return a.increaseColor; |
| 71 |
if (type === 'decrease') return a.decreaseColor; |
| 72 |
return a.totalColor; |
| 73 |
} |
| 74 |
|
| 75 |
/* ── compute bar segments for preview ── */ |
| 76 |
/* Returns array of { label, type, base, top, barColor, displayValue } */ |
| 77 |
function computeSegments(items, a) { |
| 78 |
var running = 0; |
| 79 |
return items.map(function (item) { |
| 80 |
var v = parseFloat(item.value) || 0; |
| 81 |
var type = item.type || 'increase'; |
| 82 |
var base, top; |
| 83 |
|
| 84 |
if (type === 'start') { |
| 85 |
base = 0; top = v; running = v; |
| 86 |
} else if (type === 'total') { |
| 87 |
base = 0; top = running; /* running stays same */ |
| 88 |
} else if (type === 'increase') { |
| 89 |
base = running; top = running + v; running = top; |
| 90 |
} else { /* decrease */ |
| 91 |
top = running; base = running + v; running = base; |
| 92 |
} |
| 93 |
|
| 94 |
return { |
| 95 |
label: item.label, |
| 96 |
type: type, |
| 97 |
base: base, |
| 98 |
top: top, |
| 99 |
barColor: typeColor(type, a), |
| 100 |
displayValue: v, |
| 101 |
runningAfter: running |
| 102 |
}; |
| 103 |
}); |
| 104 |
} |
| 105 |
|
| 106 |
/* ── SVG bar chart preview in editor ── */ |
| 107 |
function WaterfallPreview(props) { |
| 108 |
var a = props.attributes; |
| 109 |
var items = a.items; |
| 110 |
if (!items || !items.length) return el('div', {}, 'No data.'); |
| 111 |
|
| 112 |
var segs = computeSegments(items, a); |
| 113 |
var allVals = segs.map(function (s) { return s.top; }).concat(segs.map(function (s) { return s.base; })); |
| 114 |
var maxVal = Math.max.apply(null, allVals); |
| 115 |
var minVal = Math.min.apply(null, allVals.concat([0])); |
| 116 |
var range = maxVal - minVal || 1; |
| 117 |
|
| 118 |
var svgW = 600, svgH = Math.min(a.height, 320); |
| 119 |
var padLeft = 55, padRight = 16, padTop = 20, padBottom = 36; |
| 120 |
var chartW = svgW - padLeft - padRight; |
| 121 |
var chartH = svgH - padTop - padBottom; |
| 122 |
var barW = Math.min(a.barThickness, Math.floor(chartW / items.length) - 6); |
| 123 |
var step = chartW / items.length; |
| 124 |
|
| 125 |
function yPx(v) { return padTop + chartH - ((v - minVal) / range) * chartH; } |
| 126 |
|
| 127 |
var bars = segs.map(function (s, i) { |
| 128 |
var x = padLeft + i * step + (step - barW) / 2; |
| 129 |
var y1 = yPx(Math.max(s.base, s.top)); |
| 130 |
var y2 = yPx(Math.min(s.base, s.top)); |
| 131 |
var bh = Math.max(y2 - y1, 2); |
| 132 |
return { x: x, y: y1, width: barW, height: bh, seg: s, cx: x + barW / 2 }; |
| 133 |
}); |
| 134 |
|
| 135 |
var gridLines = []; |
| 136 |
var gridCount = 5; |
| 137 |
for (var g = 0; g <= gridCount; g++) { |
| 138 |
var gv = minVal + (range / gridCount) * g; |
| 139 |
var gy = yPx(gv); |
| 140 |
gridLines.push(el('line', { key: 'gl' + g, x1: padLeft, x2: svgW - padRight, y1: gy, y2: gy, stroke: a.gridColor, strokeWidth: 1, strokeDasharray: '4,3' })); |
| 141 |
gridLines.push(el('text', { key: 'glt' + g, x: padLeft - 4, y: gy + 4, textAnchor: 'end', fontSize: 9, fill: a.labelColor }, |
| 142 |
abbr(gv, a.valuePrefix, a.valueSuffix, a.abbreviate) |
| 143 |
)); |
| 144 |
} |
| 145 |
|
| 146 |
var connectors = []; |
| 147 |
if (a.showConnectors) { |
| 148 |
for (var ci = 0; ci < bars.length - 1; ci++) { |
| 149 |
var curr = bars[ci]; |
| 150 |
var next = bars[ci + 1]; |
| 151 |
var connY = yPx(segs[ci].type === 'decrease' ? segs[ci].base : segs[ci].top); |
| 152 |
connectors.push(el('line', { |
| 153 |
key: 'conn' + ci, |
| 154 |
x1: curr.x + curr.width, x2: next.x, |
| 155 |
y1: connY, y2: connY, |
| 156 |
stroke: a.connectorColor, strokeWidth: 1.5, strokeDasharray: '4,3' |
| 157 |
})); |
| 158 |
} |
| 159 |
} |
| 160 |
|
| 161 |
return el('div', { style: { background: a.bgColor, borderRadius: '8px' } }, |
| 162 |
a.showTitle && a.title ? el('div', { |
| 163 |
className: 'bkbg-wfc-title', |
| 164 |
style: { color: a.titleColor, padding: '0 0 12px' } |
| 165 |
}, a.title) : null, |
| 166 |
el('svg', { width: '100%', viewBox: '0 0 600 ' + svgH, style: { display: 'block', maxWidth: '100%' } }, |
| 167 |
a.showGrid ? el('g', {}, gridLines) : null, |
| 168 |
el('line', { x1: padLeft, x2: svgW - padRight, y1: yPx(0), y2: yPx(0), stroke: a.gridColor, strokeWidth: 1.5 }), |
| 169 |
el('g', {}, connectors), |
| 170 |
el('g', {}, |
| 171 |
bars.map(function (b, i) { |
| 172 |
return el('g', { key: i }, |
| 173 |
el('rect', { |
| 174 |
x: b.x, y: b.y, width: b.width, height: b.height, |
| 175 |
fill: b.seg.barColor, rx: a.borderRadius |
| 176 |
}), |
| 177 |
a.showDataLabels ? el('text', { |
| 178 |
x: b.cx, y: b.y - 4, textAnchor: 'middle', |
| 179 |
fontSize: a.valueSize, fill: b.seg.barColor, fontWeight: 700, fontFamily: 'system-ui,sans-serif' |
| 180 |
}, abbr(b.seg.displayValue, a.valuePrefix, a.valueSuffix, a.abbreviate)) : null, |
| 181 |
el('text', { |
| 182 |
x: b.cx, y: svgH - 4, textAnchor: 'middle', |
| 183 |
fontSize: a.labelSize, fill: a.labelColor, fontFamily: 'system-ui,sans-serif' |
| 184 |
}, b.seg.label.length > 10 ? b.seg.label.slice(0, 9) + '…' : b.seg.label) |
| 185 |
); |
| 186 |
}) |
| 187 |
) |
| 188 |
), |
| 189 |
a.showLegend ? el('div', { |
| 190 |
style: { display: 'flex', flexWrap: 'wrap', gap: '10px 18px', padding: '10px 0 0', fontFamily: 'system-ui,sans-serif' } |
| 191 |
}, |
| 192 |
[['start', 'Start', a.startColor], ['increase', 'Increase', a.increaseColor], ['decrease', 'Decrease', a.decreaseColor], ['total', 'Total', a.totalColor]].map(function (row) { |
| 193 |
return el('div', { key: row[0], style: { display: 'flex', alignItems: 'center', gap: '5px' } }, |
| 194 |
el('span', { style: { width: '12px', height: '12px', borderRadius: '3px', background: row[2], display: 'inline-block', flexShrink: 0 } }), |
| 195 |
el('span', { style: { fontSize: '12px', color: a.labelColor } }, row[1]) |
| 196 |
); |
| 197 |
}) |
| 198 |
) : null |
| 199 |
); |
| 200 |
} |
| 201 |
|
| 202 |
/* ── item list editor ── */ |
| 203 |
function ItemEditor(props) { |
| 204 |
var items = props.items; |
| 205 |
var setItems = props.setItems; |
| 206 |
var expanded = props.expanded; |
| 207 |
var setExpanded = props.setExpanded; |
| 208 |
|
| 209 |
return el('div', {}, |
| 210 |
items.map(function (item, i) { |
| 211 |
var isOpen = expanded === i; |
| 212 |
var col = {start:'#6366f1',increase:'#10b981',decrease:'#ef4444',total:'#8b5cf6'}[item.type] || '#6b7280'; |
| 213 |
return el('div', { |
| 214 |
key: i, |
| 215 |
style: { border: '1px solid #e5e7eb', borderRadius: '6px', marginBottom: '5px', overflow: 'hidden' } |
| 216 |
}, |
| 217 |
el('div', { |
| 218 |
onClick: function () { setExpanded(isOpen ? -1 : i); }, |
| 219 |
style: { |
| 220 |
padding: '7px 10px', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '8px', |
| 221 |
background: isOpen ? '#f9fafb' : '#fff', |
| 222 |
borderBottom: isOpen ? '1px solid #e5e7eb' : 'none' |
| 223 |
} |
| 224 |
}, |
| 225 |
el('span', { style: { width: '10px', height: '10px', borderRadius: '2px', background: col, flexShrink: 0 } }), |
| 226 |
el('span', { style: { flex: 1, fontSize: '12px', color: '#374151', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, |
| 227 |
item.label || '(empty)' |
| 228 |
), |
| 229 |
el('span', { style: { fontSize: '11px', color: '#9ca3af', marginRight: '4px' } }, |
| 230 |
(item.value > 0 ? '+' : '') + (item.value || 0) |
| 231 |
), |
| 232 |
el('button', { |
| 233 |
onClick: function (e) { |
| 234 |
e.stopPropagation(); |
| 235 |
if (items.length <= 2) return; |
| 236 |
setItems(items.filter(function (_, j) { return j !== i; })); |
| 237 |
setExpanded(-1); |
| 238 |
}, |
| 239 |
style: { background: 'none', border: 'none', cursor: 'pointer', color: '#ef4444', fontSize: '14px', padding: '0 2px', lineHeight: 1 } |
| 240 |
}, '×'), |
| 241 |
el('span', { style: { color: '#9ca3af', fontSize: '10px' } }, isOpen ? '▲' : '▼') |
| 242 |
), |
| 243 |
isOpen ? el('div', { style: { padding: '10px' } }, |
| 244 |
el(TextControl, { |
| 245 |
__nextHasNoMarginBottom: true, |
| 246 |
label: __('Label', 'blockenberg'), |
| 247 |
value: item.label, |
| 248 |
onChange: function (v) { setItems(updateItem(items, i, 'label', v)); } |
| 249 |
}), |
| 250 |
el('div', { style: { marginTop: '8px' } }, |
| 251 |
el(TextControl, { |
| 252 |
__nextHasNoMarginBottom: true, |
| 253 |
label: __('Value (negative = decrease)', 'blockenberg'), |
| 254 |
type: 'number', |
| 255 |
value: item.value, |
| 256 |
onChange: function (v) { setItems(updateItem(items, i, 'value', parseFloat(v) || 0)); } |
| 257 |
}) |
| 258 |
), |
| 259 |
el('div', { style: { marginTop: '8px' } }, |
| 260 |
el(SelectControl, { |
| 261 |
__nextHasNoMarginBottom: true, |
| 262 |
label: __('Type', 'blockenberg'), |
| 263 |
value: item.type, |
| 264 |
options: TYPE_OPTIONS, |
| 265 |
onChange: function (v) { setItems(updateItem(items, i, 'type', v)); } |
| 266 |
}) |
| 267 |
), |
| 268 |
el('div', { style: { display: 'flex', gap: '6px', marginTop: '8px' } }, |
| 269 |
i > 0 ? el(Button, { |
| 270 |
variant: 'secondary', style: { fontSize: '11px' }, |
| 271 |
onClick: function () { |
| 272 |
var arr = items.slice(); var tmp = arr[i - 1]; arr[i - 1] = arr[i]; arr[i] = tmp; |
| 273 |
setItems(arr); setExpanded(i - 1); |
| 274 |
} |
| 275 |
}, '↑') : null, |
| 276 |
i < items.length - 1 ? el(Button, { |
| 277 |
variant: 'secondary', style: { fontSize: '11px' }, |
| 278 |
onClick: function () { |
| 279 |
var arr = items.slice(); var tmp = arr[i + 1]; arr[i + 1] = arr[i]; arr[i] = tmp; |
| 280 |
setItems(arr); setExpanded(i + 1); |
| 281 |
} |
| 282 |
}, '↓') : null, |
| 283 |
el(Button, { |
| 284 |
variant: 'secondary', style: { fontSize: '11px' }, |
| 285 |
onClick: function () { |
| 286 |
var copy = Object.assign({}, item, { label: item.label + ' (copy)' }); |
| 287 |
var arr = items.slice(); arr.splice(i + 1, 0, copy); |
| 288 |
setItems(arr); setExpanded(i + 1); |
| 289 |
} |
| 290 |
}, __('Dup', 'blockenberg')) |
| 291 |
) |
| 292 |
) : null |
| 293 |
); |
| 294 |
}), |
| 295 |
el('div', { style: { marginTop: '8px', display: 'flex', gap: '6px' } }, |
| 296 |
el(Button, { |
| 297 |
variant: 'primary', style: { flex: 1, justifyContent: 'center' }, |
| 298 |
onClick: function () { |
| 299 |
var arr = items.slice(); |
| 300 |
arr.push({ label: 'New item', value: 0, type: 'increase' }); |
| 301 |
setItems(arr); setExpanded(arr.length - 1); |
| 302 |
} |
| 303 |
}, __('+ Add Item', 'blockenberg')), |
| 304 |
el(Button, { |
| 305 |
variant: 'secondary', style: { justifyContent: 'center' }, |
| 306 |
onClick: function () { |
| 307 |
var arr = items.slice(); |
| 308 |
arr.push({ label: 'Total', value: 0, type: 'total' }); |
| 309 |
setItems(arr); setExpanded(arr.length - 1); |
| 310 |
} |
| 311 |
}, __('+ Total', 'blockenberg')) |
| 312 |
) |
| 313 |
); |
| 314 |
} |
| 315 |
|
| 316 |
/* ── register ── */ |
| 317 |
registerBlockType('blockenberg/waterfall-chart', { |
| 318 |
edit: function (props) { |
| 319 |
var a = props.attributes; |
| 320 |
var setAttributes = props.setAttributes; |
| 321 |
|
| 322 |
var expState = useState(-1); |
| 323 |
var expanded = expState[0]; |
| 324 |
var setExpanded = expState[1]; |
| 325 |
|
| 326 |
function setItems(v) { setAttributes({ items: v }); } |
| 327 |
|
| 328 |
var blockProps = useBlockProps({ className: 'bkbg-wfc-editor-wrap' }); |
| 329 |
|
| 330 |
return el(Fragment, {}, |
| 331 |
|
| 332 |
el(InspectorControls, {}, |
| 333 |
|
| 334 |
/* ── Data ── */ |
| 335 |
el(PanelBody, { title: __('Chart Data', 'blockenberg'), initialOpen: true }, |
| 336 |
el(ItemEditor, { |
| 337 |
items: a.items, |
| 338 |
setItems: setItems, |
| 339 |
expanded: expanded, |
| 340 |
setExpanded: setExpanded |
| 341 |
}) |
| 342 |
), |
| 343 |
|
| 344 |
/* ── Labels ── */ |
| 345 |
el(PanelBody, { title: __('Labels & Format', 'blockenberg'), initialOpen: false }, |
| 346 |
el(TextControl, { |
| 347 |
__nextHasNoMarginBottom: true, |
| 348 |
label: __('Chart title', 'blockenberg'), |
| 349 |
value: a.title, |
| 350 |
onChange: function (v) { setAttributes({ title: v }); } |
| 351 |
}), |
| 352 |
el('div', { style: { marginTop: '10px' } }, |
| 353 |
el(ToggleControl, { |
| 354 |
__nextHasNoMarginBottom: true, |
| 355 |
label: __('Show title', 'blockenberg'), |
| 356 |
checked: a.showTitle, |
| 357 |
onChange: function (v) { setAttributes({ showTitle: v }); } |
| 358 |
}) |
| 359 |
), |
| 360 |
el('div', { style: { marginTop: '10px', display: 'flex', gap: '8px' } }, |
| 361 |
el('div', { style: { flex: 1 } }, |
| 362 |
el(TextControl, { |
| 363 |
__nextHasNoMarginBottom: true, |
| 364 |
label: __('Value prefix', 'blockenberg'), |
| 365 |
value: a.valuePrefix, |
| 366 |
onChange: function (v) { setAttributes({ valuePrefix: v }); } |
| 367 |
}) |
| 368 |
), |
| 369 |
el('div', { style: { flex: 1 } }, |
| 370 |
el(TextControl, { |
| 371 |
__nextHasNoMarginBottom: true, |
| 372 |
label: __('Value suffix', 'blockenberg'), |
| 373 |
value: a.valueSuffix, |
| 374 |
onChange: function (v) { setAttributes({ valueSuffix: v }); } |
| 375 |
}) |
| 376 |
) |
| 377 |
), |
| 378 |
el('div', { style: { marginTop: '10px' } }, |
| 379 |
el(ToggleControl, { |
| 380 |
__nextHasNoMarginBottom: true, |
| 381 |
label: __('Abbreviate large values (K, M, B)', 'blockenberg'), |
| 382 |
checked: a.abbreviate, |
| 383 |
onChange: function (v) { setAttributes({ abbreviate: v }); } |
| 384 |
}) |
| 385 |
) |
| 386 |
), |
| 387 |
|
| 388 |
/* ── Appearance ── */ |
| 389 |
el(PanelBody, { title: __('Appearance', 'blockenberg'), initialOpen: false }, |
| 390 |
el(RangeControl, { |
| 391 |
__nextHasNoMarginBottom: true, |
| 392 |
label: __('Chart height (px)', 'blockenberg'), |
| 393 |
value: a.height, min: 200, max: 700, |
| 394 |
onChange: function (v) { setAttributes({ height: v }); } |
| 395 |
}), |
| 396 |
el('div', { style: { marginTop: '10px' } }, |
| 397 |
el(RangeControl, { |
| 398 |
__nextHasNoMarginBottom: true, |
| 399 |
label: __('Bar max thickness (px)', 'blockenberg'), |
| 400 |
value: a.barThickness, min: 20, max: 100, |
| 401 |
onChange: function (v) { setAttributes({ barThickness: v }); } |
| 402 |
}) |
| 403 |
), |
| 404 |
el('div', { style: { marginTop: '10px' } }, |
| 405 |
el(RangeControl, { |
| 406 |
__nextHasNoMarginBottom: true, |
| 407 |
label: __('Bar border radius (px)', 'blockenberg'), |
| 408 |
value: a.borderRadius, min: 0, max: 20, |
| 409 |
onChange: function (v) { setAttributes({ borderRadius: v }); } |
| 410 |
}) |
| 411 |
), |
| 412 |
el('div', { style: { marginTop: '10px' } }, |
| 413 |
el(RangeControl, { |
| 414 |
__nextHasNoMarginBottom: true, |
| 415 |
label: __('Max width (px)', 'blockenberg'), |
| 416 |
value: a.maxWidth, min: 400, max: 1400, |
| 417 |
onChange: function (v) { setAttributes({ maxWidth: v }); } |
| 418 |
}) |
| 419 |
), |
| 420 |
el('div', { style: { marginTop: '10px' } }, |
| 421 |
el(ToggleControl, { |
| 422 |
__nextHasNoMarginBottom: true, |
| 423 |
label: __('Show connector lines', 'blockenberg'), |
| 424 |
checked: a.showConnectors, |
| 425 |
onChange: function (v) { setAttributes({ showConnectors: v }); } |
| 426 |
}) |
| 427 |
), |
| 428 |
el('div', { style: { marginTop: '4px' } }, |
| 429 |
el(ToggleControl, { |
| 430 |
__nextHasNoMarginBottom: true, |
| 431 |
label: __('Show data labels', 'blockenberg'), |
| 432 |
checked: a.showDataLabels, |
| 433 |
onChange: function (v) { setAttributes({ showDataLabels: v }); } |
| 434 |
}) |
| 435 |
), |
| 436 |
el('div', { style: { marginTop: '4px' } }, |
| 437 |
el(ToggleControl, { |
| 438 |
__nextHasNoMarginBottom: true, |
| 439 |
label: __('Show grid lines', 'blockenberg'), |
| 440 |
checked: a.showGrid, |
| 441 |
onChange: function (v) { setAttributes({ showGrid: v }); } |
| 442 |
}) |
| 443 |
), |
| 444 |
el('div', { style: { marginTop: '4px' } }, |
| 445 |
el(ToggleControl, { |
| 446 |
__nextHasNoMarginBottom: true, |
| 447 |
label: __('Show legend', 'blockenberg'), |
| 448 |
checked: a.showLegend, |
| 449 |
onChange: function (v) { setAttributes({ showLegend: v }); } |
| 450 |
}) |
| 451 |
), |
| 452 |
el('div', { style: { marginTop: '10px', display: 'flex', gap: '8px' } }, |
| 453 |
el('div', { style: { flex: 1 } }, |
| 454 |
el(RangeControl, { |
| 455 |
__nextHasNoMarginBottom: true, |
| 456 |
label: __('Padding top', 'blockenberg'), |
| 457 |
value: a.paddingTop, min: 0, max: 120, |
| 458 |
onChange: function (v) { setAttributes({ paddingTop: v }); } |
| 459 |
}) |
| 460 |
), |
| 461 |
el('div', { style: { flex: 1 } }, |
| 462 |
el(RangeControl, { |
| 463 |
__nextHasNoMarginBottom: true, |
| 464 |
label: __('Padding bottom', 'blockenberg'), |
| 465 |
value: a.paddingBottom, min: 0, max: 120, |
| 466 |
onChange: function (v) { setAttributes({ paddingBottom: v }); } |
| 467 |
}) |
| 468 |
) |
| 469 |
) |
| 470 |
), |
| 471 |
|
| 472 |
/* ── Colors ── */ |
| 473 |
|
| 474 |
el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false }, |
| 475 |
getTypoControl( __( 'Title', 'blockenberg' ), 'titleTypo', a, setAttributes ), |
| 476 |
el('div', { style: { marginTop: '10px', display: 'flex', gap: '8px' } }, |
| 477 |
el('div', { style: { flex: 1 } }, |
| 478 |
el(RangeControl, { |
| 479 |
__nextHasNoMarginBottom: true, |
| 480 |
label: __('Label size', 'blockenberg'), |
| 481 |
value: a.labelSize, min: 8, max: 18, |
| 482 |
onChange: function (v) { setAttributes({ labelSize: v }); } |
| 483 |
}) |
| 484 |
), |
| 485 |
el('div', { style: { flex: 1 } }, |
| 486 |
el(RangeControl, { |
| 487 |
__nextHasNoMarginBottom: true, |
| 488 |
label: __('Value size', 'blockenberg'), |
| 489 |
value: a.valueSize, min: 8, max: 18, |
| 490 |
onChange: function (v) { setAttributes({ valueSize: v }); } |
| 491 |
}) |
| 492 |
) |
| 493 |
) |
| 494 |
), |
| 495 |
el(PanelColorSettings, { |
| 496 |
title: __('Colors', 'blockenberg'), |
| 497 |
initialOpen: false, |
| 498 |
colorSettings: [ |
| 499 |
{ label: __('Background', 'blockenberg'), value: a.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '#ffffff' }); } }, |
| 500 |
{ label: __('Title', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#111827' }); } }, |
| 501 |
{ label: __('Labels / axis', 'blockenberg'), value: a.labelColor, onChange: function (v) { setAttributes({ labelColor: v || '#6b7280' }); } }, |
| 502 |
{ label: __('Grid lines', 'blockenberg'), value: a.gridColor, onChange: function (v) { setAttributes({ gridColor: v || '#e5e7eb' }); } }, |
| 503 |
{ label: __('Connectors', 'blockenberg'), value: a.connectorColor, onChange: function (v) { setAttributes({ connectorColor: v || '#9ca3af' }); } }, |
| 504 |
{ label: __('Start bars', 'blockenberg'), value: a.startColor, onChange: function (v) { setAttributes({ startColor: v || '#6366f1' }); } }, |
| 505 |
{ label: __('Increase bars', 'blockenberg'), value: a.increaseColor, onChange: function (v) { setAttributes({ increaseColor: v || '#10b981' }); } }, |
| 506 |
{ label: __('Decrease bars', 'blockenberg'), value: a.decreaseColor, onChange: function (v) { setAttributes({ decreaseColor: v || '#ef4444' }); } }, |
| 507 |
{ label: __('Total bars', 'blockenberg'), value: a.totalColor, onChange: function (v) { setAttributes({ totalColor: v || '#8b5cf6' }); } } |
| 508 |
] |
| 509 |
}) |
| 510 |
), |
| 511 |
|
| 512 |
/* ── canvas ── */ |
| 513 |
el('div', blockProps, |
| 514 |
el('div', { |
| 515 |
style: { |
| 516 |
background: a.bgColor, |
| 517 |
borderRadius: '10px', |
| 518 |
padding: '24px', |
| 519 |
paddingTop: a.paddingTop ? a.paddingTop + 'px' : '24px', |
| 520 |
paddingBottom: a.paddingBottom ? a.paddingBottom + 'px' : '24px', |
| 521 |
maxWidth: a.maxWidth + 'px', |
| 522 |
margin: '0 auto', |
| 523 |
fontFamily: 'system-ui, sans-serif' |
| 524 |
} |
| 525 |
}, |
| 526 |
el(WaterfallPreview, { attributes: a }) |
| 527 |
) |
| 528 |
) |
| 529 |
); |
| 530 |
}, |
| 531 |
|
| 532 |
save: function (props) { |
| 533 |
return el('div', useBlockProps.save({ style: getTypoCssVars(props.attributes) }), |
| 534 |
el('div', { |
| 535 |
className: 'bkbg-wfc-app', |
| 536 |
'data-opts': JSON.stringify(props.attributes) |
| 537 |
}) |
| 538 |
); |
| 539 |
} |
| 540 |
}); |
| 541 |
}() ); |
| 542 |
|