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 / interview-block / index.js

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

306 lines 17.7 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 Button = wp.components.Button;
17
18 var _TypographyControl, _typoCssVars;
19 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
20 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
21
22 function defaultItem() {
23 return { question: 'Your question here?', answer: 'The answer goes here.' };
24 }
25
26 registerBlockType('blockenberg/interview-block', {
27 edit: function (props) {
28 var attr = props.attributes;
29 var setAttr = props.setAttributes;
30 var items = attr.items || [];
31
32 var blockProps = useBlockProps((function () {
33 var _tv = getTypoCssVars();
34 var s = {};
35 Object.assign(s, _tv(attr.questionTypo, '--bkbg-ib-q-'));
36 Object.assign(s, _tv(attr.answerTypo, '--bkbg-ib-a-'));
37 return { className: 'bkbg-ib-editor', style: s };
38 })());
39
40 function updateItem(i, key, val) {
41 setAttr({ items: items.map(function (it, idx) {
42 if (idx !== i) return it;
43 var c = Object.assign({}, it); c[key] = val; return c;
44 })});
45 }
46
47 // ---- Controls ----
48 var controls = el(InspectorControls, {},
49 el(PanelBody, { title: __('Speaker Info', 'blockenberg'), initialOpen: true },
50 el(ToggleControl, {
51 label: __('Show Speaker Header', 'blockenberg'),
52 checked: attr.showSpeakerHeader,
53 onChange: function (v) { setAttr({ showSpeakerHeader: v }); },
54 __nextHasNoMarginBottom: true
55 }),
56 el(TextControl, {
57 label: __('Interviewee Name', 'blockenberg'),
58 value: attr.intervieweeName,
59 onChange: function (v) { setAttr({ intervieweeName: v }); },
60 __nextHasNoMarginBottom: true
61 }),
62 el(TextControl, {
63 label: __('Interviewee Role / Title', 'blockenberg'),
64 value: attr.intervieweeRole,
65 onChange: function (v) { setAttr({ intervieweeRole: v }); },
66 __nextHasNoMarginBottom: true
67 }),
68 el(TextControl, {
69 label: __('Interviewer Name (optional)', 'blockenberg'),
70 value: attr.interviewerName,
71 onChange: function (v) { setAttr({ interviewerName: v }); },
72 __nextHasNoMarginBottom: true
73 }),
74 el('p', { style: { margin: '8px 0 4px', fontSize: '11px', textTransform: 'uppercase', fontWeight: 600, color: '#9ca3af' } }, __('Interviewee Photo', 'blockenberg')),
75 el(MediaUploadCheck, {},
76 el(MediaUpload, {
77 onSelect: function (m) { setAttr({ intervieweeAvatarUrl: m.url, intervieweeAvatarId: m.id }); },
78 allowedTypes: ['image'], value: attr.intervieweeAvatarId,
79 render: function (ref) {
80 return attr.intervieweeAvatarUrl
81 ? el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
82 el('img', { src: attr.intervieweeAvatarUrl, style: { width: '48px', height: '48px', borderRadius: '50%', objectFit: 'cover' } }),
83 el(Button, { isSmall: true, isDestructive: true, onClick: function () { setAttr({ intervieweeAvatarUrl: '', intervieweeAvatarId: 0 }); } }, '')
84 )
85 : el(Button, { isSecondary: true, isSmall: true, onClick: ref.open }, __('Upload Photo', 'blockenberg'));
86 }
87 })
88 )
89 ),
90 el(PanelBody, { title: __('Q&A Style', 'blockenberg'), initialOpen: false },
91 el(SelectControl, {
92 label: __('Layout Style', 'blockenberg'),
93 value: attr.layout,
94 options: [
95 { label: 'Classic (prefix badge)', value: 'classic' },
96 { label: 'Magazine (large Q)', value: 'magazine' },
97 { label: 'Card (each item in card)', value: 'card' },
98 { label: 'Minimal (subtle divider)', value: 'minimal' }
99 ],
100 onChange: function (v) { setAttr({ layout: v }); },
101 __nextHasNoMarginBottom: true
102 }),
103 el(TextControl, {
104 label: __('Question Prefix Label', 'blockenberg'),
105 value: attr.questionPrefix,
106 onChange: function (v) { setAttr({ questionPrefix: v }); },
107 __nextHasNoMarginBottom: true
108 }),
109 el(TextControl, {
110 label: __('Answer Prefix Label', 'blockenberg'),
111 value: attr.answerPrefix,
112 onChange: function (v) { setAttr({ answerPrefix: v }); },
113 __nextHasNoMarginBottom: true
114 }),
115 el(ToggleControl, {
116 label: __('Show Prefix Labels (Q / A)', 'blockenberg'),
117 checked: attr.showPrefixLabel,
118 onChange: function (v) { setAttr({ showPrefixLabel: v }); },
119 __nextHasNoMarginBottom: true
120 }),
121 el(ToggleControl, {
122 label: __('Show Dividers Between Items', 'blockenberg'),
123 checked: attr.showDivider,
124 onChange: function (v) { setAttr({ showDivider: v }); },
125 __nextHasNoMarginBottom: true
126 }),
127 el(RangeControl, {
128 label: __('Border Radius (px)', 'blockenberg'),
129 value: attr.borderRadius, min: 0, max: 32,
130 onChange: function (v) { setAttr({ borderRadius: v }); },
131 __nextHasNoMarginBottom: true
132 })
133 ),
134
135 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
136 el(getTypographyControl(), { label: 'Question', value: attr.questionTypo, onChange: function (v) { setAttr({ questionTypo: v }); } }),
137 el(getTypographyControl(), { label: 'Answer', value: attr.answerTypo, onChange: function (v) { setAttr({ answerTypo: v }); } }),
138 el(RangeControl, { label: __('Name Size (px)', 'blockenberg'), value: attr.nameSize, min: 12, max: 32, __nextHasNoMarginBottom: true, onChange: function (v) { setAttr({ nameSize: v }); } }),
139 el(RangeControl, { label: __('Prefix Size (px)', 'blockenberg'), value: attr.prefixSize, min: 10, max: 24, __nextHasNoMarginBottom: true, onChange: function (v) { setAttr({ prefixSize: v }); } })
140 ),
141 el(PanelColorSettings, {
142 title: __('Colors', 'blockenberg'), initialOpen: false,
143 colorSettings: [
144 { label: __('Question Color', 'blockenberg'), value: attr.questionColor, onChange: function (v) { setAttr({ questionColor: v || '#111827' }); } },
145 { label: __('Answer Color', 'blockenberg'), value: attr.answerColor, onChange: function (v) { setAttr({ answerColor: v || '#374151' }); } },
146 { label: __('Prefix Badge BG', 'blockenberg'), value: attr.prefixBg, onChange: function (v) { setAttr({ prefixBg: v || '#7c3aed' }); } },
147 { label: __('Prefix Badge Text', 'blockenberg'), value: attr.prefixColor, onChange: function (v) { setAttr({ prefixColor: v || '#ffffff' }); } },
148 { label: __('Accent Color', 'blockenberg'), value: attr.accentColor, onChange: function (v) { setAttr({ accentColor: v || '#7c3aed' }); } },
149 { label: __('Card Background', 'blockenberg'), value: attr.cardBg, onChange: function (v) { setAttr({ cardBg: v || '#ffffff' }); } },
150 { label: __('Header Background', 'blockenberg'), value: attr.headerBg, onChange: function (v) { setAttr({ headerBg: v || '#f9fafb' }); } },
151 { label: __('Section Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '' }); } }
152 ]
153 }),
154 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
155 el(RangeControl, {
156 label: __('Max Width (px)', 'blockenberg'),
157 value: attr.maxWidth, min: 400, max: 1200,
158 onChange: function (v) { setAttr({ maxWidth: v }); },
159 __nextHasNoMarginBottom: true
160 }),
161 el(RangeControl, {
162 label: __('Padding Top (px)', 'blockenberg'),
163 value: attr.paddingTop, min: 0, max: 200,
164 onChange: function (v) { setAttr({ paddingTop: v }); },
165 __nextHasNoMarginBottom: true
166 }),
167 el(RangeControl, {
168 label: __('Padding Bottom (px)', 'blockenberg'),
169 value: attr.paddingBottom, min: 0, max: 200,
170 onChange: function (v) { setAttr({ paddingBottom: v }); },
171 __nextHasNoMarginBottom: true
172 })
173 )
174 );
175
176 // ---- Preview ----
177 function prefixBadge(letter, isQ) {
178 if (!attr.showPrefixLabel) return null;
179 var bg = isQ ? attr.prefixBg : 'transparent';
180 var color = isQ ? attr.prefixColor : attr.accentColor;
181 var border = isQ ? 'none' : ('2px solid ' + attr.accentColor);
182 if (attr.layout === 'magazine') {
183 return el('span', {
184 style: {
185 fontSize: isQ ? '48px' : '36px',
186 fontWeight: '900',
187 color: isQ ? attr.accentColor : attr.answerColor,
188 lineHeight: '0.85',
189 marginRight: '12px',
190 opacity: isQ ? 1 : 0.2,
191 fontFamily: 'Georgia, serif',
192 flexShrink: 0
193 }
194 }, letter);
195 }
196 return el('span', {
197 style: {
198 display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
199 width: '28px', height: '28px', borderRadius: '6px',
200 background: bg, color: color, border: border,
201 fontSize: attr.prefixSize + 'px', fontWeight: '700',
202 flexShrink: 0, lineHeight: 1
203 }
204 }, letter);
205 }
206
207 var containerStyle = {
208 background: attr.bgColor || 'transparent',
209 paddingTop: attr.paddingTop + 'px',
210 paddingBottom: attr.paddingBottom + 'px'
211 };
212
213 var interviewItems = items.map(function (item, i) {
214 var isCard = attr.layout === 'card';
215 var rowStyle = {
216 marginBottom: i < items.length - 1 ? '0' : '0'
217 };
218 var qRow = el('div', { style: { display: 'flex', alignItems: 'flex-start', gap: '12px', marginBottom: '10px' } },
219 prefixBadge(attr.questionPrefix, true),
220 el(RichText, {
221 tagName: 'p',
222 className: 'bkbg-ib-q-text',
223 style: { margin: 0, color: attr.questionColor },
224 value: item.question,
225 onChange: function (v) { updateItem(i, 'question', v); },
226 placeholder: __('Question…', 'blockenberg')
227 })
228 );
229 var aRow = el('div', { style: { display: 'flex', alignItems: 'flex-start', gap: '12px' } },
230 prefixBadge(attr.answerPrefix, false),
231 el(RichText, {
232 tagName: 'p',
233 className: 'bkbg-ib-a-text',
234 style: { margin: 0, color: attr.answerColor },
235 value: item.answer,
236 onChange: function (v) { updateItem(i, 'answer', v); },
237 placeholder: __('Answer…', 'blockenberg')
238 })
239 );
240 var itemContent;
241 if (isCard) {
242 itemContent = el('div', {
243 style: {
244 background: attr.cardBg, border: '1px solid ' + attr.cardBorderColor,
245 borderRadius: attr.borderRadius + 'px', padding: '24px 28px'
246 }
247 }, qRow, aRow);
248 } else {
249 itemContent = el('div', {}, qRow, aRow);
250 }
251 var divider = (attr.showDivider && !isCard && i < items.length - 1)
252 ? el('hr', { style: { border: 'none', borderTop: '1px solid ' + attr.dividerColor, margin: '24px 0' } })
253 : (isCard ? el('div', { style: { height: '12px' } }) : el('div', { style: { height: '24px' } }));
254 return el('div', { key: i }, itemContent, divider,
255 el('div', { style: { display: 'flex', gap: '8px', marginTop: isCard ? '0' : '-8px', marginBottom: isCard ? '0' : '8px' } },
256 el(Button, { isSmall: true, isDestructive: true, onClick: function () { setAttr({ items: items.filter(function (_, idx) { return idx !== i; }) }); } }, '✕ Remove')
257 )
258 );
259 });
260
261 return el('div', blockProps, controls,
262 el('div', { style: containerStyle },
263 el('div', { style: { maxWidth: attr.maxWidth + 'px', margin: '0 auto' } },
264 attr.showSpeakerHeader && el('div', {
265 style: {
266 display: 'flex', alignItems: 'center', gap: '16px',
267 background: attr.headerBg, borderRadius: attr.borderRadius + 'px',
268 padding: '20px 24px', marginBottom: '32px'
269 }
270 },
271 attr.intervieweeAvatarUrl
272 ? el('img', { src: attr.intervieweeAvatarUrl, style: { width: '56px', height: '56px', borderRadius: '50%', objectFit: 'cover', flexShrink: 0 } })
273 : el('div', { style: { width: '56px', height: '56px', borderRadius: '50%', background: attr.prefixBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 } },
274 el('span', { style: { color: '#fff', fontSize: '22px', fontWeight: '700' } }, (attr.intervieweeName || 'J').charAt(0))
275 ),
276 el('div', {},
277 el('div', { style: { fontWeight: '700', fontSize: attr.nameSize + 'px', color: attr.nameColor } }, attr.intervieweeName || ''),
278 el('div', { style: { fontSize: '14px', color: attr.roleColor, marginTop: '2px' } }, attr.intervieweeRole),
279 attr.interviewerName && el('div', { style: { fontSize: '12px', color: attr.roleColor, marginTop: '4px', opacity: 0.7 } }, __('Interviewed by', 'blockenberg') + ': ' + attr.interviewerName)
280 )
281 ),
282 interviewItems,
283 el('div', { style: { marginTop: '16px' } },
284 el(Button, {
285 isPrimary: true, isSmall: true,
286 onClick: function () { setAttr({ items: items.concat(defaultItem()) }); }
287 }, '+ ' + __('Add Q&A', 'blockenberg'))
288 )
289 )
290 )
291 );
292 },
293
294 save: function (props) {
295 var attr = props.attributes;
296 var _tv = getTypoCssVars();
297 var s = {};
298 Object.assign(s, _tv(attr.questionTypo, '--bkbg-ib-q-'));
299 Object.assign(s, _tv(attr.answerTypo, '--bkbg-ib-a-'));
300 return el('div', wp.blockEditor.useBlockProps.save({ style: s }),
301 el('div', { className: 'bkbg-ib-app', 'data-opts': JSON.stringify(attr) })
302 );
303 }
304 });
305 }() );
306