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 / split-benefits / index.js

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

388 lines 23.5 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 RichText = wp.blockEditor.RichText;
8 var MediaUpload = wp.blockEditor.MediaUpload;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var TextControl = wp.components.TextControl;
16 var Button = wp.components.Button;
17
18 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
19 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
20
21 registerBlockType('blockenberg/split-benefits', {
22 title: __('Split Benefits', 'blockenberg'),
23 icon: 'layout',
24 category: 'bkbg-marketing',
25
26 edit: function (props) {
27 var a = props.attributes;
28 var set = props.setAttributes;
29
30 var editingState = useState(null);
31 var editingIdx = editingState[0];
32 var setEditingIdx = editingState[1];
33
34 function wrapStyle(a) {
35 return {
36 '--bkbg-sb-bg': a.bgColor,
37 '--bkbg-sb-text': a.textColor,
38 '--bkbg-sb-heading-c': a.headingColor,
39 '--bkbg-sb-heading-sz': a.headingSize + 'px',
40 '--bkbg-sb-heading-w': a.headingWeight,
41 '--bkbg-sb-eyebrow-c': a.eyebrowColor,
42 '--bkbg-sb-eyebrow-sz': a.eyebrowSize + 'px',
43 '--bkbg-sb-sub-c': a.subColor,
44 '--bkbg-sb-sub-sz': a.subSize + 'px',
45 '--bkbg-sb-item-c': a.itemColor,
46 '--bkbg-sb-item-sz': a.itemFontSize + 'px',
47 '--bkbg-sb-item-w': a.itemFontWeight,
48 '--bkbg-sb-item-lh': a.itemLineHeight,
49 '--bkbg-sb-icon-c': a.iconColor,
50 '--bkbg-sb-icon-sz': a.iconSize + 'px',
51 '--bkbg-sb-accent': a.accentColor,
52 '--bkbg-sb-btn-bg': a.btnBg,
53 '--bkbg-sb-btn-text': a.btnText,
54 '--bkbg-sb-btn2-text': a.btn2Text,
55 '--bkbg-sb-btn-r': a.btnRadius + 'px',
56 '--bkbg-sb-btn-sz': a.btnSize + 'px',
57 '--bkbg-sb-gap': a.columnGap + 'px',
58 '--bkbg-sb-item-gap': a.itemGap + 'px',
59 '--bkbg-sb-img-r': a.imageRadius + 'px',
60 '--bkbg-sb-pt': a.paddingTop + 'px',
61 '--bkbg-sb-pb': a.paddingBottom + 'px',
62 };
63 }
64
65 var ICON_CHARS = {
66 'check-circle': '',
67 'arrow': '',
68 'star': '�
69 ',
70 'dot': '',
71 'lightning': '',
72 };
73
74 function getIconEl(iconType) {
75 var iconMap = {
76 'check-circle': 'dashicons-yes-alt',
77 'arrow': 'dashicons-arrow-right-alt2',
78 'star': 'dashicons-star-filled',
79 'dot': 'dashicons-marker',
80 'lightning': 'dashicons-bolt',
81 };
82 return el('span', { className: 'dashicons ' + (iconMap[iconType] || 'dashicons-yes-alt') + ' bkbg-sb-icon' });
83 }
84
85 function updateBenefit(idx, value) {
86 var arr = a.benefits.slice();
87 arr[idx] = Object.assign({}, arr[idx], { text: value });
88 set({ benefits: arr });
89 }
90
91 function addBenefit() {
92 set({ benefits: a.benefits.concat([{ text: __('Another key benefit goes here', 'blockenberg') }]) });
93 }
94
95 function removeBenefit(idx) {
96 set({ benefits: a.benefits.filter(function (_, i) { return i !== idx; }) });
97 }
98
99 function moveBenefit(idx, dir) {
100 var ni = idx + dir;
101 if (ni < 0 || ni >= a.benefits.length) return;
102 var arr = a.benefits.slice();
103 var tmp = arr[idx]; arr[idx] = arr[ni]; arr[ni] = tmp;
104 set({ benefits: arr });
105 }
106
107 var styleOptions = [
108 { label: __('Clean (white)', 'blockenberg'), value: 'clean' },
109 { label: __('Dark', 'blockenberg'), value: 'dark' },
110 { label: __('Tinted', 'blockenberg'), value: 'tinted' },
111 { label: __('Bordered', 'blockenberg'), value: 'bordered' },
112 ];
113
114 var ratioOptions = [
115 { label: __('50 / 50', 'blockenberg'), value: '50-50' },
116 { label: __('60 / 40 (content wider)', 'blockenberg'), value: '60-40' },
117 { label: __('40 / 60 (image wider)', 'blockenberg'), value: '40-60' },
118 ];
119
120 var imageStyleOptions = [
121 { label: __('Plain', 'blockenberg'), value: 'plain' },
122 { label: __('Rounded', 'blockenberg'), value: 'rounded' },
123 { label: __('Shadow', 'blockenberg'), value: 'shadow' },
124 { label: __('Card (bg box)', 'blockenberg'), value: 'card' },
125 { label: __('Overlapping', 'blockenberg'), value: 'overlapping' },
126 ];
127
128 var iconTypeOptions = [
129 { label: __('Check Circle', 'blockenberg'), value: 'check-circle' },
130 { label: __('Arrow Right', 'blockenberg'), value: 'arrow' },
131 { label: __('Star', 'blockenberg'), value: 'star' },
132 { label: __('Dot / Marker', 'blockenberg'), value: 'dot' },
133 { label: __('Lightning Bolt', 'blockenberg'), value: 'lightning' },
134 ];
135
136 var alignOptions = [
137 { label: __('Center', 'blockenberg'), value: 'center' },
138 { label: __('Top', 'blockenberg'), value: 'top' },
139 ];
140
141 var inspector = el(InspectorControls, {},
142
143 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
144 el(ToggleControl, {
145 label: __('Show Eyebrow', 'blockenberg'), checked: a.showEyebrow, __nextHasNoMarginBottom: true,
146 onChange: function (v) { set({ showEyebrow: v }); }
147 }),
148 a.showEyebrow && el(TextControl, { label: __('Eyebrow Text', 'blockenberg'), value: a.eyebrow, onChange: function (v) { set({ eyebrow: v }); } }),
149 el(ToggleControl, {
150 label: __('Show Subheading', 'blockenberg'), checked: a.showSubheading, __nextHasNoMarginBottom: true,
151 onChange: function (v) { set({ showSubheading: v }); }
152 }),
153 el(ToggleControl, {
154 label: __('Show Benefits List', 'blockenberg'), checked: a.showBenefits, __nextHasNoMarginBottom: true,
155 onChange: function (v) { set({ showBenefits: v }); }
156 }),
157 el(ToggleControl, {
158 label: __('Show Primary CTA', 'blockenberg'), checked: a.showCta, __nextHasNoMarginBottom: true,
159 onChange: function (v) { set({ showCta: v }); }
160 }),
161 a.showCta && el(TextControl, { label: __('CTA Text', 'blockenberg'), value: a.ctaText, onChange: function (v) { set({ ctaText: v }); } }),
162 a.showCta && el(TextControl, { label: __('CTA URL', 'blockenberg'), value: a.ctaUrl, onChange: function (v) { set({ ctaUrl: v }); } }),
163 el(ToggleControl, {
164 label: __('Show Secondary CTA', 'blockenberg'), checked: a.showSecondaryCta, __nextHasNoMarginBottom: true,
165 onChange: function (v) { set({ showSecondaryCta: v }); }
166 }),
167 a.showSecondaryCta && el(TextControl, { label: __('Secondary CTA Text', 'blockenberg'), value: a.ctaSecondaryText, onChange: function (v) { set({ ctaSecondaryText: v }); } }),
168 a.showSecondaryCta && el(TextControl, { label: __('Secondary CTA URL', 'blockenberg'), value: a.ctaSecondaryUrl, onChange: function (v) { set({ ctaSecondaryUrl: v }); } })
169 ),
170
171 el(PanelBody, { title: __('Image', 'blockenberg'), initialOpen: false },
172 el(MediaUpload, {
173 onSelect: function (m) { set({ imageUrl: m.url, imageId: m.id, imageAlt: m.alt || '' }); },
174 allowedTypes: ['image'],
175 value: a.imageId,
176 render: function (ref) {
177 return el('div', {},
178 a.imageUrl && el('img', { src: a.imageUrl, style: { width: '100%', maxHeight: 120, objectFit: 'cover', borderRadius: 8, marginBottom: 8 } }),
179 el(Button, { variant: 'secondary', onClick: ref.open }, a.imageUrl ? __('Change Image', 'blockenberg') : __('Upload Image', 'blockenberg')),
180 a.imageUrl && el(Button, { isDestructive: true, variant: 'link', onClick: function () { set({ imageUrl: '', imageId: 0 }); } }, __('Remove', 'blockenberg'))
181 );
182 }
183 }),
184 el(SelectControl, { label: __('Image Position', 'blockenberg'), value: a.imagePosition, options: [{ label: __('Right', 'blockenberg'), value: 'right' }, { label: __('Left', 'blockenberg'), value: 'left' }], onChange: function (v) { set({ imagePosition: v }); } }),
185 el(SelectControl, { label: __('Image Style', 'blockenberg'), value: a.imageStyle, options: imageStyleOptions, onChange: function (v) { set({ imageStyle: v }); } }),
186 el(RangeControl, { label: __('Image Border Radius', 'blockenberg'), value: a.imageRadius, onChange: function (v) { set({ imageRadius: v }); }, min: 0, max: 48 })
187 ),
188
189 el(PanelBody, { title: __('Layout & Style', 'blockenberg'), initialOpen: false },
190 el(SelectControl, { label: __('Background Style', 'blockenberg'), value: a.style, options: styleOptions, onChange: function (v) { set({ style: v }); } }),
191 el(SelectControl, { label: __('Column Ratio', 'blockenberg'), value: a.ratio, options: ratioOptions, onChange: function (v) { set({ ratio: v }); } }),
192 el(SelectControl, { label: __('Vertical Align', 'blockenberg'), value: a.verticalAlign, options: alignOptions, onChange: function (v) { set({ verticalAlign: v }); } }),
193 el(RangeControl, { label: __('Column Gap', 'blockenberg'), value: a.columnGap, onChange: function (v) { set({ columnGap: v }); }, min: 16, max: 120 }),
194 el(RangeControl, { label: __('Button Radius', 'blockenberg'), value: a.btnRadius, onChange: function (v) { set({ btnRadius: v }); }, min: 0, max: 99 })
195 ),
196
197 el(PanelBody, { title: __('Benefits List', 'blockenberg'), initialOpen: false },
198 el(SelectControl, { label: __('Icon Type', 'blockenberg'), value: a.iconType, options: iconTypeOptions, onChange: function (v) { set({ iconType: v }); } }),
199 el(RangeControl, { label: __('Icon Size', 'blockenberg'), value: a.iconSize, onChange: function (v) { set({ iconSize: v }); }, min: 12, max: 32 }),
200 el(RangeControl, { label: __('Item Gap', 'blockenberg'), value: a.itemGap, onChange: function (v) { set({ itemGap: v }); }, min: 4, max: 32 }),
201 el('br'),
202 a.benefits.map(function (b, idx) {
203 return el('div', { key: idx, className: 'bkbg-sb-benefit-ctrl' },
204 el('div', { className: 'bkbg-sb-benefit-head' },
205 el('small', { style: { fontWeight: 600 } }, (idx + 1) + '. ' + (b.text || '').substring(0, 24) + (b.text && b.text.length > 24 ? '' : '')),
206 el('div', { style: { display: 'flex', gap: 4 } },
207 el(Button, { icon: 'arrow-up-alt2', size: 'small', disabled: idx === 0, onClick: function () { moveBenefit(idx, -1); } }),
208 el(Button, { icon: 'arrow-down-alt2', size: 'small', disabled: idx === a.benefits.length - 1, onClick: function () { moveBenefit(idx, 1); } }),
209 el(Button, { icon: 'trash', size: 'small', isDestructive: true, onClick: function () { removeBenefit(idx); } })
210 )
211 ),
212 el(TextControl, { value: b.text, onChange: function (v) { updateBenefit(idx, v); } })
213 );
214 }),
215 el(Button, { variant: 'secondary', onClick: addBenefit }, __('+ Add Benefit', 'blockenberg'))
216 ),
217
218 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
219 getTypoControl() ? el(getTypoControl(), { label: __('Heading Typography', 'blockenberg'), value: a.headingTypo || {}, onChange: function (v) { set({ headingTypo: v }); } }) : null,
220 getTypoControl() ? el(getTypoControl(), { label: __('Eyebrow Typography', 'blockenberg'), value: a.eyebrowTypo || {}, onChange: function (v) { set({ eyebrowTypo: v }); } }) : null,
221 getTypoControl() ? el(getTypoControl(), { label: __('Subheading Typography', 'blockenberg'), value: a.subTypo || {}, onChange: function (v) { set({ subTypo: v }); } }) : null,
222 getTypoControl() ? el(getTypoControl(), { label: __('Item Typography', 'blockenberg'), value: a.itemTypo || {}, onChange: function (v) { set({ itemTypo: v }); } }) : null,
223 getTypoControl() ? el(getTypoControl(), { label: __('Button Typography', 'blockenberg'), value: a.btnTypo || {}, onChange: function (v) { set({ btnTypo: v }); } }) : null
224 ),
225
226 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
227 el(RangeControl, { label: __('Padding Top', 'blockenberg'), value: a.paddingTop, onChange: function (v) { set({ paddingTop: v }); }, min: 0, max: 240 }),
228 el(RangeControl, { label: __('Padding Bottom', 'blockenberg'), value: a.paddingBottom, onChange: function (v) { set({ paddingBottom: v }); }, min: 0, max: 240 })
229 ),
230
231 el(PanelColorSettings, {
232 title: __('Colors', 'blockenberg'), initialOpen: false,
233 colorSettings: [
234 { value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); }, label: __('Background', 'blockenberg') },
235 { value: a.headingColor, onChange: function (v) { set({ headingColor: v || '#0f172a' }); }, label: __('Heading Color', 'blockenberg') },
236 { value: a.eyebrowColor, onChange: function (v) { set({ eyebrowColor: v || '#6c3fb5' }); }, label: __('Eyebrow Color', 'blockenberg') },
237 { value: a.subColor, onChange: function (v) { set({ subColor: v || '#64748b' }); }, label: __('Subheading Color', 'blockenberg') },
238 { value: a.itemColor, onChange: function (v) { set({ itemColor: v || '#1e293b' }); }, label: __('Item Text Color', 'blockenberg') },
239 { value: a.iconColor, onChange: function (v) { set({ iconColor: v || '#6c3fb5' }); }, label: __('Icon Color', 'blockenberg') },
240 { value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#6c3fb5' }); }, label: __('Accent Color', 'blockenberg') },
241 { value: a.btnBg, onChange: function (v) { set({ btnBg: v || '#6c3fb5' }); }, label: __('Primary Button BG', 'blockenberg') },
242 { value: a.btnText, onChange: function (v) { set({ btnText: v || '#ffffff' }); }, label: __('Primary Button Text', 'blockenberg') },
243 { value: a.btn2Text, onChange: function (v) { set({ btn2Text: v || '#6c3fb5' }); }, label: __('Secondary Button Text', 'blockenberg') },
244 ]
245 })
246 );
247
248 var imgPos = a.imagePosition === 'left' ? 'bkbg-sb-img--left' : 'bkbg-sb-img--right';
249 var blockProps = useBlockProps({
250 className: 'bkbg-sb-wrap bkbg-sb-style--' + a.style + ' bkbg-sb-ratio--' + a.ratio + ' ' + imgPos,
251 style: wrapStyle(a)
252 });
253
254 var textCol = el('div', { className: 'bkbg-sb-text-col' },
255 a.showEyebrow && a.eyebrow && el('div', { className: 'bkbg-sb-eyebrow' }, a.eyebrow),
256 el(RichText, {
257 tagName: 'h2', className: 'bkbg-sb-heading',
258 value: a.heading, placeholder: __('Heading…', 'blockenberg'),
259 onChange: function (v) { set({ heading: v }); }
260 }),
261 a.showSubheading && el(RichText, {
262 tagName: 'p', className: 'bkbg-sb-sub',
263 value: a.subheading, placeholder: __('Supporting text…', 'blockenberg'),
264 onChange: function (v) { set({ subheading: v }); }
265 }),
266 a.showBenefits && el('ul', { className: 'bkbg-sb-list' },
267 a.benefits.map(function (b, idx) {
268 return el('li', { key: idx, className: 'bkbg-sb-item' },
269 el('span', { className: 'bkbg-sb-item-icon' }, getIconEl(a.iconType)),
270 el('span', { className: 'bkbg-sb-item-text' }, b.text)
271 );
272 })
273 ),
274 (a.showCta || a.showSecondaryCta) && el('div', { className: 'bkbg-sb-ctas' },
275 a.showCta && el('a', { className: 'bkbg-sb-btn bkbg-sb-btn--primary', href: a.ctaUrl }, a.ctaText),
276 a.showSecondaryCta && el('a', { className: 'bkbg-sb-btn bkbg-sb-btn--secondary', href: a.ctaSecondaryUrl }, a.ctaSecondaryText)
277 )
278 );
279
280 var imageCol = el('div', { className: 'bkbg-sb-image-col bkbg-sb-img-style--' + a.imageStyle },
281 a.imageUrl ?
282 el('img', { className: 'bkbg-sb-img', src: a.imageUrl, alt: a.imageAlt }) :
283 el('div', { className: 'bkbg-sb-img-placeholder' },
284 el('span', { className: 'dashicons dashicons-format-image' }),
285 el('p', {}, __('Upload an image', 'blockenberg'))
286 )
287 );
288
289 return el('div', blockProps,
290 inspector,
291 el('div', { className: 'bkbg-sb-inner bkbg-sb-valign--' + a.verticalAlign },
292 a.imagePosition === 'left' ? [imageCol, textCol] : [textCol, imageCol]
293 )
294 );
295 },
296
297 save: function (props) {
298 var a = props.attributes;
299 var el = wp.element.createElement;
300
301 function wrapStyle(a) {
302 var s = {
303 '--bkbg-sb-bg': a.bgColor,
304 '--bkbg-sb-text': a.textColor,
305 '--bkbg-sb-heading-c': a.headingColor,
306 '--bkbg-sb-heading-sz': a.headingSize + 'px',
307 '--bkbg-sb-heading-w': a.headingWeight,
308 '--bkbg-sb-eyebrow-c': a.eyebrowColor,
309 '--bkbg-sb-eyebrow-sz': a.eyebrowSize + 'px',
310 '--bkbg-sb-sub-c': a.subColor,
311 '--bkbg-sb-sub-sz': a.subSize + 'px',
312 '--bkbg-sb-item-c': a.itemColor,
313 '--bkbg-sb-item-sz': a.itemFontSize + 'px',
314 '--bkbg-sb-item-w': a.itemFontWeight,
315 '--bkbg-sb-icon-c': a.iconColor,
316 '--bkbg-sb-icon-sz': a.iconSize + 'px',
317 '--bkbg-sb-accent': a.accentColor,
318 '--bkbg-sb-btn-bg': a.btnBg,
319 '--bkbg-sb-btn-text': a.btnText,
320 '--bkbg-sb-btn2-text': a.btn2Text,
321 '--bkbg-sb-btn-r': a.btnRadius + 'px',
322 '--bkbg-sb-btn-sz': a.btnSize + 'px',
323 '--bkbg-sb-gap': a.columnGap + 'px',
324 '--bkbg-sb-item-gap': a.itemGap + 'px',
325 '--bkbg-sb-img-r': a.imageRadius + 'px',
326 '--bkbg-sb-pt': a.paddingTop + 'px',
327 '--bkbg-sb-pb': a.paddingBottom + 'px',
328 };
329 var tv = getTypoCssVars();
330 if (tv) {
331 Object.assign(s, tv(a.headingTypo, '--bksb-hd-'));
332 Object.assign(s, tv(a.eyebrowTypo, '--bksb-eb-'));
333 Object.assign(s, tv(a.subTypo, '--bksb-sh-'));
334 Object.assign(s, tv(a.itemTypo, '--bksb-it-'));
335 Object.assign(s, tv(a.btnTypo, '--bksb-bt-'));
336 }
337 return s;
338 }
339
340 var iconMap = {
341 'check-circle': 'dashicons-yes-alt',
342 'arrow': 'dashicons-arrow-right-alt2',
343 'star': 'dashicons-star-filled',
344 'dot': 'dashicons-marker',
345 'lightning': 'dashicons-bolt',
346 };
347
348 var imgPos = a.imagePosition === 'left' ? 'bkbg-sb-img--left' : 'bkbg-sb-img--right';
349 var blockProps = wp.blockEditor.useBlockProps.save({
350 className: 'bkbg-sb-wrap bkbg-sb-style--' + a.style + ' bkbg-sb-ratio--' + a.ratio + ' ' + imgPos,
351 style: wrapStyle(a)
352 });
353
354 var textCol = el('div', { className: 'bkbg-sb-text-col' },
355 a.showEyebrow && a.eyebrow && el('div', { className: 'bkbg-sb-eyebrow' }, a.eyebrow),
356 el(RichText.Content, { tagName: 'h2', className: 'bkbg-sb-heading', value: a.heading }),
357 a.showSubheading && el(RichText.Content, { tagName: 'p', className: 'bkbg-sb-sub', value: a.subheading }),
358 a.showBenefits && el('ul', { className: 'bkbg-sb-list' },
359 a.benefits.map(function (b, idx) {
360 return el('li', { key: idx, className: 'bkbg-sb-item' },
361 el('span', { className: 'bkbg-sb-item-icon' },
362 el('span', { className: 'dashicons ' + (iconMap[a.iconType] || 'dashicons-yes-alt') + ' bkbg-sb-icon' })
363 ),
364 el('span', { className: 'bkbg-sb-item-text' }, b.text)
365 );
366 })
367 ),
368 (a.showCta || a.showSecondaryCta) && el('div', { className: 'bkbg-sb-ctas' },
369 a.showCta && el('a', { className: 'bkbg-sb-btn bkbg-sb-btn--primary', href: a.ctaUrl }, a.ctaText),
370 a.showSecondaryCta && el('a', { className: 'bkbg-sb-btn bkbg-sb-btn--secondary', href: a.ctaSecondaryUrl }, a.ctaSecondaryText)
371 )
372 );
373
374 var imageCol = el('div', { className: 'bkbg-sb-image-col bkbg-sb-img-style--' + a.imageStyle },
375 a.imageUrl ?
376 el('img', { className: 'bkbg-sb-img', src: a.imageUrl, alt: a.imageAlt }) :
377 el('div', { className: 'bkbg-sb-img-placeholder' })
378 );
379
380 return el('div', blockProps,
381 el('div', { className: 'bkbg-sb-inner bkbg-sb-valign--' + a.verticalAlign },
382 a.imagePosition === 'left' ? [imageCol, textCol] : [textCol, imageCol]
383 )
384 );
385 }
386 });
387 }() );
388