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 / social-proof-popup / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/social-proof-popup/index.js

288 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var __ = wp.i18n.__;
4 var useState = wp.element.useState;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelBody = wp.components.PanelBody;
9 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
10 var ToggleControl = wp.components.ToggleControl;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var Button = wp.components.Button;
15
16 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
17 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
18
19 function updateEntry(entries, idx, field, val) {
20 return entries.map(function (e, i) {
21 if (i !== idx) return e;
22 var upd = {}; upd[field] = val;
23 return Object.assign({}, e, upd);
24 });
25 }
26
27 function PopupPreview(props) {
28 var a = props.a;
29 var entry = a.entries && a.entries[0];
30 if (!entry) return el('div', { className: 'bkbg-spop-empty' }, 'Add entries in the sidebar panel.');
31
32 var wrapStyle = {
33 background: a.bgColor,
34 color: a.textColor,
35 borderColor: a.borderColor,
36 borderRadius: a.borderRadius + 'px',
37 maxWidth: a.maxWidth + 'px',
38 boxShadow: a.shadow ? '0 4px 24px rgba(0,0,0,.12)' : 'none'
39 };
40
41 var avatarInitial = (entry.name || 'U').charAt(0).toUpperCase();
42
43 return el('div', { className: 'bkbg-spop-preview-wrap' },
44 el('p', { className: 'bkbg-spop-preview-label' }, '👁 Preview (first entry)'),
45 el('div', { className: 'bkbg-spop-popup', style: wrapStyle },
46 a.showAvatar && el('div', {
47 className: 'bkbg-spop-avatar',
48 style: { background: a.avatarBg }
49 }, entry.emoji
50 ? el('span', { className: 'bkbg-spop-emoji' }, entry.emoji)
51 : el('span', { className: 'bkbg-spop-initial' }, avatarInitial)
52 ),
53 el('div', { className: 'bkbg-spop-content' },
54 el('div', { className: 'bkbg-spop-name', style: { color: a.nameColor } },
55 entry.name,
56 entry.location && el('span', { className: 'bkbg-spop-location' }, ' · ' + entry.location)
57 ),
58 el('div', { className: 'bkbg-spop-action', style: { color: a.actionColor } }, entry.action),
59 a.showTime && entry.timeAgo && el('div', { className: 'bkbg-spop-time', style: { color: a.timeColor } }, entry.timeAgo)
60 ),
61 a.showClose && el('button', { className: 'bkbg-spop-close', style: { color: a.closeBtnColor } }, '×')
62 )
63 );
64 }
65
66 registerBlockType('blockenberg/social-proof-popup', {
67 title: __('Social Proof Popup', 'blockenberg'),
68 icon: 'heart',
69 category: 'bkbg-marketing',
70 description: __('Floating FOMO notification popups cycling through social proof entries.', 'blockenberg'),
71
72 edit: function (props) {
73 var a = props.attributes;
74 var setAttributes = props.setAttributes;
75
76 var openState = useState(null);
77 var openIdx = openState[0]; var setOpenIdx = openState[1];
78
79 var positionOpts = [
80 { label: 'Bottom Left', value: 'bottom-left' },
81 { label: 'Bottom Right', value: 'bottom-right' },
82 { label: 'Top Left', value: 'top-left' },
83 { label: 'Top Right', value: 'top-right' }
84 ];
85 var animOpts = [
86 { label: 'Slide Up', value: 'slide' },
87 { label: 'Fade', value: 'fade' },
88 { label: 'Bounce', value: 'bounce' }
89 ];
90
91 function addEntry() {
92 setAttributes({ entries: a.entries.concat([{ emoji: '🔔', name: 'Someone', location: 'City, Country', action: 'just took action', timeAgo: 'just now' }]) });
93 }
94 function removeEntry(idx) {
95 setAttributes({ entries: a.entries.filter(function (_, i) { return i !== idx; }) });
96 }
97
98 var inspector = el(InspectorControls, {},
99 el(PanelBody, { title: __('Behaviour', 'blockenberg'), initialOpen: true },
100 el(SelectControl, {
101 label: __('Position', 'blockenberg'),
102 value: a.position,
103 options: positionOpts,
104 __nextHasNoMarginBottom: true,
105 onChange: function (v) { setAttributes({ position: v }); }
106 }),
107 el(SelectControl, {
108 label: __('Animation', 'blockenberg'),
109 value: a.animationType,
110 options: animOpts,
111 __nextHasNoMarginBottom: true,
112 onChange: function (v) { setAttributes({ animationType: v }); }
113 }),
114 el(RangeControl, {
115 label: __('Display Time (ms)', 'blockenberg'),
116 value: a.displayTime,
117 min: 1000, max: 10000, step: 500,
118 __nextHasNoMarginBottom: true,
119 onChange: function (v) { setAttributes({ displayTime: v }); }
120 }),
121 el(RangeControl, {
122 label: __('Pause Between (ms)', 'blockenberg'),
123 value: a.pauseBetween,
124 min: 500, max: 8000, step: 500,
125 __nextHasNoMarginBottom: true,
126 onChange: function (v) { setAttributes({ pauseBetween: v }); }
127 }),
128 el(RangeControl, {
129 label: __('Start Delay (ms)', 'blockenberg'),
130 value: a.startDelay,
131 min: 0, max: 10000, step: 500,
132 __nextHasNoMarginBottom: true,
133 onChange: function (v) { setAttributes({ startDelay: v }); }
134 }),
135 el(ToggleControl, {
136 label: __('Loop', 'blockenberg'),
137 checked: a.loop,
138 __nextHasNoMarginBottom: true,
139 onChange: function (v) { setAttributes({ loop: v }); }
140 }),
141 el(ToggleControl, {
142 label: __('Show Avatar / Emoji', 'blockenberg'),
143 checked: a.showAvatar,
144 __nextHasNoMarginBottom: true,
145 onChange: function (v) { setAttributes({ showAvatar: v }); }
146 }),
147 el(ToggleControl, {
148 label: __('Show Timestamp', 'blockenberg'),
149 checked: a.showTime,
150 __nextHasNoMarginBottom: true,
151 onChange: function (v) { setAttributes({ showTime: v }); }
152 }),
153 el(ToggleControl, {
154 label: __('Show Close Button', 'blockenberg'),
155 checked: a.showClose,
156 __nextHasNoMarginBottom: true,
157 onChange: function (v) { setAttributes({ showClose: v }); }
158 })
159 ),
160 el(PanelBody, { title: __('Style', 'blockenberg'), initialOpen: false },
161 el(RangeControl, {
162 label: __('Border Radius', 'blockenberg'),
163 value: a.borderRadius,
164 min: 0, max: 24,
165 __nextHasNoMarginBottom: true,
166 onChange: function (v) { setAttributes({ borderRadius: v }); }
167 }),
168 el(RangeControl, {
169 label: __('Max Width (px)', 'blockenberg'),
170 value: a.maxWidth,
171 min: 200, max: 480,
172 __nextHasNoMarginBottom: true,
173 onChange: function (v) { setAttributes({ maxWidth: v }); }
174 }),
175 el(ToggleControl, {
176 label: __('Drop Shadow', 'blockenberg'),
177 checked: a.shadow,
178 __nextHasNoMarginBottom: true,
179 onChange: function (v) { setAttributes({ shadow: v }); }
180 })
181 ),
182 el(PanelBody, { title: __('Entries (' + a.entries.length + ')', 'blockenberg'), initialOpen: false },
183 a.entries.map(function (entry, i) {
184 var isOpen = openIdx === i;
185 return el('div', { key: i, className: 'bkbg-spop-entry-editor' },
186 el('div', {
187 className: 'bkbg-spop-entry-head',
188 onClick: function () { setOpenIdx(isOpen ? null : i); }
189 },
190 el('span', {}, entry.emoji + ' ' + (entry.name || 'Entry ' + (i + 1))),
191 el('div', { style: { marginLeft: 'auto', display: 'flex', gap: '4px' } },
192 el('span', {}, isOpen ? '' : ''),
193 el(Button, { isSmall: true, isDestructive: true, onClick: function (e) { e.stopPropagation(); removeEntry(i); } }, '')
194 )
195 ),
196 isOpen && el('div', { className: 'bkbg-spop-entry-fields' },
197 el(TextControl, {
198 label: __('Emoji / Icon', 'blockenberg'),
199 value: entry.emoji,
200 __nextHasNoMarginBottom: true,
201 onChange: function (v) { setAttributes({ entries: updateEntry(a.entries, i, 'emoji', v) }); }
202 }),
203 el(TextControl, {
204 label: __('Name', 'blockenberg'),
205 value: entry.name,
206 __nextHasNoMarginBottom: true,
207 onChange: function (v) { setAttributes({ entries: updateEntry(a.entries, i, 'name', v) }); }
208 }),
209 el(TextControl, {
210 label: __('Location', 'blockenberg'),
211 value: entry.location,
212 __nextHasNoMarginBottom: true,
213 onChange: function (v) { setAttributes({ entries: updateEntry(a.entries, i, 'location', v) }); }
214 }),
215 el(TextControl, {
216 label: __('Action Text', 'blockenberg'),
217 value: entry.action,
218 __nextHasNoMarginBottom: true,
219 onChange: function (v) { setAttributes({ entries: updateEntry(a.entries, i, 'action', v) }); }
220 }),
221 el(TextControl, {
222 label: __('Time Ago', 'blockenberg'),
223 value: entry.timeAgo,
224 __nextHasNoMarginBottom: true,
225 onChange: function (v) { setAttributes({ entries: updateEntry(a.entries, i, 'timeAgo', v) }); }
226 })
227 )
228 );
229 }),
230 el(Button, {
231 variant: 'secondary',
232 style: { marginTop: '8px', width: '100%' },
233 onClick: addEntry
234 }, __('+ Add Entry', 'blockenberg'))
235 ),
236 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
237 getTypoControl() && el(getTypoControl(), {
238 label: __('Name', 'blockenberg'),
239 value: a.nameTypo || {},
240 onChange: function (v) { setAttributes({ nameTypo: v }); }
241 }),
242 getTypoControl() && el(getTypoControl(), {
243 label: __('Action / Time', 'blockenberg'),
244 value: a.actionTypo || {},
245 onChange: function (v) { setAttributes({ actionTypo: v }); }
246 })
247 ),
248 el(PanelColorSettings, {
249 title: __('Colors', 'blockenberg'),
250 initialOpen: false,
251 colorSettings: [
252 { value: a.bgColor, onChange: function (c) { setAttributes({ bgColor: c || '#ffffff' }); }, label: __('Background', 'blockenberg') },
253 { value: a.borderColor, onChange: function (c) { setAttributes({ borderColor: c || '#e2e8f0' }); }, label: __('Border', 'blockenberg') },
254 { value: a.nameColor, onChange: function (c) { setAttributes({ nameColor: c || '#0f172a' }); }, label: __('Name', 'blockenberg') },
255 { value: a.actionColor, onChange: function (c) { setAttributes({ actionColor: c || '#475569' }); }, label: __('Action Text', 'blockenberg') },
256 { value: a.timeColor, onChange: function (c) { setAttributes({ timeColor: c || '#94a3b8' }); }, label: __('Timestamp', 'blockenberg') },
257 { value: a.avatarBg, onChange: function (c) { setAttributes({ avatarBg: c || '#f0f9ff' }); }, label: __('Avatar Background', 'blockenberg') },
258 { value: a.closeBtnColor, onChange: function (c) { setAttributes({ closeBtnColor: c || '#94a3b8' }); }, label: __('Close Button', 'blockenberg') }
259 ]
260 })
261 );
262
263 var blockProps = useBlockProps((function () {
264 var p = { className: 'bkbg-editor-wrap', 'data-block-label': 'Social Proof Popup' };
265 var _tvFn = getTypoCssVars();
266 if (_tvFn) {
267 var s = {};
268 Object.assign(s, _tvFn(a.nameTypo || {}, '--bkspop-nm-'));
269 Object.assign(s, _tvFn(a.actionTypo || {}, '--bkspop-ac-'));
270 p.style = s;
271 }
272 return p;
273 }()));
274
275 return el('div', blockProps,
276 inspector,
277 el(PopupPreview, { a: a })
278 );
279 },
280
281 save: function (props) {
282 return el('div', useBlockProps.save(),
283 el('div', { className: 'bkbg-spop-app', 'data-opts': JSON.stringify(props.attributes) })
284 );
285 }
286 });
287 }() );
288