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 / magnetic-button / frontend.js

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

166 lines 7.5 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 decoration:'text-decoration', transform:'text-transform',
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 function typoCssVarsForEl(el, obj, prefix) {
13 if (!obj || typeof obj !== 'object') return;
14 Object.keys(_typoKeys).forEach(function (k) {
15 var v = obj[k];
16 if (v === undefined || v === '' || v === null) return;
17 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
18 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
19 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
20 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
21 el.style.setProperty(prefix + _typoKeys[k], String(v));
22 });
23 }
24
25 function initBlock(root) {
26 var wrap = root.querySelector('.bkbg-mgb-wrap');
27 if (!wrap) return;
28
29 var raw = wrap.getAttribute('data-opts') || '{}';
30 var o;
31 try { o = JSON.parse(raw); } catch (e) { o = {}; }
32
33 var magnetStrength = Number(o.magnetStrength) || 40;
34 var magnetRadius = Number(o.magnetRadius) || 120;
35 var ripple = o.ripple !== false;
36 var buttonStyle = o.buttonStyle || 'filled';
37 var paddingX = Number(o.paddingX) || 40;
38 var paddingY = Number(o.paddingY) || 18;
39 var borderRadius = Number(o.borderRadius) || 999;
40 var borderWidth = Number(o.borderWidth) || 2;
41 var btnBg = o.btnBg || '#6366f1';
42 var btnColor = o.btnColor || '#ffffff';
43 var btnBorderColor = o.btnBorderColor || '#6366f1';
44 var hoverBg = o.hoverBg || '#4f46e5';
45 var hoverColor = o.hoverColor || '#ffffff';
46 var rippleColor = o.rippleColor || 'rgba(255,255,255,0.35)';
47 var shadowColor = o.shadowColor || 'rgba(99,102,241,0.4)';
48
49 var btn = wrap.querySelector('.bkbg-mgb-btn');
50 if (!btn) return;
51
52 var isOutline = buttonStyle === 'outline';
53 var isGhost = buttonStyle === 'ghost';
54
55 // Apply base styles
56 btn.style.padding = paddingY + 'px ' + paddingX + 'px';
57 btn.style.borderRadius = borderRadius + 'px';
58 btn.style.background = isOutline || isGhost ? 'transparent' : btnBg;
59 btn.style.color = isOutline || isGhost ? btnBg : btnColor;
60 btn.style.border = isGhost ? 'none' : borderWidth + 'px solid ' + btnBorderColor;
61 btn.style.boxShadow = isOutline || isGhost ? 'none' : '0 4px 20px ' + shadowColor;
62
63 // Apply typography CSS vars on root
64 typoCssVarsForEl(root, o.textTypo, '--bkbg-mgb-tx-');
65
66 // Respect reduced-motion
67 var reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
68
69 // ── Magnetic tracking ────────────────────────────────────────────
70 var raf = null;
71 var targetX = 0, targetY = 0, currentX = 0, currentY = 0;
72 var isHovered = false;
73 var isNear = false;
74
75 function lerp(a, b, t) { return a + (b - a) * t; }
76
77 function animate() {
78 currentX = lerp(currentX, targetX, 0.15);
79 currentY = lerp(currentY, targetY, 0.15);
80
81 btn.style.transform = 'translate(' + currentX + 'px,' + currentY + 'px)';
82
83 if (isNear || Math.abs(currentX) > 0.05 || Math.abs(currentY) > 0.05) {
84 raf = requestAnimationFrame(animate);
85 } else {
86 btn.style.transform = '';
87 raf = null;
88 }
89 }
90
91 function getCenter() {
92 var r = btn.getBoundingClientRect();
93 return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
94 }
95
96 document.addEventListener('mousemove', function (e) {
97 if (reducedMotion) return;
98 var center = getCenter();
99 var dx = e.clientX - center.x;
100 var dy = e.clientY - center.y;
101 var dist = Math.sqrt(dx * dx + dy * dy);
102
103 if (dist < magnetRadius) {
104 isNear = true;
105 var power = (1 - dist / magnetRadius); // 0→1 as cursor gets closer
106 targetX = dx * power * (magnetStrength / 100);
107 targetY = dy * power * (magnetStrength / 100);
108 if (!raf) raf = requestAnimationFrame(animate);
109 } else if (isNear) {
110 isNear = false;
111 targetX = 0;
112 targetY = 0;
113 if (!raf) raf = requestAnimationFrame(animate);
114 }
115 }, { passive: true });
116
117 // ── Hover colour swap ────────────────────────────────────────────
118 btn.addEventListener('mouseenter', function () {
119 isHovered = true;
120 btn.style.background = isOutline || isGhost ? (isGhost ? 'transparent' : 'transparent') : hoverBg;
121 btn.style.color = isOutline || isGhost ? hoverBg : hoverColor;
122 btn.style.boxShadow = isOutline || isGhost ? 'none' : '0 8px 32px ' + shadowColor;
123 });
124
125 btn.addEventListener('mouseleave', function () {
126 isHovered = false;
127 btn.style.background = isOutline || isGhost ? 'transparent' : btnBg;
128 btn.style.color = isOutline || isGhost ? btnBg : btnColor;
129 btn.style.boxShadow = isOutline || isGhost ? 'none' : '0 4px 20px ' + shadowColor;
130 });
131
132 // ── Ripple on click ──────────────────────────────────────────────
133 if (ripple) {
134 btn.addEventListener('click', function (e) {
135 var r = btn.getBoundingClientRect();
136 var x = e.clientX - r.left;
137 var y = e.clientY - r.top;
138 var size = Math.max(r.width, r.height);
139
140 var rpl = document.createElement('span');
141 rpl.className = 'bkbg-mgb-ripple';
142 rpl.style.cssText = [
143 'width:' + size + 'px',
144 'height:' + size + 'px',
145 'left:' + (x - size / 2) + 'px',
146 'top:' + (y - size / 2) + 'px',
147 'background:' + rippleColor
148 ].join(';');
149
150 btn.appendChild(rpl);
151 rpl.addEventListener('animationend', function () { rpl.remove(); });
152 });
153 }
154 }
155
156 function init() {
157 document.querySelectorAll('.wp-block-blockenberg-magnetic-button').forEach(initBlock);
158 }
159
160 if (document.readyState === 'loading') {
161 document.addEventListener('DOMContentLoaded', init);
162 } else {
163 init();
164 }
165 })();
166