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 / index.js

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

650 lines 34.1 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 __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var RichText = wp.blockEditor.RichText;
9 var PanelBody = wp.components.PanelBody;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var Button = wp.components.Button;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var __experimentalBoxControl = wp.components.__experimentalBoxControl;
16 var BoxControl = __experimentalBoxControl;
17 // Lazy lookup so the typography control is resolved at render time,
18 // not at module-init time (avoids load-order issues).
19 function getTypographyControl() {
20 return (typeof window.bkbgTypographyControl !== 'undefined') ? window.bkbgTypographyControl : null;
21 }
22 function getTypoCssVars() {
23 return (typeof window.bkbgTypoCssVars !== 'undefined') ? window.bkbgTypoCssVars : function() { return {}; };
24 }
25
26 // Icon SVGs
27 var icons = {
28 chevron: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
29 el('path', { d: 'M7 10l5 5 5-5z' })
30 ),
31 plus: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
32 el('path', { d: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z' })
33 ),
34 arrow: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
35 el('path', { d: 'M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' })
36 ),
37 caret: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
38 el('path', { d: 'M7 14l5-5 5 5H7z' })
39 )
40 };
41
42 function getIcon(type) {
43 return icons[type] || icons.chevron;
44 }
45
46 registerBlockType('blockenberg/accordion', {
47 title: __('Accordion', 'blockenberg'),
48 icon: 'list-view',
49 category: 'bkbg-content',
50 description: __('Collapsible accordion panels for FAQ, features, and more.', 'blockenberg'),
51
52 edit: function (props) {
53 var attributes = props.attributes;
54 var setAttributes = props.setAttributes;
55 var a = attributes;
56
57 function updateItem(index, field, value) {
58 var newItems = a.items.map(function (item, i) {
59 if (i === index) {
60 var updated = {};
61 for (var k in item) { updated[k] = item[k]; }
62 updated[field] = value;
63 return updated;
64 }
65 return item;
66 });
67 setAttributes({ items: newItems });
68 }
69
70 function removeItem(index) {
71 if (a.items.length <= 1) return;
72 var newItems = a.items.filter(function (_, i) { return i !== index; });
73 var newActive = a.activeItems.filter(function (i) { return i !== index; }).map(function (i) {
74 return i > index ? i - 1 : i;
75 });
76 setAttributes({ items: newItems, activeItems: newActive });
77 }
78
79 function addItem() {
80 setAttributes({
81 items: a.items.concat([{
82 title: __('New Accordion Item', 'blockenberg'),
83 content: __('Add your content here. Click to edit.', 'blockenberg')
84 }])
85 });
86 }
87
88 function moveItem(index, direction) {
89 var newIndex = index + direction;
90 if (newIndex < 0 || newIndex >= a.items.length) return;
91 var newItems = a.items.slice();
92 var temp = newItems[index];
93 newItems[index] = newItems[newIndex];
94 newItems[newIndex] = temp;
95 // Update activeItems indices
96 var newActive = a.activeItems.map(function (i) {
97 if (i === index) return newIndex;
98 if (i === newIndex) return index;
99 return i;
100 });
101 setAttributes({ items: newItems, activeItems: newActive });
102 }
103
104 function toggleItem(index) {
105 var isActive = a.activeItems.indexOf(index) !== -1;
106 var newActive;
107 if (isActive) {
108 newActive = a.activeItems.filter(function (i) { return i !== index; });
109 } else {
110 if (a.allowMultiple) {
111 newActive = a.activeItems.concat([index]);
112 } else {
113 newActive = [index];
114 }
115 }
116 setAttributes({ activeItems: newActive });
117 }
118
119 function createShadowString(h, v, blur, spread, color) {
120 return h + 'px ' + v + 'px ' + blur + 'px ' + spread + 'px ' + color;
121 }
122
123 // Style options
124 var styleOptions = [
125 { label: __('Default (Separated)', 'blockenberg'), value: 'default' },
126 { label: __('Connected', 'blockenberg'), value: 'connected' },
127 { label: __('Minimal', 'blockenberg'), value: 'minimal' },
128 { label: __('Boxed', 'blockenberg'), value: 'boxed' }
129 ];
130
131 var iconTypeOptions = [
132 { label: __('Chevron', 'blockenberg'), value: 'chevron' },
133 { label: __('Plus/Minus', 'blockenberg'), value: 'plus' },
134 { label: __('Arrow', 'blockenberg'), value: 'arrow' },
135 { label: __('Caret', 'blockenberg'), value: 'caret' }
136 ];
137
138 var iconPositionOptions = [
139 { label: __('Right', 'blockenberg'), value: 'right' },
140 { label: __('Left', 'blockenberg'), value: 'left' }
141 ];
142
143 var borderStyleOptions = [
144 { label: __('Solid', 'blockenberg'), value: 'solid' },
145 { label: __('Dashed', 'blockenberg'), value: 'dashed' },
146 { label: __('Dotted', 'blockenberg'), value: 'dotted' },
147 { label: __('None', 'blockenberg'), value: 'none' }
148 ];
149
150 var animationTypeOptions = [
151 { label: __('Slide', 'blockenberg'), value: 'slide' },
152 { label: __('Fade', 'blockenberg'), value: 'fade' },
153 { label: __('None', 'blockenberg'), value: 'none' }
154 ];
155
156
157
158 // Inspector Controls
159 var inspector = el(InspectorControls, {},
160 // Behavior Panel
161 el(PanelBody, { title: __('Behavior', 'blockenberg'), initialOpen: true },
162 el(ToggleControl, {
163 label: __('Allow multiple open', 'blockenberg'),
164 help: __('Allow several panels to be open simultaneously.', 'blockenberg'),
165 checked: a.allowMultiple,
166 __nextHasNoMarginBottom: true,
167 onChange: function (v) { setAttributes({ allowMultiple: v }); }
168 }),
169 el(ToggleControl, {
170 label: __('First panel open by default', 'blockenberg'),
171 checked: a.firstOpen,
172 __nextHasNoMarginBottom: true,
173 onChange: function (v) { setAttributes({ firstOpen: v }); }
174 }),
175 el(ToggleControl, {
176 label: __('Collapse all initially', 'blockenberg'),
177 help: __('Start with all panels closed.', 'blockenberg'),
178 checked: a.collapseAll,
179 __nextHasNoMarginBottom: true,
180 onChange: function (v) { setAttributes({ collapseAll: v }); }
181 }),
182 el(ToggleControl, {
183 label: __('Enable FAQ Schema', 'blockenberg'),
184 help: __('Add FAQPage structured data for SEO.', 'blockenberg'),
185 checked: a.schemaEnabled,
186 __nextHasNoMarginBottom: true,
187 onChange: function (v) { setAttributes({ schemaEnabled: v }); }
188 })
189 ),
190
191 // Style Panel
192 el(PanelBody, { title: __('Accordion Style', 'blockenberg'), initialOpen: false },
193 el(SelectControl, {
194 label: __('Style', 'blockenberg'),
195 value: a.accordionStyle,
196 options: styleOptions,
197 onChange: function (v) { setAttributes({ accordionStyle: v }); }
198 }),
199 el(SelectControl, {
200 label: __('Icon Type', 'blockenberg'),
201 value: a.iconType,
202 options: iconTypeOptions,
203 onChange: function (v) { setAttributes({ iconType: v }); }
204 }),
205 el(SelectControl, {
206 label: __('Icon Position', 'blockenberg'),
207 value: a.iconPosition,
208 options: iconPositionOptions,
209 onChange: function (v) { setAttributes({ iconPosition: v }); }
210 }),
211 el(RangeControl, {
212 label: __('Icon Size', 'blockenberg'),
213 value: a.iconSize,
214 min: 12,
215 max: 32,
216 onChange: function (v) { setAttributes({ iconSize: v }); }
217 })
218 ),
219
220 // Spacing Panel
221 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
222 el(RangeControl, {
223 label: __('Gap Between Items', 'blockenberg'),
224 value: a.gap,
225 min: 0,
226 max: 40,
227 onChange: function (v) { setAttributes({ gap: v }); }
228 }),
229 el('p', { className: 'components-base-control__label', style: { marginBottom: '8px' } }, __('Header Padding', 'blockenberg')),
230 el('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px', marginBottom: '16px' } },
231 el(RangeControl, { label: __('Top', 'blockenberg'), value: a.headerPaddingTop, min: 0, max: 40, onChange: function (v) { setAttributes({ headerPaddingTop: v }); } }),
232 el(RangeControl, { label: __('Right', 'blockenberg'), value: a.headerPaddingRight, min: 0, max: 40, onChange: function (v) { setAttributes({ headerPaddingRight: v }); } }),
233 el(RangeControl, { label: __('Bottom', 'blockenberg'), value: a.headerPaddingBottom, min: 0, max: 40, onChange: function (v) { setAttributes({ headerPaddingBottom: v }); } }),
234 el(RangeControl, { label: __('Left', 'blockenberg'), value: a.headerPaddingLeft, min: 0, max: 40, onChange: function (v) { setAttributes({ headerPaddingLeft: v }); } })
235 ),
236 el('p', { className: 'components-base-control__label', style: { marginBottom: '8px' } }, __('Content Padding', 'blockenberg')),
237 el('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px', marginBottom: '16px' } },
238 el(RangeControl, { label: __('Top', 'blockenberg'), value: a.contentPaddingTop, min: 0, max: 40, onChange: function (v) { setAttributes({ contentPaddingTop: v }); } }),
239 el(RangeControl, { label: __('Right', 'blockenberg'), value: a.contentPaddingRight, min: 0, max: 40, onChange: function (v) { setAttributes({ contentPaddingRight: v }); } }),
240 el(RangeControl, { label: __('Bottom', 'blockenberg'), value: a.contentPaddingBottom, min: 0, max: 40, onChange: function (v) { setAttributes({ contentPaddingBottom: v }); } }),
241 el(RangeControl, { label: __('Left', 'blockenberg'), value: a.contentPaddingLeft, min: 0, max: 40, onChange: function (v) { setAttributes({ contentPaddingLeft: v }); } })
242 )
243 ),
244
245 // Border Panel
246 el(PanelBody, { title: __('Border', 'blockenberg'), initialOpen: false },
247 el(RangeControl, {
248 label: __('Border Radius', 'blockenberg'),
249 value: a.borderRadius,
250 min: 0,
251 max: 24,
252 onChange: function (v) { setAttributes({ borderRadius: v }); }
253 }),
254 el(RangeControl, {
255 label: __('Border Width', 'blockenberg'),
256 value: a.borderWidth,
257 min: 0,
258 max: 5,
259 onChange: function (v) { setAttributes({ borderWidth: v }); }
260 }),
261 el(SelectControl, {
262 label: __('Border Style', 'blockenberg'),
263 value: a.borderStyle,
264 options: borderStyleOptions,
265 onChange: function (v) { setAttributes({ borderStyle: v }); }
266 }),
267 el(ToggleControl, {
268 label: __('Show Divider', 'blockenberg'),
269 help: __('Show line between header and content.', 'blockenberg'),
270 checked: a.dividerEnabled,
271 __nextHasNoMarginBottom: true,
272 onChange: function (v) { setAttributes({ dividerEnabled: v }); }
273 }),
274 a.dividerEnabled && el(RangeControl, {
275 label: __('Divider Width', 'blockenberg'),
276 value: a.dividerWidth,
277 min: 1,
278 max: 5,
279 onChange: function (v) { setAttributes({ dividerWidth: v }); }
280 })
281 ),
282
283 // Typography Panel
284 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
285 (function () {
286 var TC = getTypographyControl();
287 if (!TC) return el('p', { style: { color: '#999', fontSize: '12px', padding: '8px 0' } }, __('Typography control loading…', 'blockenberg'));
288 return el(Fragment, {},
289 el(TC, {
290 label: __('Title', 'blockenberg'),
291 value: a.headerTypo || {},
292 onChange: function (v) { setAttributes({ headerTypo: v }); }
293 }),
294 el(TC, {
295 label: __('Content', 'blockenberg'),
296 value: a.contentTypo || {},
297 onChange: function (v) { setAttributes({ contentTypo: v }); }
298 })
299 );
300 })()
301 ),
302
303 // Effects Panel
304 el(PanelBody, { title: __('Effects', 'blockenberg'), initialOpen: false },
305 el(ToggleControl, {
306 label: __('Enable Animation', 'blockenberg'),
307 checked: a.enableAnimation,
308 __nextHasNoMarginBottom: true,
309 onChange: function (v) { setAttributes({ enableAnimation: v }); }
310 }),
311 a.enableAnimation && el(RangeControl, {
312 label: __('Animation Duration (ms)', 'blockenberg'),
313 value: a.animationDuration,
314 min: 100,
315 max: 800,
316 step: 50,
317 onChange: function (v) { setAttributes({ animationDuration: v }); }
318 }),
319 el(ToggleControl, {
320 label: __('Enable Hover Effect', 'blockenberg'),
321 checked: a.enableHoverEffect,
322 __nextHasNoMarginBottom: true,
323 onChange: function (v) { setAttributes({ enableHoverEffect: v }); }
324 }),
325 el(ToggleControl, {
326 label: __('Enable Shadow', 'blockenberg'),
327 checked: a.enableShadow,
328 __nextHasNoMarginBottom: true,
329 onChange: function (v) { setAttributes({ enableShadow: v }); }
330 }),
331 a.enableShadow && el(Fragment, {},
332 el(RangeControl, {
333 label: __('Shadow Horizontal', 'blockenberg'),
334 value: a.shadowHorizontal,
335 min: -20,
336 max: 20,
337 onChange: function (v) { setAttributes({ shadowHorizontal: v }); }
338 }),
339 el(RangeControl, {
340 label: __('Shadow Vertical', 'blockenberg'),
341 value: a.shadowVertical,
342 min: -20,
343 max: 20,
344 onChange: function (v) { setAttributes({ shadowVertical: v }); }
345 }),
346 el(RangeControl, {
347 label: __('Shadow Blur', 'blockenberg'),
348 value: a.shadowBlur,
349 min: 0,
350 max: 40,
351 onChange: function (v) { setAttributes({ shadowBlur: v }); }
352 }),
353 el(RangeControl, {
354 label: __('Shadow Spread', 'blockenberg'),
355 value: a.shadowSpread,
356 min: -10,
357 max: 10,
358 onChange: function (v) { setAttributes({ shadowSpread: v }); }
359 })
360 )
361 ),
362
363 // Colors Panel
364 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
365 el(PanelColorSettings, {
366 title: __('Header Colors', 'blockenberg'),
367 initialOpen: false,
368 colorSettings: [
369 { value: a.headerBg, onChange: function (c) { setAttributes({ headerBg: c }); }, label: __('Background', 'blockenberg') },
370 { value: a.headerBgHover, onChange: function (c) { setAttributes({ headerBgHover: c }); }, label: __('Background (Hover)', 'blockenberg') },
371 { value: a.headerBgActive, onChange: function (c) { setAttributes({ headerBgActive: c }); }, label: __('Background (Active)', 'blockenberg') },
372 { value: a.headerColor, onChange: function (c) { setAttributes({ headerColor: c }); }, label: __('Text', 'blockenberg') },
373 { value: a.headerColorHover, onChange: function (c) { setAttributes({ headerColorHover: c }); }, label: __('Text (Hover)', 'blockenberg') },
374 { value: a.headerColorActive, onChange: function (c) { setAttributes({ headerColorActive: c }); }, label: __('Text (Active)', 'blockenberg') }
375 ]
376 }),
377
378 el(PanelColorSettings, {
379 title: __('Content Colors', 'blockenberg'),
380 initialOpen: false,
381 colorSettings: [
382 { value: a.contentBg, onChange: function (c) { setAttributes({ contentBg: c }); }, label: __('Background', 'blockenberg') },
383 { value: a.contentColor, onChange: function (c) { setAttributes({ contentColor: c }); }, label: __('Text', 'blockenberg') }
384 ]
385 }),
386
387 el(PanelColorSettings, {
388 title: __('Border & Icon Colors', 'blockenberg'),
389 initialOpen: false,
390 colorSettings: [
391 { value: a.borderColor, onChange: function (c) { setAttributes({ borderColor: c }); }, label: __('Border', 'blockenberg') },
392 { value: a.borderColorActive, onChange: function (c) { setAttributes({ borderColorActive: c }); }, label: __('Border (Active)', 'blockenberg') },
393 { value: a.iconColor, onChange: function (c) { setAttributes({ iconColor: c }); }, label: __('Icon', 'blockenberg') },
394 { value: a.iconColorActive, onChange: function (c) { setAttributes({ iconColorActive: c }); }, label: __('Icon (Active)', 'blockenberg') },
395 { value: a.accentColor, onChange: function (c) { setAttributes({ accentColor: c }); }, label: __('Accent', 'blockenberg') },
396 { value: a.dividerColor, onChange: function (c) { setAttributes({ dividerColor: c }); }, label: __('Divider', 'blockenberg') },
397 { value: a.shadowColor, onChange: function (c) { setAttributes({ shadowColor: c }); }, label: __('Shadow', 'blockenberg') }
398 ]
399 })
400 )
401 );
402
403 // CSS variables for preview
404 var wrapStyle = {
405 '--bkbg-ac-gap': a.gap + 'px',
406 '--bkbg-ac-radius': a.borderRadius + 'px',
407 '--bkbg-ac-brd-w': a.borderWidth + 'px',
408 '--bkbg-ac-brd-style': a.borderStyle,
409 '--bkbg-ac-header-padding': a.headerPaddingTop + 'px ' + a.headerPaddingRight + 'px ' + a.headerPaddingBottom + 'px ' + a.headerPaddingLeft + 'px',
410 '--bkbg-ac-content-padding': a.contentPaddingTop + 'px ' + a.contentPaddingRight + 'px ' + a.contentPaddingBottom + 'px ' + a.contentPaddingLeft + 'px',
411 '--bkbg-ac-header-bg': a.headerBg,
412 '--bkbg-ac-header-bg-hover': a.headerBgHover,
413 '--bkbg-ac-header-bg-active': a.headerBgActive,
414 '--bkbg-ac-header-color': a.headerColor,
415 '--bkbg-ac-header-color-hover': a.headerColorHover,
416 '--bkbg-ac-header-color-active': a.headerColorActive,
417 '--bkbg-ac-content-bg': a.contentBg,
418 '--bkbg-ac-content-color': a.contentColor,
419 '--bkbg-ac-border-color': a.borderColor,
420 '--bkbg-ac-border-color-active': a.borderColorActive,
421 '--bkbg-ac-icon-color': a.iconColor,
422 '--bkbg-ac-icon-color-active': a.iconColorActive,
423 '--bkbg-ac-accent': a.accentColor,
424 '--bkbg-ac-header-font-size': a.headerFontSize + 'px',
425 '--bkbg-ac-header-font-weight': a.headerFontWeight,
426 '--bkbg-ac-header-line-height': a.headerLineHeight,
427 '--bkbg-ac-content-font-size': a.contentFontSize + 'px',
428 '--bkbg-ac-content-font-weight': a.contentFontWeight,
429 '--bkbg-ac-content-line-height': a.contentLineHeight,
430 '--bkbg-ac-icon-size': a.iconSize + 'px',
431 '--bkbg-ac-shadow': a.enableShadow ? createShadowString(a.shadowHorizontal, a.shadowVertical, a.shadowBlur, a.shadowSpread, a.shadowColor) : 'none',
432 '--bkbg-ac-animation-duration': a.animationDuration + 'ms',
433 '--bkbg-ac-divider-color': a.dividerColor,
434 '--bkbg-ac-divider-width': a.dividerWidth + 'px'
435 };
436 // Merge typography CSS vars (override legacy font size/weight/line-height)
437 var _typoCssVars = getTypoCssVars();
438 Object.assign(wrapStyle, _typoCssVars(a.headerTypo || {}, '--bkbg-ac-header-'));
439 Object.assign(wrapStyle, _typoCssVars(a.contentTypo || {}, '--bkbg-ac-content-'));
440
441 var wrapDataAttrs = {
442 'data-style': a.accordionStyle,
443 'data-icon': a.iconType,
444 'data-icon-pos': a.iconPosition,
445 'data-animation': a.enableAnimation ? '1' : '0',
446 'data-hover': a.enableHoverEffect ? '1' : '0',
447 'data-shadow': a.enableShadow ? '1' : '0',
448 'data-divider': a.dividerEnabled ? '1' : '0'
449 };
450
451 // Build accordion items (WYSIWYG)
452 var itemsEl = a.items.map(function (item, index) {
453 var isActive = a.activeItems.indexOf(index) !== -1;
454
455 return el('div', {
456 className: 'bkbg-ac-item' + (isActive ? ' is-active' : ''),
457 key: 'item-' + index
458 },
459 // Item actions toolbar
460 el('div', { className: 'bkbg-ac-item-actions' },
461 el(Button, {
462 icon: 'arrow-up-alt2',
463 label: __('Move up', 'blockenberg'),
464 onClick: function () { moveItem(index, -1); },
465 disabled: index === 0,
466 isSmall: true
467 }),
468 el(Button, {
469 icon: 'arrow-down-alt2',
470 label: __('Move down', 'blockenberg'),
471 onClick: function () { moveItem(index, 1); },
472 disabled: index === a.items.length - 1,
473 isSmall: true
474 }),
475 el(Button, {
476 icon: 'trash',
477 label: __('Remove', 'blockenberg'),
478 onClick: function () { removeItem(index); },
479 isDestructive: true,
480 isSmall: true,
481 disabled: a.items.length <= 1
482 })
483 ),
484
485 // Header (clickable)
486 el('button', {
487 className: 'bkbg-ac-header',
488 'aria-expanded': isActive ? 'true' : 'false',
489 onClick: function (e) {
490 // Don't toggle if clicking on input
491 if (e.target.tagName === 'INPUT') return;
492 toggleItem(index);
493 }
494 },
495 el('input', {
496 className: 'bkbg-ac-title-input',
497 type: 'text',
498 value: item.title,
499 placeholder: __('Enter title...', 'blockenberg'),
500 onChange: function (e) { updateItem(index, 'title', e.target.value); },
501 onClick: function (e) { e.stopPropagation(); }
502 }),
503 el('span', { className: 'bkbg-ac-icon', 'aria-hidden': 'true' }, getIcon(a.iconType))
504 ),
505
506 // Content panel
507 el('div', {
508 className: 'bkbg-ac-content',
509 'aria-hidden': isActive ? 'false' : 'true'
510 },
511 el('div', { className: 'bkbg-ac-inner' },
512 el(RichText, {
513 tagName: 'div',
514 className: 'bkbg-ac-body bkbg-ac-body-editor',
515 value: item.content,
516 onChange: function (value) { updateItem(index, 'content', value); },
517 placeholder: __('Add content...', 'blockenberg')
518 })
519 )
520 )
521 );
522 });
523
524 var blockProps = useBlockProps({
525 className: 'bkbg-editor-wrap',
526 'data-block-label': 'Accordion'
527 });
528
529 return el('div', blockProps,
530 inspector,
531 el('div', Object.assign({ className: 'bkbg-ac-wrap', style: wrapStyle }, wrapDataAttrs),
532 itemsEl,
533 ),
534 el('div', { className: 'bkbg-editor-actions' },
535 el(Button, { variant: 'secondary', icon: 'plus-alt2', onClick: addItem }, __('Add Item', 'blockenberg'))
536 )
537 );
538 },
539
540 save: function (props) {
541 var a = props.attributes;
542
543 function createShadowString(h, v, blur, spread, color) {
544 return h + 'px ' + v + 'px ' + blur + 'px ' + spread + 'px ' + color;
545 }
546
547 var wrapStyle = {
548 '--bkbg-ac-gap': a.gap + 'px',
549 '--bkbg-ac-radius': a.borderRadius + 'px',
550 '--bkbg-ac-brd-w': a.borderWidth + 'px',
551 '--bkbg-ac-brd-style': a.borderStyle,
552 '--bkbg-ac-header-padding': a.headerPaddingTop + 'px ' + a.headerPaddingRight + 'px ' + a.headerPaddingBottom + 'px ' + a.headerPaddingLeft + 'px',
553 '--bkbg-ac-content-padding': a.contentPaddingTop + 'px ' + a.contentPaddingRight + 'px ' + a.contentPaddingBottom + 'px ' + a.contentPaddingLeft + 'px',
554 '--bkbg-ac-header-bg': a.headerBg,
555 '--bkbg-ac-header-bg-hover': a.headerBgHover,
556 '--bkbg-ac-header-bg-active': a.headerBgActive,
557 '--bkbg-ac-header-color': a.headerColor,
558 '--bkbg-ac-header-color-hover': a.headerColorHover,
559 '--bkbg-ac-header-color-active': a.headerColorActive,
560 '--bkbg-ac-content-bg': a.contentBg,
561 '--bkbg-ac-content-color': a.contentColor,
562 '--bkbg-ac-border-color': a.borderColor,
563 '--bkbg-ac-border-color-active': a.borderColorActive,
564 '--bkbg-ac-icon-color': a.iconColor,
565 '--bkbg-ac-icon-color-active': a.iconColorActive,
566 '--bkbg-ac-accent': a.accentColor,
567 '--bkbg-ac-header-font-size': a.headerFontSize + 'px',
568 '--bkbg-ac-header-font-weight': a.headerFontWeight,
569 '--bkbg-ac-header-line-height': a.headerLineHeight,
570 '--bkbg-ac-content-font-size': a.contentFontSize + 'px',
571 '--bkbg-ac-content-font-weight': a.contentFontWeight,
572 '--bkbg-ac-content-line-height': a.contentLineHeight,
573 '--bkbg-ac-icon-size': a.iconSize + 'px',
574 '--bkbg-ac-shadow': a.enableShadow ? createShadowString(a.shadowHorizontal, a.shadowVertical, a.shadowBlur, a.shadowSpread, a.shadowColor) : 'none',
575 '--bkbg-ac-animation-duration': a.animationDuration + 'ms',
576 '--bkbg-ac-divider-color': a.dividerColor,
577 '--bkbg-ac-divider-width': a.dividerWidth + 'px'
578 };
579 // Merge typography CSS vars from the new typography objects
580 var _typoCssVarsSave = getTypoCssVars();
581 Object.assign(wrapStyle, _typoCssVarsSave(a.headerTypo || {}, '--bkbg-ac-header-'));
582 Object.assign(wrapStyle, _typoCssVarsSave(a.contentTypo || {}, '--bkbg-ac-content-'));
583
584 // Icons
585 var iconSvgs = {
586 chevron: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: 'M7 10l5 5 5-5z' })),
587 plus: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z' })),
588 arrow: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: 'M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' })),
589 caret: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: 'M7 14l5-5 5 5H7z' }))
590 };
591 var iconEl = iconSvgs[a.iconType] || iconSvgs.chevron;
592
593 // Determine initial open items
594 var initialOpen = [];
595 if (!a.collapseAll) {
596 if (a.firstOpen) {
597 initialOpen = [0];
598 }
599 }
600
601 var itemsEl = a.items.map(function (item, index) {
602 var isOpen = initialOpen.indexOf(index) !== -1;
603 var headerId = 'bkbg-ac-h-' + index;
604 var contentId = 'bkbg-ac-c-' + index;
605
606 return el('div', { className: 'bkbg-ac-item' + (isOpen ? ' is-active' : ''), key: 'item-' + index },
607 el('button', {
608 className: 'bkbg-ac-header',
609 id: headerId,
610 'aria-expanded': isOpen ? 'true' : 'false',
611 'aria-controls': contentId
612 },
613 el('span', { className: 'bkbg-ac-title' }, item.title),
614 el('span', { className: 'bkbg-ac-icon', 'aria-hidden': 'true' }, iconEl)
615 ),
616 el('div', {
617 className: 'bkbg-ac-content',
618 id: contentId,
619 role: 'region',
620 'aria-labelledby': headerId,
621 'aria-hidden': isOpen ? 'false' : 'true'
622 },
623 el('div', { className: 'bkbg-ac-inner' },
624 el(wp.blockEditor.RichText.Content, {
625 tagName: 'div',
626 className: 'bkbg-ac-body',
627 value: item.content
628 })
629 )
630 )
631 );
632 });
633
634 return el('div', {
635 className: 'bkbg-ac-wrap',
636 style: wrapStyle,
637 'data-allow-multiple': a.allowMultiple ? '1' : '0',
638 'data-style': a.accordionStyle,
639 'data-icon': a.iconType,
640 'data-icon-pos': a.iconPosition,
641 'data-animation': a.enableAnimation ? '1' : '0',
642 'data-hover': a.enableHoverEffect ? '1' : '0',
643 'data-shadow': a.enableShadow ? '1' : '0',
644 'data-divider': a.dividerEnabled ? '1' : '0',
645 'data-schema': a.schemaEnabled ? '1' : '0'
646 }, itemsEl);
647 }
648 });
649 }() );
650