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

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

195 lines 14.5 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 __ = wp.i18n.__;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var InspectorControls = wp.blockEditor.InspectorControls;
6 var MediaUpload = wp.blockEditor.MediaUpload;
7 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var TextControl = wp.components.TextControl;
16 var TextareaControl = wp.components.TextareaControl;
17 var Button = wp.components.Button;
18
19 var LABELS = ['Written by', 'Contributors', 'Research Team', 'Authors', 'Editorial Team', 'Reviewed by'];
20
21 var _ctbTC, _ctbTV;
22 function _tc() { return _ctbTC || (_ctbTC = window.bkbgTypographyControl); }
23 function _tv(obj, prefix) { var fn = _ctbTV || (_ctbTV = window.bkbgTypoCssVars); return fn ? fn(obj, prefix) : {}; }
24
25 function initials(name) {
26 return (name || '?').split(' ').map(function (w) { return w[0]; }).slice(0, 2).join('').toUpperCase();
27 }
28
29 function updateContrib(contribs, idx, key, val) {
30 return contribs.map(function (c, i) {
31 if (i !== idx) return c;
32 var r = Object.assign({}, c); r[key] = val; return r;
33 });
34 }
35
36 registerBlockType('blockenberg/contributor-box', {
37 edit: function (props) {
38 var attr = props.attributes;
39 var set = props.setAttributes;
40 var contribs = attr.contributors || [];
41
42 var blockProps = useBlockProps({ style: Object.assign({ padding: attr.paddingTop + 'px 0 ' + attr.paddingBottom + 'px', background: attr.bgColor, borderRadius: attr.borderRadius + 'px' }, _tv(attr.typoName, '--bkbg-ctb-name-'), _tv(attr.typoRole, '--bkbg-ctb-role-'), _tv(attr.typoBio, '--bkbg-ctb-bio-')) });
43
44 var controls = el(InspectorControls, {},
45 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: true },
46 el(SelectControl, {
47 label: __('Layout', 'blockenberg'), value: attr.layout, __nextHasNoMarginBottom: true,
48 options: [
49 { label: 'Grid (cards)', value: 'grid' },
50 { label: 'List (horizontal row)', value: 'list' },
51 { label: 'Compact (avatars only)', value: 'compact' }
52 ],
53 onChange: function (v) { set({ layout: v }); }
54 }),
55 el('div', { style: { marginTop: '8px' } },
56 el(ToggleControl, { label: __('Show Label', 'blockenberg'), checked: attr.showLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showLabel: v }); } })
57 ),
58 attr.showLabel && el('div', { style: { marginTop: '8px' } },
59 el(TextControl, { label: __('Label Text', 'blockenberg'), value: attr.label, __nextHasNoMarginBottom: true, onChange: function (v) { set({ label: v }); } })
60 ),
61 el('div', { style: { marginTop: '8px' } },
62 el(ToggleControl, { label: __('Show Bios', 'blockenberg'), checked: attr.showBio, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showBio: v }); } })
63 ),
64 el('div', { style: { marginTop: '8px' } },
65 el(ToggleControl, { label: __('Show Social Links', 'blockenberg'), checked: attr.showSocial, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showSocial: v }); } })
66 ),
67 el('div', { style: { marginTop: '12px' } },
68 el(RangeControl, { label: __('Avatar Size (px)', 'blockenberg'), value: attr.avatarSize, min: 32, max: 120, __nextHasNoMarginBottom: true, onChange: function (v) { set({ avatarSize: v }); } })
69 )
70 ),
71 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
72 el(RangeControl, { label: __('Outer Border Radius', 'blockenberg'), value: attr.borderRadius, min: 0, max: 30, __nextHasNoMarginBottom: true, onChange: function (v) { set({ borderRadius: v }); } }),
73 el('div', { style: { marginTop: '12px' } },
74 el(RangeControl, { label: __('Card Radius', 'blockenberg'), value: attr.cardRadius, min: 0, max: 20, __nextHasNoMarginBottom: true, onChange: function (v) { set({ cardRadius: v }); } })
75 ),
76 el('div', { style: { marginTop: '12px' } },
77 el(RangeControl, { label: __('Padding Top', 'blockenberg'), value: attr.paddingTop, min: 0, max: 100, __nextHasNoMarginBottom: true, onChange: function (v) { set({ paddingTop: v }); } })
78 ),
79 el('div', { style: { marginTop: '12px' } },
80 el(RangeControl, { label: __('Padding Bottom', 'blockenberg'), value: attr.paddingBottom, min: 0, max: 100, __nextHasNoMarginBottom: true, onChange: function (v) { set({ paddingBottom: v }); } })
81 )
82 ),
83 el(PanelColorSettings, {
84 title: __('Colors', 'blockenberg'), initialOpen: false,
85 colorSettings: [
86 { label: __('Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { set({ bgColor: v || '#f8fafc' }); } },
87 { label: __('Card Background', 'blockenberg'), value: attr.cardBg, onChange: function (v) { set({ cardBg: v || '#ffffff' }); } },
88 { label: __('Card Border', 'blockenberg'), value: attr.cardBorder, onChange: function (v) { set({ cardBorder: v || '#e2e8f0' }); } },
89 { label: __('Label', 'blockenberg'), value: attr.labelColor, onChange: function (v) { set({ labelColor: v || '#94a3b8' }); } },
90 { label: __('Avatar BG (initials)', 'blockenberg'), value: attr.avatarBg, onChange: function (v) { set({ avatarBg: v || '#e2e8f0' }); } },
91 { label: __('Avatar Text (initials)', 'blockenberg'), value: attr.avatarColor, onChange: function (v) { set({ avatarColor: v || '#64748b' }); } },
92 { label: __('Name', 'blockenberg'), value: attr.nameColor, onChange: function (v) { set({ nameColor: v || '#0f172a' }); } },
93 { label: __('Title / Role', 'blockenberg'), value: attr.titleColor, onChange: function (v) { set({ titleColor: v || '#64748b' }); } },
94 { label: __('Bio Text', 'blockenberg'), value: attr.bioColor, onChange: function (v) { set({ bioColor: v || '#475569' }); } },
95 { label: __('Social Icons', 'blockenberg'), value: attr.socialColor, onChange: function (v) { set({ socialColor: v || '#94a3b8' }); } },
96 { label: __('Accent', 'blockenberg'), value: attr.accentColor, onChange: function (v) { set({ accentColor: v || '#2563eb' }); } }
97 ]
98 }),
99 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
100 _tc() && el(_tc(), { label: __('Name', 'blockenberg'), value: attr.typoName, onChange: function (v) { set({ typoName: v }); } }),
101 _tc() && el(_tc(), { label: __('Role', 'blockenberg'), value: attr.typoRole, onChange: function (v) { set({ typoRole: v }); } }),
102 _tc() && el(_tc(), { label: __('Bio', 'blockenberg'), value: attr.typoBio, onChange: function (v) { set({ typoBio: v }); } })
103 )
104 );
105
106 var isCompact = attr.layout === 'compact';
107 var isList = attr.layout === 'list';
108 var isGrid = attr.layout === 'grid';
109
110 var wrapStyle = { padding: '20px' };
111 var gridStyle = isGrid
112 ? { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: '16px', marginTop: '14px' }
113 : isCompact
114 ? { display: 'flex', flexWrap: 'wrap', gap: '12px', alignItems: 'center', marginTop: '10px' }
115 : { display: 'flex', flexDirection: 'column', gap: '14px', marginTop: '14px' };
116
117 var cards = el('div', { style: gridStyle },
118 contribs.map(function (c, idx) {
119 var sz = attr.avatarSize;
120 var avatarEl = el('div', { style: { flexShrink: 0 } },
121 el(MediaUploadCheck, {},
122 el(MediaUpload, {
123 onSelect: function (media) { set({ contributors: contribs.map(function (c, i) { return i !== idx ? c : Object.assign({}, c, { avatarUrl: media.url, avatarId: media.id }); }) }); },
124 allowedTypes: ['image'],
125 value: c.avatarId,
126 render: function (ref) {
127 return el(Button, { onClick: ref.open, style: { padding: 0, borderRadius: '50%', overflow: 'hidden', display: 'block', width: sz + 'px', height: sz + 'px', cursor: 'pointer' } },
128 c.avatarUrl
129 ? el('img', { src: c.avatarUrl, style: { width: sz + 'px', height: sz + 'px', objectFit: 'cover', display: 'block', borderRadius: '50%' } })
130 : el('div', { style: { width: sz + 'px', height: sz + 'px', borderRadius: '50%', background: attr.avatarBg, color: attr.avatarColor, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: Math.round(sz * 0.35) + 'px' } }, initials(c.name))
131 );
132 }
133 })
134 )
135 );
136
137 if (isCompact) {
138 return el('div', { key: idx, title: c.name + (c.title ? '' + c.title : ''), style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' } },
139 avatarEl,
140 el('div', { style: { fontSize: '11px', fontWeight: 600, color: attr.nameColor, textAlign: 'center', maxWidth: sz + 'px' } }, c.name)
141 );
142 }
143
144 var cardStyle = {
145 background: attr.cardBg,
146 border: '1px solid ' + attr.cardBorder,
147 borderRadius: attr.cardRadius + 'px',
148 padding: '14px 16px',
149 display: isList ? 'flex' : 'block',
150 gap: isList ? '14px' : undefined,
151 alignItems: isList ? 'flex-start' : undefined
152 };
153
154 return el('div', { key: idx, style: cardStyle },
155 avatarEl,
156 el('div', { style: { flex: 1, minWidth: 0, marginTop: isGrid ? '10px' : 0 } },
157 el(TextControl, { value: c.name, label: __('Name', 'blockenberg'), placeholder: __('Author Name', 'blockenberg'), __nextHasNoMarginBottom: true, style: { color: attr.nameColor }, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'name', v) }); } }),
158 el('div', { style: { marginTop: '4px' } },
159 el(TextControl, { value: c.title, label: __('Role / Title', 'blockenberg'), placeholder: __('Staff Writer', 'blockenberg'), __nextHasNoMarginBottom: true, style: { color: attr.titleColor }, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'title', v) }); } })
160 ),
161 attr.showBio && el('div', { style: { marginTop: '4px' } },
162 el(TextareaControl, { value: c.bio, label: __('Bio', 'blockenberg'), placeholder: __('Short bio…', 'blockenberg'), rows: 2, __nextHasNoMarginBottom: true, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'bio', v) }); } })
163 ),
164 attr.showSocial && el('div', { style: { display: 'flex', gap: '6px', flexWrap: 'wrap', marginTop: '6px' } },
165 el(TextControl, { value: c.twitter, label: 'Twitter/X URL', __nextHasNoMarginBottom: true, style: { width: '140px', fontSize: '11px' }, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'twitter', v) }); } }),
166 el(TextControl, { value: c.linkedin, label: 'LinkedIn URL', __nextHasNoMarginBottom: true, style: { width: '140px', fontSize: '11px' }, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'linkedin', v) }); } }),
167 el(TextControl, { value: c.website, label: 'Website URL', __nextHasNoMarginBottom: true, style: { width: '140px', fontSize: '11px' }, onChange: function (v) { set({ contributors: updateContrib(contribs, idx, 'website', v) }); } })
168 ),
169 el(Button, { variant: 'link', isDestructive: true, style: { fontSize: '11px', marginTop: '4px' }, onClick: function () { set({ contributors: contribs.filter(function (_, i) { return i !== idx; }) }); } }, __('Remove', 'blockenberg'))
170 )
171 );
172 })
173 );
174
175 return el('div', blockProps,
176 controls,
177 el('div', { style: wrapStyle },
178 attr.showLabel && el('div', { style: { fontSize: '11px', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: attr.labelColor, marginBottom: '4px' } }, attr.label),
179 cards,
180 el('div', { style: { textAlign: 'center', marginTop: '12px' } },
181 el(Button, { variant: 'secondary', onClick: function () { set({ contributors: contribs.concat([{ name: 'Author Name', title: '', avatarUrl: '', avatarId: 0, bio: '', twitter: '', linkedin: '', website: '' }]) }); } }, __('+ Add Contributor', 'blockenberg'))
182 )
183 )
184 );
185 },
186 save: function (props) {
187 var attr = props.attributes;
188 var useBlockProps = wp.blockEditor.useBlockProps;
189 return el('div', useBlockProps.save(),
190 el('div', { className: 'bkbg-ctb-app', 'data-opts': JSON.stringify(attr) })
191 );
192 }
193 });
194 }() );
195