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 / step-cards / index.js

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

381 lines 19.8 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 __ = wp.i18n.__;
5 var useState = wp.element.useState;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelBody = wp.components.PanelBody;
11 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
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 layoutOptions = [
19 { label: __('Horizontal (Row)', 'blockenberg'), value: 'horizontal' },
20 { label: __('Grid', 'blockenberg'), value: 'grid' },
21 { label: __('Vertical Stack', 'blockenberg'), value: 'vertical' }
22 ];
23
24 var cardStyleOptions = [
25 { label: __('Card (shadow)', 'blockenberg'), value: 'card' },
26 { label: __('Bordered', 'blockenberg'), value: 'bordered' },
27 { label: __('Flat', 'blockenberg'), value: 'flat' },
28 { label: __('Ghost', 'blockenberg'), value: 'ghost' }
29 ];
30
31 var numberStyleOptions = [
32 { label: __('Circle (filled)', 'blockenberg'), value: 'circle' },
33 { label: __('Circle (outlined)', 'blockenberg'), value: 'circle-outline' },
34 { label: __('Square', 'blockenberg'), value: 'square' },
35 { label: __('Large Background', 'blockenberg'), value: 'large-bg' }
36 ];
37
38 var stepIcons = [
39 'edit', 'admin-customizer', 'update', 'chart-line', 'shield', 'star-filled',
40 'admin-users', 'email-alt', 'performance', 'cloud', 'networking', 'yes-alt',
41 'admin-links', 'clipboard', 'migrate', 'info', 'flag', 'heart', 'cart', 'search'
42 ];
43
44 var columnOptions = [
45 { label: '2', value: 2 },
46 { label: '3', value: 3 },
47 { label: '4', value: 4 }
48 ];
49
50 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
51 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
52
53 registerBlockType('blockenberg/step-cards', {
54 title: __('Step Cards', 'blockenberg'),
55 icon: 'list-ul',
56 category: 'bkbg-business',
57 description: __('Process steps as cards with sequential numbers, icons, and connector lines.', 'blockenberg'),
58
59 edit: function (props) {
60 var a = props.attributes;
61 var setAttributes = props.setAttributes;
62 var openState = useState(null);
63 var openIndex = openState[0];
64 var setOpenIndex = openState[1];
65
66 function wrapStyle(a) {
67 var _tvf = getTypoCssVars();
68 var s = {
69 '--bkbg-sc-cols': a.columns,
70 '--bkbg-sc-gap': a.gap + 'px',
71 '--bkbg-sc-num-bg': a.numberBg,
72 '--bkbg-sc-num-c': a.numberColor,
73 '--bkbg-sc-num-sz': a.numberSize + 'px',
74 '--bkbg-sc-icon-c': a.iconColor,
75 '--bkbg-sc-icon-sz': a.iconSize + 'px',
76 '--bkbg-sc-title-c': a.titleColor,
77 '--bkbg-sc-title-sz': a.titleSize + 'px',
78 '--bkbg-sc-title-w': a.titleWeight,
79 '--bkbg-sc-title-lh': a.titleLineHeight,
80 '--bkbg-sc-body-c': a.bodyColor,
81 '--bkbg-sc-body-sz': a.bodySize + 'px',
82 '--bkbg-sc-body-lh': a.bodyLineHeight,
83 '--bkbg-sc-card-bg': a.cardBg,
84 '--bkbg-sc-card-border': a.cardBorder,
85 '--bkbg-sc-card-p': a.cardPadding + 'px',
86 '--bkbg-sc-card-r': a.cardRadius + 'px',
87 '--bkbg-sc-connector': a.connectorColor,
88 '--bkbg-sc-accent': a.accentColor,
89 '--bkbg-sc-pt': a.paddingTop + 'px',
90 '--bkbg-sc-pb': a.paddingBottom + 'px'
91 };
92 Object.assign(s, _tvf(a.titleTypo, '--bkbg-sc-tt-'));
93 Object.assign(s, _tvf(a.bodyTypo, '--bkbg-sc-bd-'));
94 return s;
95 }
96
97 function updateStep(index, key, value) {
98 var updated = a.steps.slice();
99 updated[index] = Object.assign({}, updated[index]);
100 updated[index][key] = value;
101 setAttributes({ steps: updated });
102 }
103
104 function addStep() {
105 var icons = stepIcons;
106 var newIcon = icons[a.steps.length % icons.length];
107 setAttributes({
108 steps: a.steps.concat([{
109 id: 's' + Date.now(),
110 icon: newIcon,
111 title: __('Step Title', 'blockenberg'),
112 body: __('Describe what happens at this step.', 'blockenberg')
113 }])
114 });
115 }
116
117 function removeStep(index) {
118 setAttributes({ steps: a.steps.filter(function (_, i) { return i !== index; }) });
119 }
120
121 function moveStep(index, dir) {
122 var newIndex = index + dir;
123 if (newIndex < 0 || newIndex >= a.steps.length) return;
124 var updated = a.steps.slice();
125 var tmp = updated[index]; updated[index] = updated[newIndex]; updated[newIndex] = tmp;
126 setAttributes({ steps: updated });
127 }
128
129 var inspector = el(InspectorControls, {},
130 el(PanelBody, { title: __('Steps', 'blockenberg'), initialOpen: true },
131 a.steps.map(function (step, index) {
132 var isOpen = openIndex === index;
133 return el('div', { key: step.id, className: 'bkbg-sc-step-ctrl' },
134 el('div', { className: 'bkbg-sc-step-head', onClick: function () { setOpenIndex(isOpen ? null : index); } },
135 el('span', { className: 'bkbg-sc-step-num' }, index + 1),
136 el('strong', {}, step.title || __('Step', 'blockenberg') + ' ' + (index + 1)),
137 el('span', { className: 'dashicons dashicons-' + (isOpen ? 'arrow-up-alt2' : 'arrow-down-alt2') })
138 ),
139 isOpen && el('div', { className: 'bkbg-sc-step-body' },
140 el(SelectControl, {
141 label: __('Icon', 'blockenberg'),
142 value: step.icon,
143 options: stepIcons.map(function (ic) { return { label: ic, value: ic }; }),
144 onChange: function (v) { updateStep(index, 'icon', v); }
145 }),
146 el(TextControl, {
147 label: __('Title', 'blockenberg'),
148 value: step.title,
149 onChange: function (v) { updateStep(index, 'title', v); }
150 }),
151 el('div', { className: 'bkbg-sc-step-actions' },
152 el(Button, { icon: 'arrow-up-alt2', size: 'small', disabled: index === 0, onClick: function () { moveStep(index, -1); } }),
153 el(Button, { icon: 'arrow-down-alt2', size: 'small', disabled: index === a.steps.length - 1, onClick: function () { moveStep(index, 1); } }),
154 el(Button, { icon: 'trash', size: 'small', isDestructive: true, onClick: function () { removeStep(index); } })
155 )
156 )
157 );
158 }),
159 el(Button, { variant: 'secondary', onClick: addStep }, __('+ Add Step', 'blockenberg'))
160 ),
161
162 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
163 el(SelectControl, {
164 label: __('Layout', 'blockenberg'),
165 value: a.layout,
166 options: layoutOptions,
167 onChange: function (v) { setAttributes({ layout: v }); }
168 }),
169 (a.layout === 'horizontal' || a.layout === 'grid') && el(SelectControl, {
170 label: __('Columns', 'blockenberg'),
171 value: a.columns,
172 options: columnOptions,
173 onChange: function (v) { setAttributes({ columns: parseInt(v, 10) }); }
174 }),
175 el(SelectControl, {
176 label: __('Card Style', 'blockenberg'),
177 value: a.cardStyle,
178 options: cardStyleOptions,
179 onChange: function (v) { setAttributes({ cardStyle: v }); }
180 }),
181 el(SelectControl, {
182 label: __('Number Style', 'blockenberg'),
183 value: a.numberStyle,
184 options: numberStyleOptions,
185 onChange: function (v) { setAttributes({ numberStyle: v }); }
186 }),
187 el(ToggleControl, {
188 label: __('Show Connector Line', 'blockenberg'),
189 checked: a.showConnector,
190 __nextHasNoMarginBottom: true,
191 onChange: function (v) { setAttributes({ showConnector: v }); }
192 }),
193 el(ToggleControl, {
194 label: __('Show Icon', 'blockenberg'),
195 checked: a.showIcon,
196 __nextHasNoMarginBottom: true,
197 onChange: function (v) { setAttributes({ showIcon: v }); }
198 }),
199 el(RangeControl, {
200 label: __('Gap (px)', 'blockenberg'),
201 value: a.gap,
202 onChange: function (v) { setAttributes({ gap: v }); },
203 min: 8, max: 80
204 }),
205 el(RangeControl, {
206 label: __('Card Padding (px)', 'blockenberg'),
207 value: a.cardPadding,
208 onChange: function (v) { setAttributes({ cardPadding: v }); },
209 min: 12, max: 60
210 }),
211 el(RangeControl, {
212 label: __('Card Radius (px)', 'blockenberg'),
213 value: a.cardRadius,
214 onChange: function (v) { setAttributes({ cardRadius: v }); },
215 min: 0, max: 32
216 }),
217 el(RangeControl, {
218 label: __('Padding Top (px)', 'blockenberg'),
219 value: a.paddingTop,
220 onChange: function (v) { setAttributes({ paddingTop: v }); },
221 min: 0, max: 120
222 }),
223 el(RangeControl, {
224 label: __('Padding Bottom (px)', 'blockenberg'),
225 value: a.paddingBottom,
226 onChange: function (v) { setAttributes({ paddingBottom: v }); },
227 min: 0, max: 120
228 })
229 ),
230
231 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
232 el(RangeControl, {
233 label: __('Number Size (px)', 'blockenberg'),
234 value: a.numberSize,
235 onChange: function (v) { setAttributes({ numberSize: v }); },
236 min: 20, max: 80
237 }),
238 el(RangeControl, {
239 label: __('Icon Size (px)', 'blockenberg'),
240 value: a.iconSize,
241 onChange: function (v) { setAttributes({ iconSize: v }); },
242 min: 14, max: 48
243 }),
244 getTypoControl() && getTypoControl()({ label: __('Title', 'blockenberg'), value: a.titleTypo, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
245 getTypoControl() && getTypoControl()({ label: __('Body', 'blockenberg'), value: a.bodyTypo, onChange: function (v) { setAttributes({ bodyTypo: v }); } })
246 ),
247
248 el(PanelColorSettings, {
249 title: __('Colors', 'blockenberg'),
250 initialOpen: false,
251 colorSettings: [
252 { value: a.numberBg, onChange: function (v) { setAttributes({ numberBg: v || '#6c3fb5' }); }, label: __('Number Background', 'blockenberg') },
253 { value: a.numberColor, onChange: function (v) { setAttributes({ numberColor: v || '#ffffff' }); }, label: __('Number Color', 'blockenberg') },
254 { value: a.iconColor, onChange: function (v) { setAttributes({ iconColor: v || '#6c3fb5' }); }, label: __('Icon Color', 'blockenberg') },
255 { value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#0f172a' }); }, label: __('Title Color', 'blockenberg') },
256 { value: a.bodyColor, onChange: function (v) { setAttributes({ bodyColor: v || '#64748b' }); }, label: __('Body Color', 'blockenberg') },
257 { value: a.cardBg, onChange: function (v) { setAttributes({ cardBg: v || '#ffffff' }); }, label: __('Card Background', 'blockenberg') },
258 { value: a.cardBorder, onChange: function (v) { setAttributes({ cardBorder: v || '#e2e8f0' }); }, label: __('Card Border', 'blockenberg') },
259 { value: a.connectorColor, onChange: function (v) { setAttributes({ connectorColor: v || '#e2e8f0' }); }, label: __('Connector Color', 'blockenberg') },
260 { value: a.accentColor, onChange: function (v) { setAttributes({ accentColor: v || '#6c3fb5' }); }, label: __('Accent Color', 'blockenberg') }
261 ]
262 })
263 );
264
265 function renderStep(step, index) {
266 var isLast = index === a.steps.length - 1;
267
268 var numberEl = el('div', { className: 'bkbg-sc-num bkbg-sc-num--' + a.numberStyle },
269 a.showIcon
270 ? el('span', { className: 'bkbg-sc-num-icon dashicons dashicons-' + step.icon })
271 : el('span', { className: 'bkbg-sc-num-digit' }, index + 1)
272 );
273
274 var connectorEl = (a.showConnector && !isLast && a.layout !== 'vertical')
275 ? el('div', { className: 'bkbg-sc-connector' })
276 : null;
277
278 return el('div', { key: step.id, className: 'bkbg-sc-step bkbg-sc-card-style--' + a.cardStyle },
279 el('div', { className: 'bkbg-sc-step-header' },
280 numberEl,
281 connectorEl
282 ),
283 el('div', { className: 'bkbg-sc-step-content' },
284 el(RichText, {
285 tagName: 'h3',
286 className: 'bkbg-sc-title',
287 value: step.title,
288 onChange: function (v) { updateStep(index, 'title', v); },
289 placeholder: __('Step Title', 'blockenberg')
290 }),
291 el(RichText, {
292 tagName: 'p',
293 className: 'bkbg-sc-body',
294 value: step.body,
295 onChange: function (v) { updateStep(index, 'body', v); },
296 placeholder: __('Step description…', 'blockenberg')
297 })
298 )
299 );
300 }
301
302 var wrapClass = 'bkbg-sc-wrap bkbg-sc-layout--' + a.layout;
303 var blockProps = useBlockProps({ className: wrapClass, style: wrapStyle(a) });
304
305 return el(Fragment, {},
306 inspector,
307 el('div', blockProps,
308 el('div', { className: 'bkbg-sc-steps' },
309 a.steps.map(function (step, index) { return renderStep(step, index); })
310 ),
311 el('div', { className: 'bkbg-editor-actions' },
312 el(Button, { variant: 'secondary', icon: 'plus-alt2', onClick: addStep }, __('Add Step', 'blockenberg'))
313 )
314 )
315 );
316 },
317
318 save: function (props) {
319 var a = props.attributes;
320
321 function wrapStyle(a) {
322 var _tvf = getTypoCssVars();
323 var s = {
324 '--bkbg-sc-cols': a.columns,
325 '--bkbg-sc-gap': a.gap + 'px',
326 '--bkbg-sc-num-bg': a.numberBg,
327 '--bkbg-sc-num-c': a.numberColor,
328 '--bkbg-sc-num-sz': a.numberSize + 'px',
329 '--bkbg-sc-icon-c': a.iconColor,
330 '--bkbg-sc-icon-sz': a.iconSize + 'px',
331 '--bkbg-sc-title-c': a.titleColor,
332 '--bkbg-sc-title-sz': a.titleSize + 'px',
333 '--bkbg-sc-title-w': a.titleWeight,
334 '--bkbg-sc-title-lh': a.titleLineHeight,
335 '--bkbg-sc-body-c': a.bodyColor,
336 '--bkbg-sc-body-sz': a.bodySize + 'px',
337 '--bkbg-sc-body-lh': a.bodyLineHeight,
338 '--bkbg-sc-card-bg': a.cardBg,
339 '--bkbg-sc-card-border': a.cardBorder,
340 '--bkbg-sc-card-p': a.cardPadding + 'px',
341 '--bkbg-sc-card-r': a.cardRadius + 'px',
342 '--bkbg-sc-connector': a.connectorColor,
343 '--bkbg-sc-accent': a.accentColor,
344 '--bkbg-sc-pt': a.paddingTop + 'px',
345 '--bkbg-sc-pb': a.paddingBottom + 'px'
346 };
347 Object.assign(s, _tvf(a.titleTypo, '--bkbg-sc-tt-'));
348 Object.assign(s, _tvf(a.bodyTypo, '--bkbg-sc-bd-'));
349 return s;
350 }
351
352 var wrapClass = 'bkbg-sc-wrap bkbg-sc-layout--' + a.layout;
353 var blockProps = wp.blockEditor.useBlockProps.save({ className: wrapClass, style: wrapStyle(a) });
354
355 return el('div', blockProps,
356 el('div', { className: 'bkbg-sc-steps' },
357 a.steps.map(function (step, index) {
358 var isLast = index === a.steps.length - 1;
359 return el('div', { key: step.id, className: 'bkbg-sc-step bkbg-sc-card-style--' + a.cardStyle },
360 el('div', { className: 'bkbg-sc-step-header' },
361 el('div', { className: 'bkbg-sc-num bkbg-sc-num--' + a.numberStyle },
362 a.showIcon
363 ? el('span', { className: 'bkbg-sc-num-icon dashicons dashicons-' + step.icon })
364 : el('span', { className: 'bkbg-sc-num-digit' }, index + 1)
365 ),
366 (a.showConnector && !isLast && a.layout !== 'vertical')
367 ? el('div', { className: 'bkbg-sc-connector' })
368 : null
369 ),
370 el('div', { className: 'bkbg-sc-step-content' },
371 el(RichText.Content, { tagName: 'h3', className: 'bkbg-sc-title', value: step.title }),
372 el(RichText.Content, { tagName: 'p', className: 'bkbg-sc-body', value: step.body })
373 )
374 );
375 })
376 )
377 );
378 }
379 });
380 }() );
381