PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / card-stack / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/card-stack/index.js

317 lines 27.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 registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
12 var PanelBody = wp.components.PanelBody;
13 var RangeControl = wp.components.RangeControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var TextControl = wp.components.TextControl;
16 var TextareaControl = wp.components.TextareaControl;
17 var SelectControl = wp.components.SelectControl;
18 var Button = wp.components.Button;
19
20 function getTypographyControl() { return (window.bkbgTypographyControl || function () { return null; }); }
21 function getTypoCssVars() { return (window.bkbgTypoCssVars || function () { return {}; }); }
22 function _tv(typo, prefix) { var fn = getTypoCssVars(); return fn(typo || {}, prefix); }
23
24 var STACK_STYLE_OPTIONS = [
25 { label: 'Fan (cards rotate on hover)', value: 'fan' },
26 { label: 'Pile (offset vertically)', value: 'pile' },
27 { label: 'Spread (horizontal fan)', value: 'spread' },
28 ];
29
30 function makeId() { return 'c' + Math.random().toString(36).substr(2, 6); }
31
32 /* Compute inline transform for each visible ghost card */
33 function ghostTransform(idx, style, rotSpread, offsetX, offsetY) {
34 if (style === 'fan') {
35 var angle = (idx + 1) * (rotSpread / 2);
36 var flip = idx % 2 === 0 ? 1 : -1;
37 return 'rotate(' + (flip * angle) + 'deg) translateY(' + ((idx + 1) * offsetY) + 'px)';
38 }
39 if (style === 'spread') {
40 return 'translateX(' + ((idx + 1) * offsetX * 1.5) + 'px) rotate(' + ((idx + 1) * (rotSpread * 0.6)) + 'deg)';
41 }
42 /* pile */
43 return 'translateX(' + ((idx + 1) * offsetX * 0.5) + 'px) translateY(' + ((idx + 1) * offsetY) + 'px)';
44 }
45
46 function QuoteSVG() {
47 return el('svg', { width: 28, height: 20, viewBox: '0 0 28 20', fill: 'currentColor', style: { opacity: 0.15, marginBottom: '6px' } },
48 el('path', { d: 'M0 20V12C0 5.333 2.667 1.333 8 0l1.6 2.4C6.933 3.467 5.467 5.2 5.2 7.6H9V20H0zm14 0V12c0-6.667 2.667-10.667 8-12l1.6 2.4c-2.667 1.067-4.133 2.8-4.4 5.2H23V20H14z' })
49 );
50 }
51
52 function CardFace(props) {
53 var card = props.card;
54 var a = props.a;
55 var isActive = props.isActive;
56 return el('div', {
57 className: 'bkbg-cardstack-face',
58 style: {
59 width: a.cardWidth + 'px',
60 minHeight: a.cardMinHeight + 'px',
61 background: card.bgColor || a.globalCardBg,
62 color: card.textColor || a.globalTextColor,
63 borderRadius: a.cardRadius + 'px',
64 padding: a.cardPadding + 'px',
65 display: 'flex',
66 flexDirection: 'column',
67 boxShadow: '0 8px 32px rgba(0,0,0,0.12)',
68 overflow: 'hidden',
69 position: 'relative',
70 }
71 },
72 card.imageUrl && el('div', { style: { position: 'absolute', inset: 0, backgroundImage: 'url(' + card.imageUrl + ')', backgroundSize: 'cover', backgroundPosition: 'center', opacity: 0.15, borderRadius: 'inherit' } }),
73 el('div', { style: { position: 'relative', flex: 1, display: 'flex', flexDirection: 'column' } },
74 a.showTag && card.tag && el('span', { style: { display: 'inline-block', alignSelf: 'flex-start', background: card.tagBg || card.accentColor || '#6c3fb5', color: card.tagColor || '#fff', borderRadius: '4px', padding: '2px 10px', fontSize: a.tagSize + 'px', fontWeight: 700, marginBottom: '12px', letterSpacing: '0.04em' } }, card.tag),
75 a.showQuoteMark && card.quote && el(QuoteSVG),
76 el('h3', { className: 'bkbg-cardstack-title', style: { margin: '0 0 10px' } }, card.title),
77 el('p', { className: 'bkbg-cardstack-desc', style: { margin: '0 0 auto', opacity: 0.85 } }, card.desc),
78 a.showAuthor && card.author && el('div', { style: { marginTop: '20px', display: 'flex', alignItems: 'center', gap: '10px', borderTop: '1px solid rgba(128,128,128,0.15)', paddingTop: '14px' } },
79 el('div', { style: { width: '34px', height: '34px', borderRadius: '50%', background: card.accentColor || '#6c3fb5', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '14px', fontWeight: 700, color: '#fff', flexShrink: 0, overflow: 'hidden' } },
80 card.avatarUrl ? el('img', { src: card.avatarUrl, alt: card.author, style: { width: '100%', height: '100%', objectFit: 'cover' } }) : (card.author || 'A').charAt(0).toUpperCase()
81 ),
82 el('div', null,
83 el('p', { style: { margin: 0, fontWeight: 700, fontSize: (a.authorSize) + 'px' } }, card.author),
84 card.role && el('p', { style: { margin: 0, fontSize: (a.authorSize - 1) + 'px', opacity: 0.65 } }, card.role)
85 )
86 )
87 )
88 );
89 }
90
91 registerBlockType('blockenberg/card-stack', {
92 edit: function (props) {
93 var attributes = props.attributes;
94 var setAttributes = props.setAttributes;
95 var cards = attributes.cards;
96 var activeIdx = useState(0);
97 var currentIdx = activeIdx[0];
98 var setCurrentIdx = activeIdx[1];
99
100 var blockProps = useBlockProps({
101 style: Object.assign({ paddingTop: attributes.paddingTop + 'px', paddingBottom: attributes.paddingBottom + 'px', backgroundColor: attributes.bgColor || undefined }, _tv(attributes.typoTitle, '--bkbg-cst-tt-'), _tv(attributes.typoDesc, '--bkbg-cst-td-'))
102 });
103
104 function setCard(id, patch) {
105 setAttributes({ cards: cards.map(function (c) { return c.id === id ? Object.assign({}, c, patch) : c; }) });
106 }
107 function addCard() {
108 setAttributes({ cards: cards.concat([{ id: makeId(), title: 'New card', desc: 'Add your content here.', quote: false, author: '', role: '', avatarUrl: '', avatarId: 0, imageUrl: '', imageId: 0, imageAlt: '', tag: 'New', tagColor: '#ffffff', tagBg: '#6c3fb5', accentColor: '#6c3fb5', bgColor: '#ffffff', textColor: '#111827' }]) });
109 }
110 function removeCard(id) {
111 if (cards.length <= 1) return;
112 setAttributes({ cards: cards.filter(function (c) { return c.id !== id; }) });
113 if (currentIdx >= cards.length - 1) setCurrentIdx(Math.max(0, cards.length - 2));
114 }
115
116 var visibleBehind = Math.min(attributes.maxVisibleBehind, cards.length - 1);
117
118 return el(Fragment, null,
119 el(InspectorControls, null,
120 el(PanelBody, { title: __('Stack', 'blockenberg'), initialOpen: true },
121 el(SelectControl, { label: __('Stack style', 'blockenberg'), value: attributes.stackStyle, options: STACK_STYLE_OPTIONS, onChange: function (v) { setAttributes({ stackStyle: v }); } }),
122 el(RangeControl, { label: __('Card width (px)', 'blockenberg'), value: attributes.cardWidth, min: 240, max: 600, onChange: function (v) { setAttributes({ cardWidth: v }); } }),
123 el(RangeControl, { label: __('Card min height (px)', 'blockenberg'), value: attributes.cardMinHeight, min: 160, max: 600, onChange: function (v) { setAttributes({ cardMinHeight: v }); } }),
124 el(RangeControl, { label: __('Card border radius (px)', 'blockenberg'), value: attributes.cardRadius, min: 0, max: 40, onChange: function (v) { setAttributes({ cardRadius: v }); } }),
125 el(RangeControl, { label: __('Card padding (px)', 'blockenberg'), value: attributes.cardPadding, min: 12, max: 64, onChange: function (v) { setAttributes({ cardPadding: v }); } }),
126 el(RangeControl, { label: __('Rotation spread (°)', 'blockenberg'), value: attributes.rotationSpread, min: 0, max: 20, onChange: function (v) { setAttributes({ rotationSpread: v }); } }),
127 el(RangeControl, { label: __('Offset X (px)', 'blockenberg'), value: attributes.offsetX, min: 0, max: 40, onChange: function (v) { setAttributes({ offsetX: v }); } }),
128 el(RangeControl, { label: __('Offset Y (px)', 'blockenberg'), value: attributes.offsetY, min: 0, max: 40, onChange: function (v) { setAttributes({ offsetY: v }); } }),
129 el(RangeControl, { label: __('Cards visible behind', 'blockenberg'), value: attributes.maxVisibleBehind, min: 1, max: 4, onChange: function (v) { setAttributes({ maxVisibleBehind: v }); } })
130 ),
131 el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: false },
132 el(ToggleControl, { label: __('Show quote mark', 'blockenberg'), checked: attributes.showQuoteMark, onChange: function (v) { setAttributes({ showQuoteMark: v }); }, __nextHasNoMarginBottom: true }),
133 el(ToggleControl, { label: __('Show tag', 'blockenberg'), checked: attributes.showTag, onChange: function (v) { setAttributes({ showTag: v }); }, __nextHasNoMarginBottom: true }),
134 el(ToggleControl, { label: __('Show author', 'blockenberg'), checked: attributes.showAuthor, onChange: function (v) { setAttributes({ showAuthor: v }); }, __nextHasNoMarginBottom: true }),
135 el(ToggleControl, { label: __('Show nav dots', 'blockenberg'), checked: attributes.showNavDots, onChange: function (v) { setAttributes({ showNavDots: v }); }, __nextHasNoMarginBottom: true }),
136 el(ToggleControl, { label: __('Animate in on scroll', 'blockenberg'), checked: attributes.animateIn, onChange: function (v) { setAttributes({ animateIn: v }); }, __nextHasNoMarginBottom: true })
137 ),
138 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
139 el(getTypographyControl(), { label: __('Title', 'blockenberg'), value: attributes.typoTitle, onChange: function (v) { setAttributes({ typoTitle: v }); } }),
140 el(getTypographyControl(), { label: __('Description', 'blockenberg'), value: attributes.typoDesc, onChange: function (v) { setAttributes({ typoDesc: v }); } }),
141 el(RangeControl, { label: __('Tag size (px)', 'blockenberg'), value: attributes.tagSize, min: 9, max: 16, onChange: function (v) { setAttributes({ tagSize: v }); } }),
142 el(RangeControl, { label: __('Author size (px)', 'blockenberg'), value: attributes.authorSize, min: 11, max: 18, onChange: function (v) { setAttributes({ authorSize: v }); } })
143 ),
144 el(PanelColorSettings, {
145 title: __('Default Colors', 'blockenberg'),
146 initialOpen: false,
147 colorSettings: [
148 { value: attributes.globalCardBg, onChange: function (v) { setAttributes({ globalCardBg: v || '' }); }, label: __('Card background', 'blockenberg') },
149 { value: attributes.globalTextColor, onChange: function (v) { setAttributes({ globalTextColor: v || '' }); }, label: __('Card text', 'blockenberg') },
150 { value: attributes.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '' }); }, label: __('Section background', 'blockenberg') },
151 ]
152 }),
153 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
154 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: attributes.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
155 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: attributes.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
156 ),
157 el(PanelBody, { title: __('Cards', 'blockenberg'), initialOpen: false },
158 cards.map(function (card, idx) {
159 return el(PanelBody, { key: card.id, title: (card.title || 'Card') + ' #' + (idx + 1), initialOpen: false },
160 el(TextControl, { label: __('Title', 'blockenberg'), value: card.title, onChange: function (v) { setCard(card.id, { title: v }); } }),
161 el(TextareaControl, { label: __('Description', 'blockenberg'), value: card.desc, rows: 3, onChange: function (v) { setCard(card.id, { desc: v }); } }),
162 el(ToggleControl, { label: __('Show as quote', 'blockenberg'), checked: card.quote, onChange: function (v) { setCard(card.id, { quote: v }); }, __nextHasNoMarginBottom: true }),
163 el(TextControl, { label: __('Tag', 'blockenberg'), value: card.tag, onChange: function (v) { setCard(card.id, { tag: v }); } }),
164 el(TextControl, { label: __('Author name', 'blockenberg'), value: card.author, onChange: function (v) { setCard(card.id, { author: v }); } }),
165 el(TextControl, { label: __('Author role', 'blockenberg'), value: card.role, onChange: function (v) { setCard(card.id, { role: v }); } }),
166 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '0.06em' } }, __('Card / Background Image', 'blockenberg')),
167 el(MediaUploadCheck, null,
168 el(MediaUpload, {
169 onSelect: function (media) { setCard(card.id, { imageUrl: media.url, imageId: media.id, imageAlt: media.alt || '' }); },
170 allowedTypes: ['image'],
171 value: card.imageId,
172 render: function (ref) {
173 return el(Button, { onClick: ref.open, variant: 'secondary', size: 'compact', style: { marginBottom: '6px' } },
174 card.imageUrl ? __('Change image', 'blockenberg') : __('Add image', 'blockenberg')
175 );
176 }
177 })
178 ),
179 card.imageUrl && el(Button, { onClick: function () { setCard(card.id, { imageUrl: '', imageId: 0 }); }, variant: 'tertiary', size: 'compact', isDestructive: true, style: { display: 'block', marginBottom: '6px' } }, __('Remove image', 'blockenberg')),
180 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '0.06em' } }, __('Author Avatar', 'blockenberg')),
181 el(MediaUploadCheck, null,
182 el(MediaUpload, {
183 onSelect: function (media) { setCard(card.id, { avatarUrl: media.url, avatarId: media.id }); },
184 allowedTypes: ['image'],
185 value: card.avatarId,
186 render: function (ref) {
187 return el(Button, { onClick: ref.open, variant: 'secondary', size: 'compact', style: { marginBottom: '6px' } },
188 card.avatarUrl ? __('Change avatar', 'blockenberg') : __('Upload avatar', 'blockenberg')
189 );
190 }
191 })
192 ),
193 card.avatarUrl && el(Button, { onClick: function () { setCard(card.id, { avatarUrl: '', avatarId: 0 }); }, variant: 'tertiary', size: 'compact', isDestructive: true, style: { display: 'block', marginBottom: '6px' } }, __('Remove avatar', 'blockenberg')),
194 el(PanelColorSettings, {
195 title: __('Card Colors', 'blockenberg'),
196 initialOpen: false,
197 colorSettings: [
198 { value: card.bgColor, onChange: function (v) { setCard(card.id, { bgColor: v || '' }); }, label: __('Background', 'blockenberg') },
199 { value: card.textColor, onChange: function (v) { setCard(card.id, { textColor: v || '' }); }, label: __('Text', 'blockenberg') },
200 { value: card.accentColor,onChange: function (v) { setCard(card.id, { accentColor: v || '' }); },label: __('Accent', 'blockenberg') },
201 { value: card.tagBg, onChange: function (v) { setCard(card.id, { tagBg: v || '' }); }, label: __('Tag background', 'blockenberg') },
202 { value: card.tagColor, onChange: function (v) { setCard(card.id, { tagColor: v || '' }); }, label: __('Tag text', 'blockenberg') },
203 ]
204 }),
205 cards.length > 1 && el(Button, { onClick: function () { removeCard(card.id); }, variant: 'tertiary', size: 'compact', isDestructive: true }, __('Remove card', 'blockenberg'))
206 );
207 }),
208 el(Button, { onClick: addCard, variant: 'primary', style: { marginTop: '8px' } }, __('+ Add Card', 'blockenberg'))
209 )
210 ),
211
212 el('div', blockProps,
213 el('div', { className: 'bkbg-cardstack-editor', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '20px' } },
214 /* Editor preview: show active card + ghost cards behind */
215 el('div', { className: 'bkbg-cardstack', 'data-style': attributes.stackStyle, 'data-animate': attributes.animateIn ? '1' : '0', style: { position: 'relative', width: attributes.cardWidth + 'px', minHeight: attributes.cardMinHeight + 'px' } },
216 /* Ghost cards */
217 Array.from({ length: visibleBehind }).map(function (_, i) {
218 var ghostIdx = (currentIdx + i + 1) % cards.length;
219 return el('div', {
220 key: 'ghost-' + i,
221 className: 'bkbg-cardstack-ghost',
222 style: {
223 position: 'absolute', inset: 0, zIndex: visibleBehind - i,
224 transform: ghostTransform(i, attributes.stackStyle, attributes.rotationSpread, attributes.offsetX, attributes.offsetY),
225 opacity: 1 - (i + 1) * 0.2,
226 transition: 'all 0.3s ease',
227 borderRadius: attributes.cardRadius + 'px',
228 background: cards[ghostIdx].bgColor || attributes.globalCardBg,
229 boxShadow: '0 8px 32px rgba(0,0,0,0.08)',
230 }
231 });
232 }),
233 /* Active card */
234 el('div', { style: { position: 'relative', zIndex: cards.length } },
235 el(CardFace, { card: cards[currentIdx], a: attributes })
236 )
237 ),
238 /* Nav dots */
239 attributes.showNavDots && el('div', { style: { display: 'flex', gap: '8px' } },
240 cards.map(function (card, idx) {
241 return el('button', {
242 key: card.id,
243 onClick: function () { setCurrentIdx(idx); },
244 style: { width: '8px', height: '8px', borderRadius: '50%', border: 'none', cursor: 'pointer', padding: 0, background: idx === currentIdx ? '#6c3fb5' : '#d1d5db', transition: 'all 0.2s ease' }
245 });
246 })
247 )
248 )
249 )
250 );
251 },
252
253 save: function (props) {
254 var a = props.attributes;
255 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkbg-card-stack-wrap' });
256 var visibleBehind = Math.min(a.maxVisibleBehind, a.cards.length - 1);
257
258 return el('div', Object.assign({}, blockProps, { style: Object.assign({ paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined }, _tv(a.typoTitle, '--bkbg-cst-tt-'), _tv(a.typoDesc, '--bkbg-cst-td-')) }),
259 el('div', { className: 'bkbg-cardstack-outer', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '20px' } },
260 el('div', {
261 className: 'bkbg-cardstack',
262 'data-style': a.stackStyle,
263 'data-animate': a.animateIn ? '1' : '0',
264 'data-rotation': a.rotationSpread,
265 'data-offset-x': a.offsetX,
266 'data-offset-y': a.offsetY,
267 'data-behind': a.maxVisibleBehind,
268 style: { position: 'relative', width: a.cardWidth + 'px', minHeight: a.cardMinHeight + 'px', cursor: 'pointer' }
269 },
270 a.cards.map(function (card, idx) {
271 var cardStyle = {
272 width: a.cardWidth + 'px',
273 minHeight: a.cardMinHeight + 'px',
274 background: card.bgColor || a.globalCardBg,
275 color: card.textColor || a.globalTextColor,
276 borderRadius: a.cardRadius + 'px',
277 padding: a.cardPadding + 'px',
278 display: 'flex',
279 flexDirection: 'column',
280 boxShadow: '0 8px 32px rgba(0,0,0,0.12)',
281 overflow: 'hidden',
282 position: idx === 0 ? 'relative' : 'absolute',
283 inset: idx === 0 ? undefined : '0',
284 zIndex: a.cards.length - idx,
285 transition: 'all 0.35s cubic-bezier(0.34,1.56,0.64,1)',
286 };
287 return el('div', { key: card.id, className: 'bkbg-cardstack-card' + (idx === 0 ? ' is-active' : ''), style: cardStyle, 'data-index': idx },
288 card.imageUrl && el('div', { style: { position: 'absolute', inset: 0, backgroundImage: 'url(' + card.imageUrl + ')', backgroundSize: 'cover', backgroundPosition: 'center', opacity: 0.15, borderRadius: 'inherit' } }),
289 el('div', { className: 'bkbg-cardstack-inner', style: { position: 'relative', flex: 1, display: 'flex', flexDirection: 'column' } },
290 a.showTag && card.tag && el('span', { className: 'bkbg-cardstack-tag', style: { display: 'inline-block', alignSelf: 'flex-start', background: card.tagBg || card.accentColor || '#6c3fb5', color: card.tagColor || '#fff', borderRadius: '4px', padding: '2px 10px', fontSize: a.tagSize + 'px', fontWeight: 700, marginBottom: '12px', letterSpacing: '0.04em' } }, card.tag),
291 a.showQuoteMark && card.quote && el('svg', { width: 28, height: 20, viewBox: '0 0 28 20', fill: 'currentColor', style: { opacity: 0.15, marginBottom: '6px' } }, el('path', { d: 'M0 20V12C0 5.333 2.667 1.333 8 0l1.6 2.4C6.933 3.467 5.467 5.2 5.2 7.6H9V20H0zm14 0V12c0-6.667 2.667-10.667 8-12l1.6 2.4c-2.667 1.067-4.133 2.8-4.4 5.2H23V20H14z' })),
292 el('h3', { className: 'bkbg-cardstack-title', style: { margin: '0 0 10px' } }, card.title),
293 el('p', { className: 'bkbg-cardstack-desc', style: { margin: '0 0 auto', opacity: 0.85 } }, card.desc),
294 a.showAuthor && card.author && el('div', { className: 'bkbg-cardstack-author', style: { marginTop: '20px', display: 'flex', alignItems: 'center', gap: '10px', borderTop: '1px solid rgba(128,128,128,0.15)', paddingTop: '14px' } },
295 el('div', { className: 'bkbg-cardstack-avatar', style: { width: '34px', height: '34px', borderRadius: '50%', background: card.accentColor || '#6c3fb5', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '14px', fontWeight: 700, color: '#fff', flexShrink: 0, overflow: 'hidden' } },
296 card.avatarUrl ? el('img', { src: card.avatarUrl, alt: card.author, style: { width: '100%', height: '100%', objectFit: 'cover' } }) : (card.author || 'A').charAt(0).toUpperCase()
297 ),
298 el('div', null,
299 el('p', { style: { margin: 0, fontWeight: 700, fontSize: a.authorSize + 'px' } }, card.author),
300 card.role && el('p', { style: { margin: 0, fontSize: (a.authorSize - 1) + 'px', opacity: 0.65 } }, card.role)
301 )
302 )
303 )
304 );
305 })
306 ),
307 a.showNavDots && el('div', { className: 'bkbg-cardstack-dots', style: { display: 'flex', gap: '8px' } },
308 a.cards.map(function (card, idx) {
309 return el('button', { key: card.id, className: 'bkbg-cardstack-dot' + (idx === 0 ? ' is-active' : ''), 'aria-label': __('Card', 'blockenberg') + ' ' + (idx + 1), style: { width: '8px', height: '8px', borderRadius: '50%', border: 'none', cursor: 'pointer', padding: 0, background: idx === 0 ? '#6c3fb5' : '#d1d5db' } });
310 })
311 )
312 )
313 );
314 }
315 });
316 }());
317