PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / interactive-steps / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/interactive-steps/frontend.js

262 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
5
6 /* ── typography CSS-var helper ──────────────────────── */
7 var _typoKeys = {
8 family:'font-family', weight:'font-weight', style:'font-style',
9 decoration:'text-decoration', transform:'text-transform',
10 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
11 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
12 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
13 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
14 };
15 function typoCssVarsForEl(el, obj, prefix) {
16 if (!obj || typeof obj !== 'object') return;
17 Object.keys(_typoKeys).forEach(function (k) {
18 var v = obj[k];
19 if (v === undefined || v === '' || v === null) return;
20 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
21 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
22 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
23 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
24 el.style.setProperty(prefix + _typoKeys[k], String(v));
25 });
26 }
27
28 function initBlock(root) {
29 var app = root.querySelector('.bkbg-is-app');
30 if (!app) return;
31
32 var raw = app.getAttribute('data-opts') || '{}';
33 var o;
34 try { o = JSON.parse(raw); } catch (e) { o = {}; }
35
36 var steps = Array.isArray(o.steps) ? o.steps : [];
37 var layout = o.layout || 'horizontal';
38 var isHoriz = layout !== 'vertical';
39 var showConnector = o.showConnector !== false;
40 var animateContent = o.animateContent !== false;
41 var initialStep = Number(o.initialStep) || 0;
42 var stepSize = Number(o.stepSize) || 52;
43 var stepFontSize = Number(o.stepFontSize) || 14;
44 var headingSize = Number(o.headingSize) || 22;
45 var bodySize = Number(o.bodySize) || 16;
46 var connectorH = Number(o.connectorHeight) || 3;
47 var contentRadius = Number(o.contentRadius) || 16;
48 var contentPadding = Number(o.contentPadding) || 32;
49 var activeBg = o.activeBg || '#6366f1';
50 var activeColor = o.activeColor || '#ffffff';
51 var inactiveBg = o.inactiveBg || '#e5e7eb';
52 var inactiveColor = o.inactiveColor || '#64748b';
53 var doneBg = o.doneBg || '#10b981';
54 var doneColor = o.doneColor || '#ffffff';
55 var connectorColor = o.connectorColor || '#e5e7eb';
56 var connectorDone = o.connectorDone || '#10b981';
57 var contentBg = o.contentBg || '#f8fafc';
58 var contentBorder = o.contentBorder || '#e5e7eb';
59 var headingColor = o.headingColor || '#0f172a';
60 var bodyColor = o.bodyColor || '#475569';
61 var labelColor = o.labelColor || '#0f172a';
62 var sectionBg = o.sectionBg || 'transparent';
63
64 if (steps.length === 0) return;
65
66 var currentIdx = typeof initialStep === 'number' && initialStep < steps.length ? initialStep : 0;
67 var total = steps.length;
68
69 /* ── Build root container ───────────────────────────────────── */
70 var rootEl = document.createElement('div');
71 rootEl.className = 'bkbg-is-root ' + (isHoriz ? 'bkbg-is-horiz' : 'bkbg-is-vert');
72 rootEl.style.cssText = 'background:' + sectionBg + ';display:flex;' +
73 (isHoriz ? 'flex-direction:column' : 'flex-direction:row;gap:32px');
74
75 typoCssVarsForEl(rootEl, o.headingTypo, '--bkbg-is-h-');
76 typoCssVarsForEl(rootEl, o.bodyTypo, '--bkbg-is-bd-');
77
78 /* ── Nav ────────────────────────────────────────────────────── */
79 var navEl = document.createElement('div');
80 navEl.className = 'bkbg-is-nav';
81 navEl.style.cssText = 'display:flex;' +
82 (isHoriz
83 ? 'flex-direction:row;align-items:flex-start;margin-bottom:32px'
84 : 'flex-direction:column;align-items:flex-start;flex-shrink:0');
85
86 var bubbles = [];
87 var connectors = [];
88 var labelEls = [];
89
90 steps.forEach(function (step, idx) {
91 /* Connector before */
92 if (idx > 0 && showConnector) {
93 var conn = document.createElement('div');
94 conn.className = 'bkbg-is-connector';
95 if (isHoriz) {
96 conn.style.cssText = 'flex:1;height:' + connectorH + 'px;background:' + connectorColor + ';align-self:center;min-width:20px;transition:background 0.4s ease';
97 } else {
98 conn.style.cssText = 'height:24px;width:' + connectorH + 'px;background:' + connectorColor +
99 ';margin:0 0 0 ' + (stepSize / 2 - connectorH / 2) + 'px;transition:background 0.4s ease';
100 }
101 navEl.appendChild(conn);
102 connectors.push({ el: conn, idx: idx });
103 }
104
105 /* Bubble + label wrapper */
106 var item = document.createElement('div');
107 item.className = 'bkbg-is-step-item';
108 item.style.cssText = 'display:flex;' +
109 (isHoriz
110 ? 'flex-direction:column;align-items:center;gap:6px'
111 : 'flex-direction:row;align-items:center;gap:10px');
112
113 var btn = document.createElement('button');
114 btn.className = 'bkbg-is-bubble';
115 btn.type = 'button';
116 btn.setAttribute('aria-label', 'Step ' + (idx + 1) + ': ' + (step.title || ''));
117 btn.style.cssText = [
118 'width:' + stepSize + 'px',
119 'height:' + stepSize + 'px',
120 'font-size:' + stepFontSize + 'px',
121 'background:' + inactiveBg,
122 'color:' + inactiveColor
123 ].join(';');
124 var _IP = window.bkbgIconPicker;
125 var _iType = step.iconType || 'custom-char';
126 if (_IP && _iType !== 'custom-char') {
127 var _in = _IP.buildFrontendIcon(_iType, step.icon, step.iconDashicon, step.iconImageUrl, step.iconDashiconColor);
128 if (_in) { btn.textContent = ''; btn.appendChild(_in); } else { btn.textContent = step.icon || (idx + 1); }
129 } else { btn.textContent = step.icon || (idx + 1); }
130 btn.addEventListener('click', function () { goTo(idx); });
131 item.appendChild(btn);
132 bubbles.push(btn);
133
134 var lbl = document.createElement('span');
135 lbl.className = 'bkbg-is-label';
136 lbl.textContent = step.title || ('Step ' + (idx + 1));
137 lbl.style.cssText = 'font-size:' + stepFontSize + 'px;color:' + labelColor + ';font-weight:500;white-space:nowrap';
138 item.appendChild(lbl);
139 labelEls.push(lbl);
140
141 navEl.appendChild(item);
142 });
143
144 /* ── Panel ──────────────────────────────────────────────────── */
145 var panelEl = document.createElement('div');
146 panelEl.className = 'bkbg-is-panel';
147 panelEl.style.cssText = [
148 'flex:1',
149 'background:' + contentBg,
150 'border:1px solid ' + contentBorder,
151 'border-radius:' + contentRadius + 'px',
152 'padding:' + contentPadding + 'px'
153 ].join(';');
154
155 var headingEl = document.createElement('div');
156 headingEl.className = 'bkbg-is-heading';
157 headingEl.style.cssText = 'color:' + headingColor;
158
159 var bodyEl = document.createElement('div');
160 bodyEl.className = 'bkbg-is-body';
161 bodyEl.style.cssText = 'color:' + bodyColor;
162
163 var navBtns = document.createElement('div');
164 navBtns.className = 'bkbg-is-nav-btns';
165
166 var prevBtn = document.createElement('button');
167 prevBtn.type = 'button';
168 prevBtn.className = 'bkbg-is-btn-prev';
169 prevBtn.textContent = '← Previous';
170 prevBtn.style.cssText = 'padding:10px 24px;border-radius:8px;border:1px solid ' + contentBorder +
171 ';background:transparent;cursor:pointer;font-size:14px;color:' + bodyColor + ';font-weight:600';
172 prevBtn.addEventListener('click', function () { if (currentIdx > 0) goTo(currentIdx - 1); });
173
174 var nextBtn = document.createElement('button');
175 nextBtn.type = 'button';
176 nextBtn.className = 'bkbg-is-btn-next';
177 nextBtn.textContent = 'Next →';
178 nextBtn.style.cssText = 'padding:10px 24px;border-radius:8px;border:none;background:' + activeBg +
179 ';color:' + activeColor + ';cursor:pointer;font-size:14px;font-weight:700';
180 nextBtn.addEventListener('click', function () { if (currentIdx < total - 1) goTo(currentIdx + 1); });
181
182 navBtns.appendChild(prevBtn);
183 navBtns.appendChild(nextBtn);
184 panelEl.appendChild(headingEl);
185 panelEl.appendChild(bodyEl);
186 panelEl.appendChild(navBtns);
187
188 rootEl.appendChild(navEl);
189 rootEl.appendChild(panelEl);
190 app.appendChild(rootEl);
191
192 /* ── Update UI ──────────────────────────────────────────────── */
193 function updateBubbles() {
194 bubbles.forEach(function (btn, i) {
195 var isActive = i === currentIdx;
196 var isDone = i < currentIdx;
197 btn.style.background = isActive ? activeBg : (isDone ? doneBg : inactiveBg);
198 btn.style.color = isActive ? activeColor : (isDone ? doneColor : inactiveColor);
199 btn.style.transform = isActive ? 'scale(1.12)' : 'scale(1)';
200 btn.style.boxShadow = isActive ? '0 4px 16px rgba(99,102,241,0.4)' : 'none';
201 btn.textContent = '';
202 while (btn.firstChild) btn.removeChild(btn.firstChild);
203 if (isDone) {
204 btn.textContent = '';
205 } else {
206 var _IP2 = window.bkbgIconPicker;
207 var _iT2 = steps[i].iconType || 'custom-char';
208 if (_IP2 && _iT2 !== 'custom-char') {
209 var _in2 = _IP2.buildFrontendIcon(_iT2, steps[i].icon, steps[i].iconDashicon, steps[i].iconImageUrl, steps[i].iconDashiconColor);
210 if (_in2) btn.appendChild(_in2); else btn.textContent = steps[i].icon || (i + 1);
211 } else { btn.textContent = steps[i].icon || (i + 1); }
212 }
213 btn.classList.toggle('bkbg-is-active', isActive);
214 btn.classList.toggle('bkbg-is-done', isDone);
215 labelEls[i].style.fontWeight = isActive ? '700' : '500';
216 labelEls[i].style.color = isActive ? activeBg : labelColor;
217 });
218 connectors.forEach(function (c) {
219 c.el.style.background = c.idx <= currentIdx ? connectorDone : connectorColor;
220 });
221 prevBtn.style.display = currentIdx > 0 ? 'inline-flex' : 'none';
222 nextBtn.style.display = currentIdx < total - 1 ? 'inline-flex' : 'none';
223 }
224
225 function updatePanel() {
226 var step = steps[currentIdx];
227 headingEl.textContent = step.heading || '';
228 bodyEl.textContent = step.body || '';
229 }
230
231 function goTo(idx) {
232 if (idx === currentIdx) return;
233 if (animateContent && !reduced) {
234 panelEl.classList.add('bkbg-is-transitioning');
235 setTimeout(function () {
236 currentIdx = idx;
237 updatePanel();
238 updateBubbles();
239 panelEl.classList.remove('bkbg-is-transitioning');
240 }, 200);
241 } else {
242 currentIdx = idx;
243 updatePanel();
244 updateBubbles();
245 }
246 }
247
248 updatePanel();
249 updateBubbles();
250 }
251
252 function init() {
253 document.querySelectorAll('.wp-block-blockenberg-interactive-steps').forEach(initBlock);
254 }
255
256 if (document.readyState === 'loading') {
257 document.addEventListener('DOMContentLoaded', init);
258 } else {
259 init();
260 }
261 })();
262