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

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

379 lines 29.6 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 PanelBody = wp.components.PanelBody;
10 var Button = wp.components.Button;
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 ColorPicker = wp.components.ColorPicker;
16 var Popover = wp.components.Popover;
17 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
18 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
19
20 // ── Platform definitions ──────────────────────────────────────────────────
21 var platforms = {
22 facebook: { label: 'Facebook', color: '#1877F2', svg: 'M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z' },
23 instagram: { label: 'Instagram', color: '#E4405F', svg: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162S8.597 18.163 12 18.163s6.162-2.759 6.162-6.162S15.403 5.838 12 5.838zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z' },
24 twitter: { label: 'Twitter / X', color: '#000000', svg: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.746l7.73-8.835L1.254 2.25H8.08l4.713 5.966zm-1.161 17.52h1.833L7.084 4.126H5.117z' },
25 youtube: { label: 'YouTube', color: '#FF0000', svg: 'M23.495 6.205a3.007 3.007 0 0 0-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 0 0 .527 6.205a31.247 31.247 0 0 0-.522 5.805 31.247 31.247 0 0 0 .522 5.783 3.007 3.007 0 0 0 2.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 0 0 2.088-2.088 31.247 31.247 0 0 0 .5-5.783 31.247 31.247 0 0 0-.5-5.805zM9.609 15.601V8.408l6.264 3.602z' },
26 linkedin: { label: 'LinkedIn', color: '#0A66C2', svg: 'M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z' },
27 tiktok: { label: 'TikTok', color: '#000000', svg: 'M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z' },
28 pinterest: { label: 'Pinterest', color: '#BD081C', svg: 'M12 0C5.373 0 0 5.373 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.632-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12S18.627 0 12 0z' },
29 github: { label: 'GitHub', color: '#181717', svg: 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12' },
30 whatsapp: { label: 'WhatsApp', color: '#25D366', svg: 'M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z' },
31 telegram: { label: 'Telegram', color: '#26A5E4', svg: 'M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z' },
32 reddit: { label: 'Reddit', color: '#FF4500', svg: 'M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z' },
33 rss: { label: 'RSS', color: '#FFA500', svg: 'M19.199 24C19.199 13.467 10.533 4.8 0 4.8V0c13.165 0 24 10.835 24 24h-4.801zM3.291 17.415a3.3 3.3 0 0 1 3.293 3.295A3.308 3.308 0 0 1 3.28 24C1.47 24 0 22.526 0 20.71s1.475-3.294 3.291-3.295zM15.909 24h-4.665c0-6.169-5.075-11.245-11.244-11.245V8.088c8.727 0 15.909 7.184 15.909 15.912z' }
34 };
35
36 var platformKeys = Object.keys(platforms);
37
38 // ── Brand colors map ──────────────────────────────────────────────────────
39 function getPlatformColor(platform) {
40 return (platforms[platform] && platforms[platform].color) || '#555';
41 }
42
43 // ── CSS vars ──────────────────────────────────────────────────────────────
44 function buildWrapStyle(a) {
45 var s = {
46 '--bkbg-sl-icon-size' : a.iconSize + 'px',
47 '--bkbg-sl-btn-size' : a.buttonSize + 'px',
48 '--bkbg-sl-gap' : a.gap + 'px',
49 '--bkbg-sl-radius' : a.borderRadius + 'px',
50 '--bkbg-sl-border-w' : a.borderWidth + 'px',
51 '--bkbg-sl-custom-icon' : a.customIconColor,
52 '--bkbg-sl-custom-bg' : a.customBgColor,
53 '--bkbg-sl-custom-icon-h': a.customHoverIconColor,
54 '--bkbg-sl-custom-bg-h' : a.customHoverBgColor,
55 '--bkbg-sl-label-size' : a.labelFontSize + 'px',
56 '--bkbg-sl-label-weight' : a.labelFontWeight,
57 '--bkbg-sl-label-line-height': a.labelLineHeight,
58 '--bkbg-sl-label-color' : a.labelColor,
59 '--bkbg-sl-label-color-h': a.labelColorHover,
60 '--bkbg-sl-pad-top' : a.wrapperPaddingTop + 'px',
61 '--bkbg-sl-pad-bottom' : a.wrapperPaddingBottom + 'px'
62 };
63 var _tvFn = getTypoCssVars();
64 if (_tvFn) Object.assign(s, _tvFn(a.labelTypo || {}, '--bksl-lb-'));
65 return s;
66 }
67
68 // ── SVG icon builder ──────────────────────────────────────────────────────
69 function buildIcon(platform) {
70 var p = platforms[platform];
71 if (!p) return el('span', { className: 'bkbg-sl-unknown' }, platform[0].toUpperCase());
72 return el('svg', {
73 xmlns: 'http://www.w3.org/2000/svg',
74 viewBox: '0 0 24 24',
75 'aria-hidden': 'true',
76 focusable: 'false',
77 className: 'bkbg-sl-svg'
78 }, el('path', { d: p.svg }));
79 }
80
81 // ── Color swatch ──────────────────────────────────────────────────────────
82 function renderColorControl(key, label, value, onChange, openKey, setOpenKey) {
83 var isOpen = openKey === key;
84 return el('div', { key: key, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' } },
85 el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label),
86 el('div', { style: { position: 'relative', flexShrink: 0 } },
87 el('button', {
88 type: 'button', title: value || 'none',
89 onClick: function () { setOpenKey(isOpen ? null : key); },
90 style: { width: '28px', height: '28px', borderRadius: '4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor: 'pointer', padding: 0, background: value || '#fff' }
91 }),
92 isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
93 el('div', { style: { padding: '8px' } },
94 el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange })
95 )
96 )
97 )
98 );
99 }
100
101 function updateLink(links, i, field, value, setAttributes) {
102 var newLinks = links.map(function (link, idx) {
103 if (idx !== i) return link;
104 var upd = {};
105 for (var k in link) { upd[k] = link[k]; }
106 upd[field] = value;
107 return upd;
108 });
109 setAttributes({ links: newLinks });
110 }
111
112 // ── Register ──────────────────────────────────────────────────────────────
113 registerBlockType('blockenberg/social-links', {
114 title: __('Social Links', 'blockenberg'),
115 icon: 'share',
116 category: 'bkbg-marketing',
117 description: __('Social media icon links with brand colors and multiple layout options.', 'blockenberg'),
118
119 edit: function (props) {
120 var a = props.attributes;
121 var setAttributes = props.setAttributes;
122
123 var openColorKeyState = useState(null);
124 var openColorKey = openColorKeyState[0];
125 var setOpenColorKey = openColorKeyState[1];
126
127 function cc(key, label, attrKey) {
128 return renderColorControl(key, label, a[attrKey], function (val) {
129 var upd = {}; upd[attrKey] = val; setAttributes(upd);
130 }, openColorKey, setOpenColorKey);
131 }
132
133 function addLink() {
134 // Find a platform not already added
135 var usedPlatforms = a.links.map(function (l) { return l.platform; });
136 var next = platformKeys.find(function (k) { return usedPlatforms.indexOf(k) === -1; }) || 'facebook';
137 setAttributes({ links: a.links.concat([{ platform: next, url: '', label: platforms[next] ? platforms[next].label : next, enabled: true }]) });
138 }
139
140 function removeLink(i) {
141 setAttributes({ links: a.links.filter(function (_, idx) { return idx !== i; }) });
142 }
143
144 function moveLink(i, dir) {
145 var ni = i + dir;
146 if (ni < 0 || ni >= a.links.length) return;
147 var arr = a.links.slice(); var tmp = arr[i]; arr[i] = arr[ni]; arr[ni] = tmp;
148 setAttributes({ links: arr });
149 }
150
151 var wrapClass = 'bkbg-sl-wrapper bkbg-sl-layout-' + a.layout + ' bkbg-sl-align-' + a.alignment + ' bkbg-sl-style-' + a.iconStyle + ' bkbg-sl-hover-' + a.hoverEffect + (a.showLabel ? ' bkbg-sl-show-label bkbg-sl-label-' + a.labelPosition : '');
152 var blockProps = useBlockProps({ className: wrapClass, style: buildWrapStyle(a) });
153
154 // ── Inspector ─────────────────────────────────────────────────────
155 var inspector = el(InspectorControls, {},
156 // Links
157 el(PanelBody, { title: __('Social Links', 'blockenberg'), initialOpen: true },
158 a.links.map(function (link, i) {
159 return el('div', {
160 key: i,
161 style: { border: '1px solid #ddd', borderRadius: '6px', padding: '10px', marginBottom: '10px', background: link.enabled ? '#fafafa' : '#f5f5f5', opacity: link.enabled ? 1 : 0.6 }
162 },
163 el('div', { style: { display: 'flex', alignItems: 'center', gap: '6px', marginBottom: '8px' } },
164 el('div', { style: { width: '20px', height: '20px', borderRadius: '4px', background: getPlatformColor(link.platform), flexShrink: 0 } }),
165 el('span', { style: { fontWeight: '600', fontSize: '12px', flex: 1 } }, link.label || link.platform),
166 el(Button, { isSmall: true, variant: 'tertiary', onClick: function () { moveLink(i, -1); }, disabled: i === 0 }, ''),
167 el(Button, { isSmall: true, variant: 'tertiary', onClick: function () { moveLink(i, 1); }, disabled: i === a.links.length - 1 }, ''),
168 el(Button, { isSmall: true, isDestructive: true, variant: 'tertiary', onClick: function () { removeLink(i); } }, '')
169 ),
170 el(SelectControl, {
171 label: __('Platform', 'blockenberg'), value: link.platform,
172 options: platformKeys.map(function (k) { return { label: platforms[k].label, value: k }; }),
173 onChange: function (v) {
174 updateLink(a.links, i, 'platform', v, setAttributes);
175 updateLink(a.links, i, 'label', platforms[v] ? platforms[v].label : v, setAttributes);
176 }
177 }),
178 el(TextControl, {
179 label: __('URL', 'blockenberg'), value: link.url, type: 'url', placeholder: 'https://',
180 onChange: function (v) { updateLink(a.links, i, 'url', v, setAttributes); }
181 }),
182 el(TextControl, {
183 label: __('Custom Label', 'blockenberg'), value: link.label,
184 onChange: function (v) { updateLink(a.links, i, 'label', v, setAttributes); }
185 }),
186 el(ToggleControl, {
187 label: __('Enabled', 'blockenberg'), checked: link.enabled,
188 onChange: function (v) { updateLink(a.links, i, 'enabled', v, setAttributes); }
189 })
190 );
191 }),
192 el(Button, { variant: 'secondary', onClick: addLink, style: { width: '100%', justifyContent: 'center' } },
193 '+ ' + __('Add Platform', 'blockenberg')
194 )
195 ),
196
197 // Layout & Style
198 el(PanelBody, { title: __('Layout & Style', 'blockenberg'), initialOpen: false },
199 el(SelectControl, {
200 label: __('Layout', 'blockenberg'), value: a.layout,
201 options: [
202 { label: __('Horizontal (row)', 'blockenberg'), value: 'horizontal' },
203 { label: __('Vertical (column)', 'blockenberg'), value: 'vertical' },
204 { label: __('Grid (wrapping)', 'blockenberg'), value: 'grid' }
205 ],
206 onChange: function (v) { setAttributes({ layout: v }); }
207 }),
208 el(SelectControl, {
209 label: __('Alignment', 'blockenberg'), value: a.alignment,
210 options: [
211 { label: __('Left', 'blockenberg'), value: 'left' },
212 { label: __('Center', 'blockenberg'), value: 'center' },
213 { label: __('Right', 'blockenberg'), value: 'right' }
214 ],
215 onChange: function (v) { setAttributes({ alignment: v }); }
216 }),
217 el(SelectControl, {
218 label: __('Icon Style', 'blockenberg'), value: a.iconStyle,
219 options: [
220 { label: __('Brand Color (filled)', 'blockenberg'), value: 'brand-solid' },
221 { label: __('Brand Color (icon only)', 'blockenberg'), value: 'brand-icon' },
222 { label: __('Monochrome (dark)', 'blockenberg'), value: 'mono-dark' },
223 { label: __('Monochrome (light)', 'blockenberg'), value: 'mono-light' },
224 { label: __('Outline (brand color)', 'blockenberg'), value: 'outline-brand' },
225 { label: __('Outline (custom)', 'blockenberg'), value: 'outline-custom' },
226 { label: __('Custom Colors', 'blockenberg'), value: 'custom' }
227 ],
228 onChange: function (v) { setAttributes({ iconStyle: v }); }
229 }),
230 el(SelectControl, {
231 label: __('Hover Effect', 'blockenberg'), value: a.hoverEffect,
232 options: [
233 { label: __('Lift', 'blockenberg'), value: 'lift' },
234 { label: __('Scale', 'blockenberg'), value: 'scale' },
235 { label: __('Fade to Brand', 'blockenberg'), value: 'fade-brand' },
236 { label: __('Fill', 'blockenberg'), value: 'fill' },
237 { label: __('None', 'blockenberg'), value: 'none' }
238 ],
239 onChange: function (v) { setAttributes({ hoverEffect: v }); }
240 }),
241 el(RangeControl, {
242 label: __('Icon Size (px)', 'blockenberg'), value: a.iconSize, min: 10, max: 48,
243 onChange: function (v) { setAttributes({ iconSize: v }); }
244 }),
245 el(RangeControl, {
246 label: __('Button Size (px)', 'blockenberg'), value: a.buttonSize, min: a.iconSize + 4, max: 100,
247 onChange: function (v) { setAttributes({ buttonSize: v }); }
248 }),
249 el(RangeControl, {
250 label: __('Gap Between Icons (px)', 'blockenberg'), value: a.gap, min: 0, max: 40,
251 onChange: function (v) { setAttributes({ gap: v }); }
252 }),
253 el(RangeControl, {
254 label: __('Border Radius (px)', 'blockenberg'), value: a.borderRadius, min: 0, max: 60,
255 onChange: function (v) { setAttributes({ borderRadius: v }); }
256 }),
257 el(RangeControl, {
258 label: __('Border Width (px)', 'blockenberg'), value: a.borderWidth, min: 0, max: 6,
259 onChange: function (v) { setAttributes({ borderWidth: v }); }
260 })
261 ),
262
263 // Labels
264 el(PanelBody, { title: __('Labels', 'blockenberg'), initialOpen: false },
265 el(ToggleControl, {
266 label: __('Show Platform Labels', 'blockenberg'), checked: a.showLabel,
267 onChange: function (v) { setAttributes({ showLabel: v }); }
268 }),
269 a.showLabel && el(Fragment, {},
270 el(SelectControl, {
271 label: __('Label Position', 'blockenberg'), value: a.labelPosition,
272 options: [
273 { label: __('Right of icon', 'blockenberg'), value: 'right' },
274 { label: __('Below icon', 'blockenberg'), value: 'bottom' }
275 ],
276 onChange: function (v) { setAttributes({ labelPosition: v }); }
277 }),
278 cc('labelColor', __('Label Color', 'blockenberg'), 'labelColor'),
279 cc('labelColorHover', __('Label Hover Color', 'blockenberg'), 'labelColorHover')
280 )
281 ),
282
283 // Custom Colors (shown when custom style selected)
284 (a.iconStyle === 'custom' || a.iconStyle === 'outline-custom' || a.iconStyle === 'mono-dark' || a.iconStyle === 'mono-light') && el(PanelBody, { title: __('Custom Colors', 'blockenberg'), initialOpen: false },
285 cc('customIconColor', __('Icon Color', 'blockenberg'), 'customIconColor'),
286 cc('customBgColor', __('Background Color', 'blockenberg'), 'customBgColor'),
287 cc('customHoverIconColor', __('Hover Icon Color', 'blockenberg'), 'customHoverIconColor'),
288 cc('customHoverBgColor', __('Hover Background Color', 'blockenberg'), 'customHoverBgColor')
289 ),
290
291 // Spacing
292 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
293 el(RangeControl, {
294 label: __('Padding Top (px)', 'blockenberg'), value: a.wrapperPaddingTop, min: 0, max: 120,
295 onChange: function (v) { setAttributes({ wrapperPaddingTop: v }); }
296 }),
297 el(RangeControl, {
298 label: __('Padding Bottom (px)', 'blockenberg'), value: a.wrapperPaddingBottom, min: 0, max: 120,
299 onChange: function (v) { setAttributes({ wrapperPaddingBottom: v }); }
300 }),
301 el(ToggleControl, {
302 label: __('Open Links in New Tab', 'blockenberg'), checked: a.openNewTab,
303 onChange: function (v) { setAttributes({ openNewTab: v }); }
304 })
305 ),
306
307 // Typography
308 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
309 getTypoControl() && el(getTypoControl(), {
310 label: __('Label', 'blockenberg'),
311 value: a.labelTypo || {},
312 onChange: function (v) { setAttributes({ labelTypo: v }); }
313 })
314 )
315 );
316
317 // ── Render ────────────────────────────────────────────────────────
318 function renderLinkItem(link, i) {
319 if (!link.enabled) return null;
320 var brandColor = getPlatformColor(link.platform);
321 var iconEl = buildIcon(link.platform);
322
323 return el('a', {
324 key: i,
325 href: link.url || '#',
326 className: 'bkbg-sl-link bkbg-sl-platform-' + link.platform,
327 style: { '--bkbg-sl-brand': brandColor },
328 onClick: function (e) { e.preventDefault(); },
329 title: link.label,
330 'aria-label': link.label
331 },
332 el('span', { className: 'bkbg-sl-icon' }, iconEl),
333 a.showLabel && el('span', { className: 'bkbg-sl-label' }, link.label)
334 );
335 }
336
337 return el(Fragment, {},
338 inspector,
339 el('div', blockProps,
340 el('div', { className: 'bkbg-sl-inner' },
341 a.links.map(function (link, i) { return renderLinkItem(link, i); })
342 )
343 )
344 );
345 },
346
347 // ── Save ─────────────────────────────────────────────────────────────
348 save: function (props) {
349 var a = props.attributes;
350 var wrapClass = 'bkbg-sl-wrapper bkbg-sl-layout-' + a.layout + ' bkbg-sl-align-' + a.alignment + ' bkbg-sl-style-' + a.iconStyle + ' bkbg-sl-hover-' + a.hoverEffect + (a.showLabel ? ' bkbg-sl-show-label bkbg-sl-label-' + a.labelPosition : '');
351
352 return el('div', wp.blockEditor.useBlockProps.save({ className: wrapClass, style: buildWrapStyle(a) }),
353 el('div', { className: 'bkbg-sl-inner' },
354 a.links.filter(function (l) { return l.enabled; }).map(function (link, i) {
355 var brandColor = getPlatformColor(link.platform);
356 var p = platforms[link.platform];
357 var svgEl = p
358 ? el('svg', { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', 'aria-hidden': 'true', focusable: 'false', className: 'bkbg-sl-svg' }, el('path', { d: p.svg }))
359 : null;
360
361 return el('a', {
362 key: i,
363 href: link.url || '#',
364 className: 'bkbg-sl-link bkbg-sl-platform-' + link.platform,
365 style: { '--bkbg-sl-brand': brandColor },
366 target: a.openNewTab ? '_blank' : undefined,
367 rel: a.openNewTab ? 'noopener noreferrer' : undefined,
368 'aria-label': link.label
369 },
370 el('span', { className: 'bkbg-sl-icon' }, svgEl),
371 a.showLabel && el('span', { className: 'bkbg-sl-label' }, link.label)
372 );
373 })
374 )
375 );
376 }
377 });
378 }() );
379