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 / code-playground / frontend.js

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

255 lines 10.0 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 _typoKeys = {
5 family:'font-family', weight:'font-weight', style:'font-style',
6 transform:'text-transform', decoration:'text-decoration',
7 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
8 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
9 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
10 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
11 };
12 var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' };
13 var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' };
14 function typoCssVarsForEl(el, obj, prefix) {
15 if (!obj || typeof obj !== 'object') return;
16 Object.keys(_typoKeys).forEach(function (k) {
17 var v = obj[k]; if (v === undefined || v === '') return;
18 var prop = _typoKeys[k];
19 var base = k.replace(/Desktop|Tablet|Mobile/, '');
20 var uKey = _typoUnits[base];
21 if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || '');
22 el.style.setProperty(prefix + prop, v);
23 });
24 }
25
26 var TAB_COLORS = { html: '#e34c26', css: '#264de4', js: '#f0db4f' };
27 var TAB_TEXT = { html: '#ffffff', css: '#ffffff', js: '#1e1b4b' };
28
29 function debounce(fn, ms) {
30 var t;
31 return function () {
32 clearTimeout(t);
33 t = setTimeout(fn, ms);
34 };
35 }
36
37 function buildSrc(html, css, js) {
38 return '<!DOCTYPE html><html><head><meta charset="utf-8"><style>' + css + '</style></head><body>' + html + '<script>' + js + '<\/script></body></html>';
39 }
40
41 function initBlock(root) {
42 var optsRaw = root.getAttribute('data-opts');
43 var opts;
44 try { opts = JSON.parse(optsRaw); } catch (e) { opts = {}; }
45
46 var layout = opts.layout || 'horizontal';
47 var editorH = opts.editorHeight || 180;
48 var previewH = opts.previewHeight || 260;
49 var accent = opts.accentColor || '#6366f1';
50 var editorBg = opts.editorBg || '#1e1b4b';
51 var editorText = opts.editorText || '#e2e8f0';
52 var headerBg = opts.headerBg || '#312e81';
53 var previewBg = opts.previewBg || '#ffffff';
54 var autoRun = opts.autoRun !== false;
55
56 // Apply section bg
57 if (opts.sectionBg) root.style.background = opts.sectionBg;
58
59 // Apply typography CSS vars on root
60 if (opts.typoTitle) typoCssVarsForEl(root, opts.typoTitle, '--bkbg-cpg-tt-');
61 if (opts.typoSubtitle) typoCssVarsForEl(root, opts.typoSubtitle, '--bkbg-cpg-st-');
62
63 // Apply title colors
64 var titleEl = root.querySelector('.bkbg-cpg-title');
65 if (titleEl) {
66 titleEl.style.color = opts.titleColor || '#1e1b4b';
67 }
68 var subtitleEl = root.querySelector('.bkbg-cpg-subtitle');
69 if (subtitleEl) {
70 subtitleEl.style.color = opts.titleColor || '#1e1b4b';
71 }
72
73 var htmlCode = opts.defaultHtml || '';
74 var cssCode = opts.defaultCss || '';
75 var jsCode = opts.defaultJs || '';
76
77 var activeTab = 'html';
78
79 // ----- Build UI elements -----
80
81 // Tabs (for tabbed layout)
82 var tabsEl = null;
83 if (layout === 'tabbed') {
84 tabsEl = document.createElement('div');
85 tabsEl.className = 'bkbg-cpg-tabs';
86
87 ['html', 'css', 'js'].forEach(function (lang) {
88 var btn = document.createElement('button');
89 btn.className = 'bkbg-cpg-tab-btn' + (lang === 'html' ? ' bkbg-cpg-active' : '');
90 btn.textContent = lang.toUpperCase();
91 btn.style.background = TAB_COLORS[lang];
92 btn.style.color = TAB_TEXT[lang];
93 btn.dataset.lang = lang;
94 tabsEl.appendChild(btn);
95 });
96
97 root.appendChild(tabsEl);
98 }
99
100 // Editors container
101 var editorsEl = document.createElement('div');
102 editorsEl.className = 'bkbg-cpg-editors bkbg-cpg-' + layout;
103 root.appendChild(editorsEl);
104
105 var textareas = {};
106
107 function createPanel(lang, defaultCode) {
108 var panel = document.createElement('div');
109 panel.className = 'bkbg-cpg-panel';
110 panel.dataset.lang = lang;
111
112 var header = document.createElement('div');
113 header.className = 'bkbg-cpg-panel-header' + (lang === 'js' ? ' bkbg-cpg-js-header' : '');
114 header.style.background = TAB_COLORS[lang];
115 header.textContent = lang.toUpperCase();
116 panel.appendChild(header);
117
118 var textarea = document.createElement('textarea');
119 textarea.className = 'bkbg-cpg-textarea';
120 textarea.value = defaultCode;
121 textarea.style.background = editorBg;
122 textarea.style.color = editorText;
123 textarea.style.height = editorH + 'px';
124 textarea.setAttribute('spellcheck', 'false');
125 textarea.setAttribute('autocorrect', 'off');
126 textarea.setAttribute('autocapitalize', 'off');
127
128 // Tab key support
129 textarea.addEventListener('keydown', function (e) {
130 if (e.key === 'Tab') {
131 e.preventDefault();
132 var start = textarea.selectionStart;
133 var end = textarea.selectionEnd;
134 textarea.value = textarea.value.substring(0, start) + ' ' + textarea.value.substring(end);
135 textarea.selectionStart = textarea.selectionEnd = start + 2;
136 }
137 });
138
139 panel.appendChild(textarea);
140 textareas[lang] = textarea;
141 return panel;
142 }
143
144 editorsEl.appendChild(createPanel('html', htmlCode));
145 editorsEl.appendChild(createPanel('css', cssCode));
146 editorsEl.appendChild(createPanel('js', jsCode));
147
148 // Tabbed mode: hide inactive panels
149 if (layout === 'tabbed') {
150 function showTab(lang) {
151 activeTab = lang;
152 var panels = editorsEl.querySelectorAll('.bkbg-cpg-panel');
153 panels.forEach(function (p) {
154 p.style.display = p.dataset.lang === lang ? 'flex' : 'none';
155 });
156 tabsEl.querySelectorAll('.bkbg-cpg-tab-btn').forEach(function (btn) {
157 btn.classList.toggle('bkbg-cpg-active', btn.dataset.lang === lang);
158 });
159 }
160 showTab('html');
161 tabsEl.addEventListener('click', function (e) {
162 if (e.target.dataset.lang) showTab(e.target.dataset.lang);
163 });
164 }
165
166 // ----- Toolbar -----
167 var toolbar = document.createElement('div');
168 toolbar.className = 'bkbg-cpg-toolbar';
169
170 var runBtn = document.createElement('button');
171 runBtn.className = 'bkbg-cpg-run-btn';
172 runBtn.textContent = '▶ Run';
173 runBtn.style.background = accent;
174 runBtn.style.color = '#fff';
175
176 var resetBtn = document.createElement('button');
177 resetBtn.className = 'bkbg-cpg-reset-btn';
178 resetBtn.textContent = '↺ Reset';
179 resetBtn.style.background = '#e5e7eb';
180 resetBtn.style.color = '#374151';
181
182 var autoLabel = document.createElement('label');
183 autoLabel.className = 'bkbg-cpg-autorun-label';
184 var autoCheck = document.createElement('input');
185 autoCheck.type = 'checkbox';
186 autoCheck.checked = autoRun;
187 autoLabel.appendChild(autoCheck);
188 autoLabel.appendChild(document.createTextNode(' Auto-run'));
189 autoLabel.style.color = opts.titleColor || '#374151';
190
191 toolbar.appendChild(runBtn);
192 toolbar.appendChild(resetBtn);
193 toolbar.appendChild(autoLabel);
194 root.appendChild(toolbar);
195
196 // ----- Preview iframe -----
197 var previewWrap = document.createElement('div');
198 previewWrap.className = 'bkbg-cpg-preview-wrap';
199
200 var previewHeader = document.createElement('div');
201 previewHeader.className = 'bkbg-cpg-preview-header';
202 previewHeader.style.background = headerBg;
203
204 var dot = document.createElement('span');
205 dot.className = 'bkbg-cpg-preview-dot';
206 previewHeader.appendChild(dot);
207 previewHeader.appendChild(document.createTextNode('Preview'));
208 previewWrap.appendChild(previewHeader);
209
210 var iframe = document.createElement('iframe');
211 iframe.className = 'bkbg-cpg-iframe';
212 iframe.style.height = previewH + 'px';
213 iframe.style.background = previewBg;
214 iframe.setAttribute('sandbox', 'allow-scripts');
215 iframe.setAttribute('title', 'Code preview');
216 previewWrap.appendChild(iframe);
217 root.appendChild(previewWrap);
218
219 // ----- Run logic -----
220 function runCode() {
221 var html = textareas.html.value;
222 var css = textareas.css.value;
223 var js = textareas.js.value;
224 var src = buildSrc(html, css, js);
225 iframe.srcdoc = src;
226 }
227
228 var debouncedRun = debounce(runCode, 500);
229
230 function handleInput() {
231 if (autoCheck.checked) debouncedRun();
232 }
233
234 Object.values(textareas).forEach(function (ta) {
235 ta.addEventListener('input', handleInput);
236 });
237
238 runBtn.addEventListener('click', runCode);
239
240 resetBtn.addEventListener('click', function () {
241 textareas.html.value = opts.defaultHtml || '';
242 textareas.css.value = opts.defaultCss || '';
243 textareas.js.value = opts.defaultJs || '';
244 runCode();
245 });
246
247 // Initial run
248 runCode();
249 }
250
251 document.querySelectorAll('.bkbg-cpg-app').forEach(function (root) {
252 initBlock(root);
253 });
254 })();
255