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 / notification-toast / frontend.js

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

235 lines 10.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 var STATE_KEY = 'bkbg-ntst-shown';
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 initials(name) {
26 return (name || 'U').split(' ').map(function (w) { return w[0] || ''; }).join('').slice(0, 2).toUpperCase();
27 }
28
29 function buildToastEl(notif, o) {
30 var toast = document.createElement('div');
31 toast.className = 'bkbg-ntst-toast anim-' + (o.animateType || 'slide') +
32 ' ' + ((o.position || '').indexOf('left') > -1 ? 'pos-left' : 'pos-right');
33 toast.style.maxWidth = (o.maxWidth || 320) + 'px';
34 toast.style.borderRadius = (o.borderRadius || 12) + 'px';
35 toast.style.background = o.toastBg || '#ffffff';
36 if ((o.toastStyle || 'shadow') === 'bordered') {
37 toast.style.border = '1px solid ' + (o.toastBorder || '#e5e7eb');
38 } else if (o.toastStyle === 'shadow') {
39 toast.style.boxShadow = '0 4px 20px rgba(0,0,0,0.13)';
40 }
41
42 if (o.showAvatar) {
43 var avatar = document.createElement('div');
44 avatar.className = 'bkbg-ntst-avatar';
45 avatar.style.width = (o.avatarSize || 40) + 'px';
46 avatar.style.height = (o.avatarSize || 40) + 'px';
47 avatar.style.fontSize = Math.round((o.avatarSize || 40) * 0.35) + 'px';
48 avatar.style.background = notif.avatarBg || '#6366f1';
49 avatar.textContent = initials(notif.name);
50 toast.appendChild(avatar);
51 }
52
53 var content = document.createElement('div');
54 content.className = 'bkbg-ntst-content';
55
56 var nameRow = document.createElement('div');
57 nameRow.className = 'bkbg-ntst-name-row';
58
59 if (o.showIcon) {
60 var iconEl = document.createElement('span');
61 iconEl.className = 'bkbg-ntst-icon';
62 iconEl.style.fontSize = (o.iconSize || 20) + 'px';
63 var _IP = window.bkbgIconPicker;
64 var _iType = notif.iconType || 'custom-char';
65 if (_IP && _iType !== 'custom-char') {
66 var _in = _IP.buildFrontendIcon(_iType, notif.icon, notif.iconDashicon, notif.iconImageUrl, notif.iconDashiconColor);
67 if (_in) iconEl.appendChild(_in); else iconEl.textContent = notif.icon || '🔔';
68 } else { iconEl.textContent = notif.icon || '🔔'; }
69 nameRow.appendChild(iconEl);
70 }
71
72 var nameEl = document.createElement('span');
73 nameEl.className = 'bkbg-ntst-name';
74 nameEl.style.color = o.nameColor || '#111827';
75 nameEl.textContent = notif.name || '';
76 nameRow.appendChild(nameEl);
77 content.appendChild(nameRow);
78
79 var msgEl = document.createElement('div');
80 msgEl.className = 'bkbg-ntst-msg';
81 msgEl.style.color = o.textColor || '#6b7280';
82 msgEl.textContent = notif.text || '';
83 content.appendChild(msgEl);
84
85 if (o.showTimeAgo && notif.timeAgo) {
86 var timeEl = document.createElement('div');
87 timeEl.className = 'bkbg-ntst-time';
88 timeEl.style.fontSize = (o.timeSize || 11) + 'px';
89 timeEl.style.color = o.timeColor || '#9ca3af';
90 timeEl.textContent = notif.timeAgo;
91 content.appendChild(timeEl);
92 }
93
94 toast.appendChild(content);
95 return toast;
96 }
97
98 function init() {
99 document.querySelectorAll('.bkbg-ntst-app').forEach(function (appEl) {
100 if (appEl.dataset.rendered) return;
101 appEl.dataset.rendered = '1';
102 var opts;
103 try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
104 var o = Object.assign({
105 notifications: [],
106 position: 'bottom-left',
107 interval: 4,
108 displayDuration: 3,
109 animateType: 'slide',
110 showOnce: false,
111 loop: true,
112 showAvatar: true,
113 showTimeAgo: true,
114 showIcon: true,
115 toastStyle: 'shadow',
116 maxWidth: 320,
117 borderRadius: 12,
118 avatarSize: 40,
119 iconSize: 20,
120 nameSize: 13,
121 textSize: 12,
122 timeSize: 11,
123 toastBg: '#ffffff',
124 toastBorder: '#e5e7eb',
125 toastShadow: true,
126 nameColor: '#111827',
127 textColor: '#6b7280',
128 timeColor: '#9ca3af',
129 }, opts);
130
131 if (!o.notifications || !o.notifications.length) return;
132
133 // showOnce check
134 if (o.showOnce) {
135 try {
136 if (sessionStorage.getItem(STATE_KEY + '-' + (appEl.id || ''))) return;
137 } catch (e) {}
138 }
139
140 // Create fixed container (attached to body, outside content flow)
141 var fixed = document.createElement('div');
142 fixed.className = 'bkbg-ntst-fixed pos-' + (o.position || 'bottom-left');
143
144 var pos = o.position || 'bottom-left';
145 fixed.style.position = 'fixed';
146 fixed.style.zIndex = '99999';
147 fixed.style.bottom = pos.indexOf('bottom') > -1 ? '24px' : 'auto';
148 fixed.style.top = pos.indexOf('top') > -1 ? '24px' : 'auto';
149 fixed.style.left = pos.indexOf('left') > -1 ? '24px' : 'auto';
150 fixed.style.right = pos.indexOf('right') > -1 ? '24px' : 'auto';
151 document.body.appendChild(fixed);
152
153 /* Typography CSS vars */
154 typoCssVarsForEl(fixed, opts.nameTypo, '--bkbg-ntst-nm-');
155 typoCssVarsForEl(fixed, opts.textTypo, '--bkbg-ntst-tx-');
156
157 var idx = 0;
158 var currentToast = null;
159 var showTimer = null;
160 var hideTimer = null;
161
162 function showNext() {
163 if (idx >= o.notifications.length) {
164 if (!o.loop) return;
165 idx = 0;
166 }
167 var notif = o.notifications[idx];
168 idx++;
169
170 // Remove previous
171 if (currentToast) {
172 currentToast.classList.remove('is-visible');
173 var ct = currentToast;
174 setTimeout(function () { if (ct.parentNode) ct.parentNode.removeChild(ct); }, 400);
175 currentToast = null;
176 }
177
178 var toast = buildToastEl(notif, o);
179 fixed.appendChild(toast);
180 currentToast = toast;
181
182 // Trigger enter animation
183 requestAnimationFrame(function () {
184 requestAnimationFrame(function () {
185 toast.classList.add('is-visible');
186 });
187 });
188
189 // Schedule hide after displayDuration
190 clearTimeout(hideTimer);
191 hideTimer = setTimeout(function () {
192 if (toast.parentNode) {
193 toast.classList.remove('is-visible');
194 setTimeout(function () {
195 if (toast.parentNode) toast.parentNode.removeChild(toast);
196 if (currentToast === toast) currentToast = null;
197 }, 400);
198 }
199 }, (o.displayDuration || 3) * 1000);
200
201 // Schedule next
202 clearTimeout(showTimer);
203 if (o.loop || idx < o.notifications.length) {
204 showTimer = setTimeout(showNext, ((o.displayDuration || 3) + (o.interval || 4)) * 1000);
205 }
206 }
207
208 // Start after first interval
209 var startTimer = setTimeout(function () {
210 showNext();
211 if (o.showOnce) {
212 try { sessionStorage.setItem(STATE_KEY + '-' + (appEl.id || ''), '1'); } catch (e) {}
213 }
214 }, (o.interval || 4) * 1000);
215
216 appEl.style.display = 'none';
217
218 // Clean up if the source element leaves DOM
219 var observer = new MutationObserver(function () {
220 if (!document.body.contains(appEl)) {
221 clearTimeout(startTimer);
222 clearTimeout(showTimer);
223 clearTimeout(hideTimer);
224 if (fixed.parentNode) fixed.parentNode.removeChild(fixed);
225 observer.disconnect();
226 }
227 });
228 observer.observe(document.body, { childList: true, subtree: true });
229 });
230 }
231
232 if (document.readyState !== 'loading') { init(); }
233 else { document.addEventListener('DOMContentLoaded', init); }
234 })();
235