PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / accordion-table / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/accordion-table/index.js

687 lines 37.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 // Lazy lookup so the typography control is resolved at render time
18 function getTypographyControl() {
19 return (typeof window.bkbgTypographyControl !== 'undefined') ? window.bkbgTypographyControl : null;
20 }
21 function getTypoCssVars() {
22 return (typeof window.bkbgTypoCssVars !== 'undefined') ? window.bkbgTypoCssVars : function() { return {}; };
23 }
24
25 /* ── ES5-safe helpers ── */
26 function updateItem(arr, idx, field, val) {
27 return arr.map(function (item, i) {
28 if (i !== idx) return item;
29 var p = {}; p[field] = val;
30 return Object.assign({}, item, p);
31 });
32 }
33
34 function updateRowCell(rows, rIdx, cIdx, val) {
35 return rows.map(function (row, i) {
36 if (i !== rIdx) return row;
37 var cells = row.cells.map(function (c, j) { return j === cIdx ? val : c; });
38 return Object.assign({}, row, { cells: cells });
39 });
40 }
41
42 function ensureCells(row, colCount) {
43 var cells = (row.cells || []).slice();
44 while (cells.length < colCount) cells.push('');
45 return cells.slice(0, colCount);
46 }
47
48 /* ── expand icon ── */
49 function iconSvg(type, open) {
50 if (type === 'plus') {
51 return open
52 ? el('span', { style: { fontSize: '18px', lineHeight: 1, display: 'block', transform: 'rotate(45deg)', transition: 'transform 0.2s' } }, '+')
53 : el('span', { style: { fontSize: '18px', lineHeight: 1, display: 'block' } }, '+');
54 }
55 if (type === 'arrow') {
56 return el('span', { style: { fontSize: '12px', display: 'block', transform: open ? 'rotate(90deg)' : 'rotate(0deg)', transition: 'transform 0.22s' } }, '');
57 }
58 /* chevron (default) */
59 return el('span', { style: { fontSize: '12px', display: 'block', transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 0.22s' } }, '');
60 }
61
62 /* ── column editor ── */
63 function ColumnEditor(props) {
64 var columns = props.columns;
65 var setColumns = props.setColumns;
66
67 return el('div', {},
68 el('div', { style: { fontSize: '11px', color: '#6b7280', marginBottom: '8px' } },
69 __('Drag-to-reorder not available in editor. Use move buttons.', 'blockenberg')
70 ),
71 columns.map(function (col, i) {
72 return el('div', {
73 key: i,
74 style: { display: 'flex', gap: '6px', alignItems: 'flex-end', marginBottom: '6px' }
75 },
76 el('div', { style: { flex: 2 } },
77 el(TextControl, {
78 __nextHasNoMarginBottom: true,
79 label: i === 0 ? __('Column headers', 'blockenberg') : '',
80 placeholder: __('Header', 'blockenberg'),
81 value: col.label,
82 onChange: function (v) {
83 setColumns(updateItem(columns, i, 'label', v));
84 }
85 })
86 ),
87 el('div', { style: { flex: 1 } },
88 el(SelectControl, {
89 __nextHasNoMarginBottom: true,
90 label: i === 0 ? __('Align', 'blockenberg') : '',
91 value: col.align || 'left',
92 options: [
93 { label: 'L', value: 'left' },
94 { label: 'C', value: 'center' },
95 { label: 'R', value: 'right' }
96 ],
97 onChange: function (v) { setColumns(updateItem(columns, i, 'align', v)); }
98 })
99 ),
100 el('div', { style: { flex: 1 } },
101 el(TextControl, {
102 __nextHasNoMarginBottom: true,
103 label: i === 0 ? __('Width', 'blockenberg') : '',
104 placeholder: 'auto',
105 value: col.width || '',
106 onChange: function (v) { setColumns(updateItem(columns, i, 'width', v)); }
107 })
108 ),
109 el('button', {
110 onClick: function () {
111 if (columns.length <= 1) return;
112 setColumns(columns.filter(function (_, j) { return j !== i; }));
113 },
114 title: 'Remove',
115 style: { background: 'none', border: 'none', cursor: 'pointer', color: '#ef4444', fontSize: '16px', padding: '0 2px', marginBottom: '2px' }
116 }, '×')
117 );
118 }),
119 el(Button, {
120 variant: 'secondary',
121 style: { marginTop: '4px', width: '100%', justifyContent: 'center' },
122 onClick: function () {
123 setColumns(columns.concat([{ label: 'Column ' + (columns.length + 1), align: 'left', width: '' }]));
124 }
125 }, __('+ Add Column', 'blockenberg'))
126 );
127 }
128
129 /* ── row editor ── */
130 function RowEditor(props) {
131 var rows = props.rows;
132 var columns = props.columns;
133 var setRows = props.setRows;
134 var expanded = props.expanded;
135 var setExpanded = props.setExpanded;
136
137 return el('div', {},
138 rows.map(function (row, i) {
139 var isOpen = expanded === i;
140 var cells = ensureCells(row, columns.length);
141 var firstCell = cells[0] || 'Row ' + (i + 1);
142
143 return el('div', {
144 key: i,
145 style: {
146 border: '1px solid ' + (row.highlight ? '#6366f1' : '#e5e7eb'),
147 borderRadius: '6px',
148 marginBottom: '5px',
149 overflow: 'hidden',
150 background: row.highlight ? '#f0f0ff' : '#fff'
151 }
152 },
153 /* header row */
154 el('div', {
155 onClick: function () { setExpanded(isOpen ? -1 : i); },
156 style: { padding: '7px 10px', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '8px' }
157 },
158 row.badge ? el('span', {
159 style: {
160 background: row.badgeColor || '#6366f1',
161 color: '#fff', fontSize: '10px', fontWeight: 700,
162 padding: '2px 6px', borderRadius: '20px', flexShrink: 0
163 }
164 }, row.badge) : null,
165 el('span', { style: { flex: 1, fontSize: '12px', color: '#374151', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontWeight: row.highlight ? 700 : 400 } },
166 firstCell
167 ),
168 el('button', {
169 onClick: function (e) {
170 e.stopPropagation();
171 if (rows.length <= 1) return;
172 setRows(rows.filter(function (_, j) { return j !== i; }));
173 setExpanded(-1);
174 },
175 title: 'Remove row',
176 style: { background: 'none', border: 'none', cursor: 'pointer', color: '#ef4444', fontSize: '14px', padding: '0 2px' }
177 }, '×'),
178 el('span', { style: { color: '#9ca3af', fontSize: '10px' } }, isOpen ? '' : '')
179 ),
180
181 /* expanded editor */
182 isOpen ? el('div', { style: { padding: '10px', borderTop: '1px solid #e5e7eb' } },
183
184 /* cells */
185 el('div', { style: { marginBottom: '10px' } },
186 el('div', { style: { fontSize: '11px', fontWeight: 600, color: '#9ca3af', textTransform: 'uppercase', marginBottom: '6px' } },
187 __('Cell values', 'blockenberg')
188 ),
189 columns.map(function (col, ci) {
190 return el('div', { key: ci, style: { marginBottom: '6px' } },
191 el(TextControl, {
192 __nextHasNoMarginBottom: true,
193 label: col.label || ('Col ' + (ci + 1)),
194 value: cells[ci] || '',
195 onChange: function (v) { setRows(updateRowCell(rows, i, ci, v)); }
196 })
197 );
198 })
199 ),
200
201 /* badge */
202 el('div', {
203 style: { borderTop: '1px solid #eee', paddingTop: '8px', marginBottom: '8px', display: 'flex', gap: '8px', alignItems: 'flex-end' }
204 },
205 el('div', { style: { flex: 2 } },
206 el(TextControl, {
207 __nextHasNoMarginBottom: true,
208 label: __('Badge text (optional)', 'blockenberg'),
209 value: row.badge || '',
210 onChange: function (v) { setRows(updateItem(rows, i, 'badge', v)); }
211 })
212 ),
213 el('div', { style: { flex: 1 } },
214 el('label', { style: { display: 'block', fontSize: '11px', fontWeight: 600, color: '#757575', marginBottom: '4px' } }, __('Badge color', 'blockenberg')),
215 el('input', {
216 type: 'color',
217 value: row.badgeColor || '#6366f1',
218 onChange: function (e) { setRows(updateItem(rows, i, 'badgeColor', e.target.value)); },
219 style: { width: '100%', height: '32px', padding: '2px', borderRadius: '4px', border: '1px solid #ddd', cursor: 'pointer' }
220 })
221 )
222 ),
223
224 /* highlight toggle */
225 el(ToggleControl, {
226 __nextHasNoMarginBottom: true,
227 label: __('Highlight this row', 'blockenberg'),
228 checked: row.highlight || false,
229 onChange: function (v) { setRows(updateItem(rows, i, 'highlight', v)); }
230 }),
231
232 /* detail section */
233 el('div', { style: { borderTop: '1px solid #eee', paddingTop: '10px', marginTop: '8px' } },
234 el('div', { style: { fontSize: '11px', fontWeight: 600, color: '#9ca3af', textTransform: 'uppercase', marginBottom: '8px' } },
235 __('Expand detail', 'blockenberg')
236 ),
237 el(TextControl, {
238 __nextHasNoMarginBottom: true,
239 label: __('Detail section title', 'blockenberg'),
240 value: row.detailTitle || '',
241 onChange: function (v) { setRows(updateItem(rows, i, 'detailTitle', v)); }
242 }),
243 el('div', { style: { marginTop: '8px' } },
244 el(SelectControl, {
245 __nextHasNoMarginBottom: true,
246 label: __('Detail type', 'blockenberg'),
247 value: row.detailType || 'list',
248 options: [
249 { label: __('Bullet list', 'blockenberg'), value: 'list' },
250 { label: __('Text paragraph', 'blockenberg'), value: 'text' }
251 ],
252 onChange: function (v) { setRows(updateItem(rows, i, 'detailType', v)); }
253 })
254 ),
255 (row.detailType || 'list') === 'list' ? el('div', { style: { marginTop: '8px' } },
256 el('label', { style: { display: 'block', fontSize: '11px', fontWeight: 600, color: '#757575', marginBottom: '4px' } },
257 __('List items (one per line)', 'blockenberg')
258 ),
259 el('textarea', {
260 value: (row.detailItems || []).join('\n'),
261 rows: 5,
262 style: { width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd', fontSize: '12px', resize: 'vertical', boxSizing: 'border-box' },
263 onChange: function (e) {
264 var items = e.target.value.split('\n').map(function (s) { return s.trimEnd(); }).filter(function (s) { return s.length > 0; });
265 setRows(updateItem(rows, i, 'detailItems', items));
266 }
267 })
268 ) : el('div', { style: { marginTop: '8px' } },
269 el('textarea', {
270 value: row.detailText || '',
271 rows: 4,
272 placeholder: __('Detail paragraph text…', 'blockenberg'),
273 style: { width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd', fontSize: '12px', resize: 'vertical', boxSizing: 'border-box' },
274 onChange: function (e) { setRows(updateItem(rows, i, 'detailText', e.target.value)); }
275 })
276 )
277 ),
278
279 /* move buttons */
280 el('div', { style: { display: 'flex', gap: '6px', marginTop: '10px' } },
281 i > 0 ? el(Button, {
282 variant: 'secondary', style: { fontSize: '11px' },
283 onClick: function () {
284 var arr = rows.slice(); var tmp = arr[i - 1]; arr[i - 1] = arr[i]; arr[i] = tmp;
285 setRows(arr); setExpanded(i - 1);
286 }
287 }, '↑ Move up') : null,
288 i < rows.length - 1 ? el(Button, {
289 variant: 'secondary', style: { fontSize: '11px' },
290 onClick: function () {
291 var arr = rows.slice(); var tmp = arr[i + 1]; arr[i + 1] = arr[i]; arr[i] = tmp;
292 setRows(arr); setExpanded(i + 1);
293 }
294 }, '↓ Move down') : null,
295 el(Button, {
296 variant: 'secondary', style: { fontSize: '11px' },
297 onClick: function () {
298 var copy = Object.assign({}, row, { badge: row.badge ? row.badge + ' (copy)' : '', cells: cells.slice() });
299 var arr = rows.slice(); arr.splice(i + 1, 0, copy);
300 setRows(arr); setExpanded(i + 1);
301 }
302 }, __('Duplicate', 'blockenberg'))
303 )
304
305 ) : null
306 );
307 }),
308
309 el(Button, {
310 variant: 'primary',
311 style: { marginTop: '8px', width: '100%', justifyContent: 'center' },
312 onClick: function () {
313 var newRow = {
314 cells: columns.map(function () { return ''; }),
315 badge: '', badgeColor: '#6366f1', highlight: false,
316 detailTitle: '', detailType: 'list', detailText: '', detailItems: []
317 };
318 var arr = rows.concat([newRow]);
319 setRows(arr);
320 setExpanded(arr.length - 1);
321 }
322 }, __('+ Add Row', 'blockenberg'))
323 );
324 }
325
326 /* ── editor table preview ── */
327 function TablePreview(props) {
328 var a = props.attributes;
329 var openRows = props.openRows;
330 var toggleRow = props.toggleRow;
331
332 var colCount = a.columns.length;
333 var iconPos = a.expandIconPosition || 'right';
334 var showNums = a.showRowNumbers;
335
336 return el('div', {
337 style: {
338 border: '1px solid ' + a.borderColor,
339 borderRadius: a.borderRadius + 'px',
340 overflow: 'hidden',
341 maxWidth: a.maxWidth + 'px',
342 margin: '0 auto',
343 fontFamily: 'system-ui, sans-serif'
344 }
345 },
346 /* header */
347 el('div', {
348 style: {
349 display: 'grid',
350 gridTemplateColumns: (showNums ? '32px ' : '') + (iconPos === 'left' ? '32px ' : '') + a.columns.map(function (c) { return c.width || '1fr'; }).join(' ') + (iconPos === 'right' ? ' 32px' : ''),
351 background: a.headerBg,
352 borderBottom: '1px solid ' + a.borderColor
353 }
354 },
355 showNums ? el('div', { className: 'bkbg-actbl-th', style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px', color: a.headerColor } }, '#') : null,
356 iconPos === 'left' ? el('div', { style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px' } }) : null,
357 a.columns.map(function (col, ci) {
358 return el('div', {
359 key: ci,
360 className: 'bkbg-actbl-th',
361 style: {
362 padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px',
363 color: a.headerColor,
364 textAlign: col.align || 'left'
365 }
366 }, col.label);
367 }),
368 iconPos === 'right' ? el('div', { style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px' } }) : null
369 ),
370
371 /* rows */
372 a.rows.map(function (row, ri) {
373 var isOpen = openRows[ri];
374 var cells = ensureCells(row, colCount);
375 var rowBg = row.highlight ? a.highlightRowBg : (a.stripedRows && ri % 2 === 1 ? a.rowAltBg : a.rowBg);
376
377 return el('div', { key: ri },
378 /* main row */
379 el('div', {
380 onClick: function () { toggleRow(ri); },
381 style: {
382 display: 'grid',
383 gridTemplateColumns: (showNums ? '32px ' : '') + (iconPos === 'left' ? '32px ' : '') + a.columns.map(function (c) { return c.width || '1fr'; }).join(' ') + (iconPos === 'right' ? ' 32px' : ''),
384 background: rowBg,
385 borderLeft: row.highlight ? '3px solid ' + a.highlightRowBorder : '3px solid transparent',
386 borderBottom: '1px solid ' + a.borderColor,
387 cursor: 'pointer',
388 transition: 'background 0.15s'
389 }
390 },
391 showNums ? el('div', { className: 'bkbg-actbl-td', style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px', color: '#9ca3af', textAlign: 'center' } }, ri + 1) : null,
392 iconPos === 'left' ? el('div', { style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px', color: a.iconColor, display: 'flex', alignItems: 'center', justifyContent: 'center' } },
393 iconSvg(a.expandIcon, isOpen)
394 ) : null,
395 cells.map(function (cell, ci) {
396 return el('div', {
397 key: ci,
398 className: 'bkbg-actbl-td' + (ci === 0 ? ' bkbg-actbl-td-first' : ''),
399 style: {
400 padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px',
401 color: a.rowColor,
402 textAlign: a.columns[ci] ? (a.columns[ci].align || 'left') : 'left',
403 display: 'flex',
404 alignItems: 'center',
405 gap: '6px'
406 }
407 },
408 ci === 0 && row.badge ? el('span', {
409 style: {
410 background: row.badgeColor || '#6366f1',
411 color: '#fff', fontSize: '10px', fontWeight: 700,
412 padding: '2px 7px', borderRadius: '20px', flexShrink: 0
413 }
414 }, row.badge) : null,
415 cell
416 );
417 }),
418 iconPos === 'right' ? el('div', { style: { padding: a.cellPaddingV + 'px ' + a.cellPaddingH + 'px', color: a.iconColor, display: 'flex', alignItems: 'center', justifyContent: 'center' } },
419 iconSvg(a.expandIcon, isOpen)
420 ) : null
421 ),
422
423 /* detail panel */
424 isOpen ? el('div', {
425 style: {
426 background: a.detailBg,
427 borderBottom: '1px solid ' + a.detailBorderColor,
428 padding: '14px ' + (a.cellPaddingH + 8) + 'px',
429 borderLeft: '3px solid ' + (row.highlight ? a.highlightRowBorder : a.borderColor)
430 }
431 },
432 row.detailTitle ? el('div', {
433 className: 'bkbg-actbl-detail-title',
434 style: { color: a.detailColor, marginBottom: '8px', opacity: 0.7 }
435 }, row.detailTitle) : null,
436 (row.detailType || 'list') === 'list'
437 ? el('ul', { style: { margin: 0, padding: '0 0 0 18px', display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: '4px 20px' } },
438 (row.detailItems || []).map(function (item, ii) {
439 return el('li', { key: ii, className: 'bkbg-actbl-detail-li', style: { color: a.detailColor } }, item);
440 })
441 )
442 : el('p', { className: 'bkbg-actbl-detail-text', style: { margin: 0, color: a.detailColor } }, row.detailText || '')
443 ) : null
444 );
445 })
446 );
447 }
448
449 /* ── register ── */
450 registerBlockType('blockenberg/accordion-table', {
451 edit: function (props) {
452 var a = props.attributes;
453 var setAttributes = props.setAttributes;
454
455 var expState = useState(-1);
456 var expanded = expState[0];
457 var setExpanded = expState[1];
458
459 var openState = useState({});
460 var openRows = openState[0];
461 var setOpenRows = openState[1];
462
463 var blockProps = useBlockProps({ className: 'bkbg-actbl-editor-wrap' });
464
465 function setColumns(v) { setAttributes({ columns: v }); }
466 function setRows(v) { setAttributes({ rows: v }); }
467
468 function toggleRow(ri) {
469 if (a.allowMultiple) {
470 var next = Object.assign({}, openRows);
471 next[ri] = !next[ri];
472 setOpenRows(next);
473 } else {
474 var next2 = {};
475 next2[ri] = !openRows[ri];
476 setOpenRows(next2);
477 }
478 }
479
480 return el(Fragment, {},
481
482 el(InspectorControls, {},
483
484 /* ── Columns ── */
485 el(PanelBody, { title: __('Columns', 'blockenberg'), initialOpen: true },
486 el(ColumnEditor, { columns: a.columns, setColumns: setColumns })
487 ),
488
489 /* ── Rows ── */
490 el(PanelBody, { title: __('Rows', 'blockenberg'), initialOpen: true },
491 el(RowEditor, {
492 rows: a.rows,
493 columns: a.columns,
494 setRows: setRows,
495 expanded: expanded,
496 setExpanded: setExpanded
497 })
498 ),
499
500 /* ── Behaviour ── */
501 el(PanelBody, { title: __('Behaviour', 'blockenberg'), initialOpen: false },
502 el(ToggleControl, {
503 __nextHasNoMarginBottom: true,
504 label: __('Allow multiple rows open simultaneously', 'blockenberg'),
505 checked: a.allowMultiple,
506 onChange: function (v) { setAttributes({ allowMultiple: v }); }
507 }),
508 el('div', { style: { marginTop: '10px' } },
509 el(ToggleControl, {
510 __nextHasNoMarginBottom: true,
511 label: __('Show row numbers', 'blockenberg'),
512 checked: a.showRowNumbers,
513 onChange: function (v) { setAttributes({ showRowNumbers: v }); }
514 })
515 ),
516 el('div', { style: { marginTop: '4px' } },
517 el(ToggleControl, {
518 __nextHasNoMarginBottom: true,
519 label: __('Striped rows', 'blockenberg'),
520 checked: a.stripedRows,
521 onChange: function (v) { setAttributes({ stripedRows: v }); }
522 })
523 ),
524 el('div', { style: { marginTop: '10px' } },
525 el(SelectControl, {
526 __nextHasNoMarginBottom: true,
527 label: __('Expand icon', 'blockenberg'),
528 value: a.expandIcon,
529 options: [
530 { label: __('Chevron (▼)', 'blockenberg'), value: 'chevron' },
531 { label: __('Plus (+)', 'blockenberg'), value: 'plus' },
532 { label: __('Arrow (▶)', 'blockenberg'), value: 'arrow' }
533 ],
534 onChange: function (v) { setAttributes({ expandIcon: v }); }
535 })
536 ),
537 el('div', { style: { marginTop: '10px' } },
538 el(SelectControl, {
539 __nextHasNoMarginBottom: true,
540 label: __('Expand icon position', 'blockenberg'),
541 value: a.expandIconPosition,
542 options: [
543 { label: __('Right', 'blockenberg'), value: 'right' },
544 { label: __('Left', 'blockenberg'), value: 'left' }
545 ],
546 onChange: function (v) { setAttributes({ expandIconPosition: v }); }
547 })
548 ),
549 el('div', { style: { marginTop: '10px' } },
550 el(RangeControl, {
551 __nextHasNoMarginBottom: true,
552 label: __('Animation duration (ms)', 'blockenberg'),
553 value: a.animDuration, min: 80, max: 600,
554 onChange: function (v) { setAttributes({ animDuration: v }); }
555 })
556 )
557 ),
558
559 /* ── Appearance ── */
560 el(PanelBody, { title: __('Appearance', 'blockenberg'), initialOpen: false },
561 el(RangeControl, {
562 __nextHasNoMarginBottom: true,
563 label: __('Max width (px)', 'blockenberg'),
564 value: a.maxWidth, min: 300, max: 1400,
565 onChange: function (v) { setAttributes({ maxWidth: v }); }
566 }),
567 el('div', { style: { marginTop: '10px' } },
568 el(RangeControl, {
569 __nextHasNoMarginBottom: true,
570 label: __('Border radius (px)', 'blockenberg'),
571 value: a.borderRadius, min: 0, max: 24,
572 onChange: function (v) { setAttributes({ borderRadius: v }); }
573 })
574 ),
575 el('div', { style: { marginTop: '10px', display: 'flex', gap: '8px' } },
576 el('div', { style: { flex: 1 } },
577 el(RangeControl, {
578 __nextHasNoMarginBottom: true,
579 label: __('Cell padding V', 'blockenberg'),
580 value: a.cellPaddingV, min: 6, max: 32,
581 onChange: function (v) { setAttributes({ cellPaddingV: v }); }
582 })
583 ),
584 el('div', { style: { flex: 1 } },
585 el(RangeControl, {
586 __nextHasNoMarginBottom: true,
587 label: __('Cell padding H', 'blockenberg'),
588 value: a.cellPaddingH, min: 6, max: 40,
589 onChange: function (v) { setAttributes({ cellPaddingH: v }); }
590 })
591 )
592 ),
593 el('div', { style: { marginTop: '10px', display: 'flex', gap: '8px' } },
594 el('div', { style: { flex: 1 } },
595 el(RangeControl, {
596 __nextHasNoMarginBottom: true,
597 label: __('Padding top', 'blockenberg'),
598 value: a.paddingTop, min: 0, max: 120,
599 onChange: function (v) { setAttributes({ paddingTop: v }); }
600 })
601 ),
602 el('div', { style: { flex: 1 } },
603 el(RangeControl, {
604 __nextHasNoMarginBottom: true,
605 label: __('Padding bottom', 'blockenberg'),
606 value: a.paddingBottom, min: 0, max: 120,
607 onChange: function (v) { setAttributes({ paddingBottom: v }); }
608 })
609 )
610 )
611 ),
612
613 /* ── Colors ── */
614
615 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
616 (function () {
617 var TC = getTypographyControl();
618 if (!TC) return el('p', { style: { color: '#999', fontSize: '12px', padding: '8px 0' } }, __('Typography control loading…', 'blockenberg'));
619 return el(Fragment, {},
620 el(TC, { label: __('Header', 'blockenberg'), value: a.headerTypo || {}, onChange: function (v) { setAttributes({ headerTypo: v }); } }),
621 el(TC, { label: __('Cells', 'blockenberg'), value: a.cellTypo || {}, onChange: function (v) { setAttributes({ cellTypo: v }); } }),
622 el(TC, { label: __('Detail', 'blockenberg'), value: a.detailTypo || {}, onChange: function (v) { setAttributes({ detailTypo: v }); } })
623 );
624 })()
625 ),
626 el(PanelColorSettings, {
627 title: __('Colors', 'blockenberg'),
628 initialOpen: false,
629 colorSettings: [
630 { label: __('Background', 'blockenberg'), value: a.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '#ffffff' }); } },
631 { label: __('Header background', 'blockenberg'), value: a.headerBg, onChange: function (v) { setAttributes({ headerBg: v || '#f8fafc' }); } },
632 { label: __('Header text', 'blockenberg'), value: a.headerColor, onChange: function (v) { setAttributes({ headerColor: v || '#374151' }); } },
633 { label: __('Row background', 'blockenberg'), value: a.rowBg, onChange: function (v) { setAttributes({ rowBg: v || '#ffffff' }); } },
634 { label: __('Row alt background', 'blockenberg'), value: a.rowAltBg, onChange: function (v) { setAttributes({ rowAltBg: v || '#f9fafb' }); } },
635 { label: __('Row text', 'blockenberg'), value: a.rowColor, onChange: function (v) { setAttributes({ rowColor: v || '#1f2937' }); } },
636 { label: __('Row hover', 'blockenberg'), value: a.rowHoverBg, onChange: function (v) { setAttributes({ rowHoverBg: v || '#f0f4ff' }); } },
637 { label: __('Highlighted row bg', 'blockenberg'), value: a.highlightRowBg, onChange: function (v) { setAttributes({ highlightRowBg: v || '#f0f0ff' }); } },
638 { label: __('Highlighted row border', 'blockenberg'), value: a.highlightRowBorder, onChange: function (v) { setAttributes({ highlightRowBorder: v || '#6366f1' }); } },
639 { label: __('Detail panel bg', 'blockenberg'), value: a.detailBg, onChange: function (v) { setAttributes({ detailBg: v || '#f8fafc' }); } },
640 { label: __('Detail text', 'blockenberg'), value: a.detailColor, onChange: function (v) { setAttributes({ detailColor: v || '#374151' }); } },
641 { label: __('Table border', 'blockenberg'), value: a.borderColor, onChange: function (v) { setAttributes({ borderColor: v || '#e5e7eb' }); } },
642 { label: __('Icon color', 'blockenberg'), value: a.iconColor, onChange: function (v) { setAttributes({ iconColor: v || '#9ca3af' }); } }
643 ]
644 })
645 ),
646
647 /* ── canvas ── */
648 el('div', blockProps,
649 el('div', {
650 className: 'bkbg-actbl-wrap',
651 style: (function () {
652 var s = {
653 paddingTop: a.paddingTop + 'px',
654 paddingBottom: a.paddingBottom + 'px',
655 background: a.bgColor,
656 '--bkbg-actbl-header-sz': a.headerSize + 'px',
657 '--bkbg-actbl-cell-sz': a.cellSize + 'px',
658 '--bkbg-actbl-detail-sz': a.detailSize + 'px'
659 };
660 var _tv = getTypoCssVars();
661 Object.assign(s, _tv(a.headerTypo || {}, '--bkbg-actbl-header-'));
662 Object.assign(s, _tv(a.cellTypo || {}, '--bkbg-actbl-cell-'));
663 Object.assign(s, _tv(a.detailTypo || {}, '--bkbg-actbl-detail-'));
664 return s;
665 })()
666 },
667 el(TablePreview, {
668 attributes: a,
669 openRows: openRows,
670 toggleRow: toggleRow
671 })
672 )
673 )
674 );
675 },
676
677 save: function (props) {
678 return el('div', useBlockProps.save(),
679 el('div', {
680 className: 'bkbg-actbl-app',
681 'data-opts': JSON.stringify(props.attributes)
682 })
683 );
684 }
685 });
686 }() );
687