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

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

409 lines 21.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var useState = wp.element.useState;
4 var __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var RichText = wp.blockEditor.RichText;
8 var MediaUpload = wp.blockEditor.MediaUpload;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var TextControl = wp.components.TextControl;
16 var Button = wp.components.Button;
17
18 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
19 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
20
21 function wrapStyle(a) {
22 return {
23 '--bkbg-tc-accent': a.accentColor,
24 '--bkbg-tc-bg': a.bgColor,
25 '--bkbg-tc-name-c': a.nameColor,
26 '--bkbg-tc-role-c': a.roleColor,
27 '--bkbg-tc-bio-c': a.bioColor,
28 '--bkbg-tc-border': a.borderColor,
29 '--bkbg-tc-icon-c': a.iconColor,
30 '--bkbg-tc-skill-bg': a.skillBg,
31 '--bkbg-tc-skill-c': a.skillColor,
32 '--bkbg-tc-photo-sz': a.photoSize + 'px',
33 '--bkbg-tc-photo-r': a.photoRadius + '%',
34 '--bkbg-tc-skill-sz': a.skillSize + 'px',
35 '--bkbg-tc-icon-sz': a.iconSize + 'px',
36 '--bkbg-tc-radius': a.cardRadius + 'px',
37 '--bkbg-tc-pad': a.cardPadding + 'px',
38 '--bkbg-tc-max-w': a.maxWidth + 'px',
39 };
40 }
41
42 function socialIcon(type) {
43 var icons = {
44 twitter: 'T', linkedin: 'in', github: '', email: '', website: ''
45 };
46 return icons[type] || '·';
47 }
48
49 registerBlockType('blockenberg/team-card', {
50 title: __('Team Card', 'blockenberg'),
51 icon: 'admin-users',
52 category: 'bkbg-business',
53
54 edit: function (props) {
55 var a = props.attributes;
56 var set = props.setAttributes;
57
58 var styleOptions = [
59 { label: __('Card (shadow)', 'blockenberg'), value: 'card' },
60 { label: __('Minimal', 'blockenberg'), value: 'minimal' },
61 { label: __('Centered', 'blockenberg'), value: 'centered' },
62 { label: __('Overlay', 'blockenberg'), value: 'overlay' },
63 ];
64 var layoutOptions = [
65 { label: __('Portrait (stacked)', 'blockenberg'), value: 'portrait' },
66 { label: __('Landscape (side-by-side)', 'blockenberg'), value: 'landscape' },
67 ];
68 var alignOptions = [
69 { label: __('Left', 'blockenberg'), value: 'left' },
70 { label: __('Center', 'blockenberg'), value: 'center' },
71 { label: __('Right', 'blockenberg'), value: 'right' },
72 ];
73 var weightOptions = [
74 { label: '400', value: 400 }, { label: '500', value: 500 },
75 { label: '600', value: 600 }, { label: '700', value: 700 }
76 ];
77
78 function updateSkill(i, val) {
79 var ns = a.skills.slice();
80 ns[i] = { label: val };
81 set({ skills: ns });
82 }
83 function addSkill() {
84 set({ skills: a.skills.concat([{ label: 'New Skill' }]) });
85 }
86 function removeSkill(i) {
87 set({ skills: a.skills.filter(function (_, idx) { return idx !== i; }) });
88 }
89
90 var SOCIALS = ['twitter', 'linkedin', 'github', 'email', 'website'];
91 var SOCIAL_LABELS = {
92 twitter: 'Twitter / X', linkedin: 'LinkedIn', github: 'GitHub',
93 email: 'Email', website: 'Website'
94 };
95 var SOCIAL_KEYS = {
96 twitter: 'twitterUrl', linkedin: 'linkedinUrl', github: 'githubUrl',
97 email: 'emailAddress', website: 'websiteUrl'
98 };
99
100 var blockProps = useBlockProps((function () {
101 var _tvf = getTypoCssVars();
102 var s = Object.assign({}, wrapStyle(a));
103 if (_tvf) {
104 Object.assign(s, _tvf(a.nameTypo, '--bktc-nm-'));
105 Object.assign(s, _tvf(a.roleTypo, '--bktc-rl-'));
106 Object.assign(s, _tvf(a.bioTypo, '--bktc-bi-'));
107 }
108 return { className: 'bkbg-tc-wrap bkbg-tc-style--' + a.style + ' bkbg-tc-layout--' + a.cardLayout + ' bkbg-tc-align--' + a.align, style: s };
109 })());
110
111 var inspector = el(InspectorControls, {},
112 el(PanelBody, { title: __('Photo', 'blockenberg'), initialOpen: true },
113 el(ToggleControl, {
114 label: __('Show Photo', 'blockenberg'),
115 checked: a.showPhoto,
116 __nextHasNoMarginBottom: true,
117 onChange: function (v) { set({ showPhoto: v }); }
118 }),
119 a.showPhoto && el(MediaUpload, {
120 onSelect: function (m) { set({ photoUrl: m.url, photoId: m.id }); },
121 allowedTypes: ['image'],
122 value: a.photoId,
123 render: function (p) {
124 return el('div', {},
125 a.photoUrl && el('img', {
126 src: a.photoUrl,
127 style: { width: '80px', height: '80px', borderRadius: '50%', objectFit: 'cover', marginBottom: '8px', display: 'block' }
128 }),
129 el(Button, {
130 onClick: p.open,
131 variant: 'secondary',
132 style: { marginBottom: '4px' }
133 }, a.photoUrl ? __('Change Photo', 'blockenberg') : __('Upload Photo', 'blockenberg')),
134 a.photoUrl && el(Button, {
135 onClick: function () { set({ photoUrl: '', photoId: 0 }); },
136 variant: 'tertiary',
137 isDestructive: true
138 }, __('Remove', 'blockenberg'))
139 );
140 }
141 }),
142 a.showPhoto && el(RangeControl, {
143 label: __('Photo Size (px)', 'blockenberg'),
144 value: a.photoSize,
145 onChange: function (v) { set({ photoSize: v }); },
146 min: 60,
147 max: 280
148 }),
149 a.showPhoto && el(RangeControl, {
150 label: __('Photo Border Radius (%)', 'blockenberg'),
151 value: a.photoRadius,
152 onChange: function (v) { set({ photoRadius: v }); },
153 min: 0,
154 max: 50
155 })
156 ),
157 el(PanelBody, { title: __('Bio & Skills', 'blockenberg'), initialOpen: false },
158 el(TextControl, {
159 label: __('Name', 'blockenberg'),
160 value: a.name,
161 onChange: function (v) { set({ name: v }); }
162 }),
163 el(TextControl, {
164 label: __('Role / Title', 'blockenberg'),
165 value: a.role,
166 onChange: function (v) { set({ role: v }); }
167 }),
168 el(ToggleControl, {
169 label: __('Show Skills Tags', 'blockenberg'),
170 checked: a.showSkills,
171 __nextHasNoMarginBottom: true,
172 onChange: function (v) { set({ showSkills: v }); }
173 }),
174 a.showSkills && a.skills.map(function (skill, i) {
175 return el('div', { key: i, style: { display: 'flex', gap: '6px', alignItems: 'center', marginBottom: '6px' } },
176 el(TextControl, {
177 value: skill.label,
178 onChange: function (v) { updateSkill(i, v); },
179 hideLabelFromVision: true,
180 label: 'Skill ' + (i + 1)
181 }),
182 el(Button, {
183 onClick: function () { removeSkill(i); },
184 variant: 'tertiary',
185 isDestructive: true,
186 isSmall: true
187 }, '')
188 );
189 }),
190 a.showSkills && el(Button, {
191 onClick: addSkill,
192 variant: 'secondary',
193 isSmall: true
194 }, __('+ Add Skill', 'blockenberg'))
195 ),
196 el(PanelBody, { title: __('Social Links', 'blockenberg'), initialOpen: false },
197 el(ToggleControl, {
198 label: __('Show Social Links', 'blockenberg'),
199 checked: a.showSocials,
200 __nextHasNoMarginBottom: true,
201 onChange: function (v) { set({ showSocials: v }); }
202 }),
203 a.showSocials && SOCIALS.map(function (type) {
204 var key = SOCIAL_KEYS[type];
205 return el(TextControl, {
206 key: type,
207 label: SOCIAL_LABELS[type],
208 value: a[key] || '',
209 onChange: function (v) {
210 var upd = {};
211 upd[key] = v;
212 set(upd);
213 },
214 placeholder: type === 'email' ? 'hello@example.com' : 'https://'
215 });
216 })
217 ),
218 el(PanelBody, { title: __('Style & Layout', 'blockenberg'), initialOpen: false },
219 el(SelectControl, {
220 label: __('Card Style', 'blockenberg'),
221 value: a.style,
222 options: styleOptions,
223 onChange: function (v) { set({ style: v }); }
224 }),
225 el(SelectControl, {
226 label: __('Layout', 'blockenberg'),
227 value: a.cardLayout,
228 options: layoutOptions,
229 onChange: function (v) { set({ cardLayout: v }); }
230 }),
231 el(SelectControl, {
232 label: __('Card Alignment', 'blockenberg'),
233 value: a.align,
234 options: alignOptions,
235 onChange: function (v) { set({ align: v }); }
236 }),
237 el(RangeControl, {
238 label: __('Max Width (px)', 'blockenberg'),
239 value: a.maxWidth,
240 onChange: function (v) { set({ maxWidth: v }); },
241 min: 240,
242 max: 720
243 }),
244 el(RangeControl, {
245 label: __('Border Radius (px)', 'blockenberg'),
246 value: a.cardRadius,
247 onChange: function (v) { set({ cardRadius: v }); },
248 min: 0,
249 max: 40
250 }),
251 el(RangeControl, {
252 label: __('Card Padding (px)', 'blockenberg'),
253 value: a.cardPadding,
254 onChange: function (v) { set({ cardPadding: v }); },
255 min: 12,
256 max: 64
257 })
258 ),
259 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
260 getTypoControl()({ label: __('Name', 'blockenberg'), value: a.nameTypo, onChange: function (v) { set({ nameTypo: v }); } }),
261 getTypoControl()({ label: __('Role', 'blockenberg'), value: a.roleTypo, onChange: function (v) { set({ roleTypo: v }); } }),
262 getTypoControl()({ label: __('Bio', 'blockenberg'), value: a.bioTypo, onChange: function (v) { set({ bioTypo: v }); } }),
263 el(RangeControl, {
264 label: __('Skill Tag Size (px)', 'blockenberg'),
265 value: a.skillSize,
266 onChange: function (v) { set({ skillSize: v }); },
267 min: 10,
268 max: 16
269 }),
270 el(RangeControl, {
271 label: __('Social Icon Size (px)', 'blockenberg'),
272 value: a.iconSize,
273 onChange: function (v) { set({ iconSize: v }); },
274 min: 12,
275 max: 28
276 })
277 ),
278 el(PanelColorSettings, {
279 title: __('Colors', 'blockenberg'),
280 initialOpen: false,
281 colorSettings: [
282 { label: __('Card Background', 'blockenberg'), value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); } },
283 { label: __('Accent / Role Color', 'blockenberg'), value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#6c3fb5' }); } },
284 { label: __('Name Color', 'blockenberg'), value: a.nameColor, onChange: function (v) { set({ nameColor: v || '#0f172a' }); } },
285 { label: __('Role Color', 'blockenberg'), value: a.roleColor, onChange: function (v) { set({ roleColor: v || '#6c3fb5' }); } },
286 { label: __('Bio Color', 'blockenberg'), value: a.bioColor, onChange: function (v) { set({ bioColor: v || '#475569' }); } },
287 { label: __('Border Color', 'blockenberg'), value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#e2e8f0' }); } },
288 { label: __('Social Icon Color', 'blockenberg'), value: a.iconColor, onChange: function (v) { set({ iconColor: v || '#64748b' }); } },
289 { label: __('Skill Tag Background', 'blockenberg'), value: a.skillBg, onChange: function (v) { set({ skillBg: v || '#f1f5f9' }); } },
290 { label: __('Skill Tag Text', 'blockenberg'), value: a.skillColor, onChange: function (v) { set({ skillColor: v || '#334155' }); } },
291 ]
292 })
293 );
294
295 function renderCard() {
296 var SOCIALS_DEF = [
297 { type: 'twitter', key: 'twitterUrl', label: 'X' },
298 { type: 'linkedin', key: 'linkedinUrl', label: 'in' },
299 { type: 'github', key: 'githubUrl', label: '' },
300 { type: 'email', key: 'emailAddress', label: '' },
301 { type: 'website', key: 'websiteUrl', label: '' },
302 ];
303 var activeSocials = SOCIALS_DEF.filter(function (s) { return a[s.key]; });
304
305 return el('div', { className: 'bkbg-tc-card' },
306 a.showPhoto && el('div', { className: 'bkbg-tc-photo-wrap' },
307 a.photoUrl
308 ? el('img', { className: 'bkbg-tc-photo', src: a.photoUrl, alt: a.name })
309 : el('div', { className: 'bkbg-tc-photo bkbg-tc-photo--placeholder' },
310 el('span', { className: 'dashicons dashicons-admin-users' })
311 )
312 ),
313 el('div', { className: 'bkbg-tc-body' },
314 el('div', { className: 'bkbg-tc-name-row' },
315 el('span', { className: 'bkbg-tc-name' }, a.name),
316 ),
317 el('span', { className: 'bkbg-tc-role' }, a.role),
318 el(RichText, {
319 tagName: 'p',
320 className: 'bkbg-tc-bio',
321 value: a.bio,
322 onChange: function (v) { set({ bio: v }); },
323 placeholder: __('Enter bio…', 'blockenberg'),
324 allowedFormats: ['core/bold', 'core/italic', 'core/link']
325 }),
326 a.showSkills && a.skills.length > 0 && el('div', { className: 'bkbg-tc-skills' },
327 a.skills.map(function (s, i) {
328 return el('span', { key: i, className: 'bkbg-tc-skill' }, s.label);
329 })
330 ),
331 a.showSocials && activeSocials.length > 0 && el('div', { className: 'bkbg-tc-socials' },
332 activeSocials.map(function (s) {
333 return el('span', { key: s.type, className: 'bkbg-tc-social bkbg-tc-social--' + s.type, title: s.label },
334 el('span', { className: 'bkbg-tc-social-icon' }, s.label)
335 );
336 })
337 )
338 )
339 );
340 }
341
342 return el('div', {},
343 inspector,
344 el('div', blockProps, renderCard())
345 );
346 },
347
348 save: function (props) {
349 var a = props.attributes;
350 var blockProps = (function () {
351 var _tvf = getTypoCssVars();
352 var s = Object.assign({}, wrapStyle(a));
353 if (_tvf) {
354 Object.assign(s, _tvf(a.nameTypo, '--bktc-nm-'));
355 Object.assign(s, _tvf(a.roleTypo, '--bktc-rl-'));
356 Object.assign(s, _tvf(a.bioTypo, '--bktc-bi-'));
357 }
358 return useBlockProps.save({ className: 'bkbg-tc-wrap bkbg-tc-style--' + a.style + ' bkbg-tc-layout--' + a.cardLayout + ' bkbg-tc-align--' + a.align, style: s });
359 })();
360
361 var SOCIALS_DEF = [
362 { type: 'twitter', key: 'twitterUrl', href: true, label: 'X', title: 'Twitter' },
363 { type: 'linkedin', key: 'linkedinUrl', href: true, label: 'in', title: 'LinkedIn' },
364 { type: 'github', key: 'githubUrl', href: true, label: '', title: 'GitHub' },
365 { type: 'email', key: 'emailAddress', email: true, label: '', title: 'Email' },
366 { type: 'website', key: 'websiteUrl', href: true, label: '', title: 'Website' },
367 ];
368 var activeSocials = SOCIALS_DEF.filter(function (s) { return a[s.key]; });
369
370 return el('div', blockProps,
371 el('div', { className: 'bkbg-tc-card' },
372 a.showPhoto && el('div', { className: 'bkbg-tc-photo-wrap' },
373 a.photoUrl
374 ? el('img', { className: 'bkbg-tc-photo', src: a.photoUrl, alt: a.name })
375 : el('div', { className: 'bkbg-tc-photo bkbg-tc-photo--placeholder' },
376 el('span', { className: 'dashicons dashicons-admin-users' })
377 )
378 ),
379 el('div', { className: 'bkbg-tc-body' },
380 el('div', { className: 'bkbg-tc-name-row' },
381 el('span', { className: 'bkbg-tc-name' }, a.name)
382 ),
383 el('span', { className: 'bkbg-tc-role' }, a.role),
384 el(RichText.Content, { tagName: 'p', className: 'bkbg-tc-bio', value: a.bio }),
385 a.showSkills && a.skills.length > 0 && el('div', { className: 'bkbg-tc-skills' },
386 a.skills.map(function (s, i) {
387 return el('span', { key: i, className: 'bkbg-tc-skill' }, s.label);
388 })
389 ),
390 a.showSocials && activeSocials.length > 0 && el('div', { className: 'bkbg-tc-socials' },
391 activeSocials.map(function (s) {
392 var href = s.email ? 'mailto:' + a[s.key] : a[s.key];
393 return el('a', {
394 key: s.type,
395 className: 'bkbg-tc-social bkbg-tc-social--' + s.type,
396 href: href,
397 title: s.title,
398 target: s.href ? '_blank' : undefined,
399 rel: s.href ? 'noopener noreferrer' : undefined
400 }, el('span', { className: 'bkbg-tc-social-icon' }, s.label));
401 })
402 )
403 )
404 )
405 );
406 }
407 });
408 }() );
409