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 / color-harmony / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/color-harmony/frontend.js

322 lines 13.4 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 /* ── Typography CSS-var helper ── */
5 var _typoKeys = {
6 family:'font-family', weight:'font-weight', style:'font-style',
7 transform:'text-transform', decoration:'text-decoration',
8 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
9 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
10 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
11 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
12 };
13 var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' };
14 var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' };
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]; if (v === undefined || v === '') return;
19 var prop = _typoKeys[k];
20 var base = k.replace(/Desktop|Tablet|Mobile/, '');
21 var uKey = _typoUnits[base];
22 if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || '');
23 el.style.setProperty(prefix + prop, v);
24 });
25 }
26
27 var HARMONIES = {
28 complementary: 'Complementary',
29 triadic: 'Triadic',
30 analogous: 'Analogous',
31 splitComplementary: 'Split-Complementary',
32 tetradic: 'Tetradic',
33 square: 'Square'
34 };
35
36 /* ---- Color math ---- */
37 function hexToHsl(hex) {
38 hex = hex.replace('#','');
39 if (hex.length === 3) hex = hex.split('').map(function(c){return c+c;}).join('');
40 var r = parseInt(hex.slice(0,2),16)/255;
41 var g = parseInt(hex.slice(2,4),16)/255;
42 var b = parseInt(hex.slice(4,6),16)/255;
43 var max = Math.max(r,g,b), min = Math.min(r,g,b);
44 var h, s, l = (max+min)/2;
45 if (max === min) { h = s = 0; }
46 else {
47 var d = max-min;
48 s = l > 0.5 ? d/(2-max-min) : d/(max+min);
49 switch(max){
50 case r: h=((g-b)/d+(g<b?6:0))/6; break;
51 case g: h=((b-r)/d+2)/6; break;
52 default: h=((r-g)/d+4)/6; break;
53 }
54 }
55 return { h:h*360, s:s*100, l:l*100 };
56 }
57
58 function hslToHex(h, s, l) {
59 h = ((h%360)+360)%360;
60 s /= 100; l /= 100;
61 var a = s*Math.min(l, 1-l);
62 function f(n) {
63 var k=(n+h/30)%12;
64 var c=l-a*Math.max(-1,Math.min(k-3,9-k,1));
65 return Math.round(255*c).toString(16).padStart(2,'0');
66 }
67 return '#'+f(0)+f(8)+f(4);
68 }
69
70 function hexToRgb(hex) {
71 hex = hex.replace('#','');
72 if (hex.length === 3) hex = hex.split('').map(function(c){return c+c;}).join('');
73 return {
74 r: parseInt(hex.slice(0,2),16),
75 g: parseInt(hex.slice(2,4),16),
76 b: parseInt(hex.slice(4,6),16)
77 };
78 }
79
80 function getHarmony(baseHex, type) {
81 var hsl = hexToHsl(baseHex);
82 var h=hsl.h, s=hsl.s, l=hsl.l;
83 var res = [baseHex];
84 switch(type){
85 case 'complementary': res.push(hslToHex(h+180,s,l)); break;
86 case 'triadic': res.push(hslToHex(h+120,s,l), hslToHex(h+240,s,l)); break;
87 case 'analogous': res.push(hslToHex(h-30,s,l), hslToHex(h+30,s,l), hslToHex(h-60,s,l), hslToHex(h+60,s,l)); break;
88 case 'splitComplementary': res.push(hslToHex(h+150,s,l), hslToHex(h+210,s,l)); break;
89 case 'tetradic': res.push(hslToHex(h+90,s,l), hslToHex(h+180,s,l), hslToHex(h+270,s,l)); break;
90 case 'square': res.push(hslToHex(h+90,s,l), hslToHex(h+180,s,l), hslToHex(h+270,s,l)); break;
91 default: res.push(hslToHex(h+180,s,l)); break;
92 }
93 return res;
94 }
95
96 function copyText(str) {
97 if (navigator.clipboard && navigator.clipboard.writeText) {
98 return navigator.clipboard.writeText(str);
99 }
100 var ta = document.createElement('textarea');
101 ta.value = str;
102 ta.style.position = 'fixed';
103 ta.style.opacity = '0';
104 document.body.appendChild(ta);
105 ta.select();
106 document.execCommand('copy');
107 document.body.removeChild(ta);
108 return Promise.resolve();
109 }
110
111 function initBlock(root) {
112 var opts = {};
113 try { opts = JSON.parse(root.getAttribute('data-opts') || '{}'); } catch(e) {}
114
115 var accentColor = opts.accentColor || '#6366f1';
116 var sectionBg = opts.sectionBg || '#f8fafc';
117 var cardBg = opts.cardBg || '#ffffff';
118 var titleColor = opts.titleColor || '#1e1b4b';
119 var swatchSize = parseInt(opts.swatchSize || 80, 10);
120 var showHex = opts.showHex !== false;
121 var showRgb = opts.showRgb === true;
122 var showExport = opts.showExport !== false;
123 var fontSize = opts.fontSize || 28;
124 var subtitleSize= opts.subtitleSize || 14;
125
126 root.style.background = sectionBg;
127 root.style.borderRadius = '16px';
128 root.style.padding = '28px 20px';
129 root.style.textAlign = 'center';
130
131 typoCssVarsForEl(root, opts.typoTitle, '--bkbg-coh-tt-');
132 typoCssVarsForEl(root, opts.typoSubtitle, '--bkbg-coh-st-');
133
134 // Style title/subtitle
135 var titleEl = root.querySelector('.bkbg-coh-title');
136 var subEl = root.querySelector('.bkbg-coh-subtitle');
137 if (titleEl) { titleEl.style.color = titleColor; titleEl.style.margin='0 0 4px'; }
138 if (subEl) { subEl.style.color = titleColor+'bb'; subEl.style.margin='0 0 20px'; }
139
140 // State
141 var currentColor = opts.defaultColor || '#6366f1';
142 var currentHarmony = opts.defaultHarmony || 'complementary';
143
144 var inner = document.createElement('div');
145 root.appendChild(inner);
146
147 function render() {
148 inner.innerHTML = '';
149
150 // Harmony tabs
151 var tabs = document.createElement('div');
152 tabs.className = 'bkbg-coh-tabs';
153 Object.keys(HARMONIES).forEach(function(k) {
154 var btn = document.createElement('button');
155 btn.className = 'bkbg-coh-tab';
156 btn.textContent = HARMONIES[k];
157 btn.style.borderColor = accentColor;
158 var active = k === currentHarmony;
159 btn.style.background = active ? accentColor : 'transparent';
160 btn.style.color = active ? '#fff' : accentColor;
161 btn.addEventListener('click', function() { currentHarmony = k; render(); });
162 tabs.appendChild(btn);
163 });
164 inner.appendChild(tabs);
165
166 // Color picker row
167 var pickerRow = document.createElement('div');
168 pickerRow.className = 'bkbg-coh-picker-row';
169
170 var previewCircle = document.createElement('div');
171 previewCircle.className = 'bkbg-coh-picker-preview';
172 previewCircle.style.background = currentColor;
173 previewCircle.style.borderColor = accentColor;
174 previewCircle.title = 'Click to pick a color';
175
176 var colorInput = document.createElement('input');
177 colorInput.type = 'color';
178 colorInput.className = 'bkbg-coh-picker-input';
179 colorInput.value = currentColor;
180 colorInput.addEventListener('input', function() {
181 currentColor = colorInput.value;
182 previewCircle.style.background = currentColor;
183 hexLbl.textContent = currentColor.toUpperCase();
184 renderSwatches();
185 });
186 previewCircle.appendChild(colorInput);
187
188 var hexLbl = document.createElement('div');
189 hexLbl.className = 'bkbg-coh-hex-label';
190 hexLbl.style.color = titleColor;
191 hexLbl.textContent = currentColor.toUpperCase();
192
193 pickerRow.appendChild(previewCircle);
194 pickerRow.appendChild(hexLbl);
195 inner.appendChild(pickerRow);
196
197 // Card with swatches
198 var card = document.createElement('div');
199 card.className = 'bkbg-coh-card';
200 card.style.background = cardBg;
201 card.id = 'bkbg-coh-swatches-' + (root.id || Math.random().toString(36).slice(2));
202
203 var swatchRow = document.createElement('div');
204 swatchRow.className = 'bkbg-coh-swatches';
205 card.appendChild(swatchRow);
206 inner.appendChild(card);
207
208 function renderSwatches() {
209 swatchRow.innerHTML = '';
210 var colors = getHarmony(currentColor, currentHarmony);
211 colors.forEach(function(hex, i) {
212 var item = document.createElement('div');
213 item.className = 'bkbg-coh-swatch-item';
214 item.title = 'Click to copy ' + hex.toUpperCase();
215
216 var box = document.createElement('div');
217 box.className = 'bkbg-coh-swatch-box';
218 box.style.width = swatchSize + 'px';
219 box.style.height = swatchSize + 'px';
220 box.style.background = hex;
221 box.style.position = 'relative';
222
223 var copiedLbl = document.createElement('div');
224 copiedLbl.className = 'bkbg-coh-copied';
225 copiedLbl.textContent = 'Copied!';
226 box.appendChild(copiedLbl);
227 item.appendChild(box);
228
229 if (showHex) {
230 var hexEl = document.createElement('div');
231 hexEl.className = 'bkbg-coh-swatch-hex';
232 hexEl.textContent = hex.toUpperCase();
233 item.appendChild(hexEl);
234 }
235
236 if (showRgb) {
237 var rgb = hexToRgb(hex);
238 var rgbEl = document.createElement('div');
239 rgbEl.className = 'bkbg-coh-swatch-rgb';
240 rgbEl.textContent = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
241 item.appendChild(rgbEl);
242 }
243
244 if (i === 0) {
245 var baseLbl = document.createElement('div');
246 baseLbl.className = 'bkbg-coh-swatch-base-lbl';
247 baseLbl.textContent = 'Base';
248 item.appendChild(baseLbl);
249 }
250
251 item.addEventListener('click', function() {
252 copyText(hex.toUpperCase()).then(function() {
253 copiedLbl.classList.add('show');
254 setTimeout(function() { copiedLbl.classList.remove('show'); }, 1200);
255 });
256 });
257
258 swatchRow.appendChild(item);
259 });
260 }
261
262 renderSwatches();
263
264 // Export button
265 if (showExport) {
266 var actions = document.createElement('div');
267 actions.className = 'bkbg-coh-actions';
268
269 var expBtn = document.createElement('button');
270 expBtn.className = 'bkbg-coh-btn';
271 expBtn.style.background = accentColor;
272 expBtn.textContent = '📋 Export Palette';
273 expBtn.addEventListener('click', function() {
274 var colors = getHarmony(currentColor, currentHarmony);
275 copyText(colors.map(function(c){return c.toUpperCase();}).join(', ')).then(function() {
276 var orig = expBtn.textContent;
277 expBtn.textContent = '�
278 Copied!';
279 setTimeout(function() { expBtn.textContent = orig; }, 1500);
280 });
281 });
282 actions.appendChild(expBtn);
283
284 var cssBtn = document.createElement('button');
285 cssBtn.className = 'bkbg-coh-btn bkbg-coh-btn-outline';
286 cssBtn.style.borderColor = accentColor;
287 cssBtn.style.color = accentColor;
288 cssBtn.textContent = 'Copy as CSS vars';
289 cssBtn.addEventListener('click', function() {
290 var colors = getHarmony(currentColor, currentHarmony);
291 var cssStr = ':root {\n' + colors.map(function(c, i) {
292 return ' --color-' + (i===0?'base':'harmony-'+i) + ': ' + c.toUpperCase() + ';';
293 }).join('\n') + '\n}';
294 copyText(cssStr).then(function() {
295 var orig = cssBtn.textContent;
296 cssBtn.textContent = '�
297 Copied!';
298 setTimeout(function() { cssBtn.textContent = orig; }, 1500);
299 });
300 });
301 actions.appendChild(cssBtn);
302
303 inner.appendChild(actions);
304 }
305 }
306
307 render();
308 }
309
310 function init() {
311 document.querySelectorAll('.bkbg-coh-app').forEach(function(root) {
312 initBlock(root);
313 });
314 }
315
316 if (document.readyState === 'loading') {
317 document.addEventListener('DOMContentLoaded', init);
318 } else {
319 init();
320 }
321 })();
322