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 / event-speaker / index.js

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

304 lines 18.2 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 registerBlockType = wp.blocks.registerBlockType;
5 var __ = wp.i18n.__;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var PanelBody = wp.components.PanelBody;
10 var TextControl = wp.components.TextControl;
11 var TextareaControl = wp.components.TextareaControl;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var Button = wp.components.Button;
16
17 var _espTC, _espTV;
18 function _tc() { return _espTC || (_espTC = window.bkbgTypographyControl); }
19 function _tv(t, p) { return (_espTV || (_espTV = window.bkbgTypoCssVars)) ? _espTV(t, p) : {}; }
20
21 // ── helpers ────────────────────────────────────────────────────
22 function upd(arr, idx, field, val) {
23 return arr.map(function (e, i) {
24 if (i !== idx) return e;
25 var u = {}; u[field] = val;
26 return Object.assign({}, e, u);
27 });
28 }
29
30 // ── speaker card renderer ──────────────────────────────────────
31 function renderSpeakerCard(spk, a) {
32 // Avatar
33 var avatar = el('div', {
34 style: {
35 width: a.avatarSize + 'px', height: a.avatarSize + 'px',
36 borderRadius: '50%',
37 background: spk.avatarBg || '#6366f1',
38 color: '#ffffff',
39 display: 'flex', alignItems: 'center', justifyContent: 'center',
40 fontSize: Math.round(a.avatarSize * 0.35) + 'px',
41 fontWeight: '700', flexShrink: '0', marginBottom: '14px'
42 }
43 }, spk.avatarInitials || '?');
44
45 // Name + title/company
46 var nameEl = el('div', { className: 'bkbg-esp-name', style: { color: a.nameColor, marginBottom: '4px' } }, spk.name);
47 var jobEl = el('div', { className: 'bkbg-esp-body', style: { color: a.jobTitleColor, marginBottom: '2px' } }, spk.title);
48 var compEl = el('div', { className: 'bkbg-esp-body bkbg-esp-company', style: { color: a.companyColor, marginBottom: '12px' } }, '@ ' + spk.company);
49
50 // Bio
51 var bioEl = (a.showBio && spk.bio) ? el('p', { className: 'bkbg-esp-body', style: { color: a.bioColor, margin: '0 0 14px' } }, spk.bio) : null;
52
53 // Session block
54 var sessionEl = null;
55 if (a.showSession && spk.session) {
56 sessionEl = el('div', {
57 style: {
58 background: a.sessionBg,
59 border: '1px solid ' + a.sessionBorderColor,
60 borderRadius: '10px', padding: '10px 12px', marginBottom: '12px'
61 }
62 },
63 el('div', { className: 'bkbg-esp-session-time', style: { color: a.sessionTimeColor, marginBottom: '4px' } }, '🕐 ' + (spk.sessionTime || '')),
64 el('div', { className: 'bkbg-esp-body', style: { color: a.sessionTitleColor } }, spk.session)
65 );
66 }
67
68 // Twitter
69 var twitterEl = (a.showTwitter && spk.twitterHandle) ? el('div', {
70 className: 'bkbg-esp-body bkbg-esp-twitter', style: { color: a.twitterColor }
71 }, '𝕏 ' + spk.twitterHandle) : null;
72
73 return el('div', {
74 className: 'bkbg-esp-card',
75 style: {
76 background: a.cardBgColor,
77 border: '1px solid ' + a.cardBorderColor,
78 borderRadius: a.borderRadius + 'px',
79 padding: '24px', display: 'flex', flexDirection: 'column'
80 }
81 }, avatar, nameEl, jobEl, compEl, bioEl, sessionEl, twitterEl);
82 }
83
84 // ── edit ───────────────────────────────────────────────────────
85 function Edit(props) {
86 var a = props.attributes;
87 var set = props.setAttributes;
88
89 var LAYOUT_OPTIONS = [
90 { value: 'grid', label: __('Grid') },
91 { value: 'list', label: __('List') }
92 ];
93
94 var colorSettings = [
95 { label: __('Page Background'), value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#f8fafc' }); } },
96 { label: __('Header Background'), value: a.headerBgColor, onChange: function (v) { set({ headerBgColor: v || '#ffffff' }); } },
97 { label: __('Outer Border'), value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#e2e8f0' }); } },
98 { label: __('Event Title'), value: a.titleColor, onChange: function (v) { set({ titleColor: v || '#0f172a' }); } },
99 { label: __('Subtitle'), value: a.subtitleColor, onChange: function (v) { set({ subtitleColor: v || '#64748b' }); } },
100 { label: __('Card Background'), value: a.cardBgColor, onChange: function (v) { set({ cardBgColor: v || '#ffffff' }); } },
101 { label: __('Card Border'), value: a.cardBorderColor, onChange: function (v) { set({ cardBorderColor: v || '#e2e8f0' }); } },
102 { label: __('Speaker Name'), value: a.nameColor, onChange: function (v) { set({ nameColor: v || '#0f172a' }); } },
103 { label: __('Job Title'), value: a.jobTitleColor, onChange: function (v) { set({ jobTitleColor: v || '#6366f1' }); } },
104 { label: __('Company'), value: a.companyColor, onChange: function (v) { set({ companyColor: v || '#64748b' }); } },
105 { label: __('Bio Text'), value: a.bioColor, onChange: function (v) { set({ bioColor: v || '#374151' }); } },
106 { label: __('Session Card BG'), value: a.sessionBg, onChange: function (v) { set({ sessionBg: v || '#f0f9ff' }); } },
107 { label: __('Session Border'), value: a.sessionBorderColor,onChange: function (v) { set({ sessionBorderColor: v || '#bae6fd' }); } },
108 { label: __('Session Title'), value: a.sessionTitleColor, onChange: function (v) { set({ sessionTitleColor: v || '#0c4a6e' }); } },
109 { label: __('Session Time'), value: a.sessionTimeColor, onChange: function (v) { set({ sessionTimeColor: v || '#0369a1' }); } },
110 { label: __('Twitter Handle'), value: a.twitterColor, onChange: function (v) { set({ twitterColor: v || '#0ea5e9' }); } },
111 ];
112
113 var AVATAR_COLORS = ['#6366f1','#0ea5e9','#f59e0b','#22c55e','#ef4444','#ec4899','#8b5cf6','#14b8a6'];
114
115 var inspector = el(InspectorControls, {},
116 el(PanelBody, { title: __('Event Settings'), initialOpen: true },
117 el(TextControl, {
118 label: __('Event title'), value: a.eventTitle, __nextHasNoMarginBottom: true,
119 onChange: function (v) { set({ eventTitle: v }); }
120 }),
121 el(TextControl, {
122 label: __('Subtitle'), value: a.eventSubtitle, __nextHasNoMarginBottom: true,
123 onChange: function (v) { set({ eventSubtitle: v }); }
124 }),
125 el(ToggleControl, {
126 label: __('Show subtitle'), checked: a.showSubtitle, __nextHasNoMarginBottom: true,
127 onChange: function (v) { set({ showSubtitle: v }); }
128 }),
129 el(SelectControl, {
130 label: __('Layout'), value: a.layout, options: LAYOUT_OPTIONS, __nextHasNoMarginBottom: true,
131 onChange: function (v) { set({ layout: v }); }
132 }),
133 a.layout === 'grid' ? el(RangeControl, {
134 label: __('Columns'), value: a.columns, min: 1, max: 4, __nextHasNoMarginBottom: true,
135 onChange: function (v) { set({ columns: v }); }
136 }) : null,
137 el(ToggleControl, {
138 label: __('Show session info'), checked: a.showSession, __nextHasNoMarginBottom: true,
139 onChange: function (v) { set({ showSession: v }); }
140 }),
141 el(ToggleControl, {
142 label: __('Show bio'), checked: a.showBio, __nextHasNoMarginBottom: true,
143 onChange: function (v) { set({ showBio: v }); }
144 }),
145 el(ToggleControl, {
146 label: __('Show Twitter handle'), checked: a.showTwitter, __nextHasNoMarginBottom: true,
147 onChange: function (v) { set({ showTwitter: v }); }
148 })
149 ),
150 el(PanelBody, { title: __('Typography'), initialOpen: false },
151 _tc() && el(_tc(), { label: 'Event Title', typo: a.typoTitle || {}, onChange: function (v) { set({ typoTitle: v }); } }),
152 _tc() && el(_tc(), { label: 'Subtitle', typo: a.typoSubtitle || {}, onChange: function (v) { set({ typoSubtitle: v }); } }),
153 _tc() && el(_tc(), { label: 'Speaker Name', typo: a.typoName || {}, onChange: function (v) { set({ typoName: v }); } }),
154 _tc() && el(_tc(), { label: 'Body Text', typo: a.typoBody || {}, onChange: function (v) { set({ typoBody: v }); } })
155 ),
156 el(PanelBody, { title: __('Appearance'), initialOpen: false },
157 el(RangeControl, {
158 label: __('Border radius'), value: a.borderRadius, min: 0, max: 32, __nextHasNoMarginBottom: true,
159 onChange: function (v) { set({ borderRadius: v }); }
160 }),
161 el(RangeControl, {
162 label: __('Avatar size (px)'), value: a.avatarSize, min: 40, max: 120, __nextHasNoMarginBottom: true,
163 onChange: function (v) { set({ avatarSize: v }); }
164 })
165 ),
166 el(PanelBody, { title: __('Speakers (' + a.speakers.length + ')'), initialOpen: false },
167 a.speakers.map(function (spk, idx) {
168 return el(PanelBody, {
169 key: idx,
170 title: (idx + 1) + '. ' + (spk.name || 'Speaker'),
171 initialOpen: false
172 },
173 el(TextControl, {
174 label: __('Name'), value: spk.name, __nextHasNoMarginBottom: true,
175 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'name', v) }); }
176 }),
177 el(TextControl, {
178 label: __('Job title'), value: spk.title, __nextHasNoMarginBottom: true,
179 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'title', v) }); }
180 }),
181 el(TextControl, {
182 label: __('Company'), value: spk.company, __nextHasNoMarginBottom: true,
183 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'company', v) }); }
184 }),
185 el(TextareaControl, {
186 label: __('Bio'), value: spk.bio, __nextHasNoMarginBottom: true,
187 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'bio', v) }); }
188 }),
189 el(TextControl, {
190 label: __('Session title'), value: spk.session, __nextHasNoMarginBottom: true,
191 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'session', v) }); }
192 }),
193 el(TextControl, {
194 label: __('Session time'), value: spk.sessionTime, __nextHasNoMarginBottom: true,
195 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'sessionTime', v) }); }
196 }),
197 el(TextControl, {
198 label: __('Avatar initials (1–2 chars)'), value: spk.avatarInitials, __nextHasNoMarginBottom: true,
199 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'avatarInitials', v.substring(0, 2).toUpperCase()) }); }
200 }),
201 el('div', { style: { marginBottom: '12px' } },
202 el('p', { style: { margin: '0 0 8px', fontSize: '11px', fontWeight: '600', textTransform: 'uppercase' } }, __('Avatar color')),
203 el('div', { style: { display: 'flex', gap: '8px', flexWrap: 'wrap' } },
204 AVATAR_COLORS.map(function (c) {
205 return el('button', {
206 key: c,
207 onClick: function () { set({ speakers: upd(a.speakers, idx, 'avatarBg', c) }); },
208 style: {
209 width: '28px', height: '28px', borderRadius: '50%', border: spk.avatarBg === c ? '3px solid #1e293b' : '2px solid #e2e8f0',
210 background: c, cursor: 'pointer', padding: '0'
211 }
212 });
213 })
214 )
215 ),
216 el(TextControl, {
217 label: __('Twitter handle (e.g. @user)'), value: spk.twitterHandle, __nextHasNoMarginBottom: true,
218 onChange: function (v) { set({ speakers: upd(a.speakers, idx, 'twitterHandle', v) }); }
219 }),
220 el(Button, {
221 variant: 'secondary', isDestructive: true, __nextHasNoMarginBottom: true,
222 onClick: function () {
223 var next = a.speakers.slice(); next.splice(idx, 1);
224 set({ speakers: next });
225 }
226 }, __('Remove speaker'))
227 );
228 }),
229 el(Button, {
230 variant: 'primary', __nextHasNoMarginBottom: true,
231 onClick: function () {
232 var colors = ['#6366f1','#0ea5e9','#f59e0b','#22c55e'];
233 var bgC = colors[a.speakers.length % colors.length];
234 set({ speakers: a.speakers.concat([{
235 name: 'New Speaker', title: 'Job Title', company: 'Company',
236 bio: 'Speaker bio goes here.',
237 session: 'Talk Title', sessionTime: '10:00 AM – 10:45 AM',
238 avatarInitials: 'NS', avatarBg: bgC, twitterHandle: ''
239 }]) });
240 }
241 }, __('+ Add speaker'))
242 ),
243 el(PanelColorSettings, {
244 title: __('Colors'),
245 initialOpen: false,
246 colorSettings: colorSettings
247 })
248 );
249
250 // ── Preview ───────────────────────────────────────────────
251 var headerSection = el('div', {
252 style: {
253 background: a.headerBgColor,
254 borderBottom: '1px solid ' + a.borderColor,
255 padding: '32px 32px 24px'
256 }
257 },
258 el('h2', { className: 'bkbg-esp-title', style: { color: a.titleColor, margin: '0 0 8px' } }, a.eventTitle),
259 a.showSubtitle ? el('p', { className: 'bkbg-esp-subtitle', style: { color: a.subtitleColor, margin: '0' } }, a.eventSubtitle) : null
260 );
261
262 var gridCols = a.layout === 'grid' ? 'repeat(' + a.columns + ', 1fr)' : '1fr';
263 var grid = el('div', {
264 style: {
265 display: 'grid',
266 gridTemplateColumns: gridCols,
267 gap: '20px',
268 padding: '28px'
269 }
270 },
271 a.speakers.map(function (spk, idx) {
272 return el('div', { key: idx }, renderSpeakerCard(spk, a));
273 })
274 );
275
276 return el(Fragment, {},
277 inspector,
278 el('div', Object.assign({}, useBlockProps(), {
279 className: 'bkbg-esp-wrap',
280 style: Object.assign({
281 background: a.bgColor,
282 border: '1px solid ' + a.borderColor,
283 borderRadius: a.borderRadius + 'px',
284 overflow: 'hidden'
285 },
286 _tv(a.typoTitle || {}, '--bkbg-esp-ttl-'),
287 _tv(a.typoSubtitle || {}, '--bkbg-esp-sub-'),
288 _tv(a.typoName || {}, '--bkbg-esp-nm-'),
289 _tv(a.typoBody || {}, '--bkbg-esp-bd-')
290 )
291 }), headerSection, grid)
292 );
293 }
294
295 registerBlockType('blockenberg/event-speaker', {
296 edit: Edit,
297 save: function (props) {
298 return el('div', useBlockProps.save(),
299 el('div', { className: 'bkbg-event-speaker-app', 'data-opts': JSON.stringify(props.attributes) })
300 );
301 }
302 });
303 })();
304