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 / reaction-bar / frontend.js

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

187 lines 7.6 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 function mk(tag, cls, styles) {
5 var d = document.createElement(tag);
6 if (cls) d.className = cls;
7 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
8 return d;
9 }
10 function tx(tag, cls, text, styles) {
11 var d = mk(tag, cls, styles);
12 d.textContent = text;
13 return d;
14 }
15 function ap(p) {
16 Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) p.appendChild(c); });
17 return p;
18 }
19
20 var _typoKeys = {
21 family:'font-family', weight:'font-weight', style:'font-style',
22 transform:'text-transform', decoration:'text-decoration',
23 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
24 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
25 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
26 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
27 };
28 var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' };
29 var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' };
30 function typoCssVarsForEl(el, obj, prefix) {
31 if (!obj || typeof obj !== 'object') return;
32 Object.keys(_typoKeys).forEach(function (k) {
33 var v = obj[k]; if (v === undefined || v === '') return;
34 var prop = _typoKeys[k];
35 var base = k.replace(/Desktop|Tablet|Mobile/, '');
36 var uKey = _typoUnits[base];
37 if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || '');
38 el.style.setProperty(prefix + prop, v);
39 });
40 }
41
42 function buildBlock(appEl) {
43 if (appEl.dataset.rendered) return;
44 appEl.dataset.rendered = '1';
45
46 var a;
47 try { a = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { a = {}; }
48
49 var reactions = a.reactions || [];
50 var isCards = a.layout === 'cards';
51 var isCompact = a.layout === 'compact';
52 var emojiSize = a.emojiSize || 22;
53 var itemRadius = (a.itemRadius || 100) + 'px';
54
55 // state: which index is "active" (toggled)
56 var activeIdx = -1;
57
58 // Wrapper
59 appEl.style.background = a.bgColor || '#ffffff';
60 appEl.style.border = '1px solid ' + (a.borderColor || '#e5e7eb');
61 appEl.style.borderRadius = (a.borderRadius || 16) + 'px';
62 appEl.style.padding = '20px 24px';
63 appEl.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
64
65 typoCssVarsForEl(appEl, a.titleTypo || {}, '--bkrab-tt-');
66 typoCssVarsForEl(appEl, a.countTypo || {}, '--bkrab-ct-');
67
68 // Title
69 if (a.showTitle && a.title) {
70 var titleEl = tx('div', 'bkrab-title', a.title, {
71 color: a.titleColor || '#111827',
72 marginBottom: '14px'
73 });
74 ap(appEl, titleEl);
75 }
76
77 // Reactions container
78 var container = mk('div', '', {
79 display: isCards ? 'grid' : 'flex',
80 gridTemplateColumns: isCards ? 'repeat(auto-fill, minmax(90px, 1fr))' : '',
81 flexWrap: 'wrap',
82 gap: '8px'
83 });
84
85 // Total tracker
86 var totalCounts = reactions.map(function (r) { return r.count || 0; });
87
88 // Total display
89 var totalEl = null;
90 var totalSum = totalCounts.reduce(function (s, c) { return s + c; }, 0);
91 if (a.showTotal) {
92 totalEl = tx('div', 'bkrab-total', totalSum + ' ' + (a.totalLabel || 'reactions'), {
93 marginTop: '12px',
94 color: a.totalColor || '#9ca3af'
95 });
96 }
97
98 // Build each reaction item
99 var itemEls = reactions.map(function (r, idx) {
100 var isActive = false;
101
102 var itemWrap = mk('div', '', {
103 display: 'inline-flex', alignItems: 'center',
104 justifyContent: isCards ? 'center' : 'flex-start',
105 flexDirection: isCards ? 'column' : 'row',
106 gap: '6px',
107 padding: isCards ? '16px 12px' : isCompact ? '4px 12px' : '7px 14px',
108 borderRadius: isCards ? '12px' : itemRadius,
109 border: '1.5px solid ' + (a.itemBorderColor || '#e5e7eb'),
110 background: a.itemBg || '#f9fafb',
111 cursor: 'pointer', userSelect: 'none',
112 transition: 'all .15s ease',
113 flexShrink: '0'
114 });
115
116 var emojiEl = tx('span', '', r.emoji || '', { fontSize: emojiSize + 'px', lineHeight: '1' });
117 var countSpan = tx('span', 'bkrab-count', String(r.count || 0), {
118 color: a.countColor || '#374151'
119 });
120 var labelSpan = null;
121 if (a.showLabel && !isCompact) {
122 labelSpan = tx('span', 'bkrab-label', r.label || '', {
123 color: a.labelColor || '#6b7280'
124 });
125 }
126
127 var metaRow = mk('div', '', {
128 display: 'flex', flexDirection: isCards ? 'column' : 'row',
129 alignItems: 'center', gap: '4px'
130 });
131 if (a.showCount) ap(metaRow, countSpan);
132 if (labelSpan) ap(metaRow, labelSpan);
133 ap(itemWrap, emojiEl, metaRow);
134
135 // Animate helper
136 function applyActive(active) {
137 var bg = active ? (a.activeItemBg || '#eff6ff') : (a.itemBg || '#f9fafb');
138 var border = active ? (a.activeItemBorder || '#bfdbfe') : (a.itemBorderColor || '#e5e7eb');
139 var cc = active ? (a.activeCountColor || '#1d4ed8') : (a.countColor || '#374151');
140 itemWrap.style.background = bg;
141 itemWrap.style.borderColor = border;
142 countSpan.style.color = cc;
143 }
144
145 itemWrap.addEventListener('click', function () {
146 isActive = !isActive;
147 applyActive(isActive);
148
149 // Update count
150 var delta = isActive ? 1 : -1;
151 totalCounts[idx] += delta;
152 countSpan.textContent = String(totalCounts[idx]);
153
154 // Bounce animation
155 if (a.animate !== false) {
156 emojiEl.style.transform = 'scale(1.4)';
157 setTimeout(function () { emojiEl.style.transform = 'scale(1)'; }, 200);
158 }
159
160 // Update total
161 if (totalEl) {
162 var sum = totalCounts.reduce(function (s, c) { return s + c; }, 0);
163 totalEl.textContent = sum + ' ' + (a.totalLabel || 'reactions');
164 }
165 });
166
167 itemWrap.addEventListener('mouseenter', function () {
168 if (!isActive) itemWrap.style.background = a.itemHoverBg || '#f3f4f6';
169 });
170 itemWrap.addEventListener('mouseleave', function () {
171 if (!isActive) itemWrap.style.background = a.itemBg || '#f9fafb';
172 });
173
174 return itemWrap;
175 });
176
177 itemEls.forEach(function (el) { ap(container, el); });
178 ap(appEl, container);
179 if (totalEl) ap(appEl, totalEl);
180 }
181
182 function init() {
183 document.querySelectorAll('.bkbg-reaction-bar-app').forEach(buildBlock);
184 }
185 if (document.readyState !== 'loading') { init(); } else { document.addEventListener('DOMContentLoaded', init); }
186 })();
187