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

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

259 lines 19.3 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 RichText = wp.blockEditor.RichText;
9 var MediaUpload = wp.blockEditor.MediaUpload;
10 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
11 var useBlockProps = wp.blockEditor.useBlockProps;
12 var PanelBody = wp.components.PanelBody;
13 var Button = wp.components.Button;
14 var ToggleControl = wp.components.ToggleControl;
15 var RangeControl = wp.components.RangeControl;
16 var SelectControl = wp.components.SelectControl;
17 var TextControl = wp.components.TextControl;
18 var ColorPicker = wp.components.ColorPicker;
19 var Popover = wp.components.Popover;
20
21 var _tc, _tv;
22 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
23 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
24 var IP = function () { return window.bkbgIconPicker; };
25
26 function makeId() { return 'lb' + Math.random().toString(36).substr(2, 5); }
27
28 var LINK_STYLE_OPTIONS = [
29 { label: __('Filled', 'blockenberg'), value: 'filled' },
30 { label: __('Outline', 'blockenberg'), value: 'outline' },
31 { label: __('Ghost', 'blockenberg'), value: 'ghost' },
32 ];
33
34 function buildWrapStyle(a) {
35 var _tvFn = getTypoCssVars();
36 var s = {
37 '--bkbg-lib-accent': a.accentColor,
38 '--bkbg-lib-name-color': a.nameColor,
39 '--bkbg-lib-title-color': a.titleColor,
40 '--bkbg-lib-bio-color': a.bioColor,
41 '--bkbg-lib-btn-bg': a.btnBg,
42 '--bkbg-lib-btn-color': a.btnColor,
43 '--bkbg-lib-btn-border': a.btnBorderColor,
44 '--bkbg-lib-btn-r': a.buttonRadius + 'px',
45 '--bkbg-lib-btn-gap': a.buttonGap + 'px',
46 '--bkbg-lib-btn-max-w': a.buttonMaxWidth + 'px',
47 '--bkbg-lib-btn-pad-v': a.buttonPaddingV + 'px',
48 '--bkbg-lib-avatar-sz': a.avatarSize + 'px',
49 '--bkbg-lib-avatar-r': a.avatarRadius + '%',
50 '--bkbg-lib-avatar-border-w': a.avatarBorderWidth + 'px',
51 '--bkbg-lib-avatar-border-c': a.avatarBorderColor,
52 paddingTop: a.paddingTop + 'px',
53 paddingBottom: a.paddingBottom + 'px',
54 backgroundColor: a.bgColor || undefined,
55 };
56 if (_tvFn) {
57 Object.assign(s, _tvFn(a.nameTypo, '--bkbg-lib-n-'));
58 Object.assign(s, _tvFn(a.taglineTypo, '--bkbg-lib-tl-'));
59 Object.assign(s, _tvFn(a.bioTypo, '--bkbg-lib-b-'));
60 Object.assign(s, _tvFn(a.buttonTypo, '--bkbg-lib-bt-'));
61 }
62 return s;
63 }
64
65 function renderColorControl(key, label, value, onChange, openKey, setOpenKey) {
66 var isOpen = openKey === key;
67 return el('div', { key: key, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' } },
68 el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label),
69 el('div', { style: { position: 'relative', flexShrink: 0 } },
70 el('button', { type: 'button', title: value || 'default', onClick: function () { setOpenKey(isOpen ? null : key); },
71 style: { width: '28px', height: '28px', borderRadius: '4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor: 'pointer', padding: 0, background: value || '#cccccc' }
72 }),
73 isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
74 el('div', { style: { padding: '8px' } },
75 el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange })
76 )
77 )
78 )
79 );
80 }
81
82 /* ───────────── Link button preview ─────────────────────────────── */
83 function LinkButton(props) {
84 var link = props.link;
85 var a = props.a;
86 var style = link.style || a.buttonStyle;
87 var isFilled = style === 'filled';
88 var isOutline = style === 'outline';
89 var bg = isFilled ? a.btnBg : 'transparent';
90 var color = isFilled ? a.btnColor : a.btnBg;
91 var border = (isFilled ? 'none' : '2px solid ' + (isOutline ? a.btnBorderColor || a.btnBg : 'transparent'));
92 return el('div', { className: 'bkbg-lib-btn bkbg-lib-btn--' + style,
93 style: {
94 display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px',
95 background: bg, color: color, border: border,
96 borderRadius: a.buttonRadius + 'px', padding: a.buttonPaddingV + 'px 20px',
97 cursor: 'default',
98 width: '100%', boxSizing: 'border-box',
99 }},
100 a.showIcons && link.icon && el('span', { 'aria-hidden': 'true' }, (link.iconType || 'custom-char') !== 'custom-char' && IP() ? IP().buildEditorIcon(link.iconType, link.icon, link.iconDashicon, link.iconImageUrl, link.iconDashiconColor) : link.icon),
101 el('span', null, link.label || __('Link', 'blockenberg'))
102 );
103 }
104
105 registerBlockType('blockenberg/link-in-bio', {
106 title: __('Link in Bio', 'blockenberg'),
107 icon: 'admin-links',
108 category: 'bkbg-business',
109
110 edit: function (props) {
111 var a = props.attributes;
112 var setAttributes = props.setAttributes;
113
114 var openColorKeyState = useState(null);
115 var openColorKey = openColorKeyState[0];
116 var setOpenColorKey = openColorKeyState[1];
117
118 var blockProps = useBlockProps({ style: buildWrapStyle(a) });
119
120 function cc(key, label, attrKey) {
121 return renderColorControl(key, label, a[attrKey], function (val) {
122 var upd = {}; upd[attrKey] = val; setAttributes(upd);
123 }, openColorKey, setOpenColorKey);
124 }
125
126 function updateLink(id, key, val) {
127 setAttributes({ links: a.links.map(function (l) { if (l.id !== id) return l; var u = Object.assign({}, l); u[key] = val; return u; }) });
128 }
129
130 var avatarEl = el('div', { className: 'bkbg-lib-avatar-wrap', style: { textAlign: 'center', marginBottom: '20px' } },
131 el(MediaUploadCheck, null,
132 el(MediaUpload, {
133 onSelect: function (m) { setAttributes({ avatarUrl: m.url, avatarId: m.id }); },
134 allowedTypes: ['image'], value: a.avatarId,
135 render: function (p) {
136 return el('div', { style: { display: 'inline-block', cursor: 'pointer' }, onClick: p.open },
137 a.avatarUrl
138 ? el('img', { src: a.avatarUrl, style: { width: a.avatarSize + 'px', height: a.avatarSize + 'px', borderRadius: a.avatarRadius + '%', objectFit: 'cover', border: a.avatarBorderWidth + 'px solid ' + a.avatarBorderColor, display: 'block' } })
139 : el('div', { style: { width: a.avatarSize + 'px', height: a.avatarSize + 'px', borderRadius: a.avatarRadius + '%', background: '#e5e7eb', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '36px', cursor: 'pointer', border: a.avatarBorderWidth + 'px solid ' + a.avatarBorderColor } }, '👤')
140 );
141 }
142 })
143 )
144 );
145
146 var linksEl = el('div', { className: 'bkbg-lib-links', style: { display: 'flex', flexDirection: 'column', gap: a.buttonGap + 'px', maxWidth: a.buttonMaxWidth + 'px', margin: '0 auto', width: '100%' } },
147 a.links.map(function (link) {
148 return el('div', { key: link.id }, el(LinkButton, { link: link, a: a }));
149 })
150 );
151
152 return el(Fragment, null,
153 el(InspectorControls, null,
154 el(PanelBody, { title: __('Avatar', 'blockenberg'), initialOpen: true },
155 el(RangeControl, { label: __('Size (px)', 'blockenberg'), value: a.avatarSize, min: 48, max: 180, onChange: function (v) { setAttributes({ avatarSize: v }); } }),
156 el(RangeControl, { label: __('Border radius (%)', 'blockenberg'), value: a.avatarRadius, min: 0, max: 50, onChange: function (v) { setAttributes({ avatarRadius: v }); } }),
157 el(RangeControl, { label: __('Border width (px)', 'blockenberg'), value: a.avatarBorderWidth, min: 0, max: 8, onChange: function (v) { setAttributes({ avatarBorderWidth: v }); } }),
158 renderColorControl('avatarBorderColor', __('Border color', 'blockenberg'), a.avatarBorderColor, function (v) { setAttributes({ avatarBorderColor: v }); }, openColorKey, setOpenColorKey),
159 el(MediaUploadCheck, null,
160 el(MediaUpload, {
161 onSelect: function (m) { setAttributes({ avatarUrl: m.url, avatarId: m.id }); },
162 allowedTypes: ['image'], value: a.avatarId,
163 render: function (p) { return el(Button, { onClick: p.open, variant: a.avatarUrl ? 'secondary' : 'primary', size: 'compact' }, a.avatarUrl ? __('Replace avatar', 'blockenberg') : __('Set avatar', 'blockenberg')); }
164 })
165 )
166 ),
167 el(PanelBody, { title: __('Profile', 'blockenberg'), initialOpen: false },
168 el(ToggleControl, { label: __('Show title / tagline', 'blockenberg'), checked: a.showTitle, onChange: function (v) { setAttributes({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
169 el(ToggleControl, { label: __('Show bio', 'blockenberg'), checked: a.showBio, onChange: function (v) { setAttributes({ showBio: v }); }, __nextHasNoMarginBottom: true })
170 ),
171 el(PanelBody, { title: __('Links', 'blockenberg'), initialOpen: false },
172 a.links.map(function (link, li) {
173 return el(PanelBody, { key: link.id, title: (link.icon ? link.icon + ' ' : '') + (link.label || 'Link ' + (li + 1)), initialOpen: false },
174 IP() && el(IP().IconPickerControl, {
175 iconType: link.iconType || 'custom-char',
176 customChar: link.icon || '',
177 dashicon: link.iconDashicon || '',
178 imageUrl: link.iconImageUrl || '',
179 onChangeType: function (v) { updateLink(link.id, 'iconType', v); },
180 onChangeChar: function (v) { updateLink(link.id, 'icon', v); },
181 onChangeDashicon: function (v) { updateLink(link.id, 'iconDashicon', v); },
182 onChangeImageUrl: function (v) { updateLink(link.id, 'iconImageUrl', v); }
183 }),
184 el(TextControl, { label: __('Label', 'blockenberg'), value: link.label, onChange: function (v) { updateLink(link.id, 'label', v); } }),
185 el(TextControl, { label: __('URL', 'blockenberg'), value: link.url, onChange: function (v) { updateLink(link.id, 'url', v); } }),
186 el(SelectControl, { label: __('Button style', 'blockenberg'), value: link.style || 'filled', options: LINK_STYLE_OPTIONS, onChange: function (v) { updateLink(link.id, 'style', v); } }),
187 el(ToggleControl, { label: __('Open in new tab', 'blockenberg'), checked: link.newTab, onChange: function (v) { updateLink(link.id, 'newTab', v); }, __nextHasNoMarginBottom: true }),
188 el(Button, { onClick: function () { setAttributes({ links: a.links.filter(function (l) { return l.id !== link.id; }) }); }, isDestructive: true, variant: 'tertiary', size: 'compact', style: { marginTop: '6px' } }, __('Remove link', 'blockenberg'))
189 );
190 }),
191 el(Button, { variant: 'primary', onClick: function () { setAttributes({ links: a.links.concat([{ id: makeId(), icon: '🔗', iconType: 'custom-char', iconDashicon: '', iconImageUrl: '', label: __('My Link', 'blockenberg'), url: '', newTab: false, style: 'filled' }]) }); }, style: { marginTop: '8px' } }, __('+ Add Link', 'blockenberg'))
192 ),
193 el(PanelBody, { title: __('Button Styling', 'blockenberg'), initialOpen: false },
194 el(SelectControl, { label: __('Default button style', 'blockenberg'), value: a.buttonStyle, options: LINK_STYLE_OPTIONS, onChange: function (v) { setAttributes({ buttonStyle: v }); } }),
195 el(RangeControl, { label: __('Border radius (px)', 'blockenberg'), value: a.buttonRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ buttonRadius: v }); } }),
196 el(RangeControl, { label: __('Gap between buttons', 'blockenberg'), value: a.buttonGap, min: 4, max: 32, onChange: function (v) { setAttributes({ buttonGap: v }); } }),
197 el(RangeControl, { label: __('Max width (px)', 'blockenberg'), value: a.buttonMaxWidth, min: 240, max: 700, onChange: function (v) { setAttributes({ buttonMaxWidth: v }); } }),
198 el(RangeControl, { label: __('Vertical padding (px)','blockenberg'), value: a.buttonPaddingV, min: 8, max: 28, onChange: function (v) { setAttributes({ buttonPaddingV: v }); } }),
199 el(ToggleControl, { label: __('Show icons', 'blockenberg'), checked: a.showIcons, onChange: function (v) { setAttributes({ showIcons: v }); }, __nextHasNoMarginBottom: true })
200 ),
201 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
202 getTypoControl() && el(getTypoControl(), { label: __('Name'), value: a.nameTypo || {}, onChange: function (v) { setAttributes({ nameTypo: v }); } }),
203 getTypoControl() && el(getTypoControl(), { label: __('Tagline'), value: a.taglineTypo || {}, onChange: function (v) { setAttributes({ taglineTypo: v }); } }),
204 getTypoControl() && el(getTypoControl(), { label: __('Bio'), value: a.bioTypo || {}, onChange: function (v) { setAttributes({ bioTypo: v }); } }),
205 getTypoControl() && el(getTypoControl(), { label: __('Button'), value: a.buttonTypo || {}, onChange: function (v) { setAttributes({ buttonTypo: v }); } })
206 ),
207 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
208 cc('accentColor', __('Accent', 'blockenberg'), 'accentColor'),
209 cc('nameColor', __('Name', 'blockenberg'), 'nameColor'),
210 cc('titleColor', __('Title / tagline', 'blockenberg'), 'titleColor'),
211 cc('bioColor', __('Bio text', 'blockenberg'), 'bioColor'),
212 cc('btnBg', __('Button background','blockenberg'), 'btnBg'),
213 cc('btnColor', __('Button text', 'blockenberg'), 'btnColor'),
214 cc('btnBorderColor',__('Button border', 'blockenberg'), 'btnBorderColor'),
215 cc('bgColor', __('Section background','blockenberg'), 'bgColor')
216 ),
217 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
218 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
219 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
220 )
221 ),
222
223 el('div', blockProps,
224 el('div', { className: 'bkbg-lib-inner', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', maxWidth: (a.buttonMaxWidth + 80) + 'px', margin: '0 auto' } },
225 avatarEl,
226 el(RichText, { tagName: 'h2', className: 'bkbg-lib-name', value: a.name, onChange: function (v) { setAttributes({ name: v }); }, placeholder: __('Your Name', 'blockenberg'), style: { color: a.nameColor, margin: '0 0 6px', textAlign: 'center' } }),
227 a.showTitle && el(RichText, { tagName: 'p', className: 'bkbg-lib-title', value: a.title, onChange: function (v) { setAttributes({ title: v }); }, placeholder: __('Your tagline', 'blockenberg'), style: { color: a.titleColor, margin: '0 0 12px', textAlign: 'center' } }),
228 a.showBio && el(RichText, { tagName: 'p', className: 'bkbg-lib-bio', value: a.bio, onChange: function (v) { setAttributes({ bio: v }); }, placeholder: __('A short bio…', 'blockenberg'), style: { color: a.bioColor, margin: '0 0 24px', textAlign: 'center' } }),
229 linksEl
230 )
231 )
232 );
233 },
234
235 save: function (props) {
236 var a = props.attributes;
237 return el('div', wp.blockEditor.useBlockProps.save({ className: 'bkbg-lib-wrapper', style: buildWrapStyle(a) }),
238 el('div', { className: 'bkbg-lib-inner' },
239 el('div', { className: 'bkbg-lib-avatar-wrap' },
240 a.avatarUrl && el('img', { src: a.avatarUrl, alt: a.name || '', loading: 'lazy', className: 'bkbg-lib-avatar' })
241 ),
242 el(RichText.Content, { tagName: 'h2', className: 'bkbg-lib-name', value: a.name }),
243 a.showTitle && el(RichText.Content, { tagName: 'p', className: 'bkbg-lib-title', value: a.title }),
244 a.showBio && el(RichText.Content, { tagName: 'p', className: 'bkbg-lib-bio', value: a.bio }),
245 el('div', { className: 'bkbg-lib-links' },
246 a.links.map(function (link) {
247 var style = link.style || 'filled';
248 return el('a', { key: link.id, href: link.url || '#', className: 'bkbg-lib-btn bkbg-lib-btn--' + style, target: link.newTab ? '_blank' : undefined, rel: link.newTab ? 'noopener noreferrer' : undefined },
249 a.showIcons && link.icon && el('span', { className: 'bkbg-lib-btn-icon', 'aria-hidden': 'true' }, (link.iconType || 'custom-char') !== 'custom-char' && IP() ? IP().buildSaveIcon(link.iconType, link.icon, link.iconDashicon, link.iconImageUrl, link.iconDashiconColor) : link.icon),
250 el('span', { className: 'bkbg-lib-btn-label' }, link.label)
251 );
252 })
253 )
254 )
255 );
256 }
257 });
258 }() );
259