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 / offer-card / index.js

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

200 lines 15.3 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 registerBlockType = wp.blocks.registerBlockType;
5 var InspectorControls = wp.blockEditor.InspectorControls;
6 var useBlockProps = wp.blockEditor.useBlockProps;
7 var RichText = wp.blockEditor.RichText;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var PanelBody = wp.components.PanelBody;
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, _tv;
17 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
18 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
19
20 var BADGE_STYLES = {
21 hot: { bg: '#fef2f2', color: '#b91c1c', icon: '🔥' },
22 sale: { bg: '#fef9c3', color: '#854d0e', icon: '💸' },
23 limited: { bg: '#fff7ed', color: '#c2410c', icon: '' },
24 new: { bg: '#f0fdf4', color: '#15803d', icon: '' }
25 };
26
27 registerBlockType('blockenberg/offer-card', {
28 edit: function (props) {
29 var attr = props.attributes;
30 var setAttr = props.setAttributes;
31 var blockProps = (function () {
32 var bp = useBlockProps({ className: 'bkbg-ofr-editor bkbg-ofr-wrap' });
33 var _tvf = getTypoCssVars();
34 var s = {};
35 if (_tvf) {
36 Object.assign(s, _tvf(attr.headingTypo, '--bkbg-ofr-hd-'));
37 Object.assign(s, _tvf(attr.descTypo, '--bkbg-ofr-ds-'));
38 Object.assign(s, _tvf(attr.ctaTypo, '--bkbg-ofr-ct-'));
39 }
40 bp.style = Object.assign(s, bp.style || {});
41 return bp;
42 }());
43
44 var isBanner = attr.layout === 'banner';
45 var isMinimal = attr.layout === 'minimal';
46
47 function updateInclude(idx, val) {
48 var next = attr.includes.map(function (it, i) { return i === idx ? { text: val } : it; });
49 setAttr({ includes: next });
50 }
51
52 var bs = BADGE_STYLES[attr.badgeStyle] || BADGE_STYLES.hot;
53
54 var card = el('div', {
55 style: {
56 background: attr.cardBg,
57 border: '1px solid ' + attr.borderColor,
58 borderRadius: attr.borderRadius + 'px',
59 padding: '32px',
60 maxWidth: attr.maxWidth + 'px',
61 margin: '0 auto',
62 boxShadow: isMinimal ? 'none' : '0 4px 32px rgba(0,0,0,0.08)',
63 display: isBanner ? 'flex' : 'block',
64 gap: isBanner ? '40px' : undefined,
65 alignItems: isBanner ? 'center' : undefined
66 }
67 },
68 /* Left / top section */
69 el('div', { style: { flex: isBanner ? '1' : undefined } },
70 attr.showBadge && el('div', { style: { marginBottom: '16px' } },
71 el('span', { style: { background: attr.badgeBg, color: attr.badgeColor, fontSize: '12px', fontWeight: '700', padding: '5px 14px', borderRadius: '999px' } },
72 el(RichText, { tagName: 'span', value: attr.badge, onChange: function (v) { setAttr({ badge: v }); } })
73 )
74 ),
75 el(RichText, {
76 tagName: 'h3', value: attr.heading,
77 className: 'bkbg-ofr-heading',
78 style: { color: attr.headingColor, margin: '0 0 10px' },
79 onChange: function (v) { setAttr({ heading: v }); }
80 }),
81 el(RichText, {
82 tagName: 'p', value: attr.description,
83 className: 'bkbg-ofr-desc',
84 style: { color: attr.descColor, margin: '0 0 20px' },
85 onChange: function (v) { setAttr({ description: v }); }
86 }),
87 attr.showPrice && el('div', { style: { display: 'flex', alignItems: 'baseline', gap: '10px', marginBottom: '20px' } },
88 el('span', { style: { fontSize: '40px', fontWeight: '800', color: attr.priceColor } }, attr.currency + attr.salePrice),
89 attr.originalPrice && el('span', { style: { fontSize: '20px', color: attr.strikethroughColor, textDecoration: 'line-through' } }, attr.currency + attr.originalPrice)
90 ),
91 attr.showCountdown && el('div', { className: 'bkbg-ofr-countdown-preview', style: { display: 'flex', gap: '8px', marginBottom: '24px', flexWrap: 'wrap' } },
92 ['HH', 'MM', 'SS'].map(function (lbl, i) {
93 return el('div', { key: i, style: { background: '#111827', color: '#fff', borderRadius: '8px', padding: '8px 14px', textAlign: 'center', minWidth: '60px' } },
94 el('div', { style: { fontSize: '22px', fontWeight: '700', lineHeight: 1 } }, '00'),
95 el('div', { style: { fontSize: '10px', opacity: 0.6, marginTop: '2px', textTransform: 'uppercase' } }, lbl)
96 );
97 }),
98 el('div', { style: { flex: 1, display: 'flex', alignItems: 'center' } },
99 el(TextControl, { label: __('Countdown end (ISO date)', 'blockenberg'), value: attr.countdownEnd, placeholder: '2025-12-31T23:59:00', onChange: function (v) { setAttr({ countdownEnd: v }); }, __nextHasNoMarginBottom: true })
100 )
101 )
102 ),
103 /* Right / bottom section */
104 el('div', { style: { flex: isBanner ? '0 0 300px' : undefined } },
105 attr.showIncludes && el('ul', { style: { listStyle: 'none', margin: '0 0 20px', padding: 0 } },
106 attr.includes.map(function (item, idx) {
107 return el('li', { key: idx, style: { display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '10px', fontSize: '15px', color: attr.includeColor } },
108 el('span', { style: { color: attr.checkColor, fontSize: '16px', fontWeight: '700', flexShrink: 0 } }, ''),
109 el(TextControl, {
110 value: item.text,
111 onChange: function (v) { updateInclude(idx, v); },
112 style: { margin: 0, flex: 1 },
113 __nextHasNoMarginBottom: true
114 }),
115 el(Button, { isSmall: true, isDestructive: true, onClick: function () { setAttr({ includes: attr.includes.filter(function (_, i) { return i !== idx; }) }); } }, '')
116 );
117 }),
118 el(Button, { isSecondary: true, isSmall: true, onClick: function () { setAttr({ includes: attr.includes.concat([{ text: 'New benefit' }]) }); } }, '+ Add item')
119 ),
120 el('a', {
121 href: '#editor',
122 className: 'bkbg-ofr-cta',
123 style: { display: 'block', background: attr.ctaBg, color: attr.ctaColor, padding: '16px', borderRadius: '8px', textAlign: 'center', textDecoration: 'none' }
124 }, attr.ctaLabel),
125 attr.showDisclaimer && el(RichText, {
126 tagName: 'p', value: attr.disclaimer,
127 style: { fontSize: '12px', color: attr.disclaimerColor, textAlign: 'center', marginTop: '12px', marginBottom: 0 },
128 onChange: function (v) { setAttr({ disclaimer: v }); }
129 })
130 )
131 );
132
133 var controls = el(InspectorControls, {},
134 el(PanelBody, { title: __('Badge & Pricing', 'blockenberg'), initialOpen: true },
135 el(ToggleControl, { label: __('Show Badge', 'blockenberg'), checked: attr.showBadge, onChange: function (v) { setAttr({ showBadge: v }); }, __nextHasNoMarginBottom: true }),
136 attr.showBadge && el(SelectControl, {
137 label: __('Badge Style', 'blockenberg'), value: attr.badgeStyle,
138 options: [{ label: '🔥 Hot', value: 'hot' }, { label: '💸 Sale', value: 'sale' }, { label: '⏳ Limited', value: 'limited' }, { label: '✨ New', value: 'new' }],
139 onChange: function (v) { setAttr({ badgeStyle: v }); }, __nextHasNoMarginBottom: true
140 }),
141 el(ToggleControl, { label: __('Show Price', 'blockenberg'), checked: attr.showPrice, onChange: function (v) { setAttr({ showPrice: v }); }, __nextHasNoMarginBottom: true }),
142 attr.showPrice && el(TextControl, { label: __('Currency Symbol', 'blockenberg'), value: attr.currency, onChange: function (v) { setAttr({ currency: v }); }, __nextHasNoMarginBottom: true }),
143 attr.showPrice && el(TextControl, { label: __('Sale Price', 'blockenberg'), value: attr.salePrice, onChange: function (v) { setAttr({ salePrice: v }); }, __nextHasNoMarginBottom: true }),
144 attr.showPrice && el(TextControl, { label: __('Original Price (strikethrough)', 'blockenberg'), value: attr.originalPrice, onChange: function (v) { setAttr({ originalPrice: v }); }, __nextHasNoMarginBottom: true }),
145 el(ToggleControl, { label: __('Show Countdown Timer', 'blockenberg'), checked: attr.showCountdown, onChange: function (v) { setAttr({ showCountdown: v }); }, __nextHasNoMarginBottom: true }),
146 el(ToggleControl, { label: __('Show Includes List', 'blockenberg'), checked: attr.showIncludes, onChange: function (v) { setAttr({ showIncludes: v }); }, __nextHasNoMarginBottom: true }),
147 el(TextControl, { label: __('CTA Label', 'blockenberg'), value: attr.ctaLabel, onChange: function (v) { setAttr({ ctaLabel: v }); }, __nextHasNoMarginBottom: true }),
148 el(TextControl, { label: __('CTA URL', 'blockenberg'), value: attr.ctaUrl, onChange: function (v) { setAttr({ ctaUrl: v }); }, __nextHasNoMarginBottom: true }),
149 el(ToggleControl, { label: __('Open CTA in new tab', 'blockenberg'), checked: attr.ctaOpenNewTab, onChange: function (v) { setAttr({ ctaOpenNewTab: v }); }, __nextHasNoMarginBottom: true }),
150 el(ToggleControl, { label: __('Show Disclaimer', 'blockenberg'), checked: attr.showDisclaimer, onChange: function (v) { setAttr({ showDisclaimer: v }); }, __nextHasNoMarginBottom: true })
151 ),
152 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
153 el(SelectControl, {
154 label: __('Card Layout', 'blockenberg'), value: attr.layout,
155 options: [{ label: 'Card (stacked)', value: 'card' }, { label: 'Banner (side-by-side)', value: 'banner' }, { label: 'Minimal', value: 'minimal' }],
156 onChange: function (v) { setAttr({ layout: v }); }, __nextHasNoMarginBottom: true
157 }),
158 el(RangeControl, { label: __('Border Radius (px)', 'blockenberg'), value: attr.borderRadius, min: 0, max: 32, onChange: function (v) { setAttr({ borderRadius: v }); }, __nextHasNoMarginBottom: true }),
159 el(RangeControl, { label: __('Max Width (px)', 'blockenberg'), value: attr.maxWidth, min: 300, max: 1400, onChange: function (v) { setAttr({ maxWidth: v }); }, __nextHasNoMarginBottom: true }),
160 el(RangeControl, { label: __('Padding Top (px)', 'blockenberg'), value: attr.paddingTop, min: 0, max: 160, onChange: function (v) { setAttr({ paddingTop: v }); }, __nextHasNoMarginBottom: true }),
161 el(RangeControl, { label: __('Padding Bottom (px)', 'blockenberg'), value: attr.paddingBottom, min: 0, max: 160, onChange: function (v) { setAttr({ paddingBottom: v }); }, __nextHasNoMarginBottom: true })
162 ),
163 el(PanelColorSettings, {
164 title: __('Colors', 'blockenberg'), initialOpen: false,
165 colorSettings: [
166 { label: __('Section BG', 'blockenberg'), value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '#ffffff' }); } },
167 { label: __('Card BG', 'blockenberg'), value: attr.cardBg, onChange: function (v) { setAttr({ cardBg: v || '#ffffff' }); } },
168 { label: __('Border', 'blockenberg'), value: attr.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#e5e7eb' }); } },
169 { label: __('Accent', 'blockenberg'), value: attr.accentColor, onChange: function (v) { setAttr({ accentColor: v || '#7c3aed' }); } },
170 { label: __('Badge BG', 'blockenberg'), value: attr.badgeBg, onChange: function (v) { setAttr({ badgeBg: v || '#fef2f2' }); } },
171 { label: __('Badge Text', 'blockenberg'), value: attr.badgeColor, onChange: function (v) { setAttr({ badgeColor: v || '#b91c1c' }); } },
172 { label: __('Heading', 'blockenberg'), value: attr.headingColor, onChange: function (v) { setAttr({ headingColor: v || '#111827' }); } },
173 { label: __('Description', 'blockenberg'), value: attr.descColor, onChange: function (v) { setAttr({ descColor: v || '#6b7280' }); } },
174 { label: __('Sale Price', 'blockenberg'), value: attr.priceColor, onChange: function (v) { setAttr({ priceColor: v || '#111827' }); } },
175 { label: __('Strikethrough', 'blockenberg'), value: attr.strikethroughColor, onChange: function (v) { setAttr({ strikethroughColor: v || '#9ca3af' }); } },
176 { label: __('CTA BG', 'blockenberg'), value: attr.ctaBg, onChange: function (v) { setAttr({ ctaBg: v || '#7c3aed' }); } },
177 { label: __('CTA Text', 'blockenberg'), value: attr.ctaColor, onChange: function (v) { setAttr({ ctaColor: v || '#ffffff' }); } },
178 { label: __('Checkmark', 'blockenberg'), value: attr.checkColor, onChange: function (v) { setAttr({ checkColor: v || '#16a34a' }); } }
179 ]
180 }),
181 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
182 el(getTypoControl(), { label: __('Heading'), value: attr.headingTypo, onChange: function (v) { setAttr({ headingTypo: v }); } }),
183 el(getTypoControl(), { label: __('Description'), value: attr.descTypo, onChange: function (v) { setAttr({ descTypo: v }); } }),
184 el(getTypoControl(), { label: __('CTA Button'), value: attr.ctaTypo, onChange: function (v) { setAttr({ ctaTypo: v }); } })
185 )
186 );
187
188 return el('div', blockProps, controls,
189 el('div', { style: { background: attr.bgColor, paddingTop: attr.paddingTop + 'px', paddingBottom: attr.paddingBottom + 'px' } }, card)
190 );
191 },
192
193 save: function (props) {
194 return el('div', wp.blockEditor.useBlockProps.save(),
195 el('div', { className: 'bkbg-ofr-app', 'data-opts': JSON.stringify(props.attributes) })
196 );
197 }
198 });
199 }() );
200