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

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

859 lines 50.8 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 useState = wp.element.useState;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelBody = wp.components.PanelBody;
11 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
12 var Button = wp.components.Button;
13 var ToggleControl = wp.components.ToggleControl;
14 var RangeControl = wp.components.RangeControl;
15 var SelectControl = wp.components.SelectControl;
16 var TextControl = wp.components.TextControl;
17 var Popover = wp.components.Popover;
18
19 var _TypographyControl, _typoCssVars;
20 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
21 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
22
23 // ── Built-in SVG icons ──────────────────────────────────────────────────────
24 var builtInIcons = {
25 check: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
26 el('path', { d: 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z' })
27 ),
28 check2: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
29 el('path', { d: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5l-4.5-4.5 1.41-1.41L10 13.67l7.59-7.59L19 7.5l-9 9z' })
30 ),
31 arrow: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
32 el('path', { d: 'M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' })
33 ),
34 'arrow-right': el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
35 el('path', { d: 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z' })
36 ),
37 star: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
38 el('path', { d: 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z' })
39 ),
40 disc: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
41 el('circle', { cx: '12', cy: '12', r: '6' })
42 ),
43 square: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
44 el('rect', { x: '6', y: '6', width: '12', height: '12', rx: '2' })
45 ),
46 dash: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
47 el('path', { d: 'M4 11h16v2H4z' })
48 ),
49 cross: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
50 el('path', { d: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z' })
51 ),
52 sparkle: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
53 el('path', { d: 'M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 17l-6.2 4.3 2.4-7.4L2 9.4h7.6z' })
54 ),
55 bolt: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
56 el('path', { d: 'M7 2v11h3v9l7-12h-4l4-8z' })
57 ),
58 heart: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
59 el('path', { d: 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' })
60 ),
61 globe: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
62 el('path', { d: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z' })
63 ),
64 shield: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
65 el('path', { d: 'M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 4l5 2.18V11c0 3.5-2.33 6.79-5 7.93-2.67-1.14-5-4.43-5-7.93V7.18L12 5z' })
66 ),
67 rocket: el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' },
68 el('path', { d: 'M9.19 6.35c-2.04 2.29-3.44 5.58-3.57 5.89L2 10.69l4.05-4.05c.38-.37.88-.57 1.41-.57L9.19 6.35zM11.17 19l5.38-5.38c-.45 2.29-2.16 5.89-5.38 5.38zm8.6-14.26c.1-.46.12-.93.07-1.39-.46-.05-.93-.03-1.39.07-1.19.27-2.3.86-3.2 1.76L9.5 11H8l-3 3 3.46.96.58.58.96 3.46 3-3v-1.5l5.82-5.75c.9-.9 1.49-2.01 1.76-3.2zM15 10c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-6.71 9.21l-1.5-1.5c-.39-.39-.39-1.02 0-1.41l.03-.03c.39-.39 1.02-.39 1.41 0l1.5 1.5c.39.39.39 1.02 0 1.41l-.03.03c-.39.39-1.02.39-1.41 0z' })
69 )
70 };
71
72 // ── Dashicons list ──────────────────────────────────────────────────────────
73 var dashicons = [
74 'yes', 'yes-alt', 'no', 'no-alt', 'arrow-right', 'arrow-right-alt', 'arrow-right-alt2',
75 'arrow-left-alt2', 'arrow-up-alt2', 'arrow-down-alt2',
76 'star-filled', 'star-half', 'star-empty', 'heart', 'thumbs-up', 'thumbs-down',
77 'awards', 'flag', 'warning', 'info', 'lightbulb', 'marker', 'tag', 'category',
78 'location', 'location-alt', 'clock', 'calendar', 'calendar-alt',
79 'groups', 'businessman', 'businesswoman', 'admin-users', 'id', 'id-alt',
80 'products', 'cart', 'money', 'money-alt', 'bank', 'feedback', 'forms',
81 'edit', 'trash', 'upload', 'download', 'cloud', 'cloud-upload', 'cloud-saved',
82 'search', 'lock', 'unlock', 'performance', 'analytics', 'chart-bar', 'chart-pie',
83 'chart-line', 'chart-area', 'list-view', 'grid-view', 'slides',
84 'desktop', 'laptop', 'tablet', 'smartphone', 'phone',
85 'media-audio', 'media-video', 'media-document', 'format-image', 'camera',
86 'portfolio', 'book', 'book-alt', 'text-page', 'welcome-write-blog',
87 'hammer', 'art', 'schedule', 'rest-api', 'database', 'code-standards',
88 'rss', 'email', 'email-alt', 'share', 'share-alt', 'networking',
89 'facebook', 'twitter', 'instagram', 'linkedin', 'youtube',
90 'shield', 'shield-alt', 'sos', 'image-rotate', 'image-flip-horizontal'
91 ];
92
93 // ── Helper: build icon element ───────────────────────────────────────────────
94 function buildIconEl(a, forSave) {
95 var type = a.iconType;
96 if (type === 'none') return null;
97
98 var inner;
99 if (type === 'custom-image') {
100 if (!a.iconImageUrl) return null;
101 inner = el('img', {
102 src: a.iconImageUrl,
103 alt: '',
104 className: 'bkbg-ib-img-icon',
105 style: { width: '100%', height: '100%', objectFit: 'contain', display: 'block' }
106 });
107 } else if (type === 'custom-char') {
108 inner = el('span', { className: 'bkbg-ib-char' }, a.iconChar || '�
109 ');
110 } else if (type === 'dashicon') {
111 inner = el('span', { className: 'dashicons dashicons-' + a.iconDashicon });
112 } else if (builtInIcons[type]) {
113 inner = builtInIcons[type];
114 } else {
115 inner = builtInIcons.star;
116 }
117
118 return el('span', {
119 className: 'bkbg-ib-icon',
120 'aria-hidden': 'true'
121 }, inner);
122 }
123
124 registerBlockType('blockenberg/icon-box', {
125 title: __('Icon Box', 'blockenberg'),
126 icon: 'star-filled',
127 category: 'bkbg-content',
128 description: __('Single card with icon, title, text, and optional link button.', 'blockenberg'),
129
130 edit: function (props) {
131 var attributes = props.attributes;
132 var setAttributes = props.setAttributes;
133 var a = attributes;
134
135 // State
136 var iconPickerState = useState(false);
137 var iconPickerOpen = iconPickerState[0];
138 var setIconPickerOpen = iconPickerState[1];
139
140 var iconSearchState = useState('');
141 var iconSearch = iconSearchState[0];
142 var setIconSearch = iconSearchState[1];
143
144 var filteredDashicons = dashicons.filter(function (ic) {
145 return !iconSearch || ic.indexOf(iconSearch) !== -1;
146 });
147
148 // ── Open media library ─────────────────────────────────────────────
149 function openMediaLibrary() {
150 var frame = wp.media({
151 title: __('Select Icon Image', 'blockenberg'),
152 button: { text: __('Use as Icon', 'blockenberg') },
153 multiple: false,
154 library: { type: 'image' }
155 });
156 frame.on('select', function () {
157 var attachment = frame.state().get('selection').first().toJSON();
158 setAttributes({ iconImageUrl: attachment.url });
159 });
160 frame.open();
161 }
162
163 // ── Option lists ───────────────────────────────────────────────────
164 var iconTypeOptions = [
165 { label: __('Star �
166 ', 'blockenberg'), value: 'star' },
167 { label: __('Checkmark ✓', 'blockenberg'), value: 'check' },
168 { label: __('Check Circle ✓●', 'blockenberg'), value: 'check2' },
169 { label: __('Arrow ›', 'blockenberg'), value: 'arrow' },
170 { label: __('Arrow Right →', 'blockenberg'), value: 'arrow-right' },
171 { label: __('Disc •', 'blockenberg'), value: 'disc' },
172 { label: __('Square ▪', 'blockenberg'), value: 'square' },
173 { label: __('Sparkle ✦', 'blockenberg'), value: 'sparkle' },
174 { label: __('Bolt ⚡', 'blockenberg'), value: 'bolt' },
175 { label: __('Dash —', 'blockenberg'), value: 'dash' },
176 { label: __('Cross ✕', 'blockenberg'), value: 'cross' },
177 { label: __('Heart ♥', 'blockenberg'), value: 'heart' },
178 { label: __('Globe 🌐', 'blockenberg'), value: 'globe' },
179 { label: __('Shield 🛡', 'blockenberg'), value: 'shield' },
180 { label: __('Rocket 🚀', 'blockenberg'), value: 'rocket' },
181 { label: __('Custom Character', 'blockenberg'), value: 'custom-char' },
182 { label: __('Dashicon', 'blockenberg'), value: 'dashicon' },
183 { label: __('Custom Image', 'blockenberg'), value: 'custom-image' },
184 { label: __('None', 'blockenberg'), value: 'none' }
185 ];
186
187 var iconShapeOptions = [
188 { label: __('None (icon only)', 'blockenberg'), value: 'none' },
189 { label: __('Circle — Filled', 'blockenberg'), value: 'circle-filled' },
190 { label: __('Circle — Outline', 'blockenberg'), value: 'circle-outline' },
191 { label: __('Square — Filled', 'blockenberg'), value: 'square-filled' },
192 { label: __('Square — Outline', 'blockenberg'), value: 'square-outline' },
193 { label: __('Rounded Square — Filled', 'blockenberg'), value: 'rounded-filled' },
194 { label: __('Rounded Square — Outline', 'blockenberg'), value: 'rounded-outline' }
195 ];
196
197 var iconPositionOptions = [
198 { label: __('Top (Centered)', 'blockenberg'), value: 'top' },
199 { label: __('Left', 'blockenberg'), value: 'left' },
200 { label: __('Right', 'blockenberg'), value: 'right' }
201 ];
202
203 var textAlignOptions = [
204 { label: __('Left', 'blockenberg'), value: 'left' },
205 { label: __('Center', 'blockenberg'), value: 'center' },
206 { label: __('Right', 'blockenberg'), value: 'right' }
207 ];
208
209 var titleTagOptions = [
210 { label: 'H2', value: 'h2' },
211 { label: 'H3', value: 'h3' },
212 { label: 'H4', value: 'h4' },
213 { label: 'P', value: 'p' }
214 ];
215
216 var fontWeightOptions = [
217 { label: '300 — Light', value: 300 },
218 { label: '400 — Regular', value: 400 },
219 { label: '500 — Medium', value: 500 },
220 { label: '600 — Semi Bold', value: 600 },
221 { label: '700 — Bold', value: 700 },
222 { label: '800 — Extra Bold', value: 800 }
223 ];
224
225 var linkStyleOptions = [
226 { label: __('Solid Button', 'blockenberg'), value: 'solid' },
227 { label: __('Outline Button', 'blockenberg'), value: 'outline' },
228 { label: __('Ghost / Subtle', 'blockenberg'), value: 'ghost' },
229 { label: __('Plain Link', 'blockenberg'), value: 'text' }
230 ];
231
232 var borderStyleOptions = [
233 { label: __('Solid', 'blockenberg'), value: 'solid' },
234 { label: __('Dashed', 'blockenberg'), value: 'dashed' },
235 { label: __('Dotted', 'blockenberg'), value: 'dotted' },
236 { label: __('None', 'blockenberg'), value: 'none' }
237 ];
238
239 var hoverEffectOptions = [
240 { label: __('None', 'blockenberg'), value: 'none' },
241 { label: __('Lift (translate up)', 'blockenberg'), value: 'lift' },
242 { label: __('Glow (shadow)', 'blockenberg'), value: 'glow' },
243 { label: __('Scale', 'blockenberg'), value: 'scale' },
244 { label: __('Border Highlight', 'blockenberg'), value: 'border' }
245 ];
246
247 var targetOptions = [
248 { label: __('Same Tab', 'blockenberg'), value: '_self' },
249 { label: __('New Tab', 'blockenberg'), value: '_blank' }
250 ];
251
252 // ── CSS Variables & data attributes ────────────────────────────────
253 var wrapStyle = {
254 '--bkbg-ib-content-gap': a.contentGap + 'px',
255 '--bkbg-ib-icon-size': a.iconSize + 'px',
256 '--bkbg-ib-icon-color': a.iconColor,
257 '--bkbg-ib-icon-bg': a.iconBgColor,
258 '--bkbg-ib-icon-bg-size': a.iconBgSize + 'px',
259 '--bkbg-ib-icon-radius': a.iconBgRadius + '%',
260 '--bkbg-ib-title-size': a.titleSize + 'px',
261 '--bkbg-ib-title-weight': a.titleWeight,
262 '--bkbg-ib-title-color': a.titleColor,
263 '--bkbg-ib-title-lh': a.titleLineHeight,
264 '--bkbg-ib-title-spacing': a.titleSpacing + 'px',
265 '--bkbg-ib-text-size': a.textSize + 'px',
266 '--bkbg-ib-text-weight': a.textWeight,
267 '--bkbg-ib-text-color': a.textColor,
268 '--bkbg-ib-text-lh': a.textLineHeight,
269 '--bkbg-ib-card-bg': a.cardBg,
270 '--bkbg-ib-card-bg-hover': a.cardBgHover || a.cardBg,
271 '--bkbg-ib-card-padding': a.cardPaddingTop + 'px ' + a.cardPaddingRight + 'px ' + a.cardPaddingBottom + 'px ' + a.cardPaddingLeft + 'px',
272 '--bkbg-ib-card-brd-w': a.cardBorderWidth + 'px',
273 '--bkbg-ib-card-brd-style': a.cardBorderStyle,
274 '--bkbg-ib-card-brd-color': a.cardBorderColor,
275 '--bkbg-ib-card-radius': a.cardBorderRadius + 'px',
276 '--bkbg-ib-card-shadow': a.cardShadow
277 ? (a.cardShadowH + 'px ' + a.cardShadowV + 'px ' + a.cardShadowBlur + 'px ' + a.cardShadowSpread + 'px ' + a.cardShadowColor)
278 : 'none',
279 '--bkbg-ib-card-shadow-hover': a.cardShadowHover,
280 '--bkbg-ib-link-bg': a.linkBg,
281 '--bkbg-ib-link-color': a.linkColor,
282 '--bkbg-ib-link-bg-hover': a.linkBgHover,
283 '--bkbg-ib-link-color-hover': a.linkColorHover,
284 '--bkbg-ib-link-brd-color': a.linkBorderColor,
285 '--bkbg-ib-link-brd-w': a.linkBorderWidth + 'px',
286 '--bkbg-ib-link-size': a.linkSize + 'px',
287 '--bkbg-ib-link-weight': a.linkWeight,
288 '--bkbg-ib-link-radius': a.linkRadius + 'px',
289 '--bkbg-ib-link-padding': a.linkPaddingV + 'px ' + a.linkPaddingH + 'px',
290 '--bkbg-ib-link-spacing': a.linkSpacingTop + 'px',
291 '--bkbg-ib-text-align': a.textAlign
292 };
293 var _tv = getTypoCssVars();
294 if (_tv) {
295 Object.assign(wrapStyle, _tv(a.titleTypo, '--bkbg-ib-tt-'));
296 Object.assign(wrapStyle, _tv(a.textTypo, '--bkbg-ib-tx-'));
297 }
298
299 var wrapDataAttrs = {
300 'data-icon-pos': a.iconPosition,
301 'data-icon-shape': a.iconShape,
302 'data-icon-align': a.iconAlignTop ? 'top' : 'center',
303 'data-text-align': a.textAlign,
304 'data-link-style': a.linkStyle,
305 'data-hover': a.hoverEffect
306 };
307
308 var iconEl = buildIconEl(a, false);
309
310 // ── Inspector Controls ─────────────────────────────────────────────
311 var inspector = el(InspectorControls, {},
312
313 // ── Layout ────────────────────────────────────────────────────
314 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: true },
315 el(SelectControl, {
316 label: __('Icon Position', 'blockenberg'),
317 value: a.iconPosition,
318 options: iconPositionOptions,
319 onChange: function (v) { setAttributes({ iconPosition: v }); }
320 }),
321 (a.iconPosition === 'left' || a.iconPosition === 'right') && el(ToggleControl, {
322 label: __('Align icon to top', 'blockenberg'),
323 checked: a.iconAlignTop,
324 __nextHasNoMarginBottom: true,
325 onChange: function (v) { setAttributes({ iconAlignTop: v }); }
326 }),
327 el(SelectControl, {
328 label: __('Text Alignment', 'blockenberg'),
329 value: a.textAlign,
330 options: textAlignOptions,
331 onChange: function (v) { setAttributes({ textAlign: v }); }
332 }),
333 el(RangeControl, {
334 label: __('Gap (icon ↔ content)', 'blockenberg'),
335 value: a.contentGap,
336 min: 4,
337 max: 60,
338 onChange: function (v) { setAttributes({ contentGap: v }); }
339 })
340 ),
341
342 // ── Icon ──────────────────────────────────────────────────────
343 el(PanelBody, { title: __('Icon', 'blockenberg'), initialOpen: false },
344 el(SelectControl, {
345 label: __('Icon Type', 'blockenberg'),
346 value: a.iconType,
347 options: iconTypeOptions,
348 onChange: function (v) { setAttributes({ iconType: v }); }
349 }),
350 // Custom char input
351 a.iconType === 'custom-char' && el(TextControl, {
352 label: __('Character', 'blockenberg'),
353 value: a.iconChar,
354 onChange: function (v) { setAttributes({ iconChar: v }); }
355 }),
356 // Dashicon picker
357 a.iconType === 'dashicon' && el('div', {},
358 el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } },
359 el('span', {
360 className: 'dashicons dashicons-' + a.iconDashicon,
361 style: { fontSize: '24px', width: '24px', height: '24px', color: a.iconColor }
362 }),
363 el(Button, {
364 variant: 'secondary',
365 isSmall: true,
366 onClick: function () { setIconPickerOpen(!iconPickerOpen); }
367 }, __('Choose Dashicon', 'blockenberg'))
368 ),
369 iconPickerOpen && el(Popover, {
370 position: 'bottom left',
371 onClose: function () { setIconPickerOpen(false); setIconSearch(''); }
372 },
373 el('div', {
374 className: 'bkbg-sc-icon-picker-modal',
375 onMouseDown: function (e) { e.stopPropagation(); }
376 },
377 el('div', { className: 'bkbg-sc-icon-picker-header' },
378 el('h3', {}, __('Choose Dashicon', 'blockenberg')),
379 el(Button, {
380 icon: 'no-alt',
381 onClick: function () { setIconPickerOpen(false); setIconSearch(''); },
382 className: 'bkbg-sc-icon-picker-close'
383 })
384 ),
385 el(TextControl, {
386 placeholder: __('Search icons…', 'blockenberg'),
387 value: iconSearch,
388 onChange: setIconSearch,
389 className: 'bkbg-sc-icon-search'
390 }),
391 el('div', { className: 'bkbg-sc-dashicons-grid' },
392 filteredDashicons.length === 0
393 ? el('p', { className: 'bkbg-sc-no-icons' }, __('No icons found', 'blockenberg'))
394 : filteredDashicons.map(function (icon) {
395 var isActive = a.iconDashicon === icon;
396 return el('button', {
397 key: icon,
398 type: 'button',
399 title: icon,
400 className: 'bkbg-sc-dashicon-btn' + (isActive ? ' is-active' : ''),
401 onClick: function () {
402 setAttributes({ iconDashicon: icon });
403 setIconPickerOpen(false);
404 setIconSearch('');
405 }
406 }, el('span', { className: 'dashicons dashicons-' + icon }));
407 })
408 )
409 )
410 )
411 ),
412 // Custom image
413 a.iconType === 'custom-image' && el('div', {},
414 a.iconImageUrl && el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } },
415 el('img', { src: a.iconImageUrl, alt: '', style: { width: '48px', height: '48px', objectFit: 'contain', border: '1px solid #e2e8f0', borderRadius: '6px' } }),
416 el(Button, {
417 isSmall: true,
418 isDestructive: true,
419 onClick: function () { setAttributes({ iconImageUrl: '' }); }
420 }, __('Remove', 'blockenberg'))
421 ),
422 el(Button, {
423 variant: 'secondary',
424 isSmall: true,
425 onClick: openMediaLibrary
426 }, a.iconImageUrl ? __('Replace Image', 'blockenberg') : __('Select Image', 'blockenberg'))
427 ),
428
429 el('hr', {}),
430
431 el(SelectControl, {
432 label: __('Icon Shape', 'blockenberg'),
433 value: a.iconShape,
434 options: iconShapeOptions,
435 onChange: function (v) { setAttributes({ iconShape: v }); }
436 }),
437 el(RangeControl, {
438 label: __('Icon Size', 'blockenberg'),
439 value: a.iconSize,
440 min: 12,
441 max: 80,
442 onChange: function (v) { setAttributes({ iconSize: v }); }
443 }),
444 a.iconShape !== 'none' && el(Fragment, {},
445 el(RangeControl, {
446 label: __('Background Size', 'blockenberg'),
447 value: a.iconBgSize,
448 min: 24,
449 max: 140,
450 onChange: function (v) { setAttributes({ iconBgSize: v }); }
451 }),
452 el(RangeControl, {
453 label: __('Background Radius (%)', 'blockenberg'),
454 value: a.iconBgRadius,
455 min: 0,
456 max: 50,
457 onChange: function (v) { setAttributes({ iconBgRadius: v }); }
458 })
459 )
460 ),
461
462 // ── Typography ────────────────────────────────────────────────
463 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
464 el(SelectControl, {
465 label: __('Title Tag', 'blockenberg'),
466 value: a.titleTag,
467 options: titleTagOptions,
468 onChange: function (v) { setAttributes({ titleTag: v }); }
469 }),
470 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __('Title', 'blockenberg')),
471 getTypographyControl() && el(getTypographyControl(), { label: __('Title', 'blockenberg'), typo: a.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
472 el(RangeControl, {
473 label: __('Spacing Below Title', 'blockenberg'),
474 value: a.titleSpacing,
475 min: 0,
476 max: 40,
477 onChange: function (v) { setAttributes({ titleSpacing: v }); }
478 }),
479 el('hr', {}),
480 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __('Body Text', 'blockenberg')),
481 getTypographyControl() && el(getTypographyControl(), { label: __('Body Text', 'blockenberg'), typo: a.textTypo || {}, onChange: function (v) { setAttributes({ textTypo: v }); } }),
482 el('hr', {}),
483 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __('Link Button', 'blockenberg')),
484 el(RangeControl, {
485 label: __('Font Size', 'blockenberg'),
486 value: a.linkSize,
487 min: 10,
488 max: 24,
489 onChange: function (v) { setAttributes({ linkSize: v }); }
490 }),
491 el(SelectControl, {
492 label: __('Font Weight', 'blockenberg'),
493 value: a.linkWeight,
494 options: fontWeightOptions,
495 onChange: function (v) { setAttributes({ linkWeight: parseInt(v, 10) }); }
496 })
497 ),
498
499 // ── Link ──────────────────────────────────────────────────────
500 el(PanelBody, { title: __('Link Button', 'blockenberg'), initialOpen: false },
501 el(ToggleControl, {
502 label: __('Show Link Button', 'blockenberg'),
503 checked: a.linkEnabled,
504 __nextHasNoMarginBottom: true,
505 onChange: function (v) { setAttributes({ linkEnabled: v }); }
506 }),
507 a.linkEnabled && el(Fragment, {},
508 el(TextControl, {
509 label: __('Button Text', 'blockenberg'),
510 value: a.linkText,
511 onChange: function (v) { setAttributes({ linkText: v }); }
512 }),
513 el(TextControl, {
514 label: __('URL', 'blockenberg'),
515 value: a.linkUrl,
516 type: 'url',
517 placeholder: 'https://',
518 onChange: function (v) { setAttributes({ linkUrl: v }); }
519 }),
520 el(SelectControl, {
521 label: __('Open In', 'blockenberg'),
522 value: a.linkTarget,
523 options: targetOptions,
524 onChange: function (v) { setAttributes({ linkTarget: v }); }
525 }),
526 el('hr', {}),
527 el(SelectControl, {
528 label: __('Button Style', 'blockenberg'),
529 value: a.linkStyle,
530 options: linkStyleOptions,
531 onChange: function (v) { setAttributes({ linkStyle: v }); }
532 }),
533 el(RangeControl, {
534 label: __('Border Radius', 'blockenberg'),
535 value: a.linkRadius,
536 min: 0,
537 max: 50,
538 onChange: function (v) { setAttributes({ linkRadius: v }); }
539 }),
540 el(RangeControl, {
541 label: __('Padding Vertical', 'blockenberg'),
542 value: a.linkPaddingV,
543 min: 4,
544 max: 28,
545 onChange: function (v) { setAttributes({ linkPaddingV: v }); }
546 }),
547 el(RangeControl, {
548 label: __('Padding Horizontal', 'blockenberg'),
549 value: a.linkPaddingH,
550 min: 8,
551 max: 60,
552 onChange: function (v) { setAttributes({ linkPaddingH: v }); }
553 }),
554 el(RangeControl, {
555 label: __('Spacing Above Button', 'blockenberg'),
556 value: a.linkSpacingTop,
557 min: 0,
558 max: 48,
559 onChange: function (v) { setAttributes({ linkSpacingTop: v }); }
560 }),
561 (a.linkStyle === 'outline' || a.linkStyle === 'ghost') && el(RangeControl, {
562 label: __('Border Width', 'blockenberg'),
563 value: a.linkBorderWidth,
564 min: 1,
565 max: 4,
566 onChange: function (v) { setAttributes({ linkBorderWidth: v }); }
567 })
568 )
569 ),
570
571 // ── Card ──────────────────────────────────────────────────────
572 el(PanelBody, { title: __('Card', 'blockenberg'), initialOpen: false },
573 el('p', { style: { margin: '0 0 6px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888' } }, __('Padding', 'blockenberg')),
574 el('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px', marginBottom: '16px' } },
575 el(RangeControl, { label: __('Top', 'blockenberg'), value: a.cardPaddingTop, min: 0, max: 80, onChange: function (v) { setAttributes({ cardPaddingTop: v }); } }),
576 el(RangeControl, { label: __('Right', 'blockenberg'), value: a.cardPaddingRight, min: 0, max: 80, onChange: function (v) { setAttributes({ cardPaddingRight: v }); } }),
577 el(RangeControl, { label: __('Bottom', 'blockenberg'), value: a.cardPaddingBottom, min: 0, max: 80, onChange: function (v) { setAttributes({ cardPaddingBottom: v }); } }),
578 el(RangeControl, { label: __('Left', 'blockenberg'), value: a.cardPaddingLeft, min: 0, max: 80, onChange: function (v) { setAttributes({ cardPaddingLeft: v }); } })
579 ),
580 el(RangeControl, {
581 label: __('Border Radius', 'blockenberg'),
582 value: a.cardBorderRadius,
583 min: 0,
584 max: 48,
585 onChange: function (v) { setAttributes({ cardBorderRadius: v }); }
586 }),
587 el(RangeControl, {
588 label: __('Border Width', 'blockenberg'),
589 value: a.cardBorderWidth,
590 min: 0,
591 max: 6,
592 onChange: function (v) { setAttributes({ cardBorderWidth: v }); }
593 }),
594 a.cardBorderWidth > 0 && el(SelectControl, {
595 label: __('Border Style', 'blockenberg'),
596 value: a.cardBorderStyle,
597 options: borderStyleOptions,
598 onChange: function (v) { setAttributes({ cardBorderStyle: v }); }
599 }),
600 el('hr', {}),
601 el(SelectControl, {
602 label: __('Hover Effect', 'blockenberg'),
603 value: a.hoverEffect,
604 options: hoverEffectOptions,
605 onChange: function (v) { setAttributes({ hoverEffect: v }); }
606 }),
607 el('hr', {}),
608 el(ToggleControl, {
609 label: __('Box Shadow', 'blockenberg'),
610 checked: a.cardShadow,
611 __nextHasNoMarginBottom: true,
612 onChange: function (v) { setAttributes({ cardShadow: v }); }
613 }),
614 a.cardShadow && el(Fragment, {},
615 el(RangeControl, {
616 label: __('Shadow H', 'blockenberg'),
617 value: a.cardShadowH, min: -20, max: 20,
618 onChange: function (v) { setAttributes({ cardShadowH: v }); }
619 }),
620 el(RangeControl, {
621 label: __('Shadow V', 'blockenberg'),
622 value: a.cardShadowV, min: -20, max: 40,
623 onChange: function (v) { setAttributes({ cardShadowV: v }); }
624 }),
625 el(RangeControl, {
626 label: __('Blur', 'blockenberg'),
627 value: a.cardShadowBlur, min: 0, max: 80,
628 onChange: function (v) { setAttributes({ cardShadowBlur: v }); }
629 }),
630 el(RangeControl, {
631 label: __('Spread', 'blockenberg'),
632 value: a.cardShadowSpread, min: -10, max: 20,
633 onChange: function (v) { setAttributes({ cardShadowSpread: v }); }
634 }),
635 el(TextControl, {
636 label: __('Shadow on Hover (CSS)', 'blockenberg'),
637 value: a.cardShadowHover,
638 help: __('Full box-shadow CSS value for hover state.', 'blockenberg'),
639 onChange: function (v) { setAttributes({ cardShadowHover: v }); }
640 })
641 )
642 ),
643
644 // ── Colors ────────────────────────────────────────────────────
645 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
646 el(PanelColorSettings, {
647 title: __('Icon', 'blockenberg'),
648 initialOpen: false,
649 colorSettings: [
650 { value: a.iconColor, onChange: function (c) { setAttributes({ iconColor: c || '#3b82f6' }); }, label: __('Icon Color', 'blockenberg') },
651 { value: a.iconBgColor, onChange: function (c) { setAttributes({ iconBgColor: c || '#dbeafe' }); }, label: __('Background', 'blockenberg') }
652 ]
653 }),
654 el(PanelColorSettings, {
655 title: __('Text', 'blockenberg'),
656 initialOpen: false,
657 colorSettings: [
658 { value: a.titleColor, onChange: function (c) { setAttributes({ titleColor: c || '#1e293b' }); }, label: __('Title', 'blockenberg') },
659 { value: a.textColor, onChange: function (c) { setAttributes({ textColor: c || '#6b7280' }); }, label: __('Body Text', 'blockenberg') }
660 ]
661 }),
662 el(PanelColorSettings, {
663 title: __('Card', 'blockenberg'),
664 initialOpen: false,
665 colorSettings: [
666 { value: a.cardBg, onChange: function (c) { setAttributes({ cardBg: c || '#ffffff' }); }, label: __('Background', 'blockenberg') },
667 { value: a.cardBgHover, onChange: function (c) { setAttributes({ cardBgHover: c || '' }); }, label: __('Background (Hover)', 'blockenberg') },
668 { value: a.cardBorderColor, onChange: function (c) { setAttributes({ cardBorderColor: c || '#e2e8f0' }); }, label: __('Border', 'blockenberg') },
669 { value: a.cardShadowColor, onChange: function (c) { setAttributes({ cardShadowColor: c || 'rgba(0,0,0,0.07)' }); }, label: __('Shadow Color', 'blockenberg') }
670 ]
671 }),
672 a.linkEnabled && el(PanelColorSettings, {
673 title: __('Link Button', 'blockenberg'),
674 initialOpen: false,
675 colorSettings: [
676 { value: a.linkBg, onChange: function (c) { setAttributes({ linkBg: c || '#3b82f6' }); }, label: __('Background', 'blockenberg') },
677 { value: a.linkColor, onChange: function (c) { setAttributes({ linkColor: c || '#ffffff' }); }, label: __('Text', 'blockenberg') },
678 { value: a.linkBgHover, onChange: function (c) { setAttributes({ linkBgHover: c || '#2563eb' }); }, label: __('Background (Hover)', 'blockenberg') },
679 { value: a.linkColorHover, onChange: function (c) { setAttributes({ linkColorHover: c || '#ffffff' }); }, label: __('Text (Hover)', 'blockenberg') },
680 { value: a.linkBorderColor, onChange: function (c) { setAttributes({ linkBorderColor: c || '#3b82f6' }); }, label: __('Border', 'blockenberg') }
681 ]
682 })
683 )
684 );
685
686 // ── Edit render ────────────────────────────────────────────────────────
687 var blockProps = useBlockProps({
688 className: 'bkbg-editor-wrap',
689 'data-block-label': 'Icon Box'
690 });
691
692 return el('div', blockProps,
693 inspector,
694 el('div', Object.assign({ className: 'bkbg-ib-wrap', style: wrapStyle }, wrapDataAttrs),
695 // Icon
696 iconEl && el('div', { className: 'bkbg-ib-icon-wrap' }, iconEl),
697
698 // Body
699 el('div', { className: 'bkbg-ib-body' },
700 el(RichText, {
701 tagName: a.titleTag,
702 className: 'bkbg-ib-title',
703 value: a.title,
704 onChange: function (v) { setAttributes({ title: v }); },
705 placeholder: __('Title…', 'blockenberg'),
706 allowedFormats: ['core/bold', 'core/italic', 'core/text-color']
707 }),
708 el(RichText, {
709 tagName: 'p',
710 className: 'bkbg-ib-text',
711 value: a.text,
712 onChange: function (v) { setAttributes({ text: v }); },
713 placeholder: __('Description…', 'blockenberg'),
714 allowedFormats: ['core/bold', 'core/italic', 'core/link', 'core/strikethrough', 'core/text-color']
715 }),
716 a.linkEnabled && el('div', { className: 'bkbg-ib-link-wrap' },
717 el('span', { className: 'bkbg-ib-link' }, a.linkText || __('Learn More', 'blockenberg')),
718 el('span', { className: 'bkbg-ib-link-url-hint' },
719 a.linkUrl ? '' + a.linkUrl : __(' (no URL set)', 'blockenberg')
720 )
721 )
722 )
723 )
724 );
725 },
726
727 // ── Save ─────────────────────────────────────────────────────────────────
728 save: function (props) {
729 var a = props.attributes;
730 var RichTextContent = wp.blockEditor.RichText.Content;
731
732 var wrapStyle = {
733 '--bkbg-ib-content-gap': a.contentGap + 'px',
734 '--bkbg-ib-icon-size': a.iconSize + 'px',
735 '--bkbg-ib-icon-color': a.iconColor,
736 '--bkbg-ib-icon-bg': a.iconBgColor,
737 '--bkbg-ib-icon-bg-size': a.iconBgSize + 'px',
738 '--bkbg-ib-icon-radius': a.iconBgRadius + '%',
739 '--bkbg-ib-title-size': a.titleSize + 'px',
740 '--bkbg-ib-title-weight': a.titleWeight,
741 '--bkbg-ib-title-color': a.titleColor,
742 '--bkbg-ib-title-lh': a.titleLineHeight,
743 '--bkbg-ib-title-spacing': a.titleSpacing + 'px',
744 '--bkbg-ib-text-size': a.textSize + 'px',
745 '--bkbg-ib-text-weight': a.textWeight,
746 '--bkbg-ib-text-color': a.textColor,
747 '--bkbg-ib-text-lh': a.textLineHeight,
748 '--bkbg-ib-card-bg': a.cardBg,
749 '--bkbg-ib-card-bg-hover': a.cardBgHover || a.cardBg,
750 '--bkbg-ib-card-padding': a.cardPaddingTop + 'px ' + a.cardPaddingRight + 'px ' + a.cardPaddingBottom + 'px ' + a.cardPaddingLeft + 'px',
751 '--bkbg-ib-card-brd-w': a.cardBorderWidth + 'px',
752 '--bkbg-ib-card-brd-style': a.cardBorderStyle,
753 '--bkbg-ib-card-brd-color': a.cardBorderColor,
754 '--bkbg-ib-card-radius': a.cardBorderRadius + 'px',
755 '--bkbg-ib-card-shadow': a.cardShadow
756 ? (a.cardShadowH + 'px ' + a.cardShadowV + 'px ' + a.cardShadowBlur + 'px ' + a.cardShadowSpread + 'px ' + a.cardShadowColor)
757 : 'none',
758 '--bkbg-ib-card-shadow-hover': a.cardShadowHover,
759 '--bkbg-ib-link-bg': a.linkBg,
760 '--bkbg-ib-link-color': a.linkColor,
761 '--bkbg-ib-link-bg-hover': a.linkBgHover,
762 '--bkbg-ib-link-color-hover': a.linkColorHover,
763 '--bkbg-ib-link-brd-color': a.linkBorderColor,
764 '--bkbg-ib-link-brd-w': a.linkBorderWidth + 'px',
765 '--bkbg-ib-link-size': a.linkSize + 'px',
766 '--bkbg-ib-link-weight': a.linkWeight,
767 '--bkbg-ib-link-radius': a.linkRadius + 'px',
768 '--bkbg-ib-link-padding': a.linkPaddingV + 'px ' + a.linkPaddingH + 'px',
769 '--bkbg-ib-link-spacing': a.linkSpacingTop + 'px',
770 '--bkbg-ib-text-align': a.textAlign
771 };
772 var _tv2 = getTypoCssVars();
773 if (_tv2) {
774 Object.assign(wrapStyle, _tv2(a.titleTypo, '--bkbg-ib-tt-'));
775 Object.assign(wrapStyle, _tv2(a.textTypo, '--bkbg-ib-tx-'));
776 }
777
778 var wrapDataAttrs = {
779 'data-icon-pos': a.iconPosition,
780 'data-icon-shape': a.iconShape,
781 'data-icon-align': a.iconAlignTop ? 'top' : 'center',
782 'data-text-align': a.textAlign,
783 'data-link-style': a.linkStyle,
784 'data-hover': a.hoverEffect
785 };
786
787 // Build save icon
788 var saveIconEl = (function () {
789 var type = a.iconType;
790 if (type === 'none') return null;
791
792 var svgPaths = {
793 check: 'M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z',
794 check2: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5l-4.5-4.5 1.41-1.41L10 13.67l7.59-7.59L19 7.5l-9 9z',
795 arrow: 'M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z',
796 'arrow-right': 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z',
797 star: 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z',
798 sparkle: 'M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 17l-6.2 4.3 2.4-7.4L2 9.4h7.6z',
799 bolt: 'M7 2v11h3v9l7-12h-4l4-8z',
800 dash: 'M4 11h16v2H4z',
801 cross: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
802 heart: 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
803 globe: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z',
804 shield: 'M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 4l5 2.18V11c0 3.5-2.33 6.79-5 7.93-2.67-1.14-5-4.43-5-7.93V7.18L12 5z',
805 rocket: 'M9.19 6.35c-2.04 2.29-3.44 5.58-3.57 5.89L2 10.69l4.05-4.05c.38-.37.88-.57 1.41-.57L9.19 6.35zM11.17 19l5.38-5.38c-.45 2.29-2.16 5.89-5.38 5.38zm8.6-14.26c.1-.46.12-.93.07-1.39-.46-.05-.93-.03-1.39.07-1.19.27-2.3.86-3.2 1.76L9.5 11H8l-3 3 3.46.96.58.58.96 3.46 3-3v-1.5l5.82-5.75c.9-.9 1.49-2.01 1.76-3.2zM15 10c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-6.71 9.21l-1.5-1.5c-.39-.39-.39-1.02 0-1.41l.03-.03c.39-.39 1.02-.39 1.41 0l1.5 1.5c.39.39.39 1.02 0 1.41l-.03.03c-.39.39-1.02.39-1.41 0z'
806 };
807
808 var inner;
809 if (type === 'custom-image') {
810 if (!a.iconImageUrl) return null;
811 inner = el('img', { src: a.iconImageUrl, alt: '', className: 'bkbg-ib-img-icon', style: { width: '100%', height: '100%', objectFit: 'contain', display: 'block' } });
812 } else if (type === 'custom-char') {
813 inner = el('span', { className: 'bkbg-ib-char' }, a.iconChar || '�
814 ');
815 } else if (type === 'dashicon') {
816 inner = el('span', { className: 'dashicons dashicons-' + a.iconDashicon });
817 } else if (type === 'disc') {
818 inner = el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('circle', { cx: '12', cy: '12', r: '6' }));
819 } else if (type === 'square') {
820 inner = el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('rect', { x: '6', y: '6', width: '12', height: '12', rx: '2' }));
821 } else if (svgPaths[type]) {
822 inner = el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: svgPaths[type] }));
823 } else {
824 inner = el('svg', { viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }, el('path', { d: svgPaths.star }));
825 }
826
827 return el('span', { className: 'bkbg-ib-icon', 'aria-hidden': 'true' }, inner);
828 })();
829
830 return el('div', Object.assign({ className: 'bkbg-ib-wrap', style: wrapStyle }, wrapDataAttrs),
831 // Icon
832 saveIconEl && el('div', { className: 'bkbg-ib-icon-wrap' }, saveIconEl),
833
834 // Body
835 el('div', { className: 'bkbg-ib-body' },
836 el(RichTextContent, {
837 tagName: a.titleTag,
838 className: 'bkbg-ib-title',
839 value: a.title
840 }),
841 el(RichTextContent, {
842 tagName: 'p',
843 className: 'bkbg-ib-text',
844 value: a.text
845 }),
846 a.linkEnabled && el('div', { className: 'bkbg-ib-link-wrap' },
847 el('a', {
848 href: a.linkUrl || '#',
849 className: 'bkbg-ib-link',
850 target: a.linkTarget,
851 rel: a.linkTarget === '_blank' ? 'noopener noreferrer' : undefined
852 }, a.linkText || 'Learn More')
853 )
854 )
855 );
856 }
857 });
858 }() );
859